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*dafb549fSGordon Ross  * Copyright 2019 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>
40dc20a302Sas 
41*dafb549fSGordon Ross static uint32_t lsa_lookup_name_int(char *, uint16_t, smb_account_t *,
42*dafb549fSGordon Ross     boolean_t);
43*dafb549fSGordon Ross static uint32_t lsa_lookup_sid_int(smb_sid_t *, smb_account_t *, boolean_t);
44*dafb549fSGordon Ross 
457f667e74Sjose borrego static uint32_t lsa_lookup_name_builtin(char *, char *, smb_account_t *);
467f667e74Sjose borrego static uint32_t lsa_lookup_name_domain(char *, smb_account_t *);
47dc20a302Sas 
487f667e74Sjose borrego static uint32_t lsa_lookup_sid_builtin(smb_sid_t *, smb_account_t *);
497f667e74Sjose borrego static uint32_t lsa_lookup_sid_domain(smb_sid_t *, smb_account_t *);
50dc20a302Sas 
51b3700b07SGordon Ross static uint32_t lsa_list_accounts(mlsvc_handle_t *);
52b3700b07SGordon Ross static uint32_t lsa_map_status(uint32_t);
53da6c28aaSamw 
54dc20a302Sas /*
55dc20a302Sas  * Lookup the given account and returns the account information
567f667e74Sjose borrego  * in the passed smb_account_t structure.
5789dc44ceSjose borrego  *
5889dc44ceSjose borrego  * The lookup is performed in the following order:
5989dc44ceSjose borrego  *    well known accounts
6089dc44ceSjose borrego  *    local accounts
6189dc44ceSjose borrego  *    domain accounts
6289dc44ceSjose borrego  *
6389dc44ceSjose borrego  * If it's established the given account is well know or local
6489dc44ceSjose borrego  * but the lookup fails for some reason, the next step(s) won't be
6589dc44ceSjose borrego  * performed.
66dc20a302Sas  *
67dc20a302Sas  * If the name is a domain account, it may refer to a user, group or
68dc20a302Sas  * alias. If it is a local account, its type should be specified
69dc20a302Sas  * in the sid_type parameter. In case the account type is unknown
70dc20a302Sas  * sid_type should be set to SidTypeUnknown.
71dc20a302Sas  *
7289dc44ceSjose borrego  * account argument could be either [domain\]name or [domain/]name.
7389dc44ceSjose borrego  *
7489dc44ceSjose borrego  * Return status:
7589dc44ceSjose borrego  *
7689dc44ceSjose borrego  *   NT_STATUS_SUCCESS		Account is successfully translated
7789dc44ceSjose borrego  *   NT_STATUS_NONE_MAPPED	Couldn't translate the account
78dc20a302Sas  */
79dc20a302Sas uint32_t
lsa_lookup_name(char * account,uint16_t type,smb_account_t * info)807f667e74Sjose borrego lsa_lookup_name(char *account, uint16_t type, smb_account_t *info)
81*dafb549fSGordon Ross {
82*dafb549fSGordon Ross 	return (lsa_lookup_name_int(account, type, info, B_TRUE));
83*dafb549fSGordon Ross }
84*dafb549fSGordon Ross 
85*dafb549fSGordon Ross /* Variant that avoids the call out to AD. */
86*dafb549fSGordon Ross uint32_t
lsa_lookup_lname(char * account,uint16_t type,smb_account_t * info)87*dafb549fSGordon Ross lsa_lookup_lname(char *account, uint16_t type, smb_account_t *info)
88*dafb549fSGordon Ross {
89*dafb549fSGordon Ross 	return (lsa_lookup_name_int(account, type, info, B_FALSE));
90*dafb549fSGordon Ross }
91*dafb549fSGordon Ross 
92*dafb549fSGordon Ross uint32_t
lsa_lookup_name_int(char * account,uint16_t type,smb_account_t * info,boolean_t try_ad)93*dafb549fSGordon Ross lsa_lookup_name_int(char *account, uint16_t type, smb_account_t *info,
94*dafb549fSGordon Ross     boolean_t try_ad)
95dc20a302Sas {
9689dc44ceSjose borrego 	char nambuf[SMB_USERNAME_MAXLEN];
9789dc44ceSjose borrego 	char dombuf[SMB_PI_MAX_DOMAIN];
9889dc44ceSjose borrego 	char *name, *domain;
9989dc44ceSjose borrego 	uint32_t status;
10089dc44ceSjose borrego 	char *slash;
10189dc44ceSjose borrego 
1025831d79bSGordon Ross 	if (account == NULL)
1035831d79bSGordon Ross 		return (NT_STATUS_NONE_MAPPED);
1045831d79bSGordon Ross 
10589dc44ceSjose borrego 	(void) strsubst(account, '/', '\\');
10689dc44ceSjose borrego 	(void) strcanon(account, "\\");
10789dc44ceSjose borrego 	/* \john -> john */
10889dc44ceSjose borrego 	account += strspn(account, "\\");
10989dc44ceSjose borrego 
11089dc44ceSjose borrego 	if ((slash = strchr(account, '\\')) != NULL) {
11189dc44ceSjose borrego 		*slash = '\0';
11289dc44ceSjose borrego 		(void) strlcpy(dombuf, account, sizeof (dombuf));
11389dc44ceSjose borrego 		(void) strlcpy(nambuf, slash + 1, sizeof (nambuf));
11489dc44ceSjose borrego 		*slash = '\\';
11589dc44ceSjose borrego 		name = nambuf;
11689dc44ceSjose borrego 		domain = dombuf;
117dc20a302Sas 	} else {
118dc20a302Sas 		name = account;
119dc20a302Sas 		domain = NULL;
120dc20a302Sas 	}
121dc20a302Sas 
12289dc44ceSjose borrego 	status = lsa_lookup_name_builtin(domain, name, info);
12389dc44ceSjose borrego 	if (status == NT_STATUS_NOT_FOUND) {
1247f667e74Sjose borrego 		status = smb_sam_lookup_name(domain, name, type, info);
12589dc44ceSjose borrego 		if (status == NT_STATUS_SUCCESS)
126dc20a302Sas 			return (status);
127dc20a302Sas 
128*dafb549fSGordon Ross 		if (try_ad && ((domain == NULL) ||
129*dafb549fSGordon Ross 		    (status == NT_STATUS_NOT_FOUND))) {
13089dc44ceSjose borrego 			status = lsa_lookup_name_domain(account, info);
131*dafb549fSGordon Ross 		}
132dc20a302Sas 	}
133dc20a302Sas 
13489dc44ceSjose borrego 	return ((status == NT_STATUS_SUCCESS) ? status : NT_STATUS_NONE_MAPPED);
135dc20a302Sas }
136dc20a302Sas 
137dc20a302Sas uint32_t
lsa_lookup_sid(smb_sid_t * sid,smb_account_t * info)1387f667e74Sjose borrego lsa_lookup_sid(smb_sid_t *sid, smb_account_t *info)
139*dafb549fSGordon Ross {
140*dafb549fSGordon Ross 	return (lsa_lookup_sid_int(sid, info, B_TRUE));
141*dafb549fSGordon Ross }
142*dafb549fSGordon Ross 
143*dafb549fSGordon Ross /* Variant that avoids the call out to AD. */
144*dafb549fSGordon Ross uint32_t
lsa_lookup_lsid(smb_sid_t * sid,smb_account_t * info)145*dafb549fSGordon Ross lsa_lookup_lsid(smb_sid_t *sid, smb_account_t *info)
146*dafb549fSGordon Ross {
147*dafb549fSGordon Ross 	return (lsa_lookup_sid_int(sid, info, B_FALSE));
148*dafb549fSGordon Ross }
149*dafb549fSGordon Ross 
150*dafb549fSGordon Ross static uint32_t
lsa_lookup_sid_int(smb_sid_t * sid,smb_account_t * info,boolean_t try_ad)151*dafb549fSGordon Ross lsa_lookup_sid_int(smb_sid_t *sid, smb_account_t *info, boolean_t try_ad)
152dc20a302Sas {
1537f667e74Sjose borrego 	uint32_t status;
1547f667e74Sjose borrego 
1556537f381Sas 	if (!smb_sid_isvalid(sid))
156dc20a302Sas 		return (NT_STATUS_INVALID_SID);
157dc20a302Sas 
1587f667e74Sjose borrego 	status = lsa_lookup_sid_builtin(sid, info);
1597f667e74Sjose borrego 	if (status == NT_STATUS_NOT_FOUND) {
1607f667e74Sjose borrego 		status = smb_sam_lookup_sid(sid, info);
161*dafb549fSGordon Ross 		if (try_ad && status == NT_STATUS_NOT_FOUND) {
1627f667e74Sjose borrego 			status = lsa_lookup_sid_domain(sid, info);
163*dafb549fSGordon Ross 		}
1647f667e74Sjose borrego 	}
165dc20a302Sas 
1667f667e74Sjose borrego 	return ((status == NT_STATUS_SUCCESS) ? status : NT_STATUS_NONE_MAPPED);
167dc20a302Sas }
168dc20a302Sas 
169da6c28aaSamw /*
170da6c28aaSamw  * Obtains the primary domain SID and name from the specified server
17129bd2886SAlan Wright  * (domain controller).
172da6c28aaSamw  *
1738d7e4166Sjose borrego  * The requested information will be returned via 'info' argument.
1748d7e4166Sjose borrego  *
175b3700b07SGordon Ross  * Returns NT status codes. (Raw, not LSA-ized)
176da6c28aaSamw  */
177da6c28aaSamw DWORD
lsa_query_primary_domain_info(char * server,char * domain,smb_domain_t * info)17829bd2886SAlan Wright lsa_query_primary_domain_info(char *server, char *domain,
179a0aa776eSAlan Wright     smb_domain_t *info)
180da6c28aaSamw {
181da6c28aaSamw 	mlsvc_handle_t domain_handle;
182a0aa776eSAlan Wright 	char user[SMB_USERNAME_MAXLEN];
183b3700b07SGordon Ross 	DWORD status;
184a0aa776eSAlan Wright 
185a0aa776eSAlan Wright 	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
186da6c28aaSamw 
187b3700b07SGordon Ross 	status = lsar_open(server, domain, user, &domain_handle);
188b3700b07SGordon Ross 	if (status != 0)
189b3700b07SGordon Ross 		return (status);
190da6c28aaSamw 
191da6c28aaSamw 	status = lsar_query_info_policy(&domain_handle,
1928d7e4166Sjose borrego 	    MSLSA_POLICY_PRIMARY_DOMAIN_INFO, info);
193da6c28aaSamw 
194da6c28aaSamw 	(void) lsar_close(&domain_handle);
195da6c28aaSamw 	return (status);
196da6c28aaSamw }
197da6c28aaSamw 
198da6c28aaSamw /*
199da6c28aaSamw  * Obtains the account domain SID and name from the current server
20029bd2886SAlan Wright  * (domain controller).
201da6c28aaSamw  *
2028d7e4166Sjose borrego  * The requested information will be returned via 'info' argument.
2038d7e4166Sjose borrego  *
204b3700b07SGordon Ross  * Returns NT status codes. (Raw, not LSA-ized)
205da6c28aaSamw  */
206da6c28aaSamw DWORD
lsa_query_account_domain_info(char * server,char * domain,smb_domain_t * info)20729bd2886SAlan Wright lsa_query_account_domain_info(char *server, char *domain,
208a0aa776eSAlan Wright     smb_domain_t *info)
209da6c28aaSamw {
210da6c28aaSamw 	mlsvc_handle_t domain_handle;
211a0aa776eSAlan Wright 	char user[SMB_USERNAME_MAXLEN];
212b3700b07SGordon Ross 	DWORD status;
213a0aa776eSAlan Wright 
214a0aa776eSAlan Wright 	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
215da6c28aaSamw 
216b3700b07SGordon Ross 	status = lsar_open(server, domain, user, &domain_handle);
217b3700b07SGordon Ross 	if (status != 0)
218b3700b07SGordon Ross 		return (status);
219da6c28aaSamw 
220da6c28aaSamw 	status = lsar_query_info_policy(&domain_handle,
2218d7e4166Sjose borrego 	    MSLSA_POLICY_ACCOUNT_DOMAIN_INFO, info);
2228d7e4166Sjose borrego 
2238d7e4166Sjose borrego 	(void) lsar_close(&domain_handle);
2248d7e4166Sjose borrego 	return (status);
2258d7e4166Sjose borrego }
2268d7e4166Sjose borrego 
2278d7e4166Sjose borrego /*
2288d7e4166Sjose borrego  * lsa_query_dns_domain_info
2298d7e4166Sjose borrego  *
2308d7e4166Sjose borrego  * Obtains the DNS domain info from the specified server
2318d7e4166Sjose borrego  * (domain controller).
2328d7e4166Sjose borrego  *
2338d7e4166Sjose borrego  * The requested information will be returned via 'info' argument.
2348d7e4166Sjose borrego  *
235b3700b07SGordon Ross  * Returns NT status codes. (Raw, not LSA-ized)
2368d7e4166Sjose borrego  */
2378d7e4166Sjose borrego DWORD
lsa_query_dns_domain_info(char * server,char * domain,smb_domain_t * info)238a0aa776eSAlan Wright lsa_query_dns_domain_info(char *server, char *domain, smb_domain_t *info)
2398d7e4166Sjose borrego {
2408d7e4166Sjose borrego 	mlsvc_handle_t domain_handle;
241a0aa776eSAlan Wright 	char user[SMB_USERNAME_MAXLEN];
242b3700b07SGordon Ross 	DWORD status;
243a0aa776eSAlan Wright 
244a0aa776eSAlan Wright 	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
2458d7e4166Sjose borrego 
246b3700b07SGordon Ross 	status = lsar_open(server, domain, user, &domain_handle);
247b3700b07SGordon Ross 	if (status != 0)
248b3700b07SGordon Ross 		return (status);
2498d7e4166Sjose borrego 
2508d7e4166Sjose borrego 	status = lsar_query_info_policy(&domain_handle,
2518d7e4166Sjose borrego 	    MSLSA_POLICY_DNS_DOMAIN_INFO, info);
252da6c28aaSamw 
253da6c28aaSamw 	(void) lsar_close(&domain_handle);
254da6c28aaSamw 	return (status);
255da6c28aaSamw }
256da6c28aaSamw 
257da6c28aaSamw /*
25829bd2886SAlan Wright  * Enumerate the trusted domains of  primary domain.
25929bd2886SAlan Wright  * This is the basic enumaration call which only returns the
26029bd2886SAlan Wright  * NetBIOS name of the domain and its SID.
261da6c28aaSamw  *
2628d7e4166Sjose borrego  * The requested information will be returned via 'info' argument.
2638d7e4166Sjose borrego  *
264b3700b07SGordon Ross  * Returns NT status codes.  (Raw, not LSA-ized)
265da6c28aaSamw  */
266da6c28aaSamw DWORD
lsa_enum_trusted_domains(char * server,char * domain,smb_trusted_domains_t * info)26729bd2886SAlan Wright lsa_enum_trusted_domains(char *server, char *domain,
26829bd2886SAlan Wright     smb_trusted_domains_t *info)
269da6c28aaSamw {
270da6c28aaSamw 	mlsvc_handle_t domain_handle;
271b3700b07SGordon Ross 	char user[SMB_USERNAME_MAXLEN];
272da6c28aaSamw 	DWORD enum_context;
273da6c28aaSamw 	DWORD status;
274a0aa776eSAlan Wright 
275a0aa776eSAlan Wright 	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
276da6c28aaSamw 
277b3700b07SGordon Ross 	status = lsar_open(server, domain, user, &domain_handle);
278b3700b07SGordon Ross 	if (status != 0)
279b3700b07SGordon Ross 		return (status);
280da6c28aaSamw 
281da6c28aaSamw 	enum_context = 0;
282da6c28aaSamw 
2838d7e4166Sjose borrego 	status = lsar_enum_trusted_domains(&domain_handle, &enum_context, info);
284148c5f43SAlan Wright 	if (status == NT_STATUS_NO_MORE_ENTRIES) {
285da6c28aaSamw 		/*
286148c5f43SAlan Wright 		 * STATUS_NO_MORE_ENTRIES indicates that we
287da6c28aaSamw 		 * have all of the available information.
288da6c28aaSamw 		 */
289da6c28aaSamw 		status = NT_STATUS_SUCCESS;
290da6c28aaSamw 	}
291da6c28aaSamw 
292da6c28aaSamw 	(void) lsar_close(&domain_handle);
293da6c28aaSamw 	return (status);
294da6c28aaSamw }
295da6c28aaSamw 
2968d7e4166Sjose borrego /*
29729bd2886SAlan Wright  * Enumerate the trusted domains of the primary domain.
29829bd2886SAlan Wright  * This is the extended enumaration call which besides
29929bd2886SAlan Wright  * NetBIOS name of the domain and its SID, it will return
30029bd2886SAlan Wright  * the FQDN plus some trust information which is not used.
30129bd2886SAlan Wright  *
30229bd2886SAlan Wright  * The requested information will be returned via 'info' argument.
30329bd2886SAlan Wright  *
304b3700b07SGordon Ross  * Returns NT status codes. (Raw, not LSA-ized)
3058d7e4166Sjose borrego  */
30629bd2886SAlan Wright DWORD
lsa_enum_trusted_domains_ex(char * server,char * domain,smb_trusted_domains_t * info)30729bd2886SAlan Wright lsa_enum_trusted_domains_ex(char *server, char *domain,
30829bd2886SAlan Wright     smb_trusted_domains_t *info)
3098d7e4166Sjose borrego {
31029bd2886SAlan Wright 	mlsvc_handle_t domain_handle;
311b3700b07SGordon Ross 	char user[SMB_USERNAME_MAXLEN];
31229bd2886SAlan Wright 	DWORD enum_context;
31329bd2886SAlan Wright 	DWORD status;
314a0aa776eSAlan Wright 
315a0aa776eSAlan Wright 	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
3168d7e4166Sjose borrego 
317b3700b07SGordon Ross 	status = lsar_open(server, domain, user, &domain_handle);
318b3700b07SGordon Ross 	if (status != 0)
319b3700b07SGordon Ross 		return (status);
3208d7e4166Sjose borrego 
32129bd2886SAlan Wright 	enum_context = 0;
3228d7e4166Sjose borrego 
32329bd2886SAlan Wright 	status = lsar_enum_trusted_domains_ex(&domain_handle, &enum_context,
32429bd2886SAlan Wright 	    info);
325148c5f43SAlan Wright 	if (status == NT_STATUS_NO_MORE_ENTRIES) {
32629bd2886SAlan Wright 		/*
327148c5f43SAlan Wright 		 * STATUS_NO_MORE_ENTRIES indicates that we
32829bd2886SAlan Wright 		 * have all of the available information.
32929bd2886SAlan Wright 		 */
33029bd2886SAlan Wright 		status = NT_STATUS_SUCCESS;
3318d7e4166Sjose borrego 	}
33229bd2886SAlan Wright 
33329bd2886SAlan Wright 	(void) lsar_close(&domain_handle);
33429bd2886SAlan Wright 	return (status);
3358d7e4166Sjose borrego }
3368d7e4166Sjose borrego 
337da6c28aaSamw /*
33889dc44ceSjose borrego  * Lookup well known accounts table
339da6c28aaSamw  *
34089dc44ceSjose borrego  * Return status:
34189dc44ceSjose borrego  *
34289dc44ceSjose borrego  *   NT_STATUS_SUCCESS		Account is translated successfully
34389dc44ceSjose borrego  *   NT_STATUS_NOT_FOUND	This is not a well known account
34489dc44ceSjose borrego  *   NT_STATUS_NONE_MAPPED	Account is found but domains don't match
34589dc44ceSjose borrego  *   NT_STATUS_NO_MEMORY	Memory shortage
34689dc44ceSjose borrego  *   NT_STATUS_INTERNAL_ERROR	Internal error/unexpected failure
347da6c28aaSamw  */
348dc20a302Sas static uint32_t
lsa_lookup_name_builtin(char * domain,char * name,smb_account_t * info)3497f667e74Sjose borrego lsa_lookup_name_builtin(char *domain, char *name, smb_account_t *info)
350da6c28aaSamw {
35189dc44ceSjose borrego 	smb_wka_t *wka;
35289dc44ceSjose borrego 	char *wkadom;
35389dc44ceSjose borrego 
3547f667e74Sjose borrego 	bzero(info, sizeof (smb_account_t));
3557f667e74Sjose borrego 
3567f667e74Sjose borrego 	if ((wka = smb_wka_lookup_name(name)) == NULL)
35789dc44ceSjose borrego 		return (NT_STATUS_NOT_FOUND);
358da6c28aaSamw 
35989dc44ceSjose borrego 	if ((wkadom = smb_wka_get_domain(wka->wka_domidx)) == NULL)
36089dc44ceSjose borrego 		return (NT_STATUS_INTERNAL_ERROR);
361da6c28aaSamw 
362bbf6f00cSJordan Brown 	if ((domain != NULL) && (smb_strcasecmp(domain, wkadom, 0) != 0))
363dc20a302Sas 		return (NT_STATUS_NONE_MAPPED);
364da6c28aaSamw 
3657f667e74Sjose borrego 	info->a_name = strdup(name);
3667f667e74Sjose borrego 	info->a_sid = smb_sid_dup(wka->wka_binsid);
3677f667e74Sjose borrego 	info->a_domain = strdup(wkadom);
3687f667e74Sjose borrego 	info->a_domsid = smb_sid_split(wka->wka_binsid, &info->a_rid);
3697f667e74Sjose borrego 	info->a_type = wka->wka_type;
370da6c28aaSamw 
3717f667e74Sjose borrego 	if (!smb_account_validate(info)) {
3727f667e74Sjose borrego 		smb_account_free(info);
37389dc44ceSjose borrego 		return (NT_STATUS_NO_MEMORY);
374dc20a302Sas 	}
375da6c28aaSamw 
376dc20a302Sas 	return (NT_STATUS_SUCCESS);
377da6c28aaSamw }
378da6c28aaSamw 
379da6c28aaSamw /*
380b3700b07SGordon Ross  * Lookup a domain account by its name.
38189dc44ceSjose borrego  *
38289dc44ceSjose borrego  * The information is returned in the user_info structure.
38389dc44ceSjose borrego  * The caller is responsible for allocating and releasing
38489dc44ceSjose borrego  * this structure.
385b3700b07SGordon Ross  *
386b3700b07SGordon Ross  * Returns NT status codes. (LSA-ized)
387da6c28aaSamw  */
388dc20a302Sas static uint32_t
lsa_lookup_name_domain(char * account_name,smb_account_t * info)3897f667e74Sjose borrego lsa_lookup_name_domain(char *account_name, smb_account_t *info)
390da6c28aaSamw {
391da6c28aaSamw 	mlsvc_handle_t domain_handle;
392a0aa776eSAlan Wright 	smb_domainex_t dinfo;
393a0aa776eSAlan Wright 	char user[SMB_USERNAME_MAXLEN];
394b3700b07SGordon Ross 	uint32_t status;
395a0aa776eSAlan Wright 
396a0aa776eSAlan Wright 	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
397da6c28aaSamw 
39889dc44ceSjose borrego 	if (!smb_domain_getinfo(&dinfo))
39989dc44ceSjose borrego 		return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
40089dc44ceSjose borrego 
401b3700b07SGordon Ross 	status = lsar_open(dinfo.d_dci.dc_name, dinfo.d_primary.di_nbname,
402b3700b07SGordon Ross 	    user, &domain_handle);
403b3700b07SGordon Ross 	if (status != 0)
404b3700b07SGordon Ross 		return (lsa_map_status(status));
405da6c28aaSamw 
406fe1c642dSBill Krier 	status = lsar_lookup_names(&domain_handle, account_name, info);
407da6c28aaSamw 
408da6c28aaSamw 	(void) lsar_close(&domain_handle);
409da6c28aaSamw 	return (status);
410da6c28aaSamw }
411da6c28aaSamw 
412da6c28aaSamw /*
413da6c28aaSamw  * lsa_lookup_privs
414da6c28aaSamw  *
415da6c28aaSamw  * Request the privileges associated with the specified account. In
416da6c28aaSamw  * order to get the privileges, we first have to lookup the name on
417da6c28aaSamw  * the specified domain controller and obtain the appropriate SID.
418da6c28aaSamw  * The SID can then be used to open the account and obtain the
419da6c28aaSamw  * account privileges. The results from both the name lookup and the
420da6c28aaSamw  * privileges are returned in the user_info structure. The caller is
421da6c28aaSamw  * responsible for allocating and releasing this structure.
422da6c28aaSamw  *
423b3700b07SGordon Ross  * Returns NT status codes. (LSA-ized)
424da6c28aaSamw  */
425da6c28aaSamw /*ARGSUSED*/
426b3700b07SGordon Ross DWORD
lsa_lookup_privs(char * account_name,char * target_name,smb_account_t * ainfo)4277f667e74Sjose borrego lsa_lookup_privs(char *account_name, char *target_name, smb_account_t *ainfo)
428da6c28aaSamw {
429da6c28aaSamw 	mlsvc_handle_t domain_handle;
430a0aa776eSAlan Wright 	smb_domainex_t dinfo;
431a0aa776eSAlan Wright 	char user[SMB_USERNAME_MAXLEN];
432b3700b07SGordon Ross 	DWORD status;
433a0aa776eSAlan Wright 
434a0aa776eSAlan Wright 	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
435da6c28aaSamw 
4368d7e4166Sjose borrego 	if (!smb_domain_getinfo(&dinfo))
437b3700b07SGordon Ross 		return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
4388d7e4166Sjose borrego 
439b3700b07SGordon Ross 	status = lsar_open(dinfo.d_dci.dc_name, dinfo.d_primary.di_nbname,
440b3700b07SGordon Ross 	    user, &domain_handle);
441b3700b07SGordon Ross 	if (status != 0)
442b3700b07SGordon Ross 		return (lsa_map_status(status));
443da6c28aaSamw 
444b3700b07SGordon Ross 	status = lsa_list_accounts(&domain_handle);
445da6c28aaSamw 	(void) lsar_close(&domain_handle);
446b3700b07SGordon Ross 	return (status);
447da6c28aaSamw }
448da6c28aaSamw 
449da6c28aaSamw /*
450da6c28aaSamw  * lsa_list_privs
451da6c28aaSamw  *
452da6c28aaSamw  * List the privileges supported by the specified server.
453da6c28aaSamw  * This function is only intended for diagnostics.
454da6c28aaSamw  *
455b3700b07SGordon Ross  * Returns NT status codes. (LSA-ized)
456da6c28aaSamw  */
457da6c28aaSamw DWORD
lsa_list_privs(char * server,char * domain)458da6c28aaSamw lsa_list_privs(char *server, char *domain)
459da6c28aaSamw {
460da6c28aaSamw 	static char name[128];
461da6c28aaSamw 	static struct ms_luid luid;
462da6c28aaSamw 	mlsvc_handle_t domain_handle;
463b3700b07SGordon Ross 	char user[SMB_USERNAME_MAXLEN];
464b3700b07SGordon Ross 	DWORD status;
465da6c28aaSamw 	int rc;
466da6c28aaSamw 	int i;
467a0aa776eSAlan Wright 
468a0aa776eSAlan Wright 	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
469da6c28aaSamw 
470b3700b07SGordon Ross 	status = lsar_open(server, domain, user, &domain_handle);
471b3700b07SGordon Ross 	if (status != 0)
472b3700b07SGordon Ross 		return (lsa_map_status(status));
473da6c28aaSamw 
474da6c28aaSamw 	for (i = 0; i < 30; ++i) {
475da6c28aaSamw 		luid.low_part = i;
476da6c28aaSamw 		rc = lsar_lookup_priv_name(&domain_handle, &luid, name, 128);
477da6c28aaSamw 		if (rc != 0)
478da6c28aaSamw 			continue;
479da6c28aaSamw 
480da6c28aaSamw 		(void) lsar_lookup_priv_value(&domain_handle, name, &luid);
481da6c28aaSamw 		(void) lsar_lookup_priv_display_name(&domain_handle, name,
482da6c28aaSamw 		    name, 128);
483da6c28aaSamw 	}
484da6c28aaSamw 
485da6c28aaSamw 	(void) lsar_close(&domain_handle);
486da6c28aaSamw 	return (NT_STATUS_SUCCESS);
487da6c28aaSamw }
488da6c28aaSamw 
489da6c28aaSamw /*
490da6c28aaSamw  * lsa_list_accounts
491da6c28aaSamw  *
492da6c28aaSamw  * This function can be used to list the accounts in the specified
493da6c28aaSamw  * domain. For now the SIDs are just listed in the system log.
494da6c28aaSamw  *
495b3700b07SGordon Ross  * Returns NT status
496da6c28aaSamw  */
497b3700b07SGordon Ross static DWORD
lsa_list_accounts(mlsvc_handle_t * domain_handle)498da6c28aaSamw lsa_list_accounts(mlsvc_handle_t *domain_handle)
499da6c28aaSamw {
500da6c28aaSamw 	mlsvc_handle_t account_handle;
501da6c28aaSamw 	struct mslsa_EnumAccountBuf accounts;
502da6c28aaSamw 	struct mslsa_sid *sid;
5037f667e74Sjose borrego 	smb_account_t ainfo;
504da6c28aaSamw 	DWORD enum_context = 0;
505b3700b07SGordon Ross 	DWORD status;
506da6c28aaSamw 	int i;
507da6c28aaSamw 
508da6c28aaSamw 	bzero(&accounts, sizeof (struct mslsa_EnumAccountBuf));
509da6c28aaSamw 
510da6c28aaSamw 	do {
511b3700b07SGordon Ross 		status = lsar_enum_accounts(domain_handle, &enum_context,
512da6c28aaSamw 		    &accounts);
513b3700b07SGordon Ross 		if (status != 0)
514b3700b07SGordon Ross 			return (status);
515da6c28aaSamw 
516da6c28aaSamw 		for (i = 0; i < accounts.entries_read; ++i) {
517da6c28aaSamw 			sid = accounts.info[i].sid;
518da6c28aaSamw 
519da6c28aaSamw 			if (lsar_open_account(domain_handle, sid,
520da6c28aaSamw 			    &account_handle) == 0) {
521da6c28aaSamw 				(void) lsar_enum_privs_account(&account_handle,
5227f667e74Sjose borrego 				    &ainfo);
523da6c28aaSamw 				(void) lsar_close(&account_handle);
524da6c28aaSamw 			}
525da6c28aaSamw 
526da6c28aaSamw 			free(accounts.info[i].sid);
527da6c28aaSamw 		}
528da6c28aaSamw 
529da6c28aaSamw 		if (accounts.info)
530da6c28aaSamw 			free(accounts.info);
531b3700b07SGordon Ross 	} while (status == 0 && accounts.entries_read != 0);
532da6c28aaSamw 
533da6c28aaSamw 	return (0);
534da6c28aaSamw }
535dc20a302Sas 
536dc20a302Sas /*
5377f667e74Sjose borrego  * Lookup well known accounts table for the given SID
538dc20a302Sas  *
5397f667e74Sjose borrego  * Return status:
5407f667e74Sjose borrego  *
5417f667e74Sjose borrego  *   NT_STATUS_SUCCESS		Account is translated successfully
5427f667e74Sjose borrego  *   NT_STATUS_NOT_FOUND	This is not a well known account
5437f667e74Sjose borrego  *   NT_STATUS_NO_MEMORY	Memory shortage
5447f667e74Sjose borrego  *   NT_STATUS_INTERNAL_ERROR	Internal error/unexpected failure
545dc20a302Sas  */
546dc20a302Sas static uint32_t
lsa_lookup_sid_builtin(smb_sid_t * sid,smb_account_t * ainfo)5477f667e74Sjose borrego lsa_lookup_sid_builtin(smb_sid_t *sid, smb_account_t *ainfo)
548dc20a302Sas {
5497f667e74Sjose borrego 	smb_wka_t *wka;
5507f667e74Sjose borrego 	char *wkadom;
551dc20a302Sas 
5527f667e74Sjose borrego 	bzero(ainfo, sizeof (smb_account_t));
553dc20a302Sas 
5547f667e74Sjose borrego 	if ((wka = smb_wka_lookup_sid(sid)) == NULL)
5557f667e74Sjose borrego 		return (NT_STATUS_NOT_FOUND);
556dc20a302Sas 
5577f667e74Sjose borrego 	if ((wkadom = smb_wka_get_domain(wka->wka_domidx)) == NULL)
558dc20a302Sas 		return (NT_STATUS_INTERNAL_ERROR);
559dc20a302Sas 
5607f667e74Sjose borrego 	ainfo->a_name = strdup(wka->wka_name);
5617f667e74Sjose borrego 	ainfo->a_sid = smb_sid_dup(wka->wka_binsid);
5627f667e74Sjose borrego 	ainfo->a_domain = strdup(wkadom);
5637f667e74Sjose borrego 	ainfo->a_domsid = smb_sid_split(ainfo->a_sid, &ainfo->a_rid);
5647f667e74Sjose borrego 	ainfo->a_type = wka->wka_type;
565dc20a302Sas 
5667f667e74Sjose borrego 	if (!smb_account_validate(ainfo)) {
5677f667e74Sjose borrego 		smb_account_free(ainfo);
568dc20a302Sas 		return (NT_STATUS_NO_MEMORY);
5697f667e74Sjose borrego 	}
570dc20a302Sas 
571dc20a302Sas 	return (NT_STATUS_SUCCESS);
572dc20a302Sas }
573dc20a302Sas 
574b3700b07SGordon Ross /*
575b3700b07SGordon Ross  * Lookup a domain account by its SID.
576b3700b07SGordon Ross  *
577b3700b07SGordon Ross  * The information is returned in the user_info structure.
578b3700b07SGordon Ross  * The caller is responsible for allocating and releasing
579b3700b07SGordon Ross  * this structure.
580b3700b07SGordon Ross  *
581b3700b07SGordon Ross  * Returns NT status codes. (LSA-ized)
582b3700b07SGordon Ross  */
583dc20a302Sas static uint32_t
lsa_lookup_sid_domain(smb_sid_t * sid,smb_account_t * ainfo)5847f667e74Sjose borrego lsa_lookup_sid_domain(smb_sid_t *sid, smb_account_t *ainfo)
585dc20a302Sas {
586dc20a302Sas 	mlsvc_handle_t domain_handle;
587a0aa776eSAlan Wright 	smb_domainex_t dinfo;
588a0aa776eSAlan Wright 	char user[SMB_USERNAME_MAXLEN];
589b3700b07SGordon Ross 	uint32_t status;
590a0aa776eSAlan Wright 
591a0aa776eSAlan Wright 	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
5928d7e4166Sjose borrego 
5938d7e4166Sjose borrego 	if (!smb_domain_getinfo(&dinfo))
5948d7e4166Sjose borrego 		return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
595dc20a302Sas 
596b3700b07SGordon Ross 	status = lsar_open(dinfo.d_dci.dc_name, dinfo.d_primary.di_nbname,
597b3700b07SGordon Ross 	    user, &domain_handle);
598b3700b07SGordon Ross 	if (status != 0)
599b3700b07SGordon Ross 		return (lsa_map_status(status));
600dc20a302Sas 
601fe1c642dSBill Krier 	status = lsar_lookup_sids(&domain_handle, sid, ainfo);
602dc20a302Sas 
603dc20a302Sas 	(void) lsar_close(&domain_handle);
604dc20a302Sas 	return (status);
605dc20a302Sas }
606b3700b07SGordon Ross 
607b3700b07SGordon Ross /*
608b3700b07SGordon Ross  * Most functions that call the local security authority expect
609b3700b07SGordon Ross  * only a limited set of status returns.  This function maps the
610b3700b07SGordon Ross  * status we get from talking to our domain controller into one
611b3700b07SGordon Ross  * that LSA functions can return.  Most common errors become:
612b3700b07SGordon Ross  * NT_STATUS_CANT_ACCESS_DOMAIN_INFO (when no DC etc.)
613b3700b07SGordon Ross  */
614b3700b07SGordon Ross static uint32_t
lsa_map_status(uint32_t status)615b3700b07SGordon Ross lsa_map_status(uint32_t status)
616b3700b07SGordon Ross {
617b3700b07SGordon Ross 	switch (status) {
618b3700b07SGordon Ross 	case NT_STATUS_SUCCESS:
619b3700b07SGordon Ross 		break;
620b3700b07SGordon Ross 	case NT_STATUS_INVALID_PARAMETER:	/* rpc bind */
621b3700b07SGordon Ross 		break;
622b3700b07SGordon Ross 	case NT_STATUS_NO_MEMORY:
623b3700b07SGordon Ross 		break;
624b3700b07SGordon Ross 	case NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND:
625b3700b07SGordon Ross 	case NT_STATUS_BAD_NETWORK_PATH:	/* get server addr */
626b3700b07SGordon Ross 	case NT_STATUS_NETWORK_ACCESS_DENIED:	/* authentication */
627b3700b07SGordon Ross 	case NT_STATUS_BAD_NETWORK_NAME:	/* tree connect */
628b3700b07SGordon Ross 	case NT_STATUS_ACCESS_DENIED:		/* open pipe */
629b3700b07SGordon Ross 		status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
630b3700b07SGordon Ross 		break;
631b3700b07SGordon Ross 	default:
632b3700b07SGordon Ross 		status = NT_STATUS_UNSUCCESSFUL;
633b3700b07SGordon Ross 		break;
634b3700b07SGordon Ross 	}
635b3700b07SGordon Ross 	return (status);
636b3700b07SGordon Ross }
637