xref: /titanic_50/usr/src/lib/smbsrv/libmlsvc/common/lsar_clnt.c (revision b3700b074e637f8c6991b70754c88a2cfffb246b)
1fe1c642dSBill Krier /*
2fe1c642dSBill Krier  * CDDL HEADER START
3fe1c642dSBill Krier  *
4fe1c642dSBill Krier  * The contents of this file are subject to the terms of the
5fe1c642dSBill Krier  * Common Development and Distribution License (the "License").
6fe1c642dSBill Krier  * You may not use this file except in compliance with the License.
7fe1c642dSBill Krier  *
8fe1c642dSBill Krier  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fe1c642dSBill Krier  * or http://www.opensolaris.org/os/licensing.
10fe1c642dSBill Krier  * See the License for the specific language governing permissions
11fe1c642dSBill Krier  * and limitations under the License.
12fe1c642dSBill Krier  *
13fe1c642dSBill Krier  * When distributing Covered Code, include this CDDL HEADER in each
14fe1c642dSBill Krier  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fe1c642dSBill Krier  * If applicable, add the following below this CDDL HEADER, with the
16fe1c642dSBill Krier  * fields enclosed by brackets "[]" replaced with your own identifying
17fe1c642dSBill Krier  * information: Portions Copyright [yyyy] [name of copyright owner]
18fe1c642dSBill Krier  *
19fe1c642dSBill Krier  * CDDL HEADER END
20fe1c642dSBill Krier  */
21148c5f43SAlan Wright 
22fe1c642dSBill Krier /*
23148c5f43SAlan Wright  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24*b3700b07SGordon Ross  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
25fe1c642dSBill Krier  */
26fe1c642dSBill Krier 
27fe1c642dSBill Krier /*
28fe1c642dSBill Krier  * Local Security Authority RPC (LSAR) client-side interface.
29fe1c642dSBill Krier  */
30fe1c642dSBill Krier 
31fe1c642dSBill Krier #include <sys/errno.h>
32fe1c642dSBill Krier #include <stdio.h>
33fe1c642dSBill Krier #include <stdlib.h>
34fe1c642dSBill Krier #include <strings.h>
35fe1c642dSBill Krier 
36fe1c642dSBill Krier #include <smbsrv/libsmb.h>
37fe1c642dSBill Krier #include <smbsrv/libmlsvc.h>
38fe1c642dSBill Krier #include <smbsrv/smbinfo.h>
39fe1c642dSBill Krier #include <smbsrv/ntaccess.h>
40fe1c642dSBill Krier #include <smbsrv/ntlocale.h>
41fe1c642dSBill Krier #include <smbsrv/string.h>
42fe1c642dSBill Krier #include <lsalib.h>
43fe1c642dSBill Krier 
44fe1c642dSBill Krier /*
45fe1c642dSBill Krier  * The maximum number of bytes we are prepared to deal with in a
46fe1c642dSBill Krier  * response.
47fe1c642dSBill Krier  */
48fe1c642dSBill Krier #define	MLSVC_MAX_RESPONSE_LEN		1024
49fe1c642dSBill Krier 
50fe1c642dSBill Krier /*
51fe1c642dSBill Krier  * This structure is used when looking up names. We only lookup one
52fe1c642dSBill Krier  * name at a time but the structure will allow for more.
53fe1c642dSBill Krier  */
54fe1c642dSBill Krier typedef struct lsa_names {
55fe1c642dSBill Krier 	uint32_t	n_entry;
56fe1c642dSBill Krier 	mslsa_string_t	name[8];
57fe1c642dSBill Krier } lsa_names_t;
58fe1c642dSBill Krier 
59fe1c642dSBill Krier typedef DWORD (*lsar_nameop_t)(mlsvc_handle_t *, lsa_names_t *,
60fe1c642dSBill Krier     smb_account_t *);
61fe1c642dSBill Krier 
62fe1c642dSBill Krier static uint32_t lsar_lookup_names1(mlsvc_handle_t *, lsa_names_t *,
63fe1c642dSBill Krier     smb_account_t *);
64fe1c642dSBill Krier static uint32_t lsar_lookup_names2(mlsvc_handle_t *, lsa_names_t *,
65fe1c642dSBill Krier     smb_account_t *);
66fe1c642dSBill Krier static uint32_t lsar_lookup_names3(mlsvc_handle_t *, lsa_names_t *,
67fe1c642dSBill Krier     smb_account_t *);
68fe1c642dSBill Krier static uint32_t lsar_lookup_sids1(mlsvc_handle_t *, lsa_sid_t *,
69fe1c642dSBill Krier     smb_account_t *);
70fe1c642dSBill Krier static uint32_t lsar_lookup_sids2(mlsvc_handle_t *, lsa_sid_t *,
71fe1c642dSBill Krier     smb_account_t *account);
72fe1c642dSBill Krier 
73fe1c642dSBill Krier static char *lsar_get_username(const char *);
74fe1c642dSBill Krier static void smb_account_trace(const smb_account_t *);
75fe1c642dSBill Krier 
76fe1c642dSBill Krier static void lsar_set_trusted_domains_ex(struct mslsa_EnumTrustedDomainBufEx *,
77fe1c642dSBill Krier     smb_trusted_domains_t *);
78fe1c642dSBill Krier static void lsar_set_trusted_domains(struct mslsa_EnumTrustedDomainBuf *,
79fe1c642dSBill Krier     smb_trusted_domains_t *);
80fe1c642dSBill Krier 
81fe1c642dSBill Krier /*
82fe1c642dSBill Krier  * lsar_open
83fe1c642dSBill Krier  *
84fe1c642dSBill Krier  * This is a wrapper round lsar_open_policy2 to ensure that we connect
85fe1c642dSBill Krier  * using the appropriate domain information.
86fe1c642dSBill Krier  *
87fe1c642dSBill Krier  * If username argument is NULL, an anonymous connection will be established.
88fe1c642dSBill Krier  * Otherwise, an authenticated connection will be established.
89fe1c642dSBill Krier  *
90*b3700b07SGordon Ross  * Returns 0 or NT status (Raw, not LSA-ized)
91fe1c642dSBill Krier  */
92*b3700b07SGordon Ross DWORD
lsar_open(char * server,char * domain,char * username,mlsvc_handle_t * domain_handle)931ed6b69aSGordon Ross lsar_open(char *server, char *domain, char *username,
94fe1c642dSBill Krier     mlsvc_handle_t *domain_handle)
95fe1c642dSBill Krier {
96*b3700b07SGordon Ross 	DWORD status;
97*b3700b07SGordon Ross 
98fe1c642dSBill Krier 	if (server == NULL || domain == NULL)
99*b3700b07SGordon Ross 		return (NT_STATUS_INTERNAL_ERROR);
100fe1c642dSBill Krier 
101fe1c642dSBill Krier 	if (username == NULL)
102fe1c642dSBill Krier 		username = MLSVC_ANON_USER;
103fe1c642dSBill Krier 
104*b3700b07SGordon Ross 	status = lsar_open_policy2(server, domain, username, domain_handle);
105*b3700b07SGordon Ross 
106*b3700b07SGordon Ross 	return (status);
107fe1c642dSBill Krier }
108fe1c642dSBill Krier 
109fe1c642dSBill Krier /*
110fe1c642dSBill Krier  * lsar_open_policy2
111fe1c642dSBill Krier  *
112fe1c642dSBill Krier  * Obtain an LSA policy handle. A policy handle is required to access
113fe1c642dSBill Krier  * LSA resources on a remote server. The server name supplied here does
114fe1c642dSBill Krier  * not need the double backslash prefix; it is added here. Call this
115fe1c642dSBill Krier  * function via lsar_open to ensure that the appropriate connection is
116fe1c642dSBill Krier  * in place.
117fe1c642dSBill Krier  *
118*b3700b07SGordon Ross  * Returns 0 or NT status (Raw, not LSA-ized)
119fe1c642dSBill Krier  */
120*b3700b07SGordon Ross DWORD
lsar_open_policy2(char * server,char * domain,char * user,mlsvc_handle_t * lsa_handle)121*b3700b07SGordon Ross lsar_open_policy2(char *server, char *domain, char *user,
122fe1c642dSBill Krier     mlsvc_handle_t *lsa_handle)
123fe1c642dSBill Krier {
124fe1c642dSBill Krier 	struct mslsa_OpenPolicy2 arg;
125*b3700b07SGordon Ross 	DWORD status;
126fe1c642dSBill Krier 	int opnum;
127fe1c642dSBill Krier 	int len;
128fe1c642dSBill Krier 
129*b3700b07SGordon Ross 	status = ndr_rpc_bind(lsa_handle, server, domain, user, "LSARPC");
130*b3700b07SGordon Ross 	if (status != 0)
131*b3700b07SGordon Ross 		return (status);
132fe1c642dSBill Krier 
133fe1c642dSBill Krier 	opnum = LSARPC_OPNUM_OpenPolicy2;
134fe1c642dSBill Krier 	bzero(&arg, sizeof (struct mslsa_OpenPolicy2));
135fe1c642dSBill Krier 
136fe1c642dSBill Krier 	len = strlen(server) + 4;
137fe1c642dSBill Krier 	arg.servername = ndr_rpc_malloc(lsa_handle, len);
138fe1c642dSBill Krier 	if (arg.servername == NULL) {
139*b3700b07SGordon Ross 		status = NT_STATUS_NO_MEMORY;
140*b3700b07SGordon Ross 		goto out;
141fe1c642dSBill Krier 	}
142fe1c642dSBill Krier 
143fe1c642dSBill Krier 	(void) snprintf((char *)arg.servername, len, "\\\\%s", server);
144fe1c642dSBill Krier 	arg.attributes.length = sizeof (struct mslsa_object_attributes);
145fe1c642dSBill Krier 	arg.desiredAccess = MAXIMUM_ALLOWED;
146fe1c642dSBill Krier 
147*b3700b07SGordon Ross 	if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
148*b3700b07SGordon Ross 		status = RPC_NT_CALL_FAILED;
149*b3700b07SGordon Ross 		goto out;
150fe1c642dSBill Krier 	}
151*b3700b07SGordon Ross 	status = arg.status;
152*b3700b07SGordon Ross 	if (status == NT_STATUS_SUCCESS) {
153fe1c642dSBill Krier 		(void) memcpy(&lsa_handle->handle, &arg.domain_handle,
154fe1c642dSBill Krier 		    sizeof (ndr_hdid_t));
155fe1c642dSBill Krier 
156fe1c642dSBill Krier 		if (ndr_is_null_handle(lsa_handle))
157*b3700b07SGordon Ross 			status = NT_STATUS_INVALID_PARAMETER;
158fe1c642dSBill Krier 	}
159fe1c642dSBill Krier 
160fe1c642dSBill Krier 	ndr_rpc_release(lsa_handle);
161fe1c642dSBill Krier 
162*b3700b07SGordon Ross out:
163*b3700b07SGordon Ross 	if (status != NT_STATUS_SUCCESS)
164fe1c642dSBill Krier 		ndr_rpc_unbind(lsa_handle);
165*b3700b07SGordon Ross 	return (status);
166fe1c642dSBill Krier }
167fe1c642dSBill Krier 
168fe1c642dSBill Krier /*
169fe1c642dSBill Krier  * lsar_open_account
170fe1c642dSBill Krier  *
171fe1c642dSBill Krier  * Obtain an LSA account handle. The lsa_handle must be a valid handle
172fe1c642dSBill Krier  * obtained via lsar_open_policy2. The main thing to remember here is
173fe1c642dSBill Krier  * to set up the context in the lsa_account_handle. I'm not sure what
174fe1c642dSBill Krier  * the requirements are for desired access. Some values require admin
175fe1c642dSBill Krier  * access.
176fe1c642dSBill Krier  *
177fe1c642dSBill Krier  * Returns 0 on success. Otherwise non-zero to indicate a failure.
178fe1c642dSBill Krier  */
179fe1c642dSBill Krier int
lsar_open_account(mlsvc_handle_t * lsa_handle,struct mslsa_sid * sid,mlsvc_handle_t * lsa_account_handle)180fe1c642dSBill Krier lsar_open_account(mlsvc_handle_t *lsa_handle, struct mslsa_sid *sid,
181fe1c642dSBill Krier     mlsvc_handle_t *lsa_account_handle)
182fe1c642dSBill Krier {
183fe1c642dSBill Krier 	struct mslsa_OpenAccount arg;
184fe1c642dSBill Krier 	int opnum;
185fe1c642dSBill Krier 	int rc;
186fe1c642dSBill Krier 
187fe1c642dSBill Krier 	if (ndr_is_null_handle(lsa_handle) || sid == NULL)
188fe1c642dSBill Krier 		return (-1);
189fe1c642dSBill Krier 
190fe1c642dSBill Krier 	opnum = LSARPC_OPNUM_OpenAccount;
191fe1c642dSBill Krier 	bzero(&arg, sizeof (struct mslsa_OpenAccount));
192fe1c642dSBill Krier 
193fe1c642dSBill Krier 	(void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
194fe1c642dSBill Krier 	arg.sid = sid;
195fe1c642dSBill Krier 	arg.access_mask = STANDARD_RIGHTS_REQUIRED
196fe1c642dSBill Krier #if 0
197fe1c642dSBill Krier 	    | POLICY_VIEW_AUDIT_INFORMATION
198fe1c642dSBill Krier 	    | POLICY_GET_PRIVATE_INFORMATION
199fe1c642dSBill Krier 	    | POLICY_TRUST_ADMIN
200fe1c642dSBill Krier #endif
201fe1c642dSBill Krier 	    | POLICY_VIEW_LOCAL_INFORMATION;
202fe1c642dSBill Krier 
203fe1c642dSBill Krier 	if ((rc = ndr_rpc_call(lsa_handle, opnum, &arg)) != 0)
204fe1c642dSBill Krier 		return (-1);
205fe1c642dSBill Krier 
206fe1c642dSBill Krier 	if (arg.status != 0) {
207fe1c642dSBill Krier 		rc = -1;
208fe1c642dSBill Krier 	} else {
209fe1c642dSBill Krier 		ndr_inherit_handle(lsa_account_handle, lsa_handle);
210fe1c642dSBill Krier 
211fe1c642dSBill Krier 		(void) memcpy(&lsa_account_handle->handle,
212fe1c642dSBill Krier 		    &arg.account_handle, sizeof (ndr_hdid_t));
213fe1c642dSBill Krier 
214fe1c642dSBill Krier 		if (ndr_is_null_handle(lsa_account_handle))
215fe1c642dSBill Krier 			rc = -1;
216fe1c642dSBill Krier 	}
217fe1c642dSBill Krier 
218fe1c642dSBill Krier 	ndr_rpc_release(lsa_handle);
219fe1c642dSBill Krier 	return (rc);
220fe1c642dSBill Krier }
221fe1c642dSBill Krier 
222fe1c642dSBill Krier /*
223fe1c642dSBill Krier  * lsar_close
224fe1c642dSBill Krier  *
225fe1c642dSBill Krier  * Close the LSA connection associated with the handle. The lsa_handle
226fe1c642dSBill Krier  * must be a valid handle obtained via a call to lsar_open_policy2 or
227fe1c642dSBill Krier  * lsar_open_account. On success the handle will be zeroed out to
228fe1c642dSBill Krier  * ensure that it is not used again. If this is the top level handle
229fe1c642dSBill Krier  * (i.e. the one obtained via lsar_open_policy2) the pipe is closed.
230fe1c642dSBill Krier  *
231fe1c642dSBill Krier  * Returns 0 on success. Otherwise non-zero to indicate a failure.
232fe1c642dSBill Krier  */
233fe1c642dSBill Krier int
lsar_close(mlsvc_handle_t * lsa_handle)234fe1c642dSBill Krier lsar_close(mlsvc_handle_t *lsa_handle)
235fe1c642dSBill Krier {
236fe1c642dSBill Krier 	struct mslsa_CloseHandle arg;
237fe1c642dSBill Krier 	int opnum;
238fe1c642dSBill Krier 
239fe1c642dSBill Krier 	if (ndr_is_null_handle(lsa_handle))
240fe1c642dSBill Krier 		return (-1);
241fe1c642dSBill Krier 
242fe1c642dSBill Krier 	opnum = LSARPC_OPNUM_CloseHandle;
243fe1c642dSBill Krier 	bzero(&arg, sizeof (struct mslsa_CloseHandle));
244fe1c642dSBill Krier 	(void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
245fe1c642dSBill Krier 
246fe1c642dSBill Krier 	(void) ndr_rpc_call(lsa_handle, opnum, &arg);
247fe1c642dSBill Krier 	ndr_rpc_release(lsa_handle);
248fe1c642dSBill Krier 
249fe1c642dSBill Krier 	if (ndr_is_bind_handle(lsa_handle))
250fe1c642dSBill Krier 		ndr_rpc_unbind(lsa_handle);
251fe1c642dSBill Krier 
252fe1c642dSBill Krier 	bzero(lsa_handle, sizeof (mlsvc_handle_t));
253fe1c642dSBill Krier 	return (0);
254fe1c642dSBill Krier }
255fe1c642dSBill Krier 
256fe1c642dSBill Krier /*
257fe1c642dSBill Krier  * lsar_query_security_desc
258fe1c642dSBill Krier  *
259fe1c642dSBill Krier  * Don't use this call yet. It is just a place holder for now.
260fe1c642dSBill Krier  */
261fe1c642dSBill Krier int
lsar_query_security_desc(mlsvc_handle_t * lsa_handle)262fe1c642dSBill Krier lsar_query_security_desc(mlsvc_handle_t *lsa_handle)
263fe1c642dSBill Krier {
264fe1c642dSBill Krier 	struct mslsa_QuerySecurityObject	arg;
265fe1c642dSBill Krier 	int	rc;
266fe1c642dSBill Krier 	int	opnum;
267fe1c642dSBill Krier 
268fe1c642dSBill Krier 	opnum = LSARPC_OPNUM_QuerySecurityObject;
269fe1c642dSBill Krier 
270fe1c642dSBill Krier 	bzero(&arg, sizeof (struct mslsa_QuerySecurityObject));
271fe1c642dSBill Krier 	(void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
272fe1c642dSBill Krier 
273fe1c642dSBill Krier 	rc = ndr_rpc_call(lsa_handle, opnum, &arg);
274fe1c642dSBill Krier 	ndr_rpc_release(lsa_handle);
275fe1c642dSBill Krier 	return (rc);
276fe1c642dSBill Krier }
277fe1c642dSBill Krier 
278fe1c642dSBill Krier /*
279fe1c642dSBill Krier  * lsar_query_info_policy
280fe1c642dSBill Krier  *
281fe1c642dSBill Krier  * The general purpose of this function is to allow various pieces of
282fe1c642dSBill Krier  * information to be queried on the domain controller. The only
283fe1c642dSBill Krier  * information queries supported are MSLSA_POLICY_PRIMARY_DOMAIN_INFO
284fe1c642dSBill Krier  * and MSLSA_POLICY_ACCOUNT_DOMAIN_INFO.
285fe1c642dSBill Krier  *
286fe1c642dSBill Krier  * On success, the return code will be 0 and the user_info structure
287fe1c642dSBill Krier  * will be set up. The sid_name_use field will be set to SidTypeDomain
288fe1c642dSBill Krier  * indicating that the domain name and domain sid fields are vaild. If
289fe1c642dSBill Krier  * the infoClass returned from the server is not one of the supported
290fe1c642dSBill Krier  * values, the sid_name_use willbe set to SidTypeUnknown. If the RPC
291fe1c642dSBill Krier  * fails, a negative error code will be returned, in which case the
292fe1c642dSBill Krier  * user_info will not have been updated.
293fe1c642dSBill Krier  */
294fe1c642dSBill Krier DWORD
lsar_query_info_policy(mlsvc_handle_t * lsa_handle,WORD infoClass,smb_domain_t * info)295fe1c642dSBill Krier lsar_query_info_policy(mlsvc_handle_t *lsa_handle, WORD infoClass,
296fe1c642dSBill Krier     smb_domain_t *info)
297fe1c642dSBill Krier {
298fe1c642dSBill Krier 	struct mslsa_QueryInfoPolicy	arg;
299fe1c642dSBill Krier 	struct mslsa_PrimaryDomainInfo	*pd_info;
300fe1c642dSBill Krier 	struct mslsa_AccountDomainInfo	*ad_info;
301fe1c642dSBill Krier 	struct mslsa_DnsDomainInfo	*dns_info;
302fe1c642dSBill Krier 	char	guid_str[UUID_PRINTABLE_STRING_LENGTH];
303fe1c642dSBill Krier 	char	sidstr[SMB_SID_STRSZ];
304fe1c642dSBill Krier 	int	opnum;
305fe1c642dSBill Krier 	DWORD	status;
306fe1c642dSBill Krier 
307fe1c642dSBill Krier 	if (lsa_handle == NULL || info == NULL)
308fe1c642dSBill Krier 		return (NT_STATUS_INVALID_PARAMETER);
309fe1c642dSBill Krier 
310fe1c642dSBill Krier 	opnum = LSARPC_OPNUM_QueryInfoPolicy;
311fe1c642dSBill Krier 
312fe1c642dSBill Krier 	bzero(info, sizeof (smb_domain_t));
313fe1c642dSBill Krier 	bzero(&arg, sizeof (struct mslsa_QueryInfoPolicy));
314fe1c642dSBill Krier 	(void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
315fe1c642dSBill Krier 
316fe1c642dSBill Krier 	arg.info_class = infoClass;
317fe1c642dSBill Krier 
318fe1c642dSBill Krier 	if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
319fe1c642dSBill Krier 		status = NT_STATUS_INVALID_PARAMETER;
320fe1c642dSBill Krier 	} else if (arg.status != 0) {
321fe1c642dSBill Krier 		ndr_rpc_status(lsa_handle, opnum, arg.status);
322fe1c642dSBill Krier 		status = NT_SC_VALUE(arg.status);
323fe1c642dSBill Krier 	} else {
324fe1c642dSBill Krier 
325fe1c642dSBill Krier 		switch (infoClass) {
326fe1c642dSBill Krier 		case MSLSA_POLICY_PRIMARY_DOMAIN_INFO:
327fe1c642dSBill Krier 			pd_info = &arg.ru.pd_info;
328fe1c642dSBill Krier 
329fe1c642dSBill Krier 			smb_sid_tostr((smb_sid_t *)pd_info->sid, sidstr);
330fe1c642dSBill Krier 			info->di_type = SMB_DOMAIN_PRIMARY;
331fe1c642dSBill Krier 			smb_domain_set_basic_info(sidstr,
332fe1c642dSBill Krier 			    (char *)pd_info->name.str, "", info);
333fe1c642dSBill Krier 
334fe1c642dSBill Krier 			status = NT_STATUS_SUCCESS;
335fe1c642dSBill Krier 			break;
336fe1c642dSBill Krier 
337fe1c642dSBill Krier 		case MSLSA_POLICY_ACCOUNT_DOMAIN_INFO:
338fe1c642dSBill Krier 			ad_info = &arg.ru.ad_info;
339fe1c642dSBill Krier 
340fe1c642dSBill Krier 			smb_sid_tostr((smb_sid_t *)ad_info->sid, sidstr);
341fe1c642dSBill Krier 			info->di_type = SMB_DOMAIN_ACCOUNT;
342fe1c642dSBill Krier 			smb_domain_set_basic_info(sidstr,
343fe1c642dSBill Krier 			    (char *)ad_info->name.str, "", info);
344fe1c642dSBill Krier 
345fe1c642dSBill Krier 			status = NT_STATUS_SUCCESS;
346fe1c642dSBill Krier 			break;
347fe1c642dSBill Krier 
348fe1c642dSBill Krier 		case MSLSA_POLICY_DNS_DOMAIN_INFO:
349fe1c642dSBill Krier 			dns_info = &arg.ru.dns_info;
350fe1c642dSBill Krier 			ndr_uuid_unparse((ndr_uuid_t *)&dns_info->guid,
351fe1c642dSBill Krier 			    guid_str);
352fe1c642dSBill Krier 			smb_sid_tostr((smb_sid_t *)dns_info->sid, sidstr);
353fe1c642dSBill Krier 
354fe1c642dSBill Krier 			info->di_type = SMB_DOMAIN_PRIMARY;
355fe1c642dSBill Krier 			smb_domain_set_dns_info(sidstr,
356fe1c642dSBill Krier 			    (char *)dns_info->nb_domain.str,
357fe1c642dSBill Krier 			    (char *)dns_info->dns_domain.str,
358fe1c642dSBill Krier 			    (char *)dns_info->forest.str,
359fe1c642dSBill Krier 			    guid_str, info);
360fe1c642dSBill Krier 			status = NT_STATUS_SUCCESS;
361fe1c642dSBill Krier 			break;
362fe1c642dSBill Krier 
363fe1c642dSBill Krier 		default:
364fe1c642dSBill Krier 			status = NT_STATUS_INVALID_INFO_CLASS;
365fe1c642dSBill Krier 			break;
366fe1c642dSBill Krier 		}
367fe1c642dSBill Krier 	}
368fe1c642dSBill Krier 
369fe1c642dSBill Krier 	ndr_rpc_release(lsa_handle);
370fe1c642dSBill Krier 	return (status);
371fe1c642dSBill Krier }
372fe1c642dSBill Krier 
373fe1c642dSBill Krier /*
374fe1c642dSBill Krier  * Lookup a name and obtain the sid/rid.
375fe1c642dSBill Krier  * This is a wrapper for the various lookup sid RPCs.
376fe1c642dSBill Krier  */
377fe1c642dSBill Krier uint32_t
lsar_lookup_names(mlsvc_handle_t * lsa_handle,char * name,smb_account_t * info)378fe1c642dSBill Krier lsar_lookup_names(mlsvc_handle_t *lsa_handle, char *name, smb_account_t *info)
379fe1c642dSBill Krier {
380fe1c642dSBill Krier 	static lsar_nameop_t ops[] = {
381fe1c642dSBill Krier 		lsar_lookup_names3,
382fe1c642dSBill Krier 		lsar_lookup_names2,
383fe1c642dSBill Krier 		lsar_lookup_names1
384fe1c642dSBill Krier 	};
385fe1c642dSBill Krier 
386fe1c642dSBill Krier 	const srvsvc_server_info_t	*svinfo;
387fe1c642dSBill Krier 	lsa_names_t	names;
388fe1c642dSBill Krier 	char		*p;
389fe1c642dSBill Krier 	uint32_t	length;
390fe1c642dSBill Krier 	uint32_t	status = NT_STATUS_INVALID_PARAMETER;
391fe1c642dSBill Krier 	int		n_op = (sizeof (ops) / sizeof (ops[0]));
392fe1c642dSBill Krier 	int		i;
393fe1c642dSBill Krier 
394fe1c642dSBill Krier 	if (lsa_handle == NULL || name == NULL || info == NULL)
395fe1c642dSBill Krier 		return (NT_STATUS_INVALID_PARAMETER);
396fe1c642dSBill Krier 
397fe1c642dSBill Krier 	bzero(info, sizeof (smb_account_t));
398fe1c642dSBill Krier 
399fe1c642dSBill Krier 	svinfo = ndr_rpc_server_info(lsa_handle);
400fe1c642dSBill Krier 	if (svinfo->sv_os == NATIVE_OS_WIN2000 &&
401fe1c642dSBill Krier 	    svinfo->sv_version_major == 5 && svinfo->sv_version_minor == 0) {
402fe1c642dSBill Krier 		/*
403fe1c642dSBill Krier 		 * Windows 2000 doesn't like an LSA lookup for
404fe1c642dSBill Krier 		 * DOMAIN\Administrator.
405fe1c642dSBill Krier 		 */
406fe1c642dSBill Krier 		if ((p = strchr(name, '\\')) != 0) {
407fe1c642dSBill Krier 			++p;
408fe1c642dSBill Krier 
409fe1c642dSBill Krier 			if (strcasecmp(p, "administrator") == 0)
410fe1c642dSBill Krier 				name = p;
411fe1c642dSBill Krier 		}
412fe1c642dSBill Krier 
413fe1c642dSBill Krier 	}
414fe1c642dSBill Krier 
415fe1c642dSBill Krier 	length = smb_wcequiv_strlen(name);
416fe1c642dSBill Krier 	names.name[0].length = length;
417fe1c642dSBill Krier 	names.name[0].allosize = length;
418fe1c642dSBill Krier 	names.name[0].str = (unsigned char *)name;
419fe1c642dSBill Krier 	names.n_entry = 1;
420fe1c642dSBill Krier 
421fe1c642dSBill Krier 	if (ndr_rpc_server_os(lsa_handle) == NATIVE_OS_WIN2000) {
422fe1c642dSBill Krier 		for (i = 0; i < n_op; ++i) {
423fe1c642dSBill Krier 			ndr_rpc_set_nonull(lsa_handle);
424fe1c642dSBill Krier 			status = (*ops[i])(lsa_handle, &names, info);
425fe1c642dSBill Krier 
426fe1c642dSBill Krier 			if (status != NT_STATUS_INVALID_PARAMETER)
427fe1c642dSBill Krier 				break;
428fe1c642dSBill Krier 		}
429fe1c642dSBill Krier 	} else {
430fe1c642dSBill Krier 		ndr_rpc_set_nonull(lsa_handle);
431fe1c642dSBill Krier 		status = lsar_lookup_names1(lsa_handle, &names, info);
432fe1c642dSBill Krier 	}
433fe1c642dSBill Krier 
434fe1c642dSBill Krier 	if (status == NT_STATUS_SUCCESS) {
435fe1c642dSBill Krier 		info->a_name = lsar_get_username(name);
436fe1c642dSBill Krier 
437fe1c642dSBill Krier 		if (!smb_account_validate(info)) {
438fe1c642dSBill Krier 			smb_account_free(info);
439fe1c642dSBill Krier 			status = NT_STATUS_NO_MEMORY;
440fe1c642dSBill Krier 		} else {
441fe1c642dSBill Krier 			smb_account_trace(info);
442fe1c642dSBill Krier 		}
443fe1c642dSBill Krier 	}
444fe1c642dSBill Krier 
445fe1c642dSBill Krier 	return (status);
446fe1c642dSBill Krier }
447fe1c642dSBill Krier 
448fe1c642dSBill Krier /*
449fe1c642dSBill Krier  * The name may be in one of the following forms:
450fe1c642dSBill Krier  *
451fe1c642dSBill Krier  *	domain\username
452fe1c642dSBill Krier  *	domain/username
453fe1c642dSBill Krier  *	username
454fe1c642dSBill Krier  *	username@domain
455fe1c642dSBill Krier  *
456fe1c642dSBill Krier  * Return a strdup'd copy of the username.  The caller is responsible
457fe1c642dSBill Krier  * for freeing the allocated memory.
458fe1c642dSBill Krier  */
459fe1c642dSBill Krier static char *
lsar_get_username(const char * name)460fe1c642dSBill Krier lsar_get_username(const char *name)
461fe1c642dSBill Krier {
462fe1c642dSBill Krier 	char	tmp[MAXNAMELEN];
463fe1c642dSBill Krier 	char	*dp = NULL;
464fe1c642dSBill Krier 	char	*np = NULL;
465fe1c642dSBill Krier 
466fe1c642dSBill Krier 	(void) strlcpy(tmp, name, MAXNAMELEN);
467fe1c642dSBill Krier 	smb_name_parse(tmp, &np, &dp);
468fe1c642dSBill Krier 
469fe1c642dSBill Krier 	if (dp != NULL && np != NULL)
470fe1c642dSBill Krier 		return (strdup(np));
471fe1c642dSBill Krier 	else
472fe1c642dSBill Krier 		return (strdup(name));
473fe1c642dSBill Krier }
474fe1c642dSBill Krier 
475fe1c642dSBill Krier /*
476fe1c642dSBill Krier  * lsar_lookup_names1
477fe1c642dSBill Krier  *
478fe1c642dSBill Krier  * Lookup a name and obtain the domain and user rid.
479fe1c642dSBill Krier  *
480fe1c642dSBill Krier  * Note: NT returns an error if the mapped_count is non-zero when the RPC
481fe1c642dSBill Krier  * is called.
482fe1c642dSBill Krier  *
483fe1c642dSBill Krier  * If the lookup fails, the status will typically be NT_STATUS_NONE_MAPPED.
484fe1c642dSBill Krier  */
485fe1c642dSBill Krier static uint32_t
lsar_lookup_names1(mlsvc_handle_t * lsa_handle,lsa_names_t * names,smb_account_t * info)486fe1c642dSBill Krier lsar_lookup_names1(mlsvc_handle_t *lsa_handle, lsa_names_t *names,
487fe1c642dSBill Krier     smb_account_t *info)
488fe1c642dSBill Krier {
489fe1c642dSBill Krier 	struct mslsa_LookupNames	arg;
490fe1c642dSBill Krier 	struct mslsa_rid_entry		*rid_entry;
491fe1c642dSBill Krier 	struct mslsa_domain_entry	*domain_entry;
492fe1c642dSBill Krier 	uint32_t			status = NT_STATUS_SUCCESS;
493fe1c642dSBill Krier 	char				*domname;
494fe1c642dSBill Krier 	int				opnum = LSARPC_OPNUM_LookupNames;
495fe1c642dSBill Krier 
496fe1c642dSBill Krier 	bzero(&arg, sizeof (struct mslsa_LookupNames));
497fe1c642dSBill Krier 	(void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
498fe1c642dSBill Krier 	arg.lookup_level = LSA_LOOKUP_WKSTA;
499fe1c642dSBill Krier 	arg.name_table = (struct mslsa_lup_name_table *)names;
500fe1c642dSBill Krier 
501fe1c642dSBill Krier 	if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
502fe1c642dSBill Krier 		ndr_rpc_release(lsa_handle);
503fe1c642dSBill Krier 		return (NT_STATUS_INVALID_PARAMETER);
504fe1c642dSBill Krier 	}
505fe1c642dSBill Krier 
506fe1c642dSBill Krier 	if (arg.status != NT_STATUS_SUCCESS) {
507fe1c642dSBill Krier 		ndr_rpc_status(lsa_handle, opnum, arg.status);
508fe1c642dSBill Krier 		ndr_rpc_release(lsa_handle);
509fe1c642dSBill Krier 		return (NT_SC_VALUE(arg.status));
510fe1c642dSBill Krier 	}
511fe1c642dSBill Krier 
512fe1c642dSBill Krier 	if (arg.mapped_count == 0) {
513fe1c642dSBill Krier 		ndr_rpc_release(lsa_handle);
514fe1c642dSBill Krier 		return (NT_STATUS_NONE_MAPPED);
515fe1c642dSBill Krier 	}
516fe1c642dSBill Krier 
517fe1c642dSBill Krier 	rid_entry = &arg.translated_sids.rids[0];
518fe1c642dSBill Krier 	if (rid_entry->domain_index != 0) {
519fe1c642dSBill Krier 		ndr_rpc_release(lsa_handle);
520fe1c642dSBill Krier 		return (NT_STATUS_NONE_MAPPED);
521fe1c642dSBill Krier 	}
522fe1c642dSBill Krier 
523fe1c642dSBill Krier 	domain_entry = &arg.domain_table->entries[0];
524fe1c642dSBill Krier 
525fe1c642dSBill Krier 	info->a_type = rid_entry->sid_name_use;
526fe1c642dSBill Krier 	info->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
527fe1c642dSBill Krier 	if ((domname = (char *)domain_entry->domain_name.str) != NULL)
528fe1c642dSBill Krier 		info->a_domain = strdup(domname);
529fe1c642dSBill Krier 	info->a_rid = rid_entry->rid;
530fe1c642dSBill Krier 	info->a_sid = smb_sid_splice(info->a_domsid, info->a_rid);
531fe1c642dSBill Krier 
532fe1c642dSBill Krier 	ndr_rpc_release(lsa_handle);
533fe1c642dSBill Krier 	return (status);
534fe1c642dSBill Krier }
535fe1c642dSBill Krier 
536fe1c642dSBill Krier /*
537fe1c642dSBill Krier  * lsar_lookup_names2
538fe1c642dSBill Krier  */
539fe1c642dSBill Krier static uint32_t
lsar_lookup_names2(mlsvc_handle_t * lsa_handle,lsa_names_t * names,smb_account_t * info)540fe1c642dSBill Krier lsar_lookup_names2(mlsvc_handle_t *lsa_handle, lsa_names_t *names,
541fe1c642dSBill Krier     smb_account_t *info)
542fe1c642dSBill Krier {
543fe1c642dSBill Krier 	struct lsar_LookupNames2	arg;
544fe1c642dSBill Krier 	struct lsar_rid_entry2		*rid_entry;
545fe1c642dSBill Krier 	struct mslsa_domain_entry	*domain_entry;
546fe1c642dSBill Krier 	uint32_t			status = NT_STATUS_SUCCESS;
547fe1c642dSBill Krier 	char				*domname;
548fe1c642dSBill Krier 	int				opnum = LSARPC_OPNUM_LookupNames2;
549fe1c642dSBill Krier 
550fe1c642dSBill Krier 	bzero(&arg, sizeof (struct lsar_LookupNames2));
551fe1c642dSBill Krier 	(void) memcpy(&arg.policy_handle, lsa_handle, sizeof (mslsa_handle_t));
552fe1c642dSBill Krier 	arg.lookup_level = LSA_LOOKUP_WKSTA;
553fe1c642dSBill Krier 	arg.client_revision = LSA_CLIENT_REVISION_AD;
554fe1c642dSBill Krier 	arg.name_table = (struct mslsa_lup_name_table *)names;
555fe1c642dSBill Krier 
556fe1c642dSBill Krier 	if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
557fe1c642dSBill Krier 		ndr_rpc_release(lsa_handle);
558fe1c642dSBill Krier 		return (NT_STATUS_INVALID_PARAMETER);
559fe1c642dSBill Krier 	}
560fe1c642dSBill Krier 
561fe1c642dSBill Krier 	if (arg.status != NT_STATUS_SUCCESS) {
562fe1c642dSBill Krier 		ndr_rpc_status(lsa_handle, opnum, arg.status);
563fe1c642dSBill Krier 		ndr_rpc_release(lsa_handle);
564fe1c642dSBill Krier 		return (NT_SC_VALUE(arg.status));
565fe1c642dSBill Krier 	}
566fe1c642dSBill Krier 
567fe1c642dSBill Krier 	if (arg.mapped_count == 0) {
568fe1c642dSBill Krier 		ndr_rpc_release(lsa_handle);
569fe1c642dSBill Krier 		return (NT_STATUS_NONE_MAPPED);
570fe1c642dSBill Krier 	}
571fe1c642dSBill Krier 
572fe1c642dSBill Krier 	rid_entry = &arg.translated_sids.rids[0];
573fe1c642dSBill Krier 	if (rid_entry->domain_index != 0) {
574fe1c642dSBill Krier 		ndr_rpc_release(lsa_handle);
575fe1c642dSBill Krier 		return (NT_STATUS_NONE_MAPPED);
576fe1c642dSBill Krier 	}
577fe1c642dSBill Krier 
578fe1c642dSBill Krier 	domain_entry = &arg.domain_table->entries[0];
579fe1c642dSBill Krier 
580fe1c642dSBill Krier 	info->a_type = rid_entry->sid_name_use;
581fe1c642dSBill Krier 	info->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
582fe1c642dSBill Krier 	if ((domname = (char *)domain_entry->domain_name.str) != NULL)
583fe1c642dSBill Krier 		info->a_domain = strdup(domname);
584fe1c642dSBill Krier 	info->a_rid = rid_entry->rid;
585fe1c642dSBill Krier 	info->a_sid = smb_sid_splice(info->a_domsid, info->a_rid);
586fe1c642dSBill Krier 
587fe1c642dSBill Krier 	ndr_rpc_release(lsa_handle);
588fe1c642dSBill Krier 	return (status);
589fe1c642dSBill Krier }
590fe1c642dSBill Krier 
591fe1c642dSBill Krier /*
592fe1c642dSBill Krier  * lsar_lookup_names3
593fe1c642dSBill Krier  */
594fe1c642dSBill Krier static uint32_t
lsar_lookup_names3(mlsvc_handle_t * lsa_handle,lsa_names_t * names,smb_account_t * info)595fe1c642dSBill Krier lsar_lookup_names3(mlsvc_handle_t *lsa_handle, lsa_names_t *names,
596fe1c642dSBill Krier     smb_account_t *info)
597fe1c642dSBill Krier {
598fe1c642dSBill Krier 	struct lsar_LookupNames3	arg;
599fe1c642dSBill Krier 	lsar_translated_sid_ex2_t	*sid_entry;
600fe1c642dSBill Krier 	struct mslsa_domain_entry	*domain_entry;
601fe1c642dSBill Krier 	uint32_t			status = NT_STATUS_SUCCESS;
602fe1c642dSBill Krier 	char				*domname;
603fe1c642dSBill Krier 	int				opnum = LSARPC_OPNUM_LookupNames3;
604fe1c642dSBill Krier 
605fe1c642dSBill Krier 	bzero(&arg, sizeof (struct lsar_LookupNames3));
606fe1c642dSBill Krier 	(void) memcpy(&arg.policy_handle, lsa_handle, sizeof (mslsa_handle_t));
607fe1c642dSBill Krier 	arg.lookup_level = LSA_LOOKUP_WKSTA;
608fe1c642dSBill Krier 	arg.client_revision = LSA_CLIENT_REVISION_AD;
609fe1c642dSBill Krier 	arg.name_table = (struct mslsa_lup_name_table *)names;
610fe1c642dSBill Krier 
611fe1c642dSBill Krier 	if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
612fe1c642dSBill Krier 		ndr_rpc_release(lsa_handle);
613fe1c642dSBill Krier 		return (NT_STATUS_INVALID_PARAMETER);
614fe1c642dSBill Krier 	}
615fe1c642dSBill Krier 
616fe1c642dSBill Krier 	if (arg.status != NT_STATUS_SUCCESS) {
617fe1c642dSBill Krier 		ndr_rpc_status(lsa_handle, opnum, arg.status);
618fe1c642dSBill Krier 		ndr_rpc_release(lsa_handle);
619fe1c642dSBill Krier 		return (NT_SC_VALUE(arg.status));
620fe1c642dSBill Krier 	}
621fe1c642dSBill Krier 
622fe1c642dSBill Krier 	if (arg.mapped_count == 0) {
623fe1c642dSBill Krier 		ndr_rpc_release(lsa_handle);
624fe1c642dSBill Krier 		return (NT_STATUS_NONE_MAPPED);
625fe1c642dSBill Krier 	}
626fe1c642dSBill Krier 
627fe1c642dSBill Krier 	sid_entry = &arg.translated_sids.sids[0];
628fe1c642dSBill Krier 	if (sid_entry->domain_index != 0) {
629fe1c642dSBill Krier 		ndr_rpc_release(lsa_handle);
630fe1c642dSBill Krier 		return (NT_STATUS_NONE_MAPPED);
631fe1c642dSBill Krier 	}
632fe1c642dSBill Krier 
633fe1c642dSBill Krier 	domain_entry = &arg.domain_table->entries[0];
634fe1c642dSBill Krier 
635fe1c642dSBill Krier 	info->a_type = sid_entry->sid_name_use;
636fe1c642dSBill Krier 	info->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
637fe1c642dSBill Krier 	if ((domname = (char *)domain_entry->domain_name.str) != NULL)
638fe1c642dSBill Krier 		info->a_domain = strdup(domname);
639fe1c642dSBill Krier 	info->a_sid = smb_sid_dup((smb_sid_t *)sid_entry->sid);
640fe1c642dSBill Krier 	(void) smb_sid_getrid(info->a_sid, &info->a_rid);
641fe1c642dSBill Krier 
642fe1c642dSBill Krier 	ndr_rpc_release(lsa_handle);
643fe1c642dSBill Krier 	return (status);
644fe1c642dSBill Krier }
645fe1c642dSBill Krier 
646fe1c642dSBill Krier /*
647fe1c642dSBill Krier  * lsar_lookup_names4
648fe1c642dSBill Krier  *
649fe1c642dSBill Krier  * This function is only valid if the remote RPC server is a domain
650fe1c642dSBill Krier  * controller and requires the security extensions defined in MS-RPCE.
651fe1c642dSBill Krier  *
652fe1c642dSBill Krier  * Domain controllers will return RPC_NT_PROTSEQ_NOT_SUPPORTED here
653fe1c642dSBill Krier  * because we don't support the RPC_C_AUTHN_NETLOGON security provider.
654fe1c642dSBill Krier  * Non-domain controllers will return NT_STATUS_INVALID_SERVER_STATE.
655fe1c642dSBill Krier  */
656fe1c642dSBill Krier static uint32_t /*LINTED E_STATIC_UNUSED*/
lsar_lookup_names4(mlsvc_handle_t * lsa_handle,lsa_names_t * names,smb_account_t * info)657fe1c642dSBill Krier lsar_lookup_names4(mlsvc_handle_t *lsa_handle, lsa_names_t *names,
658fe1c642dSBill Krier     smb_account_t *info)
659fe1c642dSBill Krier {
660fe1c642dSBill Krier 	struct lsar_LookupNames4	arg;
661fe1c642dSBill Krier 	lsar_translated_sid_ex2_t	*sid_entry;
662fe1c642dSBill Krier 	struct mslsa_domain_entry	*domain_entry;
663fe1c642dSBill Krier 	uint32_t			status = NT_STATUS_SUCCESS;
664fe1c642dSBill Krier 	char				*domname;
665fe1c642dSBill Krier 	int				opnum = LSARPC_OPNUM_LookupNames4;
666fe1c642dSBill Krier 
667fe1c642dSBill Krier 	bzero(&arg, sizeof (struct lsar_LookupNames4));
668fe1c642dSBill Krier 	arg.lookup_level = LSA_LOOKUP_WKSTA;
669fe1c642dSBill Krier 	arg.client_revision = LSA_CLIENT_REVISION_AD;
670fe1c642dSBill Krier 	arg.name_table = (struct mslsa_lup_name_table *)names;
671fe1c642dSBill Krier 
672fe1c642dSBill Krier 	if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
673fe1c642dSBill Krier 		ndr_rpc_release(lsa_handle);
674fe1c642dSBill Krier 		return (NT_STATUS_INVALID_PARAMETER);
675fe1c642dSBill Krier 	}
676fe1c642dSBill Krier 
677fe1c642dSBill Krier 	if (arg.status != NT_STATUS_SUCCESS) {
678fe1c642dSBill Krier 		ndr_rpc_status(lsa_handle, opnum, arg.status);
679fe1c642dSBill Krier 		ndr_rpc_release(lsa_handle);
680fe1c642dSBill Krier 		if (arg.status == RPC_NT_PROTSEQ_NOT_SUPPORTED ||
681fe1c642dSBill Krier 		    arg.status == NT_STATUS_INVALID_SERVER_STATE)
682fe1c642dSBill Krier 			return (NT_STATUS_INVALID_PARAMETER);
683fe1c642dSBill Krier 		return (NT_SC_VALUE(arg.status));
684fe1c642dSBill Krier 	}
685fe1c642dSBill Krier 
686fe1c642dSBill Krier 	if (arg.mapped_count == 0) {
687fe1c642dSBill Krier 		ndr_rpc_release(lsa_handle);
688fe1c642dSBill Krier 		return (NT_STATUS_NONE_MAPPED);
689fe1c642dSBill Krier 	}
690fe1c642dSBill Krier 
691fe1c642dSBill Krier 	sid_entry = &arg.translated_sids.sids[0];
692fe1c642dSBill Krier 	if (sid_entry->domain_index != 0) {
693fe1c642dSBill Krier 		ndr_rpc_release(lsa_handle);
694fe1c642dSBill Krier 		return (NT_STATUS_NONE_MAPPED);
695fe1c642dSBill Krier 	}
696fe1c642dSBill Krier 
697fe1c642dSBill Krier 	domain_entry = &arg.domain_table->entries[0];
698fe1c642dSBill Krier 
699fe1c642dSBill Krier 	info->a_type = sid_entry->sid_name_use;
700fe1c642dSBill Krier 	info->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
701fe1c642dSBill Krier 	if ((domname = (char *)domain_entry->domain_name.str) != NULL)
702fe1c642dSBill Krier 		info->a_domain = strdup(domname);
703fe1c642dSBill Krier 	info->a_sid = smb_sid_dup((smb_sid_t *)sid_entry->sid);
704fe1c642dSBill Krier 	(void) smb_sid_getrid(info->a_sid, &info->a_rid);
705fe1c642dSBill Krier 
706fe1c642dSBill Krier 	ndr_rpc_release(lsa_handle);
707fe1c642dSBill Krier 	return (status);
708fe1c642dSBill Krier }
709fe1c642dSBill Krier 
710fe1c642dSBill Krier /*
711fe1c642dSBill Krier  * Lookup a sid and obtain the domain sid and account name.
712fe1c642dSBill Krier  * This is a wrapper for the various lookup sid RPCs.
713fe1c642dSBill Krier  */
714fe1c642dSBill Krier uint32_t
lsar_lookup_sids(mlsvc_handle_t * lsa_handle,smb_sid_t * sid,smb_account_t * account)715fe1c642dSBill Krier lsar_lookup_sids(mlsvc_handle_t *lsa_handle, smb_sid_t *sid,
716fe1c642dSBill Krier     smb_account_t *account)
717fe1c642dSBill Krier {
718fe1c642dSBill Krier 	char		sidbuf[SMB_SID_STRSZ];
719fe1c642dSBill Krier 	uint32_t	status;
720fe1c642dSBill Krier 
721fe1c642dSBill Krier 	if (lsa_handle == NULL || sid == NULL || account == NULL)
722fe1c642dSBill Krier 		return (NT_STATUS_INVALID_PARAMETER);
723fe1c642dSBill Krier 
724fe1c642dSBill Krier 	bzero(account, sizeof (smb_account_t));
725fe1c642dSBill Krier 	bzero(sidbuf, SMB_SID_STRSZ);
726fe1c642dSBill Krier 	smb_sid_tostr(sid, sidbuf);
727fe1c642dSBill Krier 	smb_tracef("%s", sidbuf);
728fe1c642dSBill Krier 
729fe1c642dSBill Krier 	if (ndr_rpc_server_os(lsa_handle) == NATIVE_OS_WIN2000)
730fe1c642dSBill Krier 		status = lsar_lookup_sids2(lsa_handle, (lsa_sid_t *)sid,
731fe1c642dSBill Krier 		    account);
732fe1c642dSBill Krier 	else
733fe1c642dSBill Krier 		status = lsar_lookup_sids1(lsa_handle, (lsa_sid_t *)sid,
734fe1c642dSBill Krier 		    account);
735fe1c642dSBill Krier 
736fe1c642dSBill Krier 	if (status == NT_STATUS_SUCCESS) {
737fe1c642dSBill Krier 		if (!smb_account_validate(account)) {
738fe1c642dSBill Krier 			smb_account_free(account);
739fe1c642dSBill Krier 			status = NT_STATUS_NO_MEMORY;
740fe1c642dSBill Krier 		} else {
741fe1c642dSBill Krier 			smb_account_trace(account);
742fe1c642dSBill Krier 		}
743fe1c642dSBill Krier 	}
744fe1c642dSBill Krier 
745fe1c642dSBill Krier 	return (status);
746fe1c642dSBill Krier }
747fe1c642dSBill Krier 
748fe1c642dSBill Krier /*
749fe1c642dSBill Krier  * lsar_lookup_sids1
750fe1c642dSBill Krier  */
751fe1c642dSBill Krier static uint32_t
lsar_lookup_sids1(mlsvc_handle_t * lsa_handle,lsa_sid_t * sid,smb_account_t * account)752fe1c642dSBill Krier lsar_lookup_sids1(mlsvc_handle_t *lsa_handle, lsa_sid_t *sid,
753fe1c642dSBill Krier     smb_account_t *account)
754fe1c642dSBill Krier {
755fe1c642dSBill Krier 	struct mslsa_LookupSids		arg;
756fe1c642dSBill Krier 	struct mslsa_lup_sid_entry	sid_entry;
757fe1c642dSBill Krier 	struct mslsa_name_entry		*name_entry;
758fe1c642dSBill Krier 	struct mslsa_domain_entry	*domain_entry;
759fe1c642dSBill Krier 	uint32_t			status = NT_STATUS_SUCCESS;
760fe1c642dSBill Krier 	char				*name;
761fe1c642dSBill Krier 	int				opnum = LSARPC_OPNUM_LookupSids;
762fe1c642dSBill Krier 
763fe1c642dSBill Krier 	bzero(&arg, sizeof (struct mslsa_LookupSids));
764fe1c642dSBill Krier 	(void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
765fe1c642dSBill Krier 	arg.lookup_level = LSA_LOOKUP_WKSTA;
766fe1c642dSBill Krier 
767fe1c642dSBill Krier 	sid_entry.psid = sid;
768fe1c642dSBill Krier 	arg.lup_sid_table.n_entry = 1;
769fe1c642dSBill Krier 	arg.lup_sid_table.entries = &sid_entry;
770fe1c642dSBill Krier 
771fe1c642dSBill Krier 	if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
772fe1c642dSBill Krier 		ndr_rpc_release(lsa_handle);
773fe1c642dSBill Krier 		return (NT_STATUS_INVALID_PARAMETER);
774fe1c642dSBill Krier 	}
775fe1c642dSBill Krier 
776fe1c642dSBill Krier 	if (arg.status != NT_STATUS_SUCCESS) {
777fe1c642dSBill Krier 		ndr_rpc_status(lsa_handle, opnum, arg.status);
778fe1c642dSBill Krier 		ndr_rpc_release(lsa_handle);
779fe1c642dSBill Krier 		return (NT_SC_VALUE(arg.status));
780fe1c642dSBill Krier 	}
781fe1c642dSBill Krier 
782fe1c642dSBill Krier 	if (arg.mapped_count == 0) {
783fe1c642dSBill Krier 		ndr_rpc_release(lsa_handle);
784fe1c642dSBill Krier 		return (NT_STATUS_NONE_MAPPED);
785fe1c642dSBill Krier 	}
786fe1c642dSBill Krier 
787fe1c642dSBill Krier 	name_entry = &arg.name_table.entries[0];
788fe1c642dSBill Krier 	if (name_entry->domain_ix != 0) {
789fe1c642dSBill Krier 		ndr_rpc_release(lsa_handle);
790fe1c642dSBill Krier 		return (NT_STATUS_NONE_MAPPED);
791fe1c642dSBill Krier 	}
792fe1c642dSBill Krier 
793fe1c642dSBill Krier 	name = (char *)name_entry->name.str;
794fe1c642dSBill Krier 	account->a_name = (name) ? strdup(name) : strdup("");
795fe1c642dSBill Krier 	account->a_type = name_entry->sid_name_use;
796fe1c642dSBill Krier 	account->a_sid = smb_sid_dup((smb_sid_t *)sid);
797fe1c642dSBill Krier 	(void) smb_sid_getrid(account->a_sid, &account->a_rid);
798fe1c642dSBill Krier 
799fe1c642dSBill Krier 	domain_entry = &arg.domain_table->entries[0];
800fe1c642dSBill Krier 	if ((name = (char *)domain_entry->domain_name.str) != NULL)
801fe1c642dSBill Krier 		account->a_domain = strdup(name);
802fe1c642dSBill Krier 	account->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
803fe1c642dSBill Krier 
804fe1c642dSBill Krier 	ndr_rpc_release(lsa_handle);
805fe1c642dSBill Krier 	return (status);
806fe1c642dSBill Krier }
807fe1c642dSBill Krier 
808fe1c642dSBill Krier /*
809fe1c642dSBill Krier  * lsar_lookup_sids2
810fe1c642dSBill Krier  */
811fe1c642dSBill Krier static uint32_t
lsar_lookup_sids2(mlsvc_handle_t * lsa_handle,lsa_sid_t * sid,smb_account_t * account)812fe1c642dSBill Krier lsar_lookup_sids2(mlsvc_handle_t *lsa_handle, lsa_sid_t *sid,
813fe1c642dSBill Krier     smb_account_t *account)
814fe1c642dSBill Krier {
815fe1c642dSBill Krier 	struct lsar_lookup_sids2	arg;
816fe1c642dSBill Krier 	struct lsar_name_entry2		*name_entry;
817fe1c642dSBill Krier 	struct mslsa_lup_sid_entry	sid_entry;
818fe1c642dSBill Krier 	struct mslsa_domain_entry	*domain_entry;
819fe1c642dSBill Krier 	uint32_t			status = NT_STATUS_SUCCESS;
820fe1c642dSBill Krier 	char				*name;
821fe1c642dSBill Krier 	int				opnum = LSARPC_OPNUM_LookupSids2;
822fe1c642dSBill Krier 
823fe1c642dSBill Krier 	bzero(&arg, sizeof (struct lsar_lookup_sids2));
824fe1c642dSBill Krier 	(void) memcpy(&arg.policy_handle, lsa_handle, sizeof (mslsa_handle_t));
825fe1c642dSBill Krier 
826fe1c642dSBill Krier 	sid_entry.psid = sid;
827fe1c642dSBill Krier 	arg.lup_sid_table.n_entry = 1;
828fe1c642dSBill Krier 	arg.lup_sid_table.entries = &sid_entry;
829fe1c642dSBill Krier 	arg.lookup_level = LSA_LOOKUP_WKSTA;
830fe1c642dSBill Krier 	arg.client_revision = LSA_CLIENT_REVISION_AD;
831fe1c642dSBill Krier 
832fe1c642dSBill Krier 	if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
833fe1c642dSBill Krier 		ndr_rpc_release(lsa_handle);
834fe1c642dSBill Krier 		return (NT_STATUS_INVALID_PARAMETER);
835fe1c642dSBill Krier 	}
836fe1c642dSBill Krier 
837fe1c642dSBill Krier 	if (arg.status != NT_STATUS_SUCCESS) {
838fe1c642dSBill Krier 		ndr_rpc_status(lsa_handle, opnum, arg.status);
839fe1c642dSBill Krier 		ndr_rpc_release(lsa_handle);
840fe1c642dSBill Krier 		return (NT_SC_VALUE(arg.status));
841fe1c642dSBill Krier 	}
842fe1c642dSBill Krier 
843fe1c642dSBill Krier 	if (arg.mapped_count == 0) {
844fe1c642dSBill Krier 		ndr_rpc_release(lsa_handle);
845fe1c642dSBill Krier 		return (NT_STATUS_NONE_MAPPED);
846fe1c642dSBill Krier 	}
847fe1c642dSBill Krier 
848fe1c642dSBill Krier 	name_entry = &arg.name_table.entries[0];
849fe1c642dSBill Krier 	if (name_entry->domain_ix != 0) {
850fe1c642dSBill Krier 		ndr_rpc_release(lsa_handle);
851fe1c642dSBill Krier 		return (NT_STATUS_NONE_MAPPED);
852fe1c642dSBill Krier 	}
853fe1c642dSBill Krier 
854fe1c642dSBill Krier 	name = (char *)name_entry->name.str;
855fe1c642dSBill Krier 	account->a_name = (name) ? strdup(name) : strdup("");
856fe1c642dSBill Krier 	account->a_type = name_entry->sid_name_use;
857fe1c642dSBill Krier 	account->a_sid = smb_sid_dup((smb_sid_t *)sid);
858fe1c642dSBill Krier 	(void) smb_sid_getrid(account->a_sid, &account->a_rid);
859fe1c642dSBill Krier 
860fe1c642dSBill Krier 	domain_entry = &arg.domain_table->entries[0];
861fe1c642dSBill Krier 	if ((name = (char *)domain_entry->domain_name.str) != NULL)
862fe1c642dSBill Krier 		account->a_domain = strdup(name);
863fe1c642dSBill Krier 	account->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
864fe1c642dSBill Krier 
865fe1c642dSBill Krier 	ndr_rpc_release(lsa_handle);
866fe1c642dSBill Krier 	return (status);
867fe1c642dSBill Krier }
868fe1c642dSBill Krier 
869fe1c642dSBill Krier /*
870fe1c642dSBill Krier  * lsar_lookup_sids3
871fe1c642dSBill Krier  *
872fe1c642dSBill Krier  * This function is only valid if the remote RPC server is a domain
873fe1c642dSBill Krier  * controller and requires the security extensions defined in MS-RPCE.
874fe1c642dSBill Krier  *
875fe1c642dSBill Krier  * Domain controllers will return RPC_NT_PROTSEQ_NOT_SUPPORTED here
876fe1c642dSBill Krier  * because we don't support the RPC_C_AUTHN_NETLOGON security provider.
877fe1c642dSBill Krier  * Non-domain controllers will return NT_STATUS_INVALID_SERVER_STATE.
878fe1c642dSBill Krier  */
879fe1c642dSBill Krier static uint32_t /*LINTED E_STATIC_UNUSED*/
lsar_lookup_sids3(mlsvc_handle_t * lsa_handle,lsa_sid_t * sid,smb_account_t * account)880fe1c642dSBill Krier lsar_lookup_sids3(mlsvc_handle_t *lsa_handle, lsa_sid_t *sid,
881fe1c642dSBill Krier     smb_account_t *account)
882fe1c642dSBill Krier {
883fe1c642dSBill Krier 	struct lsar_lookup_sids3	arg;
884fe1c642dSBill Krier 	lsar_translated_name_ex_t	*name_entry;
885fe1c642dSBill Krier 	struct mslsa_lup_sid_entry	sid_entry;
886fe1c642dSBill Krier 	struct mslsa_domain_entry	*domain_entry;
887fe1c642dSBill Krier 	uint32_t			status = NT_STATUS_SUCCESS;
888fe1c642dSBill Krier 	char				*name;
889fe1c642dSBill Krier 	int				opnum = LSARPC_OPNUM_LookupSids3;
890fe1c642dSBill Krier 
891fe1c642dSBill Krier 	bzero(&arg, sizeof (struct lsar_lookup_sids3));
892fe1c642dSBill Krier 
893fe1c642dSBill Krier 	sid_entry.psid = sid;
894fe1c642dSBill Krier 	arg.lup_sid_table.n_entry = 1;
895fe1c642dSBill Krier 	arg.lup_sid_table.entries = &sid_entry;
896fe1c642dSBill Krier 	arg.lookup_level = LSA_LOOKUP_WKSTA;
897fe1c642dSBill Krier 	arg.client_revision = LSA_CLIENT_REVISION_AD;
898fe1c642dSBill Krier 
899fe1c642dSBill Krier 	if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
900fe1c642dSBill Krier 		ndr_rpc_release(lsa_handle);
901fe1c642dSBill Krier 		return (NT_STATUS_INVALID_PARAMETER);
902fe1c642dSBill Krier 	}
903fe1c642dSBill Krier 
904fe1c642dSBill Krier 	if (arg.status != NT_STATUS_SUCCESS) {
905fe1c642dSBill Krier 		ndr_rpc_status(lsa_handle, opnum, arg.status);
906fe1c642dSBill Krier 		ndr_rpc_release(lsa_handle);
907fe1c642dSBill Krier 		if (arg.status == RPC_NT_PROTSEQ_NOT_SUPPORTED ||
908fe1c642dSBill Krier 		    arg.status == NT_STATUS_INVALID_SERVER_STATE)
909fe1c642dSBill Krier 			return (NT_STATUS_INVALID_PARAMETER);
910fe1c642dSBill Krier 		return (NT_SC_VALUE(arg.status));
911fe1c642dSBill Krier 	}
912fe1c642dSBill Krier 
913fe1c642dSBill Krier 	if (arg.mapped_count == 0) {
914fe1c642dSBill Krier 		ndr_rpc_release(lsa_handle);
915fe1c642dSBill Krier 		return (NT_STATUS_NONE_MAPPED);
916fe1c642dSBill Krier 	}
917fe1c642dSBill Krier 
918fe1c642dSBill Krier 	name_entry = &arg.name_table.entries[0];
919fe1c642dSBill Krier 	if (name_entry->domain_ix != 0) {
920fe1c642dSBill Krier 		ndr_rpc_release(lsa_handle);
921fe1c642dSBill Krier 		return (NT_STATUS_NONE_MAPPED);
922fe1c642dSBill Krier 	}
923fe1c642dSBill Krier 
924fe1c642dSBill Krier 	name = (char *)name_entry->name.str;
925fe1c642dSBill Krier 	account->a_name = (name) ? strdup(name) : strdup("");
926fe1c642dSBill Krier 	account->a_type = name_entry->sid_name_use;
927fe1c642dSBill Krier 	account->a_sid = smb_sid_dup((smb_sid_t *)sid);
928fe1c642dSBill Krier 	(void) smb_sid_getrid(account->a_sid, &account->a_rid);
929fe1c642dSBill Krier 
930fe1c642dSBill Krier 	domain_entry = &arg.domain_table->entries[0];
931fe1c642dSBill Krier 	if ((name = (char *)domain_entry->domain_name.str) != NULL)
932fe1c642dSBill Krier 		account->a_domain = strdup(name);
933fe1c642dSBill Krier 	account->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
934fe1c642dSBill Krier 
935fe1c642dSBill Krier 	ndr_rpc_release(lsa_handle);
936fe1c642dSBill Krier 	return (status);
937fe1c642dSBill Krier }
938fe1c642dSBill Krier 
939fe1c642dSBill Krier /*
940fe1c642dSBill Krier  * lsar_enum_accounts
941fe1c642dSBill Krier  *
942fe1c642dSBill Krier  * Enumerate the list of accounts (i.e. SIDs). Use the handle returned
943fe1c642dSBill Krier  * from lsa_open_policy2. The enum_context is used to support multiple
944fe1c642dSBill Krier  * calls to this enumeration function. It should be set to 0 on the
945fe1c642dSBill Krier  * first call. It will be updated by the domain controller and should
946fe1c642dSBill Krier  * simply be passed unchanged to subsequent calls until there are no
947fe1c642dSBill Krier  * more accounts. A warning status of 0x1A indicates that no more data
948fe1c642dSBill Krier  * is available. The list of accounts will be returned in accounts.
949fe1c642dSBill Krier  * This list is dynamically allocated using malloc, it should be freed
950fe1c642dSBill Krier  * by the caller when it is no longer required.
951fe1c642dSBill Krier  */
952*b3700b07SGordon Ross DWORD
lsar_enum_accounts(mlsvc_handle_t * lsa_handle,DWORD * enum_context,struct mslsa_EnumAccountBuf * accounts)953fe1c642dSBill Krier lsar_enum_accounts(mlsvc_handle_t *lsa_handle, DWORD *enum_context,
954fe1c642dSBill Krier     struct mslsa_EnumAccountBuf *accounts)
955fe1c642dSBill Krier {
956fe1c642dSBill Krier 	struct mslsa_EnumerateAccounts	arg;
957fe1c642dSBill Krier 	struct mslsa_AccountInfo	*info;
958fe1c642dSBill Krier 	int	opnum;
959fe1c642dSBill Krier 	int	rc;
960*b3700b07SGordon Ross 	DWORD	status;
961fe1c642dSBill Krier 	DWORD	n_entries;
962fe1c642dSBill Krier 	DWORD	i;
963fe1c642dSBill Krier 	int	nbytes;
964fe1c642dSBill Krier 
965fe1c642dSBill Krier 	if (lsa_handle == NULL || enum_context == NULL || accounts == NULL)
966*b3700b07SGordon Ross 		return (NT_STATUS_INTERNAL_ERROR);
967fe1c642dSBill Krier 
968fe1c642dSBill Krier 	accounts->entries_read = 0;
969fe1c642dSBill Krier 	accounts->info = 0;
970fe1c642dSBill Krier 
971fe1c642dSBill Krier 	opnum = LSARPC_OPNUM_EnumerateAccounts;
972fe1c642dSBill Krier 
973fe1c642dSBill Krier 	bzero(&arg, sizeof (struct mslsa_EnumerateAccounts));
974fe1c642dSBill Krier 	(void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
975fe1c642dSBill Krier 	arg.enum_context = *enum_context;
976fe1c642dSBill Krier 	arg.max_length = MLSVC_MAX_RESPONSE_LEN;
977fe1c642dSBill Krier 
978fe1c642dSBill Krier 	rc = ndr_rpc_call(lsa_handle, opnum, &arg);
979fe1c642dSBill Krier 	if (rc == 0) {
980*b3700b07SGordon Ross 		status = arg.status;
981fe1c642dSBill Krier 		if (arg.status != 0) {
982148c5f43SAlan Wright 			if (arg.status == NT_STATUS_NO_MORE_ENTRIES) {
983fe1c642dSBill Krier 				*enum_context = arg.enum_context;
984fe1c642dSBill Krier 			} else {
985fe1c642dSBill Krier 				ndr_rpc_status(lsa_handle, opnum, arg.status);
986fe1c642dSBill Krier 			}
987fe1c642dSBill Krier 		} else if (arg.enum_buf->entries_read != 0) {
988fe1c642dSBill Krier 			n_entries = arg.enum_buf->entries_read;
989fe1c642dSBill Krier 			nbytes = n_entries * sizeof (struct mslsa_AccountInfo);
990fe1c642dSBill Krier 
991fe1c642dSBill Krier 			if ((info = malloc(nbytes)) == NULL) {
992fe1c642dSBill Krier 				ndr_rpc_release(lsa_handle);
993*b3700b07SGordon Ross 				return (NT_STATUS_NO_MEMORY);
994fe1c642dSBill Krier 			}
995fe1c642dSBill Krier 
996fe1c642dSBill Krier 			for (i = 0; i < n_entries; ++i)
997fe1c642dSBill Krier 				info[i].sid = (lsa_sid_t *)smb_sid_dup(
998fe1c642dSBill Krier 				    (smb_sid_t *)arg.enum_buf->info[i].sid);
999fe1c642dSBill Krier 
1000fe1c642dSBill Krier 			accounts->entries_read = n_entries;
1001fe1c642dSBill Krier 			accounts->info = info;
1002fe1c642dSBill Krier 			*enum_context = arg.enum_context;
1003fe1c642dSBill Krier 		}
1004*b3700b07SGordon Ross 	} else {
1005*b3700b07SGordon Ross 		status = NT_STATUS_INVALID_PARAMETER;
1006fe1c642dSBill Krier 	}
1007fe1c642dSBill Krier 
1008fe1c642dSBill Krier 	ndr_rpc_release(lsa_handle);
1009*b3700b07SGordon Ross 	return (status);
1010fe1c642dSBill Krier }
1011fe1c642dSBill Krier 
1012fe1c642dSBill Krier /*
1013fe1c642dSBill Krier  * lsar_enum_trusted_domains
1014fe1c642dSBill Krier  *
1015fe1c642dSBill Krier  * Enumerate the list of trusted domains. Use the handle returned from
1016fe1c642dSBill Krier  * lsa_open_policy2. The enum_context is used to support multiple calls
1017fe1c642dSBill Krier  * to this enumeration function. It should be set to 0 on the first
1018fe1c642dSBill Krier  * call. It will be updated by the domain controller and should simply
1019fe1c642dSBill Krier  * be passed unchanged to subsequent calls until there are no more
1020fe1c642dSBill Krier  * domains.
1021fe1c642dSBill Krier  *
1022fe1c642dSBill Krier  * The trusted domains aren't actually returned here. They are added
1023fe1c642dSBill Krier  * to the NT domain database. After all of the trusted domains have
1024fe1c642dSBill Krier  * been discovered, the database can be interrogated to find all of
1025fe1c642dSBill Krier  * the trusted domains.
1026fe1c642dSBill Krier  */
1027fe1c642dSBill Krier DWORD
lsar_enum_trusted_domains(mlsvc_handle_t * lsa_handle,DWORD * enum_context,smb_trusted_domains_t * list)1028fe1c642dSBill Krier lsar_enum_trusted_domains(mlsvc_handle_t *lsa_handle, DWORD *enum_context,
1029fe1c642dSBill Krier     smb_trusted_domains_t *list)
1030fe1c642dSBill Krier {
1031fe1c642dSBill Krier 	struct mslsa_EnumTrustedDomain	arg;
1032fe1c642dSBill Krier 	int	opnum;
1033fe1c642dSBill Krier 	DWORD	status;
1034fe1c642dSBill Krier 
1035fe1c642dSBill Krier 	if (list == NULL)
1036fe1c642dSBill Krier 		return (NT_STATUS_INVALID_PARAMETER);
1037fe1c642dSBill Krier 
1038fe1c642dSBill Krier 	opnum = LSARPC_OPNUM_EnumTrustedDomain;
1039fe1c642dSBill Krier 
1040fe1c642dSBill Krier 	bzero(list, sizeof (smb_trusted_domains_t));
1041fe1c642dSBill Krier 	bzero(&arg, sizeof (struct mslsa_EnumTrustedDomain));
1042fe1c642dSBill Krier 	(void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
1043fe1c642dSBill Krier 	arg.enum_context = *enum_context;
1044fe1c642dSBill Krier 	arg.max_length = MLSVC_MAX_RESPONSE_LEN;
1045fe1c642dSBill Krier 
1046fe1c642dSBill Krier 	if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
1047fe1c642dSBill Krier 		status = NT_STATUS_INVALID_PARAMETER;
1048fe1c642dSBill Krier 	} else if (arg.status != 0) {
1049fe1c642dSBill Krier 		*enum_context = arg.enum_context;
1050fe1c642dSBill Krier 		status = NT_SC_VALUE(arg.status);
1051fe1c642dSBill Krier 
1052fe1c642dSBill Krier 		/*
1053148c5f43SAlan Wright 		 * STATUS_NO_MORE_ENTRIES provides call
1054148c5f43SAlan Wright 		 * status but does not indicate an error.
1055fe1c642dSBill Krier 		 */
1056148c5f43SAlan Wright 		if (status != NT_STATUS_NO_MORE_ENTRIES)
1057fe1c642dSBill Krier 			ndr_rpc_status(lsa_handle, opnum, arg.status);
1058fe1c642dSBill Krier 	} else if (arg.enum_buf->entries_read == 0) {
1059fe1c642dSBill Krier 		*enum_context = arg.enum_context;
1060fe1c642dSBill Krier 		status = 0;
1061fe1c642dSBill Krier 	} else {
1062fe1c642dSBill Krier 		lsar_set_trusted_domains(arg.enum_buf, list);
1063fe1c642dSBill Krier 		*enum_context = arg.enum_context;
1064fe1c642dSBill Krier 		status = 0;
1065fe1c642dSBill Krier 	}
1066fe1c642dSBill Krier 
1067fe1c642dSBill Krier 	ndr_rpc_release(lsa_handle);
1068fe1c642dSBill Krier 	return (status);
1069fe1c642dSBill Krier }
1070fe1c642dSBill Krier 
1071fe1c642dSBill Krier DWORD
lsar_enum_trusted_domains_ex(mlsvc_handle_t * lsa_handle,DWORD * enum_context,smb_trusted_domains_t * list)1072fe1c642dSBill Krier lsar_enum_trusted_domains_ex(mlsvc_handle_t *lsa_handle, DWORD *enum_context,
1073fe1c642dSBill Krier     smb_trusted_domains_t *list)
1074fe1c642dSBill Krier {
1075fe1c642dSBill Krier 	struct mslsa_EnumTrustedDomainEx	arg;
1076fe1c642dSBill Krier 	int	opnum;
1077fe1c642dSBill Krier 	DWORD	status;
1078fe1c642dSBill Krier 
1079fe1c642dSBill Krier 	if (list == NULL)
1080fe1c642dSBill Krier 		return (NT_STATUS_INVALID_PARAMETER);
1081fe1c642dSBill Krier 
1082fe1c642dSBill Krier 	opnum = LSARPC_OPNUM_EnumTrustedDomainsEx;
1083fe1c642dSBill Krier 
1084fe1c642dSBill Krier 	bzero(list, sizeof (smb_trusted_domains_t));
1085fe1c642dSBill Krier 	bzero(&arg, sizeof (struct mslsa_EnumTrustedDomainEx));
1086fe1c642dSBill Krier 	(void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
1087fe1c642dSBill Krier 	arg.enum_context = *enum_context;
1088fe1c642dSBill Krier 	arg.max_length = MLSVC_MAX_RESPONSE_LEN;
1089fe1c642dSBill Krier 
1090fe1c642dSBill Krier 	if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
1091fe1c642dSBill Krier 		status = NT_STATUS_INVALID_PARAMETER;
1092fe1c642dSBill Krier 	} else if (arg.status != 0) {
1093fe1c642dSBill Krier 		*enum_context = arg.enum_context;
1094fe1c642dSBill Krier 		status = NT_SC_VALUE(arg.status);
1095fe1c642dSBill Krier 
1096fe1c642dSBill Krier 		/*
1097148c5f43SAlan Wright 		 * STATUS_NO_MORE_ENTRIES provides call
1098148c5f43SAlan Wright 		 * status but does not indicate an error.
1099fe1c642dSBill Krier 		 */
1100148c5f43SAlan Wright 		if (status != NT_STATUS_NO_MORE_ENTRIES)
1101fe1c642dSBill Krier 			ndr_rpc_status(lsa_handle, opnum, arg.status);
1102fe1c642dSBill Krier 	} else if (arg.enum_buf->entries_read == 0) {
1103fe1c642dSBill Krier 		*enum_context = arg.enum_context;
1104fe1c642dSBill Krier 		status = 0;
1105fe1c642dSBill Krier 	} else {
1106fe1c642dSBill Krier 		lsar_set_trusted_domains_ex(arg.enum_buf, list);
1107fe1c642dSBill Krier 		*enum_context = arg.enum_context;
1108fe1c642dSBill Krier 		status = 0;
1109fe1c642dSBill Krier 	}
1110fe1c642dSBill Krier 
1111fe1c642dSBill Krier 	ndr_rpc_release(lsa_handle);
1112fe1c642dSBill Krier 	return (status);
1113fe1c642dSBill Krier }
1114fe1c642dSBill Krier 
1115fe1c642dSBill Krier /*
1116fe1c642dSBill Krier  * lsar_enum_privs_account
1117fe1c642dSBill Krier  *
1118fe1c642dSBill Krier  * Privileges enum? Need an account handle.
1119fe1c642dSBill Krier  */
1120fe1c642dSBill Krier /*ARGSUSED*/
1121fe1c642dSBill Krier int
lsar_enum_privs_account(mlsvc_handle_t * account_handle,smb_account_t * account)1122fe1c642dSBill Krier lsar_enum_privs_account(mlsvc_handle_t *account_handle, smb_account_t *account)
1123fe1c642dSBill Krier {
1124fe1c642dSBill Krier 	struct mslsa_EnumPrivsAccount	arg;
1125fe1c642dSBill Krier 	int	opnum;
1126fe1c642dSBill Krier 	int	rc;
1127fe1c642dSBill Krier 
1128fe1c642dSBill Krier 	opnum = LSARPC_OPNUM_EnumPrivsAccount;
1129fe1c642dSBill Krier 
1130fe1c642dSBill Krier 	bzero(&arg, sizeof (struct mslsa_EnumPrivsAccount));
1131fe1c642dSBill Krier 	(void) memcpy(&arg.account_handle, &account_handle->handle,
1132fe1c642dSBill Krier 	    sizeof (mslsa_handle_t));
1133fe1c642dSBill Krier 
1134fe1c642dSBill Krier 	rc = ndr_rpc_call(account_handle, opnum, &arg);
1135fe1c642dSBill Krier 	if ((rc == 0) && (arg.status != 0)) {
1136fe1c642dSBill Krier 		ndr_rpc_status(account_handle, opnum, arg.status);
1137fe1c642dSBill Krier 		rc = -1;
1138fe1c642dSBill Krier 	}
1139fe1c642dSBill Krier 	ndr_rpc_release(account_handle);
1140fe1c642dSBill Krier 	return (rc);
1141fe1c642dSBill Krier }
1142fe1c642dSBill Krier 
1143fe1c642dSBill Krier /*
1144fe1c642dSBill Krier  * lsar_lookup_priv_value
1145fe1c642dSBill Krier  *
1146fe1c642dSBill Krier  * Map a privilege name to a local unique id (LUID). Privilege names
1147fe1c642dSBill Krier  * are consistent across the network. LUIDs are machine specific.
1148fe1c642dSBill Krier  * This function provides the means to map a privilege name to the
1149fe1c642dSBill Krier  * LUID used by a remote server to represent it. The handle here is
1150fe1c642dSBill Krier  * a policy handle.
1151fe1c642dSBill Krier  */
1152fe1c642dSBill Krier int
lsar_lookup_priv_value(mlsvc_handle_t * lsa_handle,char * name,struct ms_luid * luid)1153fe1c642dSBill Krier lsar_lookup_priv_value(mlsvc_handle_t *lsa_handle, char *name,
1154fe1c642dSBill Krier     struct ms_luid *luid)
1155fe1c642dSBill Krier {
1156fe1c642dSBill Krier 	struct mslsa_LookupPrivValue	arg;
1157fe1c642dSBill Krier 	int	opnum;
1158fe1c642dSBill Krier 	int	rc;
1159fe1c642dSBill Krier 	size_t	length;
1160fe1c642dSBill Krier 
1161fe1c642dSBill Krier 	if (lsa_handle == NULL || name == NULL || luid == NULL)
1162fe1c642dSBill Krier 		return (-1);
1163fe1c642dSBill Krier 
1164fe1c642dSBill Krier 	opnum = LSARPC_OPNUM_LookupPrivValue;
1165fe1c642dSBill Krier 
1166fe1c642dSBill Krier 	bzero(&arg, sizeof (struct mslsa_LookupPrivValue));
1167fe1c642dSBill Krier 	(void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
1168fe1c642dSBill Krier 
1169fe1c642dSBill Krier 	length = smb_wcequiv_strlen(name);
1170fe1c642dSBill Krier 	if (ndr_rpc_server_os(lsa_handle) == NATIVE_OS_WIN2000)
1171fe1c642dSBill Krier 		length += sizeof (smb_wchar_t);
1172fe1c642dSBill Krier 
1173fe1c642dSBill Krier 	arg.name.length = length;
1174fe1c642dSBill Krier 	arg.name.allosize = length;
1175fe1c642dSBill Krier 	arg.name.str = (unsigned char *)name;
1176fe1c642dSBill Krier 
1177fe1c642dSBill Krier 	rc = ndr_rpc_call(lsa_handle, opnum, &arg);
1178fe1c642dSBill Krier 	if (rc == 0) {
1179fe1c642dSBill Krier 		if (arg.status != 0)
1180fe1c642dSBill Krier 			rc = -1;
1181fe1c642dSBill Krier 		else
1182fe1c642dSBill Krier 			(void) memcpy(luid, &arg.luid, sizeof (struct ms_luid));
1183fe1c642dSBill Krier 	}
1184fe1c642dSBill Krier 
1185fe1c642dSBill Krier 	ndr_rpc_release(lsa_handle);
1186fe1c642dSBill Krier 	return (rc);
1187fe1c642dSBill Krier }
1188fe1c642dSBill Krier 
1189fe1c642dSBill Krier /*
1190fe1c642dSBill Krier  * lsar_lookup_priv_name
1191fe1c642dSBill Krier  *
1192fe1c642dSBill Krier  * Map a local unique id (LUID) to a privilege name. Privilege names
1193fe1c642dSBill Krier  * are consistent across the network. LUIDs are machine specific.
1194fe1c642dSBill Krier  * This function the means to map the LUID used by a remote server to
1195fe1c642dSBill Krier  * the appropriate privilege name. The handle here is a policy handle.
1196fe1c642dSBill Krier  */
1197fe1c642dSBill Krier int
lsar_lookup_priv_name(mlsvc_handle_t * lsa_handle,struct ms_luid * luid,char * name,int namelen)1198fe1c642dSBill Krier lsar_lookup_priv_name(mlsvc_handle_t *lsa_handle, struct ms_luid *luid,
1199fe1c642dSBill Krier     char *name, int namelen)
1200fe1c642dSBill Krier {
1201fe1c642dSBill Krier 	struct mslsa_LookupPrivName	arg;
1202fe1c642dSBill Krier 	int	opnum;
1203fe1c642dSBill Krier 	int	rc;
1204fe1c642dSBill Krier 
1205fe1c642dSBill Krier 	if (lsa_handle == NULL || luid == NULL || name == NULL)
1206fe1c642dSBill Krier 		return (-1);
1207fe1c642dSBill Krier 
1208fe1c642dSBill Krier 	opnum = LSARPC_OPNUM_LookupPrivName;
1209fe1c642dSBill Krier 
1210fe1c642dSBill Krier 	bzero(&arg, sizeof (struct mslsa_LookupPrivName));
1211fe1c642dSBill Krier 	(void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
1212fe1c642dSBill Krier 	(void) memcpy(&arg.luid, luid, sizeof (struct ms_luid));
1213fe1c642dSBill Krier 
1214fe1c642dSBill Krier 	rc = ndr_rpc_call(lsa_handle, opnum, &arg);
1215fe1c642dSBill Krier 	if (rc == 0) {
1216fe1c642dSBill Krier 		if (arg.status != 0)
1217fe1c642dSBill Krier 			rc = -1;
1218fe1c642dSBill Krier 		else
1219fe1c642dSBill Krier 			(void) strlcpy(name, (char const *)arg.name->str,
1220fe1c642dSBill Krier 			    namelen);
1221fe1c642dSBill Krier 	}
1222fe1c642dSBill Krier 
1223fe1c642dSBill Krier 	ndr_rpc_release(lsa_handle);
1224fe1c642dSBill Krier 	return (rc);
1225fe1c642dSBill Krier }
1226fe1c642dSBill Krier 
1227fe1c642dSBill Krier /*
1228fe1c642dSBill Krier  * lsar_lookup_priv_display_name
1229fe1c642dSBill Krier  *
1230fe1c642dSBill Krier  * Map a privilege name to a privilege display name. The input handle
1231fe1c642dSBill Krier  * should be an LSA policy handle and the name would normally be one
1232fe1c642dSBill Krier  * of the privileges defined in smb_privilege.h
1233fe1c642dSBill Krier  *
1234fe1c642dSBill Krier  * There's something peculiar about the return status from NT servers,
1235fe1c642dSBill Krier  * it's not always present. So for now, I'm ignoring the status in the
1236fe1c642dSBill Krier  * RPC response.
1237fe1c642dSBill Krier  *
1238fe1c642dSBill Krier  * Returns NT status codes.
1239fe1c642dSBill Krier  */
1240fe1c642dSBill Krier DWORD
lsar_lookup_priv_display_name(mlsvc_handle_t * lsa_handle,char * name,char * display_name,int display_len)1241fe1c642dSBill Krier lsar_lookup_priv_display_name(mlsvc_handle_t *lsa_handle, char *name,
1242fe1c642dSBill Krier     char *display_name, int display_len)
1243fe1c642dSBill Krier {
1244fe1c642dSBill Krier 	struct mslsa_LookupPrivDisplayName	arg;
1245fe1c642dSBill Krier 	int	opnum;
1246fe1c642dSBill Krier 	size_t	length;
1247fe1c642dSBill Krier 	DWORD	status;
1248fe1c642dSBill Krier 
1249fe1c642dSBill Krier 	if (lsa_handle == NULL || name == NULL || display_name == NULL)
1250fe1c642dSBill Krier 		return (NT_STATUS_INVALID_PARAMETER);
1251fe1c642dSBill Krier 
1252fe1c642dSBill Krier 	opnum = LSARPC_OPNUM_LookupPrivDisplayName;
1253fe1c642dSBill Krier 
1254fe1c642dSBill Krier 	bzero(&arg, sizeof (struct mslsa_LookupPrivDisplayName));
1255fe1c642dSBill Krier 	(void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
1256fe1c642dSBill Krier 
1257fe1c642dSBill Krier 	length = smb_wcequiv_strlen(name);
1258fe1c642dSBill Krier 	arg.name.length = length;
1259fe1c642dSBill Krier 	arg.name.allosize = length;
1260fe1c642dSBill Krier 	arg.name.str = (unsigned char *)name;
1261fe1c642dSBill Krier 
1262fe1c642dSBill Krier 	arg.client_language = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
1263fe1c642dSBill Krier 	arg.default_language = MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL);
1264fe1c642dSBill Krier 
1265fe1c642dSBill Krier 	if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0)
1266fe1c642dSBill Krier 		status = NT_STATUS_INVALID_PARAMETER;
1267fe1c642dSBill Krier #if 0
1268fe1c642dSBill Krier 	else if (arg.status != 0)
1269fe1c642dSBill Krier 		status = NT_SC_VALUE(arg.status);
1270fe1c642dSBill Krier #endif
1271fe1c642dSBill Krier 	else {
1272fe1c642dSBill Krier 		(void) strlcpy(display_name,
1273fe1c642dSBill Krier 		    (char const *)arg.display_name->str, display_len);
1274fe1c642dSBill Krier 		status = NT_STATUS_SUCCESS;
1275fe1c642dSBill Krier 	}
1276fe1c642dSBill Krier 
1277fe1c642dSBill Krier 	ndr_rpc_release(lsa_handle);
1278fe1c642dSBill Krier 	return (status);
1279fe1c642dSBill Krier }
1280fe1c642dSBill Krier 
1281fe1c642dSBill Krier static void
lsar_set_trusted_domains_ex(struct mslsa_EnumTrustedDomainBufEx * enum_buf,smb_trusted_domains_t * list)1282fe1c642dSBill Krier lsar_set_trusted_domains_ex(struct mslsa_EnumTrustedDomainBufEx *enum_buf,
1283fe1c642dSBill Krier     smb_trusted_domains_t *list)
1284fe1c642dSBill Krier {
1285fe1c642dSBill Krier 	char	sidstr[SMB_SID_STRSZ];
1286fe1c642dSBill Krier 	int	i;
1287fe1c642dSBill Krier 
1288fe1c642dSBill Krier 	if (list == NULL || enum_buf == NULL || enum_buf->entries_read == 0)
1289fe1c642dSBill Krier 		return;
1290fe1c642dSBill Krier 
1291fe1c642dSBill Krier 	list->td_num = 0;
1292fe1c642dSBill Krier 	list->td_domains = calloc(enum_buf->entries_read,
1293fe1c642dSBill Krier 	    sizeof (smb_domain_t));
1294fe1c642dSBill Krier 
1295fe1c642dSBill Krier 	if (list->td_domains == NULL)
1296fe1c642dSBill Krier 		return;
1297fe1c642dSBill Krier 
1298fe1c642dSBill Krier 	list->td_num = enum_buf->entries_read;
1299fe1c642dSBill Krier 	for (i = 0; i < list->td_num; i++) {
1300fe1c642dSBill Krier 		smb_sid_tostr((smb_sid_t *)enum_buf->info[i].sid, sidstr);
1301fe1c642dSBill Krier 		smb_domain_set_trust_info(
1302fe1c642dSBill Krier 		    sidstr,
1303fe1c642dSBill Krier 		    (char *)enum_buf->info[i].nb_name.str,
1304fe1c642dSBill Krier 		    (char *)enum_buf->info[i].dns_name.str,
1305fe1c642dSBill Krier 		    enum_buf->info[i].trust_direction,
1306fe1c642dSBill Krier 		    enum_buf->info[i].trust_type,
1307fe1c642dSBill Krier 		    enum_buf->info[i].trust_attrs,
1308fe1c642dSBill Krier 		    &list->td_domains[i]);
1309fe1c642dSBill Krier 	}
1310fe1c642dSBill Krier }
1311fe1c642dSBill Krier 
1312fe1c642dSBill Krier static void
lsar_set_trusted_domains(struct mslsa_EnumTrustedDomainBuf * enum_buf,smb_trusted_domains_t * list)1313fe1c642dSBill Krier lsar_set_trusted_domains(struct mslsa_EnumTrustedDomainBuf *enum_buf,
1314fe1c642dSBill Krier     smb_trusted_domains_t *list)
1315fe1c642dSBill Krier {
1316fe1c642dSBill Krier 	char	sidstr[SMB_SID_STRSZ];
1317fe1c642dSBill Krier 	int	i;
1318fe1c642dSBill Krier 
1319fe1c642dSBill Krier 	if (list == NULL || enum_buf == NULL || enum_buf->entries_read == 0)
1320fe1c642dSBill Krier 		return;
1321fe1c642dSBill Krier 
1322fe1c642dSBill Krier 	list->td_num = 0;
1323fe1c642dSBill Krier 	list->td_domains = calloc(enum_buf->entries_read,
1324fe1c642dSBill Krier 	    sizeof (smb_domain_t));
1325fe1c642dSBill Krier 
1326fe1c642dSBill Krier 	if (list->td_domains == NULL)
1327fe1c642dSBill Krier 		return;
1328fe1c642dSBill Krier 
1329fe1c642dSBill Krier 	list->td_num = enum_buf->entries_read;
1330fe1c642dSBill Krier 	for (i = 0; i < list->td_num; i++) {
1331fe1c642dSBill Krier 		smb_sid_tostr((smb_sid_t *)enum_buf->info[i].sid, sidstr);
1332fe1c642dSBill Krier 		smb_domain_set_trust_info(
1333fe1c642dSBill Krier 		    sidstr, (char *)enum_buf->info[i].name.str,
1334fe1c642dSBill Krier 		    "", 0, 0, 0, &list->td_domains[i]);
1335fe1c642dSBill Krier 	}
1336fe1c642dSBill Krier }
1337fe1c642dSBill Krier 
1338fe1c642dSBill Krier static void
smb_account_trace(const smb_account_t * info)1339fe1c642dSBill Krier smb_account_trace(const smb_account_t *info)
1340fe1c642dSBill Krier {
1341fe1c642dSBill Krier 	char	sidbuf[SMB_SID_STRSZ];
1342fe1c642dSBill Krier 
1343fe1c642dSBill Krier 	bzero(sidbuf, SMB_SID_STRSZ);
1344fe1c642dSBill Krier 	smb_sid_tostr(info->a_sid, sidbuf);
1345fe1c642dSBill Krier 
1346fe1c642dSBill Krier 	smb_tracef("%s %s %s %lu %s", info->a_domain, info->a_name,
1347fe1c642dSBill Krier 	    sidbuf, info->a_rid, smb_sid_type2str(info->a_type));
1348fe1c642dSBill Krier }
1349