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  */
21da6c28aaSamw /*
2289dc44ceSjose borrego  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23da6c28aaSamw  * Use is subject to license terms.
24da6c28aaSamw  */
25da6c28aaSamw 
26da6c28aaSamw /*
27da6c28aaSamw  * This module provides the high level interface to the LSA RPC functions.
28da6c28aaSamw  */
29da6c28aaSamw 
30da6c28aaSamw #include <strings.h>
31da6c28aaSamw #include <unistd.h>
32da6c28aaSamw 
33da6c28aaSamw #include <smbsrv/libsmb.h>
34da6c28aaSamw #include <smbsrv/libmlsvc.h>
35da6c28aaSamw #include <smbsrv/ntstatus.h>
36da6c28aaSamw #include <smbsrv/smbinfo.h>
37da6c28aaSamw #include <smbsrv/smb_token.h>
38da6c28aaSamw 
3989dc44ceSjose borrego #include <lsalib.h>
40dc20a302Sas 
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 *);
43dc20a302Sas 
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 *);
46dc20a302Sas 
47da6c28aaSamw static int lsa_list_accounts(mlsvc_handle_t *);
48da6c28aaSamw 
49dc20a302Sas /*
50dc20a302Sas  * Lookup the given account and returns the account information
517f667e74Sjose borrego  * in the passed smb_account_t structure.
5289dc44ceSjose borrego  *
5389dc44ceSjose borrego  * The lookup is performed in the following order:
5489dc44ceSjose borrego  *    well known accounts
5589dc44ceSjose borrego  *    local accounts
5689dc44ceSjose borrego  *    domain accounts
5789dc44ceSjose borrego  *
5889dc44ceSjose borrego  * If it's established the given account is well know or local
5989dc44ceSjose borrego  * but the lookup fails for some reason, the next step(s) won't be
6089dc44ceSjose borrego  * performed.
61dc20a302Sas  *
62dc20a302Sas  * If the name is a domain account, it may refer to a user, group or
63dc20a302Sas  * alias. If it is a local account, its type should be specified
64dc20a302Sas  * in the sid_type parameter. In case the account type is unknown
65dc20a302Sas  * sid_type should be set to SidTypeUnknown.
66dc20a302Sas  *
6789dc44ceSjose borrego  * account argument could be either [domain\]name or [domain/]name.
6889dc44ceSjose borrego  *
6989dc44ceSjose borrego  * Return status:
7089dc44ceSjose borrego  *
7189dc44ceSjose borrego  *   NT_STATUS_SUCCESS		Account is successfully translated
7289dc44ceSjose borrego  *   NT_STATUS_NONE_MAPPED	Couldn't translate the account
73dc20a302Sas  */
74dc20a302Sas uint32_t
757f667e74Sjose borrego lsa_lookup_name(char *account, uint16_t type, smb_account_t *info)
76dc20a302Sas {
7789dc44ceSjose borrego 	char nambuf[SMB_USERNAME_MAXLEN];
7889dc44ceSjose borrego 	char dombuf[SMB_PI_MAX_DOMAIN];
7989dc44ceSjose borrego 	char *name, *domain;
8089dc44ceSjose borrego 	uint32_t status;
8189dc44ceSjose borrego 	char *slash;
8289dc44ceSjose borrego 
8389dc44ceSjose borrego 	(void) strsubst(account, '/', '\\');
8489dc44ceSjose borrego 	(void) strcanon(account, "\\");
8589dc44ceSjose borrego 	/* \john -> john */
8689dc44ceSjose borrego 	account += strspn(account, "\\");
8789dc44ceSjose borrego 
8889dc44ceSjose borrego 	if ((slash = strchr(account, '\\')) != NULL) {
8989dc44ceSjose borrego 		*slash = '\0';
9089dc44ceSjose borrego 		(void) strlcpy(dombuf, account, sizeof (dombuf));
9189dc44ceSjose borrego 		(void) strlcpy(nambuf, slash + 1, sizeof (nambuf));
9289dc44ceSjose borrego 		*slash = '\\';
9389dc44ceSjose borrego 		name = nambuf;
9489dc44ceSjose borrego 		domain = dombuf;
95dc20a302Sas 	} else {
96dc20a302Sas 		name = account;
97dc20a302Sas 		domain = NULL;
98dc20a302Sas 	}
99dc20a302Sas 
10089dc44ceSjose borrego 	status = lsa_lookup_name_builtin(domain, name, info);
10189dc44ceSjose borrego 	if (status == NT_STATUS_NOT_FOUND) {
1027f667e74Sjose borrego 		status = smb_sam_lookup_name(domain, name, type, info);
10389dc44ceSjose borrego 		if (status == NT_STATUS_SUCCESS)
104dc20a302Sas 			return (status);
105dc20a302Sas 
10689dc44ceSjose borrego 		if ((domain == NULL) || (status == NT_STATUS_NOT_FOUND))
10789dc44ceSjose borrego 			status = lsa_lookup_name_domain(account, info);
108dc20a302Sas 	}
109dc20a302Sas 
11089dc44ceSjose borrego 	return ((status == NT_STATUS_SUCCESS) ? status : NT_STATUS_NONE_MAPPED);
111dc20a302Sas }
112dc20a302Sas 
113dc20a302Sas uint32_t
1147f667e74Sjose borrego lsa_lookup_sid(smb_sid_t *sid, smb_account_t *info)
115dc20a302Sas {
1167f667e74Sjose borrego 	uint32_t status;
1177f667e74Sjose borrego 
1186537f381Sas 	if (!smb_sid_isvalid(sid))
119dc20a302Sas 		return (NT_STATUS_INVALID_SID);
120dc20a302Sas 
1217f667e74Sjose borrego 	status = lsa_lookup_sid_builtin(sid, info);
1227f667e74Sjose borrego 	if (status == NT_STATUS_NOT_FOUND) {
1237f667e74Sjose borrego 		status = smb_sam_lookup_sid(sid, info);
1247f667e74Sjose borrego 		if (status == NT_STATUS_NOT_FOUND)
1257f667e74Sjose borrego 			status = lsa_lookup_sid_domain(sid, info);
1267f667e74Sjose borrego 	}
127dc20a302Sas 
1287f667e74Sjose borrego 	return ((status == NT_STATUS_SUCCESS) ? status : NT_STATUS_NONE_MAPPED);
129dc20a302Sas }
130dc20a302Sas 
131da6c28aaSamw /*
132da6c28aaSamw  * Obtains the primary domain SID and name from the specified server
13329bd2886SAlan Wright  * (domain controller).
134da6c28aaSamw  *
1358d7e4166Sjose borrego  * The requested information will be returned via 'info' argument.
1368d7e4166Sjose borrego  *
137da6c28aaSamw  * Returns NT status codes.
138da6c28aaSamw  */
139da6c28aaSamw DWORD
14029bd2886SAlan Wright lsa_query_primary_domain_info(char *server, char *domain,
141*a0aa776eSAlan Wright     smb_domain_t *info)
142da6c28aaSamw {
143da6c28aaSamw 	mlsvc_handle_t domain_handle;
144da6c28aaSamw 	DWORD status;
145*a0aa776eSAlan Wright 	char user[SMB_USERNAME_MAXLEN];
146*a0aa776eSAlan Wright 
147*a0aa776eSAlan Wright 	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
148da6c28aaSamw 
1498d7e4166Sjose borrego 	if ((lsar_open(server, domain, user, &domain_handle)) != 0)
150da6c28aaSamw 		return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
151da6c28aaSamw 
152da6c28aaSamw 	status = lsar_query_info_policy(&domain_handle,
1538d7e4166Sjose borrego 	    MSLSA_POLICY_PRIMARY_DOMAIN_INFO, info);
154da6c28aaSamw 
155da6c28aaSamw 	(void) lsar_close(&domain_handle);
156da6c28aaSamw 	return (status);
157da6c28aaSamw }
158da6c28aaSamw 
159da6c28aaSamw /*
160da6c28aaSamw  * Obtains the account domain SID and name from the current server
16129bd2886SAlan Wright  * (domain controller).
162da6c28aaSamw  *
1638d7e4166Sjose borrego  * The requested information will be returned via 'info' argument.
1648d7e4166Sjose borrego  *
165da6c28aaSamw  * Returns NT status codes.
166da6c28aaSamw  */
167da6c28aaSamw DWORD
16829bd2886SAlan Wright lsa_query_account_domain_info(char *server, char *domain,
169*a0aa776eSAlan Wright     smb_domain_t *info)
170da6c28aaSamw {
171da6c28aaSamw 	mlsvc_handle_t domain_handle;
172da6c28aaSamw 	DWORD status;
173*a0aa776eSAlan Wright 	char user[SMB_USERNAME_MAXLEN];
174*a0aa776eSAlan Wright 
175*a0aa776eSAlan Wright 	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
176da6c28aaSamw 
1778d7e4166Sjose borrego 	if ((lsar_open(server, domain, user, &domain_handle)) != 0)
178da6c28aaSamw 		return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
179da6c28aaSamw 
180da6c28aaSamw 	status = lsar_query_info_policy(&domain_handle,
1818d7e4166Sjose borrego 	    MSLSA_POLICY_ACCOUNT_DOMAIN_INFO, info);
1828d7e4166Sjose borrego 
1838d7e4166Sjose borrego 	(void) lsar_close(&domain_handle);
1848d7e4166Sjose borrego 	return (status);
1858d7e4166Sjose borrego }
1868d7e4166Sjose borrego 
1878d7e4166Sjose borrego /*
1888d7e4166Sjose borrego  * lsa_query_dns_domain_info
1898d7e4166Sjose borrego  *
1908d7e4166Sjose borrego  * Obtains the DNS domain info from the specified server
1918d7e4166Sjose borrego  * (domain controller).
1928d7e4166Sjose borrego  *
1938d7e4166Sjose borrego  * The requested information will be returned via 'info' argument.
1948d7e4166Sjose borrego  *
1958d7e4166Sjose borrego  * Returns NT status codes.
1968d7e4166Sjose borrego  */
1978d7e4166Sjose borrego DWORD
198*a0aa776eSAlan Wright lsa_query_dns_domain_info(char *server, char *domain, smb_domain_t *info)
1998d7e4166Sjose borrego {
2008d7e4166Sjose borrego 	mlsvc_handle_t domain_handle;
2018d7e4166Sjose borrego 	DWORD status;
202*a0aa776eSAlan Wright 	char user[SMB_USERNAME_MAXLEN];
203*a0aa776eSAlan Wright 
204*a0aa776eSAlan Wright 	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
2058d7e4166Sjose borrego 
2068d7e4166Sjose borrego 	if ((lsar_open(server, domain, user, &domain_handle)) != 0)
2078d7e4166Sjose borrego 		return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
2088d7e4166Sjose borrego 
2098d7e4166Sjose borrego 	status = lsar_query_info_policy(&domain_handle,
2108d7e4166Sjose borrego 	    MSLSA_POLICY_DNS_DOMAIN_INFO, info);
211da6c28aaSamw 
212da6c28aaSamw 	(void) lsar_close(&domain_handle);
213da6c28aaSamw 	return (status);
214da6c28aaSamw }
215da6c28aaSamw 
216da6c28aaSamw /*
21729bd2886SAlan Wright  * Enumerate the trusted domains of  primary domain.
21829bd2886SAlan Wright  * This is the basic enumaration call which only returns the
21929bd2886SAlan Wright  * NetBIOS name of the domain and its SID.
220da6c28aaSamw  *
2218d7e4166Sjose borrego  * The requested information will be returned via 'info' argument.
2228d7e4166Sjose borrego  *
223da6c28aaSamw  * Returns NT status codes.
224da6c28aaSamw  */
225da6c28aaSamw DWORD
22629bd2886SAlan Wright lsa_enum_trusted_domains(char *server, char *domain,
22729bd2886SAlan Wright     smb_trusted_domains_t *info)
228da6c28aaSamw {
229da6c28aaSamw 	mlsvc_handle_t domain_handle;
230da6c28aaSamw 	DWORD enum_context;
231da6c28aaSamw 	DWORD status;
232*a0aa776eSAlan Wright 	char user[SMB_USERNAME_MAXLEN];
233*a0aa776eSAlan Wright 
234*a0aa776eSAlan Wright 	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
235da6c28aaSamw 
2368d7e4166Sjose borrego 	if ((lsar_open(server, domain, user, &domain_handle)) != 0)
237da6c28aaSamw 		return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
238da6c28aaSamw 
239da6c28aaSamw 	enum_context = 0;
240da6c28aaSamw 
2418d7e4166Sjose borrego 	status = lsar_enum_trusted_domains(&domain_handle, &enum_context, info);
242da6c28aaSamw 	if (status == MLSVC_NO_MORE_DATA) {
243da6c28aaSamw 		/*
244da6c28aaSamw 		 * MLSVC_NO_MORE_DATA indicates that we
245da6c28aaSamw 		 * have all of the available information.
246da6c28aaSamw 		 */
247da6c28aaSamw 		status = NT_STATUS_SUCCESS;
248da6c28aaSamw 	}
249da6c28aaSamw 
250da6c28aaSamw 	(void) lsar_close(&domain_handle);
251da6c28aaSamw 	return (status);
252da6c28aaSamw }
253da6c28aaSamw 
2548d7e4166Sjose borrego /*
25529bd2886SAlan Wright  * Enumerate the trusted domains of the primary domain.
25629bd2886SAlan Wright  * This is the extended enumaration call which besides
25729bd2886SAlan Wright  * NetBIOS name of the domain and its SID, it will return
25829bd2886SAlan Wright  * the FQDN plus some trust information which is not used.
25929bd2886SAlan Wright  *
26029bd2886SAlan Wright  * The requested information will be returned via 'info' argument.
26129bd2886SAlan Wright  *
26229bd2886SAlan Wright  * Returns NT status codes.
2638d7e4166Sjose borrego  */
26429bd2886SAlan Wright DWORD
26529bd2886SAlan Wright lsa_enum_trusted_domains_ex(char *server, char *domain,
26629bd2886SAlan Wright     smb_trusted_domains_t *info)
2678d7e4166Sjose borrego {
26829bd2886SAlan Wright 	mlsvc_handle_t domain_handle;
26929bd2886SAlan Wright 	DWORD enum_context;
27029bd2886SAlan Wright 	DWORD status;
271*a0aa776eSAlan Wright 	char user[SMB_USERNAME_MAXLEN];
272*a0aa776eSAlan Wright 
273*a0aa776eSAlan Wright 	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
2748d7e4166Sjose borrego 
27529bd2886SAlan Wright 	if ((lsar_open(server, domain, user, &domain_handle)) != 0)
27629bd2886SAlan Wright 		return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
2778d7e4166Sjose borrego 
27829bd2886SAlan Wright 	enum_context = 0;
2798d7e4166Sjose borrego 
28029bd2886SAlan Wright 	status = lsar_enum_trusted_domains_ex(&domain_handle, &enum_context,
28129bd2886SAlan Wright 	    info);
28229bd2886SAlan Wright 	if (status == MLSVC_NO_MORE_DATA) {
28329bd2886SAlan Wright 		/*
28429bd2886SAlan Wright 		 * MLSVC_NO_MORE_DATA indicates that we
28529bd2886SAlan Wright 		 * have all of the available information.
28629bd2886SAlan Wright 		 */
28729bd2886SAlan Wright 		status = NT_STATUS_SUCCESS;
2888d7e4166Sjose borrego 	}
28929bd2886SAlan Wright 
29029bd2886SAlan Wright 	(void) lsar_close(&domain_handle);
29129bd2886SAlan Wright 	return (status);
2928d7e4166Sjose borrego }
2938d7e4166Sjose borrego 
294da6c28aaSamw /*
29589dc44ceSjose borrego  * Lookup well known accounts table
296da6c28aaSamw  *
29789dc44ceSjose borrego  * Return status:
29889dc44ceSjose borrego  *
29989dc44ceSjose borrego  *   NT_STATUS_SUCCESS		Account is translated successfully
30089dc44ceSjose borrego  *   NT_STATUS_NOT_FOUND	This is not a well known account
30189dc44ceSjose borrego  *   NT_STATUS_NONE_MAPPED	Account is found but domains don't match
30289dc44ceSjose borrego  *   NT_STATUS_NO_MEMORY	Memory shortage
30389dc44ceSjose borrego  *   NT_STATUS_INTERNAL_ERROR	Internal error/unexpected failure
304da6c28aaSamw  */
305dc20a302Sas static uint32_t
3067f667e74Sjose borrego lsa_lookup_name_builtin(char *domain, char *name, smb_account_t *info)
307da6c28aaSamw {
30889dc44ceSjose borrego 	smb_wka_t *wka;
30989dc44ceSjose borrego 	char *wkadom;
31089dc44ceSjose borrego 
3117f667e74Sjose borrego 	bzero(info, sizeof (smb_account_t));
3127f667e74Sjose borrego 
3137f667e74Sjose borrego 	if ((wka = smb_wka_lookup_name(name)) == NULL)
31489dc44ceSjose borrego 		return (NT_STATUS_NOT_FOUND);
315da6c28aaSamw 
31689dc44ceSjose borrego 	if ((wkadom = smb_wka_get_domain(wka->wka_domidx)) == NULL)
31789dc44ceSjose borrego 		return (NT_STATUS_INTERNAL_ERROR);
318da6c28aaSamw 
31989dc44ceSjose borrego 	if ((domain != NULL) && (utf8_strcasecmp(domain, wkadom) != 0))
320dc20a302Sas 		return (NT_STATUS_NONE_MAPPED);
321da6c28aaSamw 
3227f667e74Sjose borrego 	info->a_name = strdup(name);
3237f667e74Sjose borrego 	info->a_sid = smb_sid_dup(wka->wka_binsid);
3247f667e74Sjose borrego 	info->a_domain = strdup(wkadom);
3257f667e74Sjose borrego 	info->a_domsid = smb_sid_split(wka->wka_binsid, &info->a_rid);
3267f667e74Sjose borrego 	info->a_type = wka->wka_type;
327da6c28aaSamw 
3287f667e74Sjose borrego 	if (!smb_account_validate(info)) {
3297f667e74Sjose borrego 		smb_account_free(info);
33089dc44ceSjose borrego 		return (NT_STATUS_NO_MEMORY);
331dc20a302Sas 	}
332da6c28aaSamw 
333dc20a302Sas 	return (NT_STATUS_SUCCESS);
334da6c28aaSamw }
335da6c28aaSamw 
336da6c28aaSamw /*
33789dc44ceSjose borrego  * Lookup the given account in domain.
33889dc44ceSjose borrego  *
33989dc44ceSjose borrego  * The information is returned in the user_info structure.
34089dc44ceSjose borrego  * The caller is responsible for allocating and releasing
34189dc44ceSjose borrego  * this structure.
342da6c28aaSamw  */
343dc20a302Sas static uint32_t
3447f667e74Sjose borrego lsa_lookup_name_domain(char *account_name, smb_account_t *info)
345da6c28aaSamw {
346da6c28aaSamw 	mlsvc_handle_t domain_handle;
347*a0aa776eSAlan Wright 	smb_domainex_t dinfo;
348dc20a302Sas 	uint32_t status;
349*a0aa776eSAlan Wright 	char user[SMB_USERNAME_MAXLEN];
350*a0aa776eSAlan Wright 
351*a0aa776eSAlan Wright 	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
352da6c28aaSamw 
35389dc44ceSjose borrego 	if (!smb_domain_getinfo(&dinfo))
35489dc44ceSjose borrego 		return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
35589dc44ceSjose borrego 
356*a0aa776eSAlan Wright 	if (lsar_open(dinfo.d_dc, dinfo.d_primary.di_nbname, user,
35729bd2886SAlan Wright 	    &domain_handle) != 0)
358da6c28aaSamw 		return (NT_STATUS_INVALID_PARAMETER);
359da6c28aaSamw 
3607f667e74Sjose borrego 	status = lsar_lookup_names2(&domain_handle, account_name, info);
361da6c28aaSamw 	if (status == NT_STATUS_REVISION_MISMATCH) {
362da6c28aaSamw 		/*
363da6c28aaSamw 		 * Not a Windows 2000 domain controller:
364da6c28aaSamw 		 * use the NT compatible call.
365da6c28aaSamw 		 */
3667f667e74Sjose borrego 		status = lsar_lookup_names(&domain_handle, account_name, info);
367da6c28aaSamw 	}
368da6c28aaSamw 
369da6c28aaSamw 	(void) lsar_close(&domain_handle);
370da6c28aaSamw 	return (status);
371da6c28aaSamw }
372da6c28aaSamw 
373da6c28aaSamw /*
374da6c28aaSamw  * lsa_lookup_privs
375da6c28aaSamw  *
376da6c28aaSamw  * Request the privileges associated with the specified account. In
377da6c28aaSamw  * order to get the privileges, we first have to lookup the name on
378da6c28aaSamw  * the specified domain controller and obtain the appropriate SID.
379da6c28aaSamw  * The SID can then be used to open the account and obtain the
380da6c28aaSamw  * account privileges. The results from both the name lookup and the
381da6c28aaSamw  * privileges are returned in the user_info structure. The caller is
382da6c28aaSamw  * responsible for allocating and releasing this structure.
383da6c28aaSamw  *
384da6c28aaSamw  * On success 0 is returned. Otherwise a -ve error code.
385da6c28aaSamw  */
386da6c28aaSamw /*ARGSUSED*/
387da6c28aaSamw int
3887f667e74Sjose borrego lsa_lookup_privs(char *account_name, char *target_name, smb_account_t *ainfo)
389da6c28aaSamw {
390da6c28aaSamw 	mlsvc_handle_t domain_handle;
391da6c28aaSamw 	int rc;
392*a0aa776eSAlan Wright 	smb_domainex_t dinfo;
393*a0aa776eSAlan Wright 	char user[SMB_USERNAME_MAXLEN];
394*a0aa776eSAlan Wright 
395*a0aa776eSAlan Wright 	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
396da6c28aaSamw 
3978d7e4166Sjose borrego 	if (!smb_domain_getinfo(&dinfo))
3988d7e4166Sjose borrego 		return (-1);
3998d7e4166Sjose borrego 
400*a0aa776eSAlan Wright 	if ((lsar_open(dinfo.d_dc, dinfo.d_primary.di_nbname, user,
4018d7e4166Sjose borrego 	    &domain_handle)) != 0)
402da6c28aaSamw 		return (-1);
403da6c28aaSamw 
404da6c28aaSamw 	rc = lsa_list_accounts(&domain_handle);
405da6c28aaSamw 	(void) lsar_close(&domain_handle);
406da6c28aaSamw 	return (rc);
407da6c28aaSamw }
408da6c28aaSamw 
409da6c28aaSamw /*
410da6c28aaSamw  * lsa_list_privs
411da6c28aaSamw  *
412da6c28aaSamw  * List the privileges supported by the specified server.
413da6c28aaSamw  * This function is only intended for diagnostics.
414da6c28aaSamw  *
415da6c28aaSamw  * Returns NT status codes.
416da6c28aaSamw  */
417da6c28aaSamw DWORD
418da6c28aaSamw lsa_list_privs(char *server, char *domain)
419da6c28aaSamw {
420da6c28aaSamw 	static char name[128];
421da6c28aaSamw 	static struct ms_luid luid;
422da6c28aaSamw 	mlsvc_handle_t domain_handle;
423da6c28aaSamw 	int rc;
424da6c28aaSamw 	int i;
425*a0aa776eSAlan Wright 	char user[SMB_USERNAME_MAXLEN];
426*a0aa776eSAlan Wright 
427*a0aa776eSAlan Wright 	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
428da6c28aaSamw 
42955bf511dSas 	rc = lsar_open(server, domain, user, &domain_handle);
430da6c28aaSamw 	if (rc != 0)
431da6c28aaSamw 		return (NT_STATUS_INVALID_PARAMETER);
432da6c28aaSamw 
433da6c28aaSamw 	for (i = 0; i < 30; ++i) {
434da6c28aaSamw 		luid.low_part = i;
435da6c28aaSamw 		rc = lsar_lookup_priv_name(&domain_handle, &luid, name, 128);
436da6c28aaSamw 		if (rc != 0)
437da6c28aaSamw 			continue;
438da6c28aaSamw 
439da6c28aaSamw 		(void) lsar_lookup_priv_value(&domain_handle, name, &luid);
440da6c28aaSamw 		(void) lsar_lookup_priv_display_name(&domain_handle, name,
441da6c28aaSamw 		    name, 128);
442da6c28aaSamw 	}
443da6c28aaSamw 
444da6c28aaSamw 	(void) lsar_close(&domain_handle);
445da6c28aaSamw 	return (NT_STATUS_SUCCESS);
446da6c28aaSamw }
447da6c28aaSamw 
448da6c28aaSamw /*
449da6c28aaSamw  * lsa_list_accounts
450da6c28aaSamw  *
451da6c28aaSamw  * This function can be used to list the accounts in the specified
452da6c28aaSamw  * domain. For now the SIDs are just listed in the system log.
453da6c28aaSamw  *
454da6c28aaSamw  * On success 0 is returned. Otherwise a -ve error code.
455da6c28aaSamw  */
456da6c28aaSamw static int
457da6c28aaSamw lsa_list_accounts(mlsvc_handle_t *domain_handle)
458da6c28aaSamw {
459da6c28aaSamw 	mlsvc_handle_t account_handle;
460da6c28aaSamw 	struct mslsa_EnumAccountBuf accounts;
461da6c28aaSamw 	struct mslsa_sid *sid;
4627f667e74Sjose borrego 	smb_account_t ainfo;
463da6c28aaSamw 	DWORD enum_context = 0;
464da6c28aaSamw 	int rc;
465da6c28aaSamw 	int i;
466da6c28aaSamw 
467da6c28aaSamw 	bzero(&accounts, sizeof (struct mslsa_EnumAccountBuf));
468da6c28aaSamw 
469da6c28aaSamw 	do {
470da6c28aaSamw 		rc = lsar_enum_accounts(domain_handle, &enum_context,
471da6c28aaSamw 		    &accounts);
472da6c28aaSamw 		if (rc != 0)
473da6c28aaSamw 			return (rc);
474da6c28aaSamw 
475da6c28aaSamw 		for (i = 0; i < accounts.entries_read; ++i) {
476da6c28aaSamw 			sid = accounts.info[i].sid;
477da6c28aaSamw 
478da6c28aaSamw 			if (lsar_open_account(domain_handle, sid,
479da6c28aaSamw 			    &account_handle) == 0) {
480da6c28aaSamw 				(void) lsar_enum_privs_account(&account_handle,
4817f667e74Sjose borrego 				    &ainfo);
482da6c28aaSamw 				(void) lsar_close(&account_handle);
483da6c28aaSamw 			}
484da6c28aaSamw 
485da6c28aaSamw 			free(accounts.info[i].sid);
486da6c28aaSamw 		}
487da6c28aaSamw 
488da6c28aaSamw 		if (accounts.info)
489da6c28aaSamw 			free(accounts.info);
490da6c28aaSamw 	} while (rc == 0 && accounts.entries_read != 0);
491da6c28aaSamw 
492da6c28aaSamw 	return (0);
493da6c28aaSamw }
494dc20a302Sas 
495dc20a302Sas /*
4967f667e74Sjose borrego  * Lookup well known accounts table for the given SID
497dc20a302Sas  *
4987f667e74Sjose borrego  * Return status:
4997f667e74Sjose borrego  *
5007f667e74Sjose borrego  *   NT_STATUS_SUCCESS		Account is translated successfully
5017f667e74Sjose borrego  *   NT_STATUS_NOT_FOUND	This is not a well known account
5027f667e74Sjose borrego  *   NT_STATUS_NO_MEMORY	Memory shortage
5037f667e74Sjose borrego  *   NT_STATUS_INTERNAL_ERROR	Internal error/unexpected failure
504dc20a302Sas  */
505dc20a302Sas static uint32_t
5067f667e74Sjose borrego lsa_lookup_sid_builtin(smb_sid_t *sid, smb_account_t *ainfo)
507dc20a302Sas {
5087f667e74Sjose borrego 	smb_wka_t *wka;
5097f667e74Sjose borrego 	char *wkadom;
510dc20a302Sas 
5117f667e74Sjose borrego 	bzero(ainfo, sizeof (smb_account_t));
512dc20a302Sas 
5137f667e74Sjose borrego 	if ((wka = smb_wka_lookup_sid(sid)) == NULL)
5147f667e74Sjose borrego 		return (NT_STATUS_NOT_FOUND);
515dc20a302Sas 
5167f667e74Sjose borrego 	if ((wkadom = smb_wka_get_domain(wka->wka_domidx)) == NULL)
517dc20a302Sas 		return (NT_STATUS_INTERNAL_ERROR);
518dc20a302Sas 
5197f667e74Sjose borrego 	ainfo->a_name = strdup(wka->wka_name);
5207f667e74Sjose borrego 	ainfo->a_sid = smb_sid_dup(wka->wka_binsid);
5217f667e74Sjose borrego 	ainfo->a_domain = strdup(wkadom);
5227f667e74Sjose borrego 	ainfo->a_domsid = smb_sid_split(ainfo->a_sid, &ainfo->a_rid);
5237f667e74Sjose borrego 	ainfo->a_type = wka->wka_type;
524dc20a302Sas 
5257f667e74Sjose borrego 	if (!smb_account_validate(ainfo)) {
5267f667e74Sjose borrego 		smb_account_free(ainfo);
527dc20a302Sas 		return (NT_STATUS_NO_MEMORY);
5287f667e74Sjose borrego 	}
529dc20a302Sas 
530dc20a302Sas 	return (NT_STATUS_SUCCESS);
531dc20a302Sas }
532dc20a302Sas 
533dc20a302Sas static uint32_t
5347f667e74Sjose borrego lsa_lookup_sid_domain(smb_sid_t *sid, smb_account_t *ainfo)
535dc20a302Sas {
536dc20a302Sas 	mlsvc_handle_t domain_handle;
537dc20a302Sas 	uint32_t status;
538*a0aa776eSAlan Wright 	smb_domainex_t dinfo;
539*a0aa776eSAlan Wright 	char user[SMB_USERNAME_MAXLEN];
540*a0aa776eSAlan Wright 
541*a0aa776eSAlan Wright 	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
5428d7e4166Sjose borrego 
5438d7e4166Sjose borrego 	if (!smb_domain_getinfo(&dinfo))
5448d7e4166Sjose borrego 		return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
545dc20a302Sas 
546*a0aa776eSAlan Wright 	if (lsar_open(dinfo.d_dc, dinfo.d_primary.di_nbname, user,
54729bd2886SAlan Wright 	    &domain_handle) != 0)
548dc20a302Sas 		return (NT_STATUS_INVALID_PARAMETER);
549dc20a302Sas 
5507f667e74Sjose borrego 	status = lsar_lookup_sids2(&domain_handle, (struct mslsa_sid *)sid,
5517f667e74Sjose borrego 	    ainfo);
552dc20a302Sas 
553dc20a302Sas 	if (status == NT_STATUS_REVISION_MISMATCH) {
554dc20a302Sas 		/*
555dc20a302Sas 		 * Not a Windows 2000 domain controller:
556dc20a302Sas 		 * use the NT compatible call.
557dc20a302Sas 		 */
558dc20a302Sas 		status = lsar_lookup_sids(&domain_handle,
559dc20a302Sas 		    (struct mslsa_sid *)sid, ainfo);
560dc20a302Sas 	}
561dc20a302Sas 
562dc20a302Sas 	(void) lsar_close(&domain_handle);
563dc20a302Sas 	return (status);
564dc20a302Sas }
565