xref: /titanic_51/usr/src/lib/smbsrv/libmlsvc/common/lsalib.c (revision b3700b074e637f8c6991b70754c88a2cfffb246b)
1da6c28aaSamw /*
2da6c28aaSamw  * CDDL HEADER START
3da6c28aaSamw  *
4da6c28aaSamw  * The contents of this file are subject to the terms of the
5da6c28aaSamw  * Common Development and Distribution License (the "License").
6da6c28aaSamw  * You may not use this file except in compliance with the License.
7da6c28aaSamw  *
8da6c28aaSamw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9da6c28aaSamw  * or http://www.opensolaris.org/os/licensing.
10da6c28aaSamw  * See the License for the specific language governing permissions
11da6c28aaSamw  * and limitations under the License.
12da6c28aaSamw  *
13da6c28aaSamw  * When distributing Covered Code, include this CDDL HEADER in each
14da6c28aaSamw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15da6c28aaSamw  * If applicable, add the following below this CDDL HEADER, with the
16da6c28aaSamw  * fields enclosed by brackets "[]" replaced with your own identifying
17da6c28aaSamw  * information: Portions Copyright [yyyy] [name of copyright owner]
18da6c28aaSamw  *
19da6c28aaSamw  * CDDL HEADER END
20da6c28aaSamw  */
21148c5f43SAlan Wright 
22da6c28aaSamw /*
23148c5f43SAlan Wright  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24*b3700b07SGordon Ross  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
25da6c28aaSamw  */
26da6c28aaSamw 
27da6c28aaSamw /*
28da6c28aaSamw  * This module provides the high level interface to the LSA RPC functions.
29da6c28aaSamw  */
30da6c28aaSamw 
31da6c28aaSamw #include <strings.h>
32da6c28aaSamw #include <unistd.h>
33da6c28aaSamw 
34da6c28aaSamw #include <smbsrv/libsmb.h>
35da6c28aaSamw #include <smbsrv/libmlsvc.h>
36da6c28aaSamw #include <smbsrv/smbinfo.h>
37da6c28aaSamw #include <smbsrv/smb_token.h>
38da6c28aaSamw 
3989dc44ceSjose borrego #include <lsalib.h>
40dc20a302Sas200622 
417f667e74Sjose borrego static uint32_t lsa_lookup_name_builtin(char *, char *, smb_account_t *);
427f667e74Sjose borrego static uint32_t lsa_lookup_name_domain(char *, smb_account_t *);
43dc20a302Sas200622 
447f667e74Sjose borrego static uint32_t lsa_lookup_sid_builtin(smb_sid_t *, smb_account_t *);
457f667e74Sjose borrego static uint32_t lsa_lookup_sid_domain(smb_sid_t *, smb_account_t *);
46dc20a302Sas200622 
47*b3700b07SGordon Ross static uint32_t lsa_list_accounts(mlsvc_handle_t *);
48*b3700b07SGordon Ross static uint32_t lsa_map_status(uint32_t);
49da6c28aaSamw 
50da6c28aaSamw /*
51dc20a302Sas200622  * Lookup the given account and returns the account information
527f667e74Sjose borrego  * in the passed smb_account_t structure.
5389dc44ceSjose borrego  *
5489dc44ceSjose borrego  * The lookup is performed in the following order:
5589dc44ceSjose borrego  *    well known accounts
5689dc44ceSjose borrego  *    local accounts
5789dc44ceSjose borrego  *    domain accounts
5889dc44ceSjose borrego  *
5989dc44ceSjose borrego  * If it's established the given account is well know or local
6089dc44ceSjose borrego  * but the lookup fails for some reason, the next step(s) won't be
6189dc44ceSjose borrego  * performed.
62dc20a302Sas200622  *
63dc20a302Sas200622  * If the name is a domain account, it may refer to a user, group or
64dc20a302Sas200622  * alias. If it is a local account, its type should be specified
65dc20a302Sas200622  * in the sid_type parameter. In case the account type is unknown
66dc20a302Sas200622  * sid_type should be set to SidTypeUnknown.
67dc20a302Sas200622  *
6889dc44ceSjose borrego  * account argument could be either [domain\]name or [domain/]name.
6989dc44ceSjose borrego  *
7089dc44ceSjose borrego  * Return status:
7189dc44ceSjose borrego  *
7289dc44ceSjose borrego  *   NT_STATUS_SUCCESS		Account is successfully translated
7389dc44ceSjose borrego  *   NT_STATUS_NONE_MAPPED	Couldn't translate the account
74dc20a302Sas200622  */
75dc20a302Sas200622 uint32_t
767f667e74Sjose borrego lsa_lookup_name(char *account, uint16_t type, smb_account_t *info)
77dc20a302Sas200622 {
7889dc44ceSjose borrego 	char nambuf[SMB_USERNAME_MAXLEN];
7989dc44ceSjose borrego 	char dombuf[SMB_PI_MAX_DOMAIN];
8089dc44ceSjose borrego 	char *name, *domain;
8189dc44ceSjose borrego 	uint32_t status;
8289dc44ceSjose borrego 	char *slash;
83dc20a302Sas200622 
8489dc44ceSjose borrego 	(void) strsubst(account, '/', '\\');
8589dc44ceSjose borrego 	(void) strcanon(account, "\\");
8689dc44ceSjose borrego 	/* \john -> john */
8789dc44ceSjose borrego 	account += strspn(account, "\\");
8889dc44ceSjose borrego 
8989dc44ceSjose borrego 	if ((slash = strchr(account, '\\')) != NULL) {
9089dc44ceSjose borrego 		*slash = '\0';
9189dc44ceSjose borrego 		(void) strlcpy(dombuf, account, sizeof (dombuf));
9289dc44ceSjose borrego 		(void) strlcpy(nambuf, slash + 1, sizeof (nambuf));
9389dc44ceSjose borrego 		*slash = '\\';
9489dc44ceSjose borrego 		name = nambuf;
9589dc44ceSjose borrego 		domain = dombuf;
96dc20a302Sas200622 	} else {
97dc20a302Sas200622 		name = account;
98dc20a302Sas200622 		domain = NULL;
99dc20a302Sas200622 	}
100dc20a302Sas200622 
10189dc44ceSjose borrego 	status = lsa_lookup_name_builtin(domain, name, info);
10289dc44ceSjose borrego 	if (status == NT_STATUS_NOT_FOUND) {
1037f667e74Sjose borrego 		status = smb_sam_lookup_name(domain, name, type, info);
10489dc44ceSjose borrego 		if (status == NT_STATUS_SUCCESS)
105dc20a302Sas200622 			return (status);
106dc20a302Sas200622 
10789dc44ceSjose borrego 		if ((domain == NULL) || (status == NT_STATUS_NOT_FOUND))
10889dc44ceSjose borrego 			status = lsa_lookup_name_domain(account, info);
109dc20a302Sas200622 	}
110dc20a302Sas200622 
11189dc44ceSjose borrego 	return ((status == NT_STATUS_SUCCESS) ? status : NT_STATUS_NONE_MAPPED);
112dc20a302Sas200622 }
113dc20a302Sas200622 
114dc20a302Sas200622 uint32_t
1157f667e74Sjose borrego lsa_lookup_sid(smb_sid_t *sid, smb_account_t *info)
116dc20a302Sas200622 {
1177f667e74Sjose borrego 	uint32_t status;
1187f667e74Sjose borrego 
1196537f381Sas200622 	if (!smb_sid_isvalid(sid))
120dc20a302Sas200622 		return (NT_STATUS_INVALID_SID);
121dc20a302Sas200622 
1227f667e74Sjose borrego 	status = lsa_lookup_sid_builtin(sid, info);
1237f667e74Sjose borrego 	if (status == NT_STATUS_NOT_FOUND) {
1247f667e74Sjose borrego 		status = smb_sam_lookup_sid(sid, info);
1257f667e74Sjose borrego 		if (status == NT_STATUS_NOT_FOUND)
1267f667e74Sjose borrego 			status = lsa_lookup_sid_domain(sid, info);
1277f667e74Sjose borrego 	}
128dc20a302Sas200622 
1297f667e74Sjose borrego 	return ((status == NT_STATUS_SUCCESS) ? status : NT_STATUS_NONE_MAPPED);
130dc20a302Sas200622 }
131dc20a302Sas200622 
132dc20a302Sas200622 /*
133da6c28aaSamw  * Obtains the primary domain SID and name from the specified server
13429bd2886SAlan Wright  * (domain controller).
135da6c28aaSamw  *
1368d7e4166Sjose borrego  * The requested information will be returned via 'info' argument.
1378d7e4166Sjose borrego  *
138*b3700b07SGordon Ross  * Returns NT status codes. (Raw, not LSA-ized)
139da6c28aaSamw  */
140da6c28aaSamw DWORD
14129bd2886SAlan Wright lsa_query_primary_domain_info(char *server, char *domain,
142a0aa776eSAlan Wright     smb_domain_t *info)
143da6c28aaSamw {
144da6c28aaSamw 	mlsvc_handle_t domain_handle;
145a0aa776eSAlan Wright 	char user[SMB_USERNAME_MAXLEN];
146*b3700b07SGordon Ross 	DWORD status;
147a0aa776eSAlan Wright 
148a0aa776eSAlan Wright 	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
149da6c28aaSamw 
150*b3700b07SGordon Ross 	status = lsar_open(server, domain, user, &domain_handle);
151*b3700b07SGordon Ross 	if (status != 0)
152*b3700b07SGordon Ross 		return (status);
153da6c28aaSamw 
154da6c28aaSamw 	status = lsar_query_info_policy(&domain_handle,
1558d7e4166Sjose borrego 	    MSLSA_POLICY_PRIMARY_DOMAIN_INFO, info);
156da6c28aaSamw 
157da6c28aaSamw 	(void) lsar_close(&domain_handle);
158da6c28aaSamw 	return (status);
159da6c28aaSamw }
160da6c28aaSamw 
161da6c28aaSamw /*
162da6c28aaSamw  * Obtains the account domain SID and name from the current server
16329bd2886SAlan Wright  * (domain controller).
164da6c28aaSamw  *
1658d7e4166Sjose borrego  * The requested information will be returned via 'info' argument.
1668d7e4166Sjose borrego  *
167*b3700b07SGordon Ross  * Returns NT status codes. (Raw, not LSA-ized)
168da6c28aaSamw  */
169da6c28aaSamw DWORD
17029bd2886SAlan Wright lsa_query_account_domain_info(char *server, char *domain,
171a0aa776eSAlan Wright     smb_domain_t *info)
172da6c28aaSamw {
173da6c28aaSamw 	mlsvc_handle_t domain_handle;
174a0aa776eSAlan Wright 	char user[SMB_USERNAME_MAXLEN];
175*b3700b07SGordon Ross 	DWORD status;
176a0aa776eSAlan Wright 
177a0aa776eSAlan Wright 	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
178da6c28aaSamw 
179*b3700b07SGordon Ross 	status = lsar_open(server, domain, user, &domain_handle);
180*b3700b07SGordon Ross 	if (status != 0)
181*b3700b07SGordon Ross 		return (status);
182da6c28aaSamw 
183da6c28aaSamw 	status = lsar_query_info_policy(&domain_handle,
1848d7e4166Sjose borrego 	    MSLSA_POLICY_ACCOUNT_DOMAIN_INFO, info);
1858d7e4166Sjose borrego 
1868d7e4166Sjose borrego 	(void) lsar_close(&domain_handle);
1878d7e4166Sjose borrego 	return (status);
1888d7e4166Sjose borrego }
1898d7e4166Sjose borrego 
1908d7e4166Sjose borrego /*
1918d7e4166Sjose borrego  * lsa_query_dns_domain_info
1928d7e4166Sjose borrego  *
1938d7e4166Sjose borrego  * Obtains the DNS domain info from the specified server
1948d7e4166Sjose borrego  * (domain controller).
1958d7e4166Sjose borrego  *
1968d7e4166Sjose borrego  * The requested information will be returned via 'info' argument.
1978d7e4166Sjose borrego  *
198*b3700b07SGordon Ross  * Returns NT status codes. (Raw, not LSA-ized)
1998d7e4166Sjose borrego  */
2008d7e4166Sjose borrego DWORD
201a0aa776eSAlan Wright lsa_query_dns_domain_info(char *server, char *domain, smb_domain_t *info)
2028d7e4166Sjose borrego {
2038d7e4166Sjose borrego 	mlsvc_handle_t domain_handle;
204a0aa776eSAlan Wright 	char user[SMB_USERNAME_MAXLEN];
205*b3700b07SGordon Ross 	DWORD status;
206a0aa776eSAlan Wright 
207a0aa776eSAlan Wright 	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
2088d7e4166Sjose borrego 
209*b3700b07SGordon Ross 	status = lsar_open(server, domain, user, &domain_handle);
210*b3700b07SGordon Ross 	if (status != 0)
211*b3700b07SGordon Ross 		return (status);
2128d7e4166Sjose borrego 
2138d7e4166Sjose borrego 	status = lsar_query_info_policy(&domain_handle,
2148d7e4166Sjose borrego 	    MSLSA_POLICY_DNS_DOMAIN_INFO, info);
215da6c28aaSamw 
216da6c28aaSamw 	(void) lsar_close(&domain_handle);
217da6c28aaSamw 	return (status);
218da6c28aaSamw }
219da6c28aaSamw 
220da6c28aaSamw /*
22129bd2886SAlan Wright  * Enumerate the trusted domains of  primary domain.
22229bd2886SAlan Wright  * This is the basic enumaration call which only returns the
22329bd2886SAlan Wright  * NetBIOS name of the domain and its SID.
224da6c28aaSamw  *
2258d7e4166Sjose borrego  * The requested information will be returned via 'info' argument.
2268d7e4166Sjose borrego  *
227*b3700b07SGordon Ross  * Returns NT status codes.  (Raw, not LSA-ized)
228da6c28aaSamw  */
229da6c28aaSamw DWORD
23029bd2886SAlan Wright lsa_enum_trusted_domains(char *server, char *domain,
23129bd2886SAlan Wright     smb_trusted_domains_t *info)
232da6c28aaSamw {
233da6c28aaSamw 	mlsvc_handle_t domain_handle;
234*b3700b07SGordon Ross 	char user[SMB_USERNAME_MAXLEN];
235da6c28aaSamw 	DWORD enum_context;
236da6c28aaSamw 	DWORD status;
237a0aa776eSAlan Wright 
238a0aa776eSAlan Wright 	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
239da6c28aaSamw 
240*b3700b07SGordon Ross 	status = lsar_open(server, domain, user, &domain_handle);
241*b3700b07SGordon Ross 	if (status != 0)
242*b3700b07SGordon Ross 		return (status);
243da6c28aaSamw 
244da6c28aaSamw 	enum_context = 0;
245da6c28aaSamw 
2468d7e4166Sjose borrego 	status = lsar_enum_trusted_domains(&domain_handle, &enum_context, info);
247148c5f43SAlan Wright 	if (status == NT_STATUS_NO_MORE_ENTRIES) {
248da6c28aaSamw 		/*
249148c5f43SAlan Wright 		 * STATUS_NO_MORE_ENTRIES indicates that we
250da6c28aaSamw 		 * have all of the available information.
251da6c28aaSamw 		 */
252da6c28aaSamw 		status = NT_STATUS_SUCCESS;
253da6c28aaSamw 	}
254da6c28aaSamw 
255da6c28aaSamw 	(void) lsar_close(&domain_handle);
256da6c28aaSamw 	return (status);
257da6c28aaSamw }
258da6c28aaSamw 
259da6c28aaSamw /*
26029bd2886SAlan Wright  * Enumerate the trusted domains of the primary domain.
26129bd2886SAlan Wright  * This is the extended enumaration call which besides
26229bd2886SAlan Wright  * NetBIOS name of the domain and its SID, it will return
26329bd2886SAlan Wright  * the FQDN plus some trust information which is not used.
26429bd2886SAlan Wright  *
26529bd2886SAlan Wright  * The requested information will be returned via 'info' argument.
26629bd2886SAlan Wright  *
267*b3700b07SGordon Ross  * Returns NT status codes. (Raw, not LSA-ized)
2688d7e4166Sjose borrego  */
26929bd2886SAlan Wright DWORD
27029bd2886SAlan Wright lsa_enum_trusted_domains_ex(char *server, char *domain,
27129bd2886SAlan Wright     smb_trusted_domains_t *info)
2728d7e4166Sjose borrego {
27329bd2886SAlan Wright 	mlsvc_handle_t domain_handle;
274*b3700b07SGordon Ross 	char user[SMB_USERNAME_MAXLEN];
27529bd2886SAlan Wright 	DWORD enum_context;
27629bd2886SAlan Wright 	DWORD status;
277a0aa776eSAlan Wright 
278a0aa776eSAlan Wright 	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
2798d7e4166Sjose borrego 
280*b3700b07SGordon Ross 	status = lsar_open(server, domain, user, &domain_handle);
281*b3700b07SGordon Ross 	if (status != 0)
282*b3700b07SGordon Ross 		return (status);
2838d7e4166Sjose borrego 
28429bd2886SAlan Wright 	enum_context = 0;
2858d7e4166Sjose borrego 
28629bd2886SAlan Wright 	status = lsar_enum_trusted_domains_ex(&domain_handle, &enum_context,
28729bd2886SAlan Wright 	    info);
288148c5f43SAlan Wright 	if (status == NT_STATUS_NO_MORE_ENTRIES) {
28929bd2886SAlan Wright 		/*
290148c5f43SAlan Wright 		 * STATUS_NO_MORE_ENTRIES indicates that we
29129bd2886SAlan Wright 		 * have all of the available information.
29229bd2886SAlan Wright 		 */
29329bd2886SAlan Wright 		status = NT_STATUS_SUCCESS;
2948d7e4166Sjose borrego 	}
29529bd2886SAlan Wright 
29629bd2886SAlan Wright 	(void) lsar_close(&domain_handle);
29729bd2886SAlan Wright 	return (status);
2988d7e4166Sjose borrego }
2998d7e4166Sjose borrego 
3008d7e4166Sjose borrego /*
30189dc44ceSjose borrego  * Lookup well known accounts table
302dc20a302Sas200622  *
30389dc44ceSjose borrego  * Return status:
30489dc44ceSjose borrego  *
30589dc44ceSjose borrego  *   NT_STATUS_SUCCESS		Account is translated successfully
30689dc44ceSjose borrego  *   NT_STATUS_NOT_FOUND	This is not a well known account
30789dc44ceSjose borrego  *   NT_STATUS_NONE_MAPPED	Account is found but domains don't match
30889dc44ceSjose borrego  *   NT_STATUS_NO_MEMORY	Memory shortage
30989dc44ceSjose borrego  *   NT_STATUS_INTERNAL_ERROR	Internal error/unexpected failure
310dc20a302Sas200622  */
311dc20a302Sas200622 static uint32_t
3127f667e74Sjose borrego lsa_lookup_name_builtin(char *domain, char *name, smb_account_t *info)
313dc20a302Sas200622 {
31489dc44ceSjose borrego 	smb_wka_t *wka;
31589dc44ceSjose borrego 	char *wkadom;
316dc20a302Sas200622 
3177f667e74Sjose borrego 	bzero(info, sizeof (smb_account_t));
3187f667e74Sjose borrego 
3197f667e74Sjose borrego 	if ((wka = smb_wka_lookup_name(name)) == NULL)
32089dc44ceSjose borrego 		return (NT_STATUS_NOT_FOUND);
321dc20a302Sas200622 
32289dc44ceSjose borrego 	if ((wkadom = smb_wka_get_domain(wka->wka_domidx)) == NULL)
323dc20a302Sas200622 		return (NT_STATUS_INTERNAL_ERROR);
324dc20a302Sas200622 
325bbf6f00cSJordan Brown 	if ((domain != NULL) && (smb_strcasecmp(domain, wkadom, 0) != 0))
32689dc44ceSjose borrego 		return (NT_STATUS_NONE_MAPPED);
32789dc44ceSjose borrego 
3287f667e74Sjose borrego 	info->a_name = strdup(name);
3297f667e74Sjose borrego 	info->a_sid = smb_sid_dup(wka->wka_binsid);
3307f667e74Sjose borrego 	info->a_domain = strdup(wkadom);
3317f667e74Sjose borrego 	info->a_domsid = smb_sid_split(wka->wka_binsid, &info->a_rid);
3327f667e74Sjose borrego 	info->a_type = wka->wka_type;
33389dc44ceSjose borrego 
3347f667e74Sjose borrego 	if (!smb_account_validate(info)) {
3357f667e74Sjose borrego 		smb_account_free(info);
33689dc44ceSjose borrego 		return (NT_STATUS_NO_MEMORY);
337dc20a302Sas200622 	}
338dc20a302Sas200622 
339dc20a302Sas200622 	return (NT_STATUS_SUCCESS);
340dc20a302Sas200622 }
341dc20a302Sas200622 
342dc20a302Sas200622 /*
343*b3700b07SGordon Ross  * Lookup a domain account by its name.
344dc20a302Sas200622  *
34589dc44ceSjose borrego  * The information is returned in the user_info structure.
34689dc44ceSjose borrego  * The caller is responsible for allocating and releasing
34789dc44ceSjose borrego  * this structure.
348*b3700b07SGordon Ross  *
349*b3700b07SGordon Ross  * Returns NT status codes. (LSA-ized)
350dc20a302Sas200622  */
351dc20a302Sas200622 static uint32_t
3527f667e74Sjose borrego lsa_lookup_name_domain(char *account_name, smb_account_t *info)
353dc20a302Sas200622 {
354dc20a302Sas200622 	mlsvc_handle_t domain_handle;
355a0aa776eSAlan Wright 	smb_domainex_t dinfo;
356a0aa776eSAlan Wright 	char user[SMB_USERNAME_MAXLEN];
357*b3700b07SGordon Ross 	uint32_t status;
358a0aa776eSAlan Wright 
359a0aa776eSAlan Wright 	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
360dc20a302Sas200622 
36189dc44ceSjose borrego 	if (!smb_domain_getinfo(&dinfo))
36289dc44ceSjose borrego 		return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
36389dc44ceSjose borrego 
364*b3700b07SGordon Ross 	status = lsar_open(dinfo.d_dci.dc_name, dinfo.d_primary.di_nbname,
365*b3700b07SGordon Ross 	    user, &domain_handle);
366*b3700b07SGordon Ross 	if (status != 0)
367*b3700b07SGordon Ross 		return (lsa_map_status(status));
368dc20a302Sas200622 
3697f667e74Sjose borrego 	status = lsar_lookup_names(&domain_handle, account_name, info);
370dc20a302Sas200622 
371dc20a302Sas200622 	(void) lsar_close(&domain_handle);
372dc20a302Sas200622 	return (status);
373dc20a302Sas200622 }
374dc20a302Sas200622 
375dc20a302Sas200622 /*
376da6c28aaSamw  * lsa_lookup_privs
377da6c28aaSamw  *
378da6c28aaSamw  * Request the privileges associated with the specified account. In
379da6c28aaSamw  * order to get the privileges, we first have to lookup the name on
380da6c28aaSamw  * the specified domain controller and obtain the appropriate SID.
381da6c28aaSamw  * The SID can then be used to open the account and obtain the
382da6c28aaSamw  * account privileges. The results from both the name lookup and the
383da6c28aaSamw  * privileges are returned in the user_info structure. The caller is
384da6c28aaSamw  * responsible for allocating and releasing this structure.
385da6c28aaSamw  *
386*b3700b07SGordon Ross  * Returns NT status codes. (LSA-ized)
387da6c28aaSamw  */
388da6c28aaSamw /*ARGSUSED*/
389*b3700b07SGordon Ross DWORD
3907f667e74Sjose borrego lsa_lookup_privs(char *account_name, char *target_name, smb_account_t *ainfo)
391da6c28aaSamw {
392da6c28aaSamw 	mlsvc_handle_t domain_handle;
393a0aa776eSAlan Wright 	smb_domainex_t dinfo;
394a0aa776eSAlan Wright 	char user[SMB_USERNAME_MAXLEN];
395*b3700b07SGordon Ross 	DWORD status;
396a0aa776eSAlan Wright 
397a0aa776eSAlan Wright 	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
398da6c28aaSamw 
3998d7e4166Sjose borrego 	if (!smb_domain_getinfo(&dinfo))
400*b3700b07SGordon Ross 		return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
4018d7e4166Sjose borrego 
402*b3700b07SGordon Ross 	status = lsar_open(dinfo.d_dci.dc_name, dinfo.d_primary.di_nbname,
403*b3700b07SGordon Ross 	    user, &domain_handle);
404*b3700b07SGordon Ross 	if (status != 0)
405*b3700b07SGordon Ross 		return (lsa_map_status(status));
406da6c28aaSamw 
407*b3700b07SGordon Ross 	status = lsa_list_accounts(&domain_handle);
408da6c28aaSamw 	(void) lsar_close(&domain_handle);
409*b3700b07SGordon Ross 	return (status);
410da6c28aaSamw }
411da6c28aaSamw 
412da6c28aaSamw /*
413da6c28aaSamw  * lsa_list_privs
414da6c28aaSamw  *
415da6c28aaSamw  * List the privileges supported by the specified server.
416da6c28aaSamw  * This function is only intended for diagnostics.
417da6c28aaSamw  *
418*b3700b07SGordon Ross  * Returns NT status codes. (LSA-ized)
419da6c28aaSamw  */
420da6c28aaSamw DWORD
421da6c28aaSamw lsa_list_privs(char *server, char *domain)
422da6c28aaSamw {
423da6c28aaSamw 	static char name[128];
424da6c28aaSamw 	static struct ms_luid luid;
425da6c28aaSamw 	mlsvc_handle_t domain_handle;
426*b3700b07SGordon Ross 	char user[SMB_USERNAME_MAXLEN];
427*b3700b07SGordon Ross 	DWORD status;
428da6c28aaSamw 	int rc;
429da6c28aaSamw 	int i;
430a0aa776eSAlan Wright 
431a0aa776eSAlan Wright 	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
432da6c28aaSamw 
433*b3700b07SGordon Ross 	status = lsar_open(server, domain, user, &domain_handle);
434*b3700b07SGordon Ross 	if (status != 0)
435*b3700b07SGordon Ross 		return (lsa_map_status(status));
436da6c28aaSamw 
437da6c28aaSamw 	for (i = 0; i < 30; ++i) {
438da6c28aaSamw 		luid.low_part = i;
439da6c28aaSamw 		rc = lsar_lookup_priv_name(&domain_handle, &luid, name, 128);
440da6c28aaSamw 		if (rc != 0)
441da6c28aaSamw 			continue;
442da6c28aaSamw 
443da6c28aaSamw 		(void) lsar_lookup_priv_value(&domain_handle, name, &luid);
444da6c28aaSamw 		(void) lsar_lookup_priv_display_name(&domain_handle, name,
445da6c28aaSamw 		    name, 128);
446da6c28aaSamw 	}
447da6c28aaSamw 
448da6c28aaSamw 	(void) lsar_close(&domain_handle);
449da6c28aaSamw 	return (NT_STATUS_SUCCESS);
450da6c28aaSamw }
451da6c28aaSamw 
452da6c28aaSamw /*
453da6c28aaSamw  * lsa_list_accounts
454da6c28aaSamw  *
455da6c28aaSamw  * This function can be used to list the accounts in the specified
456da6c28aaSamw  * domain. For now the SIDs are just listed in the system log.
457da6c28aaSamw  *
458*b3700b07SGordon Ross  * Returns NT status
459da6c28aaSamw  */
460*b3700b07SGordon Ross static DWORD
461da6c28aaSamw lsa_list_accounts(mlsvc_handle_t *domain_handle)
462da6c28aaSamw {
463da6c28aaSamw 	mlsvc_handle_t account_handle;
464da6c28aaSamw 	struct mslsa_EnumAccountBuf accounts;
465da6c28aaSamw 	struct mslsa_sid *sid;
4667f667e74Sjose borrego 	smb_account_t ainfo;
467da6c28aaSamw 	DWORD enum_context = 0;
468*b3700b07SGordon Ross 	DWORD status;
469da6c28aaSamw 	int i;
470da6c28aaSamw 
471da6c28aaSamw 	bzero(&accounts, sizeof (struct mslsa_EnumAccountBuf));
472da6c28aaSamw 
473da6c28aaSamw 	do {
474*b3700b07SGordon Ross 		status = lsar_enum_accounts(domain_handle, &enum_context,
475da6c28aaSamw 		    &accounts);
476*b3700b07SGordon Ross 		if (status != 0)
477*b3700b07SGordon Ross 			return (status);
478da6c28aaSamw 
479da6c28aaSamw 		for (i = 0; i < accounts.entries_read; ++i) {
480da6c28aaSamw 			sid = accounts.info[i].sid;
481da6c28aaSamw 
482da6c28aaSamw 			if (lsar_open_account(domain_handle, sid,
483da6c28aaSamw 			    &account_handle) == 0) {
484da6c28aaSamw 				(void) lsar_enum_privs_account(&account_handle,
4857f667e74Sjose borrego 				    &ainfo);
486da6c28aaSamw 				(void) lsar_close(&account_handle);
487da6c28aaSamw 			}
488da6c28aaSamw 
489da6c28aaSamw 			free(accounts.info[i].sid);
490da6c28aaSamw 		}
491da6c28aaSamw 
492da6c28aaSamw 		if (accounts.info)
493da6c28aaSamw 			free(accounts.info);
494*b3700b07SGordon Ross 	} while (status == 0 && accounts.entries_read != 0);
495da6c28aaSamw 
496da6c28aaSamw 	return (0);
497da6c28aaSamw }
498dc20a302Sas200622 
499dc20a302Sas200622 /*
5007f667e74Sjose borrego  * Lookup well known accounts table for the given SID
501dc20a302Sas200622  *
5027f667e74Sjose borrego  * Return status:
5037f667e74Sjose borrego  *
5047f667e74Sjose borrego  *   NT_STATUS_SUCCESS		Account is translated successfully
5057f667e74Sjose borrego  *   NT_STATUS_NOT_FOUND	This is not a well known account
5067f667e74Sjose borrego  *   NT_STATUS_NO_MEMORY	Memory shortage
5077f667e74Sjose borrego  *   NT_STATUS_INTERNAL_ERROR	Internal error/unexpected failure
508dc20a302Sas200622  */
509dc20a302Sas200622 static uint32_t
5107f667e74Sjose borrego lsa_lookup_sid_builtin(smb_sid_t *sid, smb_account_t *ainfo)
511dc20a302Sas200622 {
5127f667e74Sjose borrego 	smb_wka_t *wka;
5137f667e74Sjose borrego 	char *wkadom;
514dc20a302Sas200622 
5157f667e74Sjose borrego 	bzero(ainfo, sizeof (smb_account_t));
516dc20a302Sas200622 
5177f667e74Sjose borrego 	if ((wka = smb_wka_lookup_sid(sid)) == NULL)
5187f667e74Sjose borrego 		return (NT_STATUS_NOT_FOUND);
519dc20a302Sas200622 
5207f667e74Sjose borrego 	if ((wkadom = smb_wka_get_domain(wka->wka_domidx)) == NULL)
521dc20a302Sas200622 		return (NT_STATUS_INTERNAL_ERROR);
5227f667e74Sjose borrego 
5237f667e74Sjose borrego 	ainfo->a_name = strdup(wka->wka_name);
5247f667e74Sjose borrego 	ainfo->a_sid = smb_sid_dup(wka->wka_binsid);
5257f667e74Sjose borrego 	ainfo->a_domain = strdup(wkadom);
5267f667e74Sjose borrego 	ainfo->a_domsid = smb_sid_split(ainfo->a_sid, &ainfo->a_rid);
5277f667e74Sjose borrego 	ainfo->a_type = wka->wka_type;
5287f667e74Sjose borrego 
5297f667e74Sjose borrego 	if (!smb_account_validate(ainfo)) {
5307f667e74Sjose borrego 		smb_account_free(ainfo);
531dc20a302Sas200622 		return (NT_STATUS_NO_MEMORY);
5327f667e74Sjose borrego 	}
533dc20a302Sas200622 
534dc20a302Sas200622 	return (NT_STATUS_SUCCESS);
535dc20a302Sas200622 }
536dc20a302Sas200622 
537*b3700b07SGordon Ross /*
538*b3700b07SGordon Ross  * Lookup a domain account by its SID.
539*b3700b07SGordon Ross  *
540*b3700b07SGordon Ross  * The information is returned in the user_info structure.
541*b3700b07SGordon Ross  * The caller is responsible for allocating and releasing
542*b3700b07SGordon Ross  * this structure.
543*b3700b07SGordon Ross  *
544*b3700b07SGordon Ross  * Returns NT status codes. (LSA-ized)
545*b3700b07SGordon Ross  */
546dc20a302Sas200622 static uint32_t
5477f667e74Sjose borrego lsa_lookup_sid_domain(smb_sid_t *sid, smb_account_t *ainfo)
548dc20a302Sas200622 {
549dc20a302Sas200622 	mlsvc_handle_t domain_handle;
550a0aa776eSAlan Wright 	smb_domainex_t dinfo;
551a0aa776eSAlan Wright 	char user[SMB_USERNAME_MAXLEN];
552*b3700b07SGordon Ross 	uint32_t status;
553a0aa776eSAlan Wright 
554a0aa776eSAlan Wright 	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
555dc20a302Sas200622 
5568d7e4166Sjose borrego 	if (!smb_domain_getinfo(&dinfo))
5578d7e4166Sjose borrego 		return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
5588d7e4166Sjose borrego 
559*b3700b07SGordon Ross 	status = lsar_open(dinfo.d_dci.dc_name, dinfo.d_primary.di_nbname,
560*b3700b07SGordon Ross 	    user, &domain_handle);
561*b3700b07SGordon Ross 	if (status != 0)
562*b3700b07SGordon Ross 		return (lsa_map_status(status));
563dc20a302Sas200622 
564fe1c642dSBill Krier 	status = lsar_lookup_sids(&domain_handle, sid, ainfo);
565dc20a302Sas200622 
566dc20a302Sas200622 	(void) lsar_close(&domain_handle);
567dc20a302Sas200622 	return (status);
568dc20a302Sas200622 }
569*b3700b07SGordon Ross 
570*b3700b07SGordon Ross /*
571*b3700b07SGordon Ross  * Most functions that call the local security authority expect
572*b3700b07SGordon Ross  * only a limited set of status returns.  This function maps the
573*b3700b07SGordon Ross  * status we get from talking to our domain controller into one
574*b3700b07SGordon Ross  * that LSA functions can return.  Most common errors become:
575*b3700b07SGordon Ross  * NT_STATUS_CANT_ACCESS_DOMAIN_INFO (when no DC etc.)
576*b3700b07SGordon Ross  */
577*b3700b07SGordon Ross static uint32_t
578*b3700b07SGordon Ross lsa_map_status(uint32_t status)
579*b3700b07SGordon Ross {
580*b3700b07SGordon Ross 	switch (status) {
581*b3700b07SGordon Ross 	case NT_STATUS_SUCCESS:
582*b3700b07SGordon Ross 		break;
583*b3700b07SGordon Ross 	case NT_STATUS_INVALID_PARAMETER:	/* rpc bind */
584*b3700b07SGordon Ross 		break;
585*b3700b07SGordon Ross 	case NT_STATUS_NO_MEMORY:
586*b3700b07SGordon Ross 		break;
587*b3700b07SGordon Ross 	case NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND:
588*b3700b07SGordon Ross 	case NT_STATUS_BAD_NETWORK_PATH:	/* get server addr */
589*b3700b07SGordon Ross 	case NT_STATUS_NETWORK_ACCESS_DENIED:	/* authentication */
590*b3700b07SGordon Ross 	case NT_STATUS_BAD_NETWORK_NAME:	/* tree connect */
591*b3700b07SGordon Ross 	case NT_STATUS_ACCESS_DENIED:		/* open pipe */
592*b3700b07SGordon Ross 		status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
593*b3700b07SGordon Ross 		break;
594*b3700b07SGordon Ross 	default:
595*b3700b07SGordon Ross 		status = NT_STATUS_UNSUCCESSFUL;
596*b3700b07SGordon Ross 		break;
597*b3700b07SGordon Ross 	}
598*b3700b07SGordon Ross 	return (status);
599*b3700b07SGordon Ross }
600