1*da6c28aaSamw /*
2*da6c28aaSamw  * CDDL HEADER START
3*da6c28aaSamw  *
4*da6c28aaSamw  * The contents of this file are subject to the terms of the
5*da6c28aaSamw  * Common Development and Distribution License (the "License").
6*da6c28aaSamw  * You may not use this file except in compliance with the License.
7*da6c28aaSamw  *
8*da6c28aaSamw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*da6c28aaSamw  * or http://www.opensolaris.org/os/licensing.
10*da6c28aaSamw  * See the License for the specific language governing permissions
11*da6c28aaSamw  * and limitations under the License.
12*da6c28aaSamw  *
13*da6c28aaSamw  * When distributing Covered Code, include this CDDL HEADER in each
14*da6c28aaSamw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*da6c28aaSamw  * If applicable, add the following below this CDDL HEADER, with the
16*da6c28aaSamw  * fields enclosed by brackets "[]" replaced with your own identifying
17*da6c28aaSamw  * information: Portions Copyright [yyyy] [name of copyright owner]
18*da6c28aaSamw  *
19*da6c28aaSamw  * CDDL HEADER END
20*da6c28aaSamw  */
21*da6c28aaSamw /*
22*da6c28aaSamw  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23*da6c28aaSamw  * Use is subject to license terms.
24*da6c28aaSamw  */
25*da6c28aaSamw 
26*da6c28aaSamw #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*da6c28aaSamw 
28*da6c28aaSamw /*
29*da6c28aaSamw  * This module provides the high level interface to the LSA RPC functions.
30*da6c28aaSamw  */
31*da6c28aaSamw 
32*da6c28aaSamw #include <strings.h>
33*da6c28aaSamw #include <unistd.h>
34*da6c28aaSamw #include <netdb.h>
35*da6c28aaSamw 
36*da6c28aaSamw #include <smbsrv/libsmb.h>
37*da6c28aaSamw #include <smbsrv/libsmbns.h>
38*da6c28aaSamw #include <smbsrv/libmlsvc.h>
39*da6c28aaSamw #include <smbsrv/lsalib.h>
40*da6c28aaSamw #include <smbsrv/ntstatus.h>
41*da6c28aaSamw #include <smbsrv/smbinfo.h>
42*da6c28aaSamw #include <smbsrv/ntsid.h>
43*da6c28aaSamw #include <smbsrv/smb_token.h>
44*da6c28aaSamw 
45*da6c28aaSamw static int lsa_list_accounts(mlsvc_handle_t *);
46*da6c28aaSamw 
47*da6c28aaSamw /*
48*da6c28aaSamw  * lsa_query_primary_domain_info
49*da6c28aaSamw  *
50*da6c28aaSamw  * Obtains the primary domain SID and name from the specified server
51*da6c28aaSamw  * (domain controller). The information is stored in the NT domain
52*da6c28aaSamw  * database by the lower level lsar_query_info_policy call. The caller
53*da6c28aaSamw  * should query the database to obtain a reference to the primary
54*da6c28aaSamw  * domain information.
55*da6c28aaSamw  *
56*da6c28aaSamw  * Returns NT status codes.
57*da6c28aaSamw  */
58*da6c28aaSamw DWORD
59*da6c28aaSamw lsa_query_primary_domain_info(void)
60*da6c28aaSamw {
61*da6c28aaSamw 	mlsvc_handle_t domain_handle;
62*da6c28aaSamw 	DWORD status;
63*da6c28aaSamw 
64*da6c28aaSamw 	if ((lsar_open(MLSVC_IPC_ANON, 0, 0, 0, 0, &domain_handle)) != 0)
65*da6c28aaSamw 		return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
66*da6c28aaSamw 
67*da6c28aaSamw 	status = lsar_query_info_policy(&domain_handle,
68*da6c28aaSamw 	    MSLSA_POLICY_PRIMARY_DOMAIN_INFO);
69*da6c28aaSamw 
70*da6c28aaSamw 	(void) lsar_close(&domain_handle);
71*da6c28aaSamw 	return (status);
72*da6c28aaSamw }
73*da6c28aaSamw 
74*da6c28aaSamw /*
75*da6c28aaSamw  * lsa_query_account_domain_info
76*da6c28aaSamw  *
77*da6c28aaSamw  * Obtains the account domain SID and name from the current server
78*da6c28aaSamw  * (domain controller). The information is stored in the NT domain
79*da6c28aaSamw  * database by the lower level lsar_query_info_policy call. The caller
80*da6c28aaSamw  * should query the database to obtain a reference to the account
81*da6c28aaSamw  * domain information.
82*da6c28aaSamw  *
83*da6c28aaSamw  * Returns NT status codes.
84*da6c28aaSamw  */
85*da6c28aaSamw DWORD
86*da6c28aaSamw lsa_query_account_domain_info(void)
87*da6c28aaSamw {
88*da6c28aaSamw 	mlsvc_handle_t domain_handle;
89*da6c28aaSamw 	DWORD status;
90*da6c28aaSamw 
91*da6c28aaSamw 	if ((lsar_open(MLSVC_IPC_ANON, 0, 0, 0, 0, &domain_handle)) != 0)
92*da6c28aaSamw 		return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
93*da6c28aaSamw 
94*da6c28aaSamw 	status = lsar_query_info_policy(&domain_handle,
95*da6c28aaSamw 	    MSLSA_POLICY_ACCOUNT_DOMAIN_INFO);
96*da6c28aaSamw 
97*da6c28aaSamw 	(void) lsar_close(&domain_handle);
98*da6c28aaSamw 	return (status);
99*da6c28aaSamw }
100*da6c28aaSamw 
101*da6c28aaSamw /*
102*da6c28aaSamw  * lsa_enum_trusted_domains
103*da6c28aaSamw  *
104*da6c28aaSamw  * Enumerate the trusted domains in our primary domain. The information
105*da6c28aaSamw  * is stored in the NT domain database by the lower level
106*da6c28aaSamw  * lsar_enum_trusted_domains call. The caller should query the database
107*da6c28aaSamw  * to obtain a reference to the trusted domain information.
108*da6c28aaSamw  *
109*da6c28aaSamw  * Returns NT status codes.
110*da6c28aaSamw  */
111*da6c28aaSamw DWORD
112*da6c28aaSamw lsa_enum_trusted_domains(void)
113*da6c28aaSamw {
114*da6c28aaSamw 	mlsvc_handle_t domain_handle;
115*da6c28aaSamw 	DWORD enum_context;
116*da6c28aaSamw 	DWORD status;
117*da6c28aaSamw 
118*da6c28aaSamw 	if ((lsar_open(MLSVC_IPC_ANON, 0, 0, 0, 0, &domain_handle)) != 0)
119*da6c28aaSamw 		return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
120*da6c28aaSamw 
121*da6c28aaSamw 	enum_context = 0;
122*da6c28aaSamw 
123*da6c28aaSamw 	status = lsar_enum_trusted_domains(&domain_handle, &enum_context);
124*da6c28aaSamw 	if (status == MLSVC_NO_MORE_DATA) {
125*da6c28aaSamw 		/*
126*da6c28aaSamw 		 * MLSVC_NO_MORE_DATA indicates that we
127*da6c28aaSamw 		 * have all of the available information.
128*da6c28aaSamw 		 */
129*da6c28aaSamw 		status = NT_STATUS_SUCCESS;
130*da6c28aaSamw 	}
131*da6c28aaSamw 
132*da6c28aaSamw 	(void) lsar_close(&domain_handle);
133*da6c28aaSamw 	return (status);
134*da6c28aaSamw }
135*da6c28aaSamw 
136*da6c28aaSamw /*
137*da6c28aaSamw  * lsa_test_lookup
138*da6c28aaSamw  *
139*da6c28aaSamw  * Test routine for lsa_lookup_name and lsa_lookup_sid.
140*da6c28aaSamw  */
141*da6c28aaSamw void
142*da6c28aaSamw lsa_test_lookup(char *name)
143*da6c28aaSamw {
144*da6c28aaSamw 	smb_userinfo_t *user_info;
145*da6c28aaSamw 	nt_sid_t *sid;
146*da6c28aaSamw 	DWORD status;
147*da6c28aaSamw 	smb_ntdomain_t *di;
148*da6c28aaSamw 
149*da6c28aaSamw 	if ((di = smb_getdomaininfo(0)) == 0)
150*da6c28aaSamw 		return;
151*da6c28aaSamw 
152*da6c28aaSamw 	user_info = mlsvc_alloc_user_info();
153*da6c28aaSamw 
154*da6c28aaSamw 	if (lsa_lookup_builtin_name(name, user_info) != 0) {
155*da6c28aaSamw 		status = lsa_lookup_name(di->server, di->domain, name,
156*da6c28aaSamw 		    user_info);
157*da6c28aaSamw 
158*da6c28aaSamw 		if (status == 0) {
159*da6c28aaSamw 			sid = nt_sid_splice(user_info->domain_sid,
160*da6c28aaSamw 			    user_info->rid);
161*da6c28aaSamw 
162*da6c28aaSamw 			(void) lsa_lookup_sid(sid, user_info);
163*da6c28aaSamw 			free(sid);
164*da6c28aaSamw 		}
165*da6c28aaSamw 	}
166*da6c28aaSamw 
167*da6c28aaSamw 	mlsvc_free_user_info(user_info);
168*da6c28aaSamw }
169*da6c28aaSamw 
170*da6c28aaSamw /*
171*da6c28aaSamw  * lsa_lookup_builtin_name
172*da6c28aaSamw  *
173*da6c28aaSamw  * lookup builtin account table to see if account_name is
174*da6c28aaSamw  * there. If it is there, set sid_name_use, domain_sid,
175*da6c28aaSamw  * domain_name, and rid fields of the passed user_info
176*da6c28aaSamw  * structure and return 0. If lookup fails return 1.
177*da6c28aaSamw  */
178*da6c28aaSamw int
179*da6c28aaSamw lsa_lookup_builtin_name(char *account_name, smb_userinfo_t *user_info)
180*da6c28aaSamw {
181*da6c28aaSamw 	char *domain;
182*da6c28aaSamw 	int res;
183*da6c28aaSamw 
184*da6c28aaSamw 	user_info->domain_sid = nt_builtin_lookup_name(account_name,
185*da6c28aaSamw 	    &user_info->sid_name_use);
186*da6c28aaSamw 
187*da6c28aaSamw 	if (user_info->domain_sid == 0)
188*da6c28aaSamw 		return (1);
189*da6c28aaSamw 
190*da6c28aaSamw 	res = nt_sid_split(user_info->domain_sid, &user_info->rid);
191*da6c28aaSamw 	if (res < 0)
192*da6c28aaSamw 		return (1);
193*da6c28aaSamw 
194*da6c28aaSamw 	domain = nt_builtin_lookup_domain(account_name);
195*da6c28aaSamw 	if (domain) {
196*da6c28aaSamw 		user_info->domain_name = strdup(domain);
197*da6c28aaSamw 		return (0);
198*da6c28aaSamw 	}
199*da6c28aaSamw 
200*da6c28aaSamw 	return (1);
201*da6c28aaSamw }
202*da6c28aaSamw 
203*da6c28aaSamw /*
204*da6c28aaSamw  * lsa_lookup_local_sam
205*da6c28aaSamw  *
206*da6c28aaSamw  * lookup for the given account name in the local SAM database.
207*da6c28aaSamw  * Returns 0 on success. If lookup fails return 1.
208*da6c28aaSamw  */
209*da6c28aaSamw int
210*da6c28aaSamw lsa_lookup_local_sam(char *domain, char *account_name,
211*da6c28aaSamw     smb_userinfo_t *user_info)
212*da6c28aaSamw {
213*da6c28aaSamw 	nt_group_t *grp;
214*da6c28aaSamw 
215*da6c28aaSamw 	if (*domain == '\0' || *account_name == '\0')
216*da6c28aaSamw 		return (1);
217*da6c28aaSamw 
218*da6c28aaSamw 	grp = nt_group_getinfo(account_name, RWLOCK_READER);
219*da6c28aaSamw 	if (grp == 0)
220*da6c28aaSamw 		return (1);
221*da6c28aaSamw 
222*da6c28aaSamw 	user_info->sid_name_use = *grp->sid_name_use;
223*da6c28aaSamw 	user_info->domain_sid = nt_sid_dup(grp->sid);
224*da6c28aaSamw 	nt_group_putinfo(grp);
225*da6c28aaSamw 
226*da6c28aaSamw 	if (user_info->domain_sid == 0)
227*da6c28aaSamw 		return (1);
228*da6c28aaSamw 
229*da6c28aaSamw 	(void) nt_sid_split(user_info->domain_sid, &user_info->rid);
230*da6c28aaSamw 	user_info->domain_name = strdup(domain);
231*da6c28aaSamw 
232*da6c28aaSamw 	if (user_info->domain_name == 0) {
233*da6c28aaSamw 		free(user_info->domain_sid);
234*da6c28aaSamw 		user_info->domain_sid = 0;
235*da6c28aaSamw 		return (1);
236*da6c28aaSamw 	}
237*da6c28aaSamw 
238*da6c28aaSamw 	return (0);
239*da6c28aaSamw }
240*da6c28aaSamw 
241*da6c28aaSamw /*
242*da6c28aaSamw  * lsa_lookup_local
243*da6c28aaSamw  *
244*da6c28aaSamw  * if given account name has domain part, check to see if
245*da6c28aaSamw  * it matches with host name or any of host's primary addresses.
246*da6c28aaSamw  * if any match found first lookup in builtin accounts table and
247*da6c28aaSamw  * then in local SAM table.
248*da6c28aaSamw  *
249*da6c28aaSamw  * if account name doesn't have domain part, first do local lookups
250*da6c28aaSamw  * if nothing is found return 1. This means that caller function should
251*da6c28aaSamw  * do domain lookup.
252*da6c28aaSamw  * if any error happened return -1, if name is found return 0.
253*da6c28aaSamw  */
254*da6c28aaSamw int
255*da6c28aaSamw lsa_lookup_local(char *name, smb_userinfo_t *user_info)
256*da6c28aaSamw {
257*da6c28aaSamw 	char hostname[MAXHOSTNAMELEN];
258*da6c28aaSamw 	int res = 0;
259*da6c28aaSamw 	int local_lookup = 0;
260*da6c28aaSamw 	char *tmp;
261*da6c28aaSamw 	net_cfg_t cfg;
262*da6c28aaSamw 	uint32_t addr;
263*da6c28aaSamw 
264*da6c28aaSamw 	if (smb_gethostname(hostname, MAXHOSTNAMELEN, 1) != 0)
265*da6c28aaSamw 		return (-1);
266*da6c28aaSamw 
267*da6c28aaSamw 	tmp = strchr(name, '\\');
268*da6c28aaSamw 	if (tmp != 0) {
269*da6c28aaSamw 		*tmp = 0;
270*da6c28aaSamw 		if (strcasecmp(name, hostname) == 0)
271*da6c28aaSamw 			local_lookup = 1;
272*da6c28aaSamw 
273*da6c28aaSamw 		if (!local_lookup) {
274*da6c28aaSamw 			addr = inet_addr(name);
275*da6c28aaSamw 			if (smb_nic_get_byip(addr, &cfg) != NULL) {
276*da6c28aaSamw 				local_lookup = 1;
277*da6c28aaSamw 			}
278*da6c28aaSamw 		}
279*da6c28aaSamw 
280*da6c28aaSamw 		if (!local_lookup) {
281*da6c28aaSamw 			/* do domain lookup */
282*da6c28aaSamw 			*tmp = '\\';
283*da6c28aaSamw 			return (1);
284*da6c28aaSamw 		}
285*da6c28aaSamw 
286*da6c28aaSamw 		name = tmp + 1;
287*da6c28aaSamw 		local_lookup = 1;
288*da6c28aaSamw 	}
289*da6c28aaSamw 
290*da6c28aaSamw 	res = lsa_lookup_builtin_name(name, user_info);
291*da6c28aaSamw 	if (res != 0)
292*da6c28aaSamw 		res = lsa_lookup_local_sam(hostname, name, user_info);
293*da6c28aaSamw 
294*da6c28aaSamw 	if (res == 0)
295*da6c28aaSamw 		return (0);
296*da6c28aaSamw 
297*da6c28aaSamw 	if (local_lookup)
298*da6c28aaSamw 		return (-1);
299*da6c28aaSamw 
300*da6c28aaSamw 	return (1);
301*da6c28aaSamw }
302*da6c28aaSamw 
303*da6c28aaSamw /*
304*da6c28aaSamw  * lsa_lookup_name
305*da6c28aaSamw  *
306*da6c28aaSamw  * Lookup a name on the specified server (domain controller) and obtain
307*da6c28aaSamw  * the appropriate SID. The information is returned in the user_info
308*da6c28aaSamw  * structure. The caller is responsible for allocating and releasing
309*da6c28aaSamw  * this structure. On success sid_name_use will be set to indicate the
310*da6c28aaSamw  * type of SID. If the name is the domain name, this function will be
311*da6c28aaSamw  * identical to lsa_domain_info. Otherwise the rid and name fields will
312*da6c28aaSamw  * also be valid. On failure sid_name_use will be set to SidTypeUnknown.
313*da6c28aaSamw  *
314*da6c28aaSamw  * On success 0 is returned. Otherwise a -ve error code.
315*da6c28aaSamw  */
316*da6c28aaSamw int lsa_lookup_name(char *server, char *domain, char *account_name,
317*da6c28aaSamw     smb_userinfo_t *user_info)
318*da6c28aaSamw {
319*da6c28aaSamw 	mlsvc_handle_t domain_handle;
320*da6c28aaSamw 	int rc;
321*da6c28aaSamw 
322*da6c28aaSamw 	rc = lsar_open(MLSVC_IPC_ANON, server, domain, 0, 0, &domain_handle);
323*da6c28aaSamw 	if (rc != 0)
324*da6c28aaSamw 		return (-1);
325*da6c28aaSamw 
326*da6c28aaSamw 	rc = lsar_lookup_names(&domain_handle, account_name, user_info);
327*da6c28aaSamw 
328*da6c28aaSamw 	(void) lsar_close(&domain_handle);
329*da6c28aaSamw 	return (rc);
330*da6c28aaSamw }
331*da6c28aaSamw 
332*da6c28aaSamw /*
333*da6c28aaSamw  * lsa_lookup_name2
334*da6c28aaSamw  *
335*da6c28aaSamw  * Returns NT status codes.
336*da6c28aaSamw  */
337*da6c28aaSamw DWORD lsa_lookup_name2(char *server, char *domain, char *account_name,
338*da6c28aaSamw     smb_userinfo_t *user_info)
339*da6c28aaSamw {
340*da6c28aaSamw 	mlsvc_handle_t domain_handle;
341*da6c28aaSamw 	DWORD status;
342*da6c28aaSamw 	int rc;
343*da6c28aaSamw 
344*da6c28aaSamw 	rc = lsar_open(MLSVC_IPC_ANON, server, domain, 0, 0, &domain_handle);
345*da6c28aaSamw 	if (rc != 0)
346*da6c28aaSamw 		return (NT_STATUS_INVALID_PARAMETER);
347*da6c28aaSamw 
348*da6c28aaSamw 	status = lsar_lookup_names2(&domain_handle, account_name, user_info);
349*da6c28aaSamw 	if (status == NT_STATUS_REVISION_MISMATCH) {
350*da6c28aaSamw 		/*
351*da6c28aaSamw 		 * Not a Windows 2000 domain controller:
352*da6c28aaSamw 		 * use the NT compatible call.
353*da6c28aaSamw 		 */
354*da6c28aaSamw 		if (lsar_lookup_names(&domain_handle, account_name,
355*da6c28aaSamw 		    user_info) != 0)
356*da6c28aaSamw 			status = NT_STATUS_NONE_MAPPED;
357*da6c28aaSamw 		else
358*da6c28aaSamw 			status = 0;
359*da6c28aaSamw 	}
360*da6c28aaSamw 
361*da6c28aaSamw 	(void) lsar_close(&domain_handle);
362*da6c28aaSamw 	return (status);
363*da6c28aaSamw }
364*da6c28aaSamw 
365*da6c28aaSamw /*
366*da6c28aaSamw  * lsa_lookup_sid
367*da6c28aaSamw  *
368*da6c28aaSamw  * Lookup a SID on the specified server (domain controller) and obtain
369*da6c28aaSamw  * the appropriate name. The information is returned in the user_info
370*da6c28aaSamw  * structure. The caller is responsible for allocating and releasing
371*da6c28aaSamw  * this structure. On success sid_name_use will be set to indicate the
372*da6c28aaSamw  * type of SID. On failure sid_name_use will be set to SidTypeUnknown.
373*da6c28aaSamw  *
374*da6c28aaSamw  * On success 0 is returned. Otherwise a -ve error code.
375*da6c28aaSamw  */
376*da6c28aaSamw int
377*da6c28aaSamw lsa_lookup_sid(nt_sid_t *sid, smb_userinfo_t *user_info)
378*da6c28aaSamw {
379*da6c28aaSamw 	mlsvc_handle_t domain_handle;
380*da6c28aaSamw 	int rc;
381*da6c28aaSamw 
382*da6c28aaSamw 	rc = lsar_open(MLSVC_IPC_ANON, 0, 0, 0, 0, &domain_handle);
383*da6c28aaSamw 	if (rc != 0)
384*da6c28aaSamw 		return (-1);
385*da6c28aaSamw 
386*da6c28aaSamw 	rc = lsar_lookup_sids(&domain_handle,
387*da6c28aaSamw 	    (struct mslsa_sid *)sid, user_info);
388*da6c28aaSamw 
389*da6c28aaSamw 	(void) lsar_close(&domain_handle);
390*da6c28aaSamw 	return (rc);
391*da6c28aaSamw }
392*da6c28aaSamw 
393*da6c28aaSamw /*
394*da6c28aaSamw  * lsa_lookup_sid2
395*da6c28aaSamw  *
396*da6c28aaSamw  * Returns NT status codes.
397*da6c28aaSamw  */
398*da6c28aaSamw DWORD
399*da6c28aaSamw lsa_lookup_sid2(nt_sid_t *sid, smb_userinfo_t *user_info)
400*da6c28aaSamw {
401*da6c28aaSamw 	mlsvc_handle_t domain_handle;
402*da6c28aaSamw 	DWORD status;
403*da6c28aaSamw 	int rc;
404*da6c28aaSamw 
405*da6c28aaSamw 	rc = lsar_open(MLSVC_IPC_ANON, 0, 0, 0, 0, &domain_handle);
406*da6c28aaSamw 	if (rc != 0)
407*da6c28aaSamw 		return (NT_STATUS_INVALID_PARAMETER);
408*da6c28aaSamw 
409*da6c28aaSamw 	status = lsar_lookup_sids2(&domain_handle,
410*da6c28aaSamw 	    (struct mslsa_sid *)sid, user_info);
411*da6c28aaSamw 
412*da6c28aaSamw 	if (status == NT_STATUS_REVISION_MISMATCH) {
413*da6c28aaSamw 		/*
414*da6c28aaSamw 		 * Not a Windows 2000 domain controller:
415*da6c28aaSamw 		 * use the NT compatible call.
416*da6c28aaSamw 		 */
417*da6c28aaSamw 		if (lsar_lookup_sids(&domain_handle, (struct mslsa_sid *)sid,
418*da6c28aaSamw 		    user_info) != 0)
419*da6c28aaSamw 			status = NT_STATUS_NONE_MAPPED;
420*da6c28aaSamw 		else
421*da6c28aaSamw 			status = 0;
422*da6c28aaSamw 	}
423*da6c28aaSamw 
424*da6c28aaSamw 	(void) lsar_close(&domain_handle);
425*da6c28aaSamw 	return (status);
426*da6c28aaSamw }
427*da6c28aaSamw 
428*da6c28aaSamw /*
429*da6c28aaSamw  * lsa_test_lookup2
430*da6c28aaSamw  *
431*da6c28aaSamw  * Test routine for lsa_lookup_name2 and lsa_lookup_sid2.
432*da6c28aaSamw  */
433*da6c28aaSamw void
434*da6c28aaSamw lsa_test_lookup2(char *name)
435*da6c28aaSamw {
436*da6c28aaSamw 	smb_userinfo_t *user_info;
437*da6c28aaSamw 	nt_sid_t *sid;
438*da6c28aaSamw 	DWORD status;
439*da6c28aaSamw 	smb_ntdomain_t *di;
440*da6c28aaSamw 
441*da6c28aaSamw 	if ((di = smb_getdomaininfo(0)) == 0)
442*da6c28aaSamw 		return;
443*da6c28aaSamw 
444*da6c28aaSamw 	user_info = mlsvc_alloc_user_info();
445*da6c28aaSamw 
446*da6c28aaSamw 	if (lsa_lookup_builtin_name(name, user_info) != 0) {
447*da6c28aaSamw 		status = lsa_lookup_name2(di->server, di->domain, name,
448*da6c28aaSamw 		    user_info);
449*da6c28aaSamw 
450*da6c28aaSamw 		if (status == 0) {
451*da6c28aaSamw 			sid = nt_sid_splice(user_info->domain_sid,
452*da6c28aaSamw 			    user_info->rid);
453*da6c28aaSamw 
454*da6c28aaSamw 			(void) lsa_lookup_sid2(sid, user_info);
455*da6c28aaSamw 			free(sid);
456*da6c28aaSamw 		}
457*da6c28aaSamw 	}
458*da6c28aaSamw 
459*da6c28aaSamw 	mlsvc_free_user_info(user_info);
460*da6c28aaSamw }
461*da6c28aaSamw 
462*da6c28aaSamw /*
463*da6c28aaSamw  * lsa_lookup_privs
464*da6c28aaSamw  *
465*da6c28aaSamw  * Request the privileges associated with the specified account. In
466*da6c28aaSamw  * order to get the privileges, we first have to lookup the name on
467*da6c28aaSamw  * the specified domain controller and obtain the appropriate SID.
468*da6c28aaSamw  * The SID can then be used to open the account and obtain the
469*da6c28aaSamw  * account privileges. The results from both the name lookup and the
470*da6c28aaSamw  * privileges are returned in the user_info structure. The caller is
471*da6c28aaSamw  * responsible for allocating and releasing this structure.
472*da6c28aaSamw  *
473*da6c28aaSamw  * On success 0 is returned. Otherwise a -ve error code.
474*da6c28aaSamw  */
475*da6c28aaSamw /*ARGSUSED*/
476*da6c28aaSamw int
477*da6c28aaSamw lsa_lookup_privs(char *server, char *account_name, char *target_name,
478*da6c28aaSamw     smb_userinfo_t *user_info)
479*da6c28aaSamw {
480*da6c28aaSamw 	mlsvc_handle_t domain_handle;
481*da6c28aaSamw 	int rc;
482*da6c28aaSamw #if 0
483*da6c28aaSamw 	mlsvc_handle_t account_handle;
484*da6c28aaSamw 	struct mslsa_sid *sid;
485*da6c28aaSamw 
486*da6c28aaSamw 	lsa_lookup_name(0, 0, target_name, user_info);
487*da6c28aaSamw 
488*da6c28aaSamw 	sid = (struct mslsa_sid *)
489*da6c28aaSamw 	    nt_sid_splice(user_info->domain_sid, user_info->rid);
490*da6c28aaSamw 
491*da6c28aaSamw 	lsa_lookup_sid(server, account_name, (nt_sid_t *)sid, user_info);
492*da6c28aaSamw #endif
493*da6c28aaSamw 	if ((lsar_open(MLSVC_IPC_ANON, 0, 0, 0, 0, &domain_handle)) != 0)
494*da6c28aaSamw 		return (-1);
495*da6c28aaSamw 
496*da6c28aaSamw 	rc = lsa_list_accounts(&domain_handle);
497*da6c28aaSamw #if 0
498*da6c28aaSamw 	rc = lsar_open_account(&domain_handle, sid, &account_handle);
499*da6c28aaSamw 	if (rc == 0) {
500*da6c28aaSamw 		(void) lsar_enum_privs_account(&account_handle, user_info);
501*da6c28aaSamw 		(void) lsar_close(&account_handle);
502*da6c28aaSamw 	}
503*da6c28aaSamw 
504*da6c28aaSamw 	free(sid);
505*da6c28aaSamw #endif
506*da6c28aaSamw 	(void) lsar_close(&domain_handle);
507*da6c28aaSamw 	return (rc);
508*da6c28aaSamw }
509*da6c28aaSamw 
510*da6c28aaSamw /*
511*da6c28aaSamw  * lsa_list_privs
512*da6c28aaSamw  *
513*da6c28aaSamw  * List the privileges supported by the specified server.
514*da6c28aaSamw  * This function is only intended for diagnostics.
515*da6c28aaSamw  *
516*da6c28aaSamw  * Returns NT status codes.
517*da6c28aaSamw  */
518*da6c28aaSamw DWORD
519*da6c28aaSamw lsa_list_privs(char *server, char *domain)
520*da6c28aaSamw {
521*da6c28aaSamw 	static char name[128];
522*da6c28aaSamw 	static struct ms_luid luid;
523*da6c28aaSamw 	mlsvc_handle_t domain_handle;
524*da6c28aaSamw 	int rc;
525*da6c28aaSamw 	int i;
526*da6c28aaSamw 
527*da6c28aaSamw 	rc = lsar_open(MLSVC_IPC_ANON, server, domain, 0, 0, &domain_handle);
528*da6c28aaSamw 	if (rc != 0)
529*da6c28aaSamw 		return (NT_STATUS_INVALID_PARAMETER);
530*da6c28aaSamw 
531*da6c28aaSamw 	for (i = 0; i < 30; ++i) {
532*da6c28aaSamw 		luid.low_part = i;
533*da6c28aaSamw 		rc = lsar_lookup_priv_name(&domain_handle, &luid, name, 128);
534*da6c28aaSamw 		if (rc != 0)
535*da6c28aaSamw 			continue;
536*da6c28aaSamw 
537*da6c28aaSamw 		(void) lsar_lookup_priv_value(&domain_handle, name, &luid);
538*da6c28aaSamw 		(void) lsar_lookup_priv_display_name(&domain_handle, name,
539*da6c28aaSamw 		    name, 128);
540*da6c28aaSamw 	}
541*da6c28aaSamw 
542*da6c28aaSamw 	(void) lsar_close(&domain_handle);
543*da6c28aaSamw 	return (NT_STATUS_SUCCESS);
544*da6c28aaSamw }
545*da6c28aaSamw 
546*da6c28aaSamw /*
547*da6c28aaSamw  * lsa_test
548*da6c28aaSamw  *
549*da6c28aaSamw  * LSA test routine: open and close the LSA interface.
550*da6c28aaSamw  * TBD: the parameters should be server and domain.
551*da6c28aaSamw  *
552*da6c28aaSamw  * On success 0 is returned. Otherwise a -ve error code.
553*da6c28aaSamw  */
554*da6c28aaSamw /*ARGSUSED*/
555*da6c28aaSamw int
556*da6c28aaSamw lsa_test(char *server, char *account_name)
557*da6c28aaSamw {
558*da6c28aaSamw 	mlsvc_handle_t domain_handle;
559*da6c28aaSamw 	int rc;
560*da6c28aaSamw 
561*da6c28aaSamw 	rc = lsar_open(MLSVC_IPC_ANON, 0, 0, 0, 0, &domain_handle);
562*da6c28aaSamw 	if (rc != 0)
563*da6c28aaSamw 		return (-1);
564*da6c28aaSamw 
565*da6c28aaSamw 	if (lsar_close(&domain_handle) != 0)
566*da6c28aaSamw 		return (-1);
567*da6c28aaSamw 
568*da6c28aaSamw 	return (0);
569*da6c28aaSamw }
570*da6c28aaSamw 
571*da6c28aaSamw /*
572*da6c28aaSamw  * lsa_list_accounts
573*da6c28aaSamw  *
574*da6c28aaSamw  * This function can be used to list the accounts in the specified
575*da6c28aaSamw  * domain. For now the SIDs are just listed in the system log.
576*da6c28aaSamw  *
577*da6c28aaSamw  * On success 0 is returned. Otherwise a -ve error code.
578*da6c28aaSamw  */
579*da6c28aaSamw static int
580*da6c28aaSamw lsa_list_accounts(mlsvc_handle_t *domain_handle)
581*da6c28aaSamw {
582*da6c28aaSamw 	mlsvc_handle_t account_handle;
583*da6c28aaSamw 	struct mslsa_EnumAccountBuf accounts;
584*da6c28aaSamw 	struct mslsa_sid *sid;
585*da6c28aaSamw 	char *name;
586*da6c28aaSamw 	WORD sid_name_use;
587*da6c28aaSamw 	smb_userinfo_t *user_info;
588*da6c28aaSamw 	DWORD enum_context = 0;
589*da6c28aaSamw 	int rc;
590*da6c28aaSamw 	int i;
591*da6c28aaSamw 
592*da6c28aaSamw 	user_info = mlsvc_alloc_user_info();
593*da6c28aaSamw 	bzero(&accounts, sizeof (struct mslsa_EnumAccountBuf));
594*da6c28aaSamw 
595*da6c28aaSamw 	do {
596*da6c28aaSamw 		rc = lsar_enum_accounts(domain_handle, &enum_context,
597*da6c28aaSamw 		    &accounts);
598*da6c28aaSamw 		if (rc != 0)
599*da6c28aaSamw 			return (rc);
600*da6c28aaSamw 
601*da6c28aaSamw 		for (i = 0; i < accounts.entries_read; ++i) {
602*da6c28aaSamw 			sid = accounts.info[i].sid;
603*da6c28aaSamw 
604*da6c28aaSamw 			name = nt_builtin_lookup_sid((nt_sid_t *)sid,
605*da6c28aaSamw 			    &sid_name_use);
606*da6c28aaSamw 
607*da6c28aaSamw 			if (name == 0) {
608*da6c28aaSamw 				if (lsar_lookup_sids(domain_handle, sid,
609*da6c28aaSamw 				    user_info) == 0) {
610*da6c28aaSamw 					name = user_info->name;
611*da6c28aaSamw 					sid_name_use = user_info->sid_name_use;
612*da6c28aaSamw 				} else {
613*da6c28aaSamw 					name = "unknown";
614*da6c28aaSamw 					sid_name_use = SidTypeUnknown;
615*da6c28aaSamw 				}
616*da6c28aaSamw 			}
617*da6c28aaSamw 
618*da6c28aaSamw 			nt_sid_logf((nt_sid_t *)sid);
619*da6c28aaSamw 
620*da6c28aaSamw 			if (lsar_open_account(domain_handle, sid,
621*da6c28aaSamw 			    &account_handle) == 0) {
622*da6c28aaSamw 				(void) lsar_enum_privs_account(&account_handle,
623*da6c28aaSamw 				    user_info);
624*da6c28aaSamw 				(void) lsar_close(&account_handle);
625*da6c28aaSamw 			}
626*da6c28aaSamw 
627*da6c28aaSamw 			free(accounts.info[i].sid);
628*da6c28aaSamw 			mlsvc_release_user_info(user_info);
629*da6c28aaSamw 		}
630*da6c28aaSamw 
631*da6c28aaSamw 		if (accounts.info)
632*da6c28aaSamw 			free(accounts.info);
633*da6c28aaSamw 	} while (rc == 0 && accounts.entries_read != 0);
634*da6c28aaSamw 
635*da6c28aaSamw 	mlsvc_free_user_info(user_info);
636*da6c28aaSamw 	return (0);
637*da6c28aaSamw }
638