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