lsalib.c revision 6537f381d2d9e7b4e2f7b29c3e7a3f13be036f2e
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* This module provides the high level interface to the LSA RPC functions.
*/
#include <strings.h>
#include <unistd.h>
#include <netdb.h>
#include <pwd.h>
#include <grp.h>
#include <smbsrv/libsmbns.h>
#include <smbsrv/libmlsvc.h>
#include <smbsrv/libsmbrdr.h>
#include <smbsrv/ntstatus.h>
#include <smbsrv/smb_token.h>
/*
* Name Lookup modes
*/
#define MLSVC_LOOKUP_BUILTIN 1
#define MLSVC_LOOKUP_LOCAL 2
#define MLSVC_LOOKUP_DOMAIN 3
#define MLSVC_LOOKUP_DOMLOC 4
static int lsa_lookup_mode(const char *, const char *);
smb_userinfo_t *);
static uint32_t lsa_lookup_name_domain(char *, char *, char *,
smb_userinfo_t *);
static int lsa_list_accounts(mlsvc_handle_t *);
/*
* lsa_lookup_name
*
* Lookup the given account and returns the account information
* in 'ainfo'
*
* If the name is a domain account, it may refer to a user, group or
* alias. If it is a local account, its type should be specified
* in the sid_type parameter. In case the account type is unknown
* sid_type should be set to SidTypeUnknown.
*
* account argument could be either [domain\\]name or [domain/]name.
* If domain is not specified and service is in domain mode then it
* first does a domain lookup and then a local lookup.
*/
{
int lookup_mode;
char *name;
char *domain;
if (name) {
/* domain is specified */
*name++ = '\0';
} else {
}
switch (lookup_mode) {
case MLSVC_LOOKUP_BUILTIN:
case MLSVC_LOOKUP_LOCAL:
case MLSVC_LOOKUP_DOMAIN:
default:
/* lookup the name in domain */
return (NT_STATUS_INTERNAL_ERROR);
ainfo);
if (status != NT_STATUS_NONE_MAPPED)
return (status);
/* lookup the name locally */
}
return (status);
}
{
if (!smb_sid_isvalid(sid))
return (NT_STATUS_INVALID_SID);
if (smb_sid_islocal(sid))
}
/*
* lsa_query_primary_domain_info
*
* Obtains the primary domain SID and name from the specified server
* (domain controller). The information is stored in the NT domain
* database by the lower level lsar_query_info_policy call. The caller
* should query the database to obtain a reference to the primary
* domain information.
*
* Returns NT status codes.
*/
{
char *user = smbrdr_ipc_get_user();
return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
(void) lsar_close(&domain_handle);
return (status);
}
/*
* lsa_query_account_domain_info
*
* Obtains the account domain SID and name from the current server
* (domain controller). The information is stored in the NT domain
* database by the lower level lsar_query_info_policy call. The caller
* should query the database to obtain a reference to the account
* domain information.
*
* Returns NT status codes.
*/
{
char *user = smbrdr_ipc_get_user();
return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
(void) lsar_close(&domain_handle);
return (status);
}
/*
* lsa_enum_trusted_domains
*
* Enumerate the trusted domains in our primary domain. The information
* is stored in the NT domain database by the lower level
* lsar_enum_trusted_domains call. The caller should query the database
* to obtain a reference to the trusted domain information.
*
* Returns NT status codes.
*/
lsa_enum_trusted_domains(void)
{
char *user = smbrdr_ipc_get_user();
return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
enum_context = 0;
if (status == MLSVC_NO_MORE_DATA) {
/*
* MLSVC_NO_MORE_DATA indicates that we
* have all of the available information.
*/
}
(void) lsar_close(&domain_handle);
return (status);
}
/*
* lsa_lookup_name_builtin
*
* lookup builtin account table to see if account_name is
* there. If it is there, set sid_name_use, domain_sid,
* domain_name, and rid fields of the passed user_info
* structure.
*/
static uint32_t
{
char *domain;
int res;
return (NT_STATUS_NONE_MAPPED);
if (res < 0)
return (NT_STATUS_INTERNAL_ERROR);
if (domain) {
return (NT_STATUS_SUCCESS);
}
return (NT_STATUS_INTERNAL_ERROR);
}
/*
* lsa_lookup_name_local
*
* Obtains the infomation for the given local account name if it
* can be found. The type of account is specified by sid_type,
* which can be of user, group or unknown type. If the caller
* doesn't know whether the name is a user or group name then
* SidTypeUnknown should be passed, in which case this
* function first tries to find a user and then a group match.
*
* CAVEAT: if there are both a user and a group account with
* the same name, user SID will always be returned.
*/
static uint32_t
{
char hostname[MAXHOSTNAMELEN];
switch (sid_type) {
case SidTypeUser:
if (status != NT_STATUS_SUCCESS)
return (status);
break;
case SidTypeGroup:
case SidTypeAlias:
if (status != NT_STATUS_SUCCESS)
return (status);
break;
case SidTypeUnknown:
if (status == NT_STATUS_SUCCESS)
break;
if (status == NT_STATUS_NONE_MAPPED)
return (status);
if (status != NT_STATUS_SUCCESS)
return (status);
break;
default:
return (NT_STATUS_INVALID_PARAMETER);
}
return (NT_STATUS_NO_MEMORY);
} else {
}
return (NT_STATUS_NO_MEMORY);
return (NT_STATUS_SUCCESS);
}
/*
* lsa_lookup_name_domain
*
* Lookup a name on the specified server (domain controller) and obtain
* the appropriate SID. The information is returned in the user_info
* structure. The caller is responsible for allocating and releasing
* this structure. On success sid_name_use will be set to indicate the
* type of SID. If the name is the domain name, this function will be
* identical to lsa_domain_info. Otherwise the rid and name fields will
* also be valid. On failure sid_name_use will be set to SidTypeUnknown.
*/
static uint32_t
{
char *user = smbrdr_ipc_get_user();
return (NT_STATUS_INVALID_PARAMETER);
if (status == NT_STATUS_REVISION_MISMATCH) {
/*
* Not a Windows 2000 domain controller:
* use the NT compatible call.
*/
}
(void) lsar_close(&domain_handle);
return (status);
}
/*
* lsa_test_lookup
*
* Test routine for lsa_lookup_name_domain and lsa_lookup_sid2.
*/
void
lsa_test_lookup(char *name)
{
if ((di = smb_getdomaininfo(0)) == 0)
return;
if (status == 0) {
}
}
}
/*
* lsa_lookup_privs
*
* Request the privileges associated with the specified account. In
* order to get the privileges, we first have to lookup the name on
* the specified domain controller and obtain the appropriate SID.
* The SID can then be used to open the account and obtain the
* account privileges. The results from both the name lookup and the
* privileges are returned in the user_info structure. The caller is
* responsible for allocating and releasing this structure.
*
* On success 0 is returned. Otherwise a -ve error code.
*/
/*ARGSUSED*/
int
{
int rc;
char *user = smbrdr_ipc_get_user();
return (-1);
(void) lsar_close(&domain_handle);
return (rc);
}
/*
* lsa_list_privs
*
* List the privileges supported by the specified server.
* This function is only intended for diagnostics.
*
* Returns NT status codes.
*/
{
static char name[128];
int rc;
int i;
char *user = smbrdr_ipc_get_user();
if (rc != 0)
return (NT_STATUS_INVALID_PARAMETER);
for (i = 0; i < 30; ++i) {
if (rc != 0)
continue;
name, 128);
}
(void) lsar_close(&domain_handle);
return (NT_STATUS_SUCCESS);
}
/*
* lsa_test
*
* LSA test routine: open and close the LSA interface.
* TBD: the parameters should be server and domain.
*
* On success 0 is returned. Otherwise a -ve error code.
*/
/*ARGSUSED*/
int
{
int rc;
char *user = smbrdr_ipc_get_user();
if (rc != 0)
return (-1);
if (lsar_close(&domain_handle) != 0)
return (-1);
return (0);
}
/*
* lsa_list_accounts
*
* This function can be used to list the accounts in the specified
* domain. For now the SIDs are just listed in the system log.
*
* On success 0 is returned. Otherwise a -ve error code.
*/
static int
{
struct mslsa_EnumAccountBuf accounts;
char *name;
DWORD enum_context = 0;
int rc;
int i;
do {
&accounts);
if (rc != 0)
return (rc);
for (i = 0; i < accounts.entries_read; ++i) {
&sid_name_use);
if (name == 0) {
user_info) == 0) {
} else {
name = "unknown";
}
}
&account_handle) == 0) {
(void) lsar_enum_privs_account(&account_handle,
(void) lsar_close(&account_handle);
}
}
return (0);
}
/*
* lsa_lookup_name_lusr
*
* Obtains the SID for the given local user name if it
* can be found. Upon successful return the allocated memory
* for the returned SID must be freed by the caller.
*
* Note that in domain mode this function might actually return
* a domain SID if local users are mapped to domain users.
*/
static uint32_t
{
return (NT_STATUS_NO_SUCH_USER);
return (NT_STATUS_NONE_MAPPED);
return (NT_STATUS_SUCCESS);
}
/*
* lsa_lookup_name_lgrp
*
* Obtains the SID for the given local group name if it
* can be found. Upon successful return the allocated memory
* for the returned SID must be freed by the caller.
*
* Note that in domain mode this function might actually return
* a domain SID if local groups are mapped to domain groups.
*/
static uint32_t
{
return (NT_STATUS_NO_SUCH_ALIAS);
return (NT_STATUS_NONE_MAPPED);
return (NT_STATUS_SUCCESS);
}
static int
{
int lookup_mode;
if (smb_wka_lookup((char *)name))
return (MLSVC_LOOKUP_BUILTIN);
if (smb_config_get_secmode() == SMB_SECMODE_WORKGRP)
return (MLSVC_LOOKUP_LOCAL);
return (MLSVC_LOOKUP_DOMLOC);
else
return (lookup_mode);
}
static uint32_t
{
char hostname[MAXHOSTNAMELEN];
int id_type;
return (NT_STATUS_NONE_MAPPED);
switch (id_type) {
case SMB_IDMAP_USER:
return (NT_STATUS_NO_SUCH_USER);
break;
case SMB_IDMAP_GROUP:
return (NT_STATUS_NO_SUCH_ALIAS);
break;
default:
return (NT_STATUS_NONE_MAPPED);
}
return (NT_STATUS_NO_MEMORY);
return (NT_STATUS_INTERNAL_ERROR);
*hostname = '\0';
return (NT_STATUS_NO_MEMORY);
return (NT_STATUS_SUCCESS);
}
static uint32_t
{
char *name;
return (NT_STATUS_NONE_MAPPED);
return (NT_STATUS_NO_MEMORY);
if (sid_name_use != SidTypeDomain)
else
return (NT_STATUS_NO_MEMORY);
return (NT_STATUS_SUCCESS);
}
static uint32_t
{
char *user = smbrdr_ipc_get_user();
return (NT_STATUS_INVALID_PARAMETER);
if (status == NT_STATUS_REVISION_MISMATCH) {
/*
* Not a Windows 2000 domain controller:
* use the NT compatible call.
*/
}
(void) lsar_close(&domain_handle);
return (status);
}