1da6c28aaSamw /*
2da6c28aaSamw  * CDDL HEADER START
3da6c28aaSamw  *
4da6c28aaSamw  * The contents of this file are subject to the terms of the
5da6c28aaSamw  * Common Development and Distribution License (the "License").
6da6c28aaSamw  * You may not use this file except in compliance with the License.
7da6c28aaSamw  *
8da6c28aaSamw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9da6c28aaSamw  * or http://www.opensolaris.org/os/licensing.
10da6c28aaSamw  * See the License for the specific language governing permissions
11da6c28aaSamw  * and limitations under the License.
12da6c28aaSamw  *
13da6c28aaSamw  * When distributing Covered Code, include this CDDL HEADER in each
14da6c28aaSamw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15da6c28aaSamw  * If applicable, add the following below this CDDL HEADER, with the
16da6c28aaSamw  * fields enclosed by brackets "[]" replaced with your own identifying
17da6c28aaSamw  * information: Portions Copyright [yyyy] [name of copyright owner]
18da6c28aaSamw  *
19da6c28aaSamw  * CDDL HEADER END
20da6c28aaSamw  */
21148c5f43SAlan Wright 
22da6c28aaSamw /*
23c5866007SKeyur Desai  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24*9242c919SMatt Barden  * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
25da6c28aaSamw  */
26da6c28aaSamw 
27da6c28aaSamw /*
28fe1c642dSBill Krier  * Security Accounts Manager RPC (SAMR) server-side interface.
29fe1c642dSBill Krier  *
30fe1c642dSBill Krier  * The SAM is a hierarchical database:
31fe1c642dSBill Krier  * - If you want to talk to the SAM you need a SAM handle.
32fe1c642dSBill Krier  * - If you want to work with a domain, use the SAM handle.
33fe1c642dSBill Krier  *   to obtain a domain handle.
34fe1c642dSBill Krier  * - Use domain handles to obtain user handles etc.
35da6c28aaSamw  */
36da6c28aaSamw 
37da6c28aaSamw #include <strings.h>
38da6c28aaSamw #include <unistd.h>
39da6c28aaSamw #include <netdb.h>
403db3f65cSamw #include <assert.h>
41c5866007SKeyur Desai #include <grp.h>
423299f39fSGordon Ross #include <libmlrpc/libmlrpc.h>
43da6c28aaSamw #include <smbsrv/libsmb.h>
446537f381Sas #include <smbsrv/libmlsvc.h>
45da6c28aaSamw #include <smbsrv/smbinfo.h>
46da6c28aaSamw #include <smbsrv/nmpipes.h>
47da6c28aaSamw #include <smbsrv/ndl/samrpc.ndl>
488d7e4166Sjose borrego #include <samlib.h>
49da6c28aaSamw 
50da6c28aaSamw /*
51dc20a302Sas  * The keys associated with the various handles dispensed by the SAMR
52dc20a302Sas  * server.  These keys can be used to validate client activity.
53dc20a302Sas  * These values are never passed over the wire so security shouldn't
54dc20a302Sas  * be an issue.
55da6c28aaSamw  */
56dc20a302Sas typedef enum {
57dc20a302Sas 	SAMR_KEY_NULL = 0,
58dc20a302Sas 	SAMR_KEY_CONNECT,
59dc20a302Sas 	SAMR_KEY_DOMAIN,
60dc20a302Sas 	SAMR_KEY_USER,
61dc20a302Sas 	SAMR_KEY_GROUP,
62dc20a302Sas 	SAMR_KEY_ALIAS
63dc20a302Sas } samr_key_t;
64dc20a302Sas 
65dc20a302Sas typedef struct samr_keydata {
66dc20a302Sas 	samr_key_t kd_key;
67a0aa776eSAlan Wright 	smb_domain_type_t kd_type;
68dc20a302Sas 	DWORD kd_rid;
69dc20a302Sas } samr_keydata_t;
70dc20a302Sas 
713db3f65cSamw /*
723db3f65cSamw  * DomainDisplayUser	All user objects (or those derived from user) with
73*9242c919SMatt Barden  *			userAccountControl containing the UF_NORMAL_ACCOUNT bit.
743db3f65cSamw  *
753db3f65cSamw  * DomainDisplayMachine	All user objects (or those derived from user) with
76*9242c919SMatt Barden  *			userAccountControl containing the
77*9242c919SMatt Barden  *			UF_WORKSTATION_TRUST_ACCOUNT or UF_SERVER_TRUST_ACCOUNT
78*9242c919SMatt Barden  *			bit.
793db3f65cSamw  *
803db3f65cSamw  * DomainDisplayGroup	All group objects (or those derived from group) with
81*9242c919SMatt Barden  *			groupType equal to GROUP_TYPE_SECURITY_UNIVERSAL or
82*9242c919SMatt Barden  *			GROUP_TYPE_SECURITY_ACCOUNT.
833db3f65cSamw  *
843db3f65cSamw  * DomainDisplayOemUser	Same as DomainDisplayUser with OEM strings
853db3f65cSamw  *
863db3f65cSamw  * DomainDisplayOemGroup Same as DomainDisplayGroup with OEM strings
873db3f65cSamw  */
883db3f65cSamw typedef enum {
893db3f65cSamw 	DomainDisplayUser = 1,
903db3f65cSamw 	DomainDisplayMachine,
913db3f65cSamw 	DomainDispalyGroup,
923db3f65cSamw 	DomainDisplayOemUser,
933db3f65cSamw 	DomainDisplayOemGroup
943db3f65cSamw } samr_displvl_t;
953db3f65cSamw 
963db3f65cSamw #define	SAMR_VALID_DISPLEVEL(lvl) \
973db3f65cSamw 	(((lvl) >= DomainDisplayUser) && ((lvl) <= DomainDisplayOemGroup))
983db3f65cSamw 
993db3f65cSamw #define	SAMR_SUPPORTED_DISPLEVEL(lvl) (lvl == DomainDisplayUser)
1003db3f65cSamw 
101a0aa776eSAlan Wright static ndr_hdid_t *samr_hdalloc(ndr_xa_t *, samr_key_t, smb_domain_type_t,
102dc20a302Sas     DWORD);
103dc20a302Sas static void samr_hdfree(ndr_xa_t *, ndr_hdid_t *);
104dc20a302Sas static ndr_handle_t *samr_hdlookup(ndr_xa_t *, ndr_hdid_t *, samr_key_t);
105*9242c919SMatt Barden static ndr_handle_t *samr_hdlookup_any(ndr_xa_t *, ndr_hdid_t *);
1068d7e4166Sjose borrego static int samr_call_stub(ndr_xa_t *mxa);
107da6c28aaSamw static DWORD samr_s_enum_local_domains(struct samr_EnumLocalDomain *,
1088d7e4166Sjose borrego     ndr_xa_t *);
109da6c28aaSamw 
1108d7e4166Sjose borrego static ndr_stub_table_t samr_stub_table[];
111da6c28aaSamw 
1128d7e4166Sjose borrego static ndr_service_t samr_service = {
113da6c28aaSamw 	"SAMR",				/* name */
114da6c28aaSamw 	"Security Accounts Manager",	/* desc */
115da6c28aaSamw 	"\\samr",			/* endpoint */
116da6c28aaSamw 	PIPE_LSASS,			/* sec_addr_port */
1178d7e4166Sjose borrego 	"12345778-1234-abcd-ef00-0123456789ac", 1,	/* abstract */
1188d7e4166Sjose borrego 	NDR_TRANSFER_SYNTAX_UUID,		2,	/* transfer */
119da6c28aaSamw 	0,				/* no bind_instance_size */
12055bf511dSas 	NULL,				/* no bind_req() */
12155bf511dSas 	NULL,				/* no unbind_and_close() */
12255bf511dSas 	samr_call_stub,			/* call_stub() */
123da6c28aaSamw 	&TYPEINFO(samr_interface),	/* interface ti */
124da6c28aaSamw 	samr_stub_table			/* stub_table */
125da6c28aaSamw };
126da6c28aaSamw 
127da6c28aaSamw /*
128da6c28aaSamw  * samr_initialize
129da6c28aaSamw  *
130da6c28aaSamw  * This function registers the SAM RPC interface with the RPC runtime
131da6c28aaSamw  * library. It must be called in order to use either the client side
132da6c28aaSamw  * or the server side functions.
133da6c28aaSamw  */
134da6c28aaSamw void
samr_initialize(void)135da6c28aaSamw samr_initialize(void)
136da6c28aaSamw {
1378d7e4166Sjose borrego 	(void) ndr_svc_register(&samr_service);
138da6c28aaSamw }
139da6c28aaSamw 
14055bf511dSas /*
14155bf511dSas  * Custom call_stub to set the stream string policy.
14255bf511dSas  */
14355bf511dSas static int
samr_call_stub(ndr_xa_t * mxa)1448d7e4166Sjose borrego samr_call_stub(ndr_xa_t *mxa)
14555bf511dSas {
1468d7e4166Sjose borrego 	NDS_SETF(&mxa->send_nds, NDS_F_NOTERM);
1478d7e4166Sjose borrego 	NDS_SETF(&mxa->recv_nds, NDS_F_NOTERM);
14855bf511dSas 
1498d7e4166Sjose borrego 	return (ndr_generic_call_stub(mxa));
15055bf511dSas }
15155bf511dSas 
152dc20a302Sas /*
153dc20a302Sas  * Handle allocation wrapper to setup the local context.
154dc20a302Sas  */
155dc20a302Sas static ndr_hdid_t *
samr_hdalloc(ndr_xa_t * mxa,samr_key_t key,smb_domain_type_t domain_type,DWORD rid)156a0aa776eSAlan Wright samr_hdalloc(ndr_xa_t *mxa, samr_key_t key, smb_domain_type_t domain_type,
157dc20a302Sas     DWORD rid)
158dc20a302Sas {
1599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	ndr_handle_t	*hd;
1609fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	ndr_hdid_t	*id;
1619fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	samr_keydata_t	*data;
162dc20a302Sas 
163dc20a302Sas 	if ((data = malloc(sizeof (samr_keydata_t))) == NULL)
164dc20a302Sas 		return (NULL);
165dc20a302Sas 
166dc20a302Sas 	data->kd_key = key;
167dc20a302Sas 	data->kd_type = domain_type;
168dc20a302Sas 	data->kd_rid = rid;
169dc20a302Sas 
1709fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if ((id = ndr_hdalloc(mxa, data)) == NULL) {
1719fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		free(data);
1729fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (NULL);
1739fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
1749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
1759fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if ((hd = ndr_hdlookup(mxa, id)) != NULL)
1769fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		hd->nh_data_free = free;
1779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
1789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	return (id);
179dc20a302Sas }
180dc20a302Sas 
181dc20a302Sas /*
182dc20a302Sas  * Handle deallocation wrapper to free the local context.
183dc20a302Sas  */
184dc20a302Sas static void
samr_hdfree(ndr_xa_t * mxa,ndr_hdid_t * id)185dc20a302Sas samr_hdfree(ndr_xa_t *mxa, ndr_hdid_t *id)
186dc20a302Sas {
187dc20a302Sas 	ndr_handle_t *hd;
188dc20a302Sas 
189dc20a302Sas 	if ((hd = ndr_hdlookup(mxa, id)) != NULL) {
190dc20a302Sas 		free(hd->nh_data);
1919fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		hd->nh_data = NULL;
192dc20a302Sas 		ndr_hdfree(mxa, id);
193dc20a302Sas 	}
194dc20a302Sas }
195dc20a302Sas 
196dc20a302Sas /*
197dc20a302Sas  * Handle lookup wrapper to validate the local context.
198dc20a302Sas  */
199dc20a302Sas static ndr_handle_t *
samr_hdlookup(ndr_xa_t * mxa,ndr_hdid_t * id,samr_key_t key)200dc20a302Sas samr_hdlookup(ndr_xa_t *mxa, ndr_hdid_t *id, samr_key_t key)
201dc20a302Sas {
202dc20a302Sas 	ndr_handle_t *hd;
203dc20a302Sas 	samr_keydata_t *data;
204dc20a302Sas 
205dc20a302Sas 	if ((hd = ndr_hdlookup(mxa, id)) == NULL)
206dc20a302Sas 		return (NULL);
207dc20a302Sas 
208dc20a302Sas 	if ((data = (samr_keydata_t *)hd->nh_data) == NULL)
209dc20a302Sas 		return (NULL);
210dc20a302Sas 
211dc20a302Sas 	if (data->kd_key != key)
212dc20a302Sas 		return (NULL);
213dc20a302Sas 
214dc20a302Sas 	return (hd);
215dc20a302Sas }
216dc20a302Sas 
217*9242c919SMatt Barden /*
218*9242c919SMatt Barden  * Handle lookup wrapper to validate the local context,
219*9242c919SMatt Barden  * but don't limit to one type.
220*9242c919SMatt Barden  */
221*9242c919SMatt Barden static ndr_handle_t *
samr_hdlookup_any(ndr_xa_t * mxa,ndr_hdid_t * id)222*9242c919SMatt Barden samr_hdlookup_any(ndr_xa_t *mxa, ndr_hdid_t *id)
223*9242c919SMatt Barden {
224*9242c919SMatt Barden 	ndr_handle_t *hd;
225*9242c919SMatt Barden 
226*9242c919SMatt Barden 	if ((hd = ndr_hdlookup(mxa, id)) == NULL)
227*9242c919SMatt Barden 		return (NULL);
228*9242c919SMatt Barden 
229*9242c919SMatt Barden 	if (hd->nh_data == NULL)
230*9242c919SMatt Barden 		return (NULL);
231*9242c919SMatt Barden 
232*9242c919SMatt Barden 	return (hd);
233*9242c919SMatt Barden }
234*9242c919SMatt Barden 
235da6c28aaSamw /*
236cb174861Sjoyce mcintosh  * samr_s_Connect
237da6c28aaSamw  *
238da6c28aaSamw  * This is a request to connect to the local SAM database. We don't
239da6c28aaSamw  * support any form of update request and our database doesn't
240da6c28aaSamw  * contain any private information, so there is little point in
241da6c28aaSamw  * doing any access access checking here.
242da6c28aaSamw  *
243da6c28aaSamw  * Return a handle for use with subsequent SAM requests.
244da6c28aaSamw  */
245da6c28aaSamw static int
samr_s_Connect(void * arg,ndr_xa_t * mxa)246cb174861Sjoyce mcintosh samr_s_Connect(void *arg, ndr_xa_t *mxa)
247da6c28aaSamw {
248cb174861Sjoyce mcintosh 	struct samr_Connect *param = arg;
249dc20a302Sas 	ndr_hdid_t *id;
250da6c28aaSamw 
251a0aa776eSAlan Wright 	id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, SMB_DOMAIN_NULL, 0);
252dc20a302Sas 	if (id) {
253dc20a302Sas 		bcopy(id, &param->handle, sizeof (samr_handle_t));
254dc20a302Sas 		param->status = 0;
255dc20a302Sas 	} else {
256dc20a302Sas 		bzero(&param->handle, sizeof (samr_handle_t));
257dc20a302Sas 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
258dc20a302Sas 	}
259da6c28aaSamw 
2608d7e4166Sjose borrego 	return (NDR_DRC_OK);
261da6c28aaSamw }
262da6c28aaSamw 
263da6c28aaSamw /*
264da6c28aaSamw  * samr_s_CloseHandle
265da6c28aaSamw  *
266dc20a302Sas  * Close the SAM interface specified by the handle.
267da6c28aaSamw  * Free the handle and zero out the result handle for the client.
268da6c28aaSamw  */
269da6c28aaSamw static int
samr_s_CloseHandle(void * arg,ndr_xa_t * mxa)2708d7e4166Sjose borrego samr_s_CloseHandle(void *arg, ndr_xa_t *mxa)
271da6c28aaSamw {
272da6c28aaSamw 	struct samr_CloseHandle *param = arg;
273dc20a302Sas 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
274da6c28aaSamw 
275dc20a302Sas 	samr_hdfree(mxa, id);
276da6c28aaSamw 
277da6c28aaSamw 	bzero(&param->result_handle, sizeof (samr_handle_t));
278da6c28aaSamw 	param->status = 0;
2798d7e4166Sjose borrego 	return (NDR_DRC_OK);
280da6c28aaSamw }
281da6c28aaSamw 
282*9242c919SMatt Barden /*
283*9242c919SMatt Barden  * samr_s_QuerySecObject
284*9242c919SMatt Barden  */
285*9242c919SMatt Barden static int
samr_s_QuerySecObject(void * arg,ndr_xa_t * mxa)286*9242c919SMatt Barden samr_s_QuerySecObject(void *arg, ndr_xa_t *mxa)
287*9242c919SMatt Barden {
288*9242c919SMatt Barden 	struct samr_QuerySecObject	*param = arg;
289*9242c919SMatt Barden 	ndr_hdid_t			*id;
290*9242c919SMatt Barden 	uint32_t			status;
291*9242c919SMatt Barden 	struct samr_sec_desc		*sd;
292*9242c919SMatt Barden 
293*9242c919SMatt Barden 	id = (ndr_hdid_t *)&param->obj_handle;
294*9242c919SMatt Barden 	if (samr_hdlookup_any(mxa, id) == NULL) {
295*9242c919SMatt Barden 		status = NT_STATUS_INVALID_HANDLE;
296*9242c919SMatt Barden 		goto QuerySecObjectError;
297*9242c919SMatt Barden 	}
298*9242c919SMatt Barden 
299*9242c919SMatt Barden 	param->sd = NDR_MALLOC(mxa, sizeof (samr_sd_t));
300*9242c919SMatt Barden 	if (param->sd == NULL) {
301*9242c919SMatt Barden 		status = NT_STATUS_NO_MEMORY;
302*9242c919SMatt Barden 		goto QuerySecObjectError;
303*9242c919SMatt Barden 	}
304*9242c919SMatt Barden 	param->sd->length = sizeof (struct samr_sec_desc);
305*9242c919SMatt Barden 
306*9242c919SMatt Barden 	sd = NDR_MALLOC(mxa, param->sd->length);
307*9242c919SMatt Barden 	if (sd == NULL) {
308*9242c919SMatt Barden 		status = NT_STATUS_NO_MEMORY;
309*9242c919SMatt Barden 		goto QuerySecObjectError;
310*9242c919SMatt Barden 	}
311*9242c919SMatt Barden 	bzero(sd, param->sd->length);
312*9242c919SMatt Barden 	sd->Revision = 1;
313*9242c919SMatt Barden 	sd->Control = SE_SELF_RELATIVE;
314*9242c919SMatt Barden 
315*9242c919SMatt Barden 	param->sd->data = (void *)sd;
316*9242c919SMatt Barden 	param->status = NT_STATUS_SUCCESS;
317*9242c919SMatt Barden 	return (NDR_DRC_OK);
318*9242c919SMatt Barden 
319*9242c919SMatt Barden QuerySecObjectError:
320*9242c919SMatt Barden 	bzero(param, sizeof (struct samr_QuerySecObject));
321*9242c919SMatt Barden 	param->status = NT_SC_ERROR(status);
322*9242c919SMatt Barden 	return (NDR_DRC_OK);
323*9242c919SMatt Barden }
324*9242c919SMatt Barden 
325da6c28aaSamw /*
326da6c28aaSamw  * samr_s_LookupDomain
327da6c28aaSamw  *
328da6c28aaSamw  * This is a request to map a domain name to a domain SID. We can map
329da6c28aaSamw  * the primary domain name, our local domain name (hostname) and the
330da6c28aaSamw  * builtin domain names to the appropriate SID. Anything else will be
331da6c28aaSamw  * rejected.
332da6c28aaSamw  */
333da6c28aaSamw static int
samr_s_LookupDomain(void * arg,ndr_xa_t * mxa)3348d7e4166Sjose borrego samr_s_LookupDomain(void *arg, ndr_xa_t *mxa)
335da6c28aaSamw {
336da6c28aaSamw 	struct samr_LookupDomain *param = arg;
337da6c28aaSamw 	char *domain_name;
338a0aa776eSAlan Wright 	smb_domain_t di;
339da6c28aaSamw 
340da6c28aaSamw 	if ((domain_name = (char *)param->domain_name.str) == NULL) {
341da6c28aaSamw 		bzero(param, sizeof (struct samr_LookupDomain));
342da6c28aaSamw 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER);
3438d7e4166Sjose borrego 		return (NDR_DRC_OK);
344da6c28aaSamw 	}
345da6c28aaSamw 
346a0aa776eSAlan Wright 	if (!smb_domain_lookup_name(domain_name, &di)) {
34729bd2886SAlan Wright 		bzero(param, sizeof (struct samr_LookupDomain));
34829bd2886SAlan Wright 		param->status = NT_SC_ERROR(NT_STATUS_NO_SUCH_DOMAIN);
34929bd2886SAlan Wright 		return (NDR_DRC_OK);
350da6c28aaSamw 	}
351da6c28aaSamw 
35229bd2886SAlan Wright 	param->sid = (struct samr_sid *)NDR_SIDDUP(mxa, di.di_binsid);
35329bd2886SAlan Wright 	if (param->sid == NULL) {
35429bd2886SAlan Wright 		bzero(param, sizeof (struct samr_LookupDomain));
35529bd2886SAlan Wright 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
35629bd2886SAlan Wright 		return (NDR_DRC_OK);
357da6c28aaSamw 	}
358da6c28aaSamw 
35929bd2886SAlan Wright 	param->status = NT_STATUS_SUCCESS;
3608d7e4166Sjose borrego 	return (NDR_DRC_OK);
361da6c28aaSamw }
362da6c28aaSamw 
363da6c28aaSamw /*
364da6c28aaSamw  * samr_s_EnumLocalDomains
365da6c28aaSamw  *
366da6c28aaSamw  * This is a request for the local domains supported by this server.
367da6c28aaSamw  * All we do here is validate the handle and set the status. The real
368da6c28aaSamw  * work is done in samr_s_enum_local_domains.
369da6c28aaSamw  */
370da6c28aaSamw static int
samr_s_EnumLocalDomains(void * arg,ndr_xa_t * mxa)3718d7e4166Sjose borrego samr_s_EnumLocalDomains(void *arg, ndr_xa_t *mxa)
372da6c28aaSamw {
373da6c28aaSamw 	struct samr_EnumLocalDomain *param = arg;
374dc20a302Sas 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
375da6c28aaSamw 	DWORD status;
376da6c28aaSamw 
377dc20a302Sas 	if (samr_hdlookup(mxa, id, SAMR_KEY_CONNECT) == NULL)
378da6c28aaSamw 		status = NT_STATUS_ACCESS_DENIED;
379da6c28aaSamw 	else
380da6c28aaSamw 		status = samr_s_enum_local_domains(param, mxa);
381da6c28aaSamw 
382da6c28aaSamw 	if (status == NT_STATUS_SUCCESS) {
383da6c28aaSamw 		param->enum_context = param->info->entries_read;
384da6c28aaSamw 		param->total_entries = param->info->entries_read;
385da6c28aaSamw 		param->status = NT_STATUS_SUCCESS;
386da6c28aaSamw 	} else {
387da6c28aaSamw 		bzero(param, sizeof (struct samr_EnumLocalDomain));
388da6c28aaSamw 		param->status = NT_SC_ERROR(status);
389da6c28aaSamw 	}
390da6c28aaSamw 
3918d7e4166Sjose borrego 	return (NDR_DRC_OK);
392da6c28aaSamw }
393da6c28aaSamw 
394da6c28aaSamw 
395da6c28aaSamw /*
396da6c28aaSamw  * samr_s_enum_local_domains
397da6c28aaSamw  *
398da6c28aaSamw  * This function should only be called via samr_s_EnumLocalDomains to
399da6c28aaSamw  * ensure that the appropriate validation is performed. We will answer
400da6c28aaSamw  * queries about two domains: the local domain, synonymous with the
401da6c28aaSamw  * local hostname, and the BUILTIN domain. So we return these two
402da6c28aaSamw  * strings.
403da6c28aaSamw  *
404da6c28aaSamw  * Returns NT status values.
405da6c28aaSamw  */
406da6c28aaSamw static DWORD
samr_s_enum_local_domains(struct samr_EnumLocalDomain * param,ndr_xa_t * mxa)407da6c28aaSamw samr_s_enum_local_domains(struct samr_EnumLocalDomain *param,
4088d7e4166Sjose borrego     ndr_xa_t *mxa)
409da6c28aaSamw {
410da6c28aaSamw 	struct samr_LocalDomainInfo *info;
411da6c28aaSamw 	struct samr_LocalDomainEntry *entry;
412da6c28aaSamw 	char *hostname;
413da6c28aaSamw 
4148d7e4166Sjose borrego 	hostname = NDR_MALLOC(mxa, NETBIOS_NAME_SZ);
415da6c28aaSamw 	if (hostname == NULL)
416da6c28aaSamw 		return (NT_STATUS_NO_MEMORY);
417da6c28aaSamw 
418b89a8333Snatalie li - Sun Microsystems - Irvine United States 	if (smb_getnetbiosname(hostname, NETBIOS_NAME_SZ) != 0)
419da6c28aaSamw 		return (NT_STATUS_NO_MEMORY);
420da6c28aaSamw 
4218d7e4166Sjose borrego 	entry = NDR_NEWN(mxa, struct samr_LocalDomainEntry, 2);
422da6c28aaSamw 	if (entry == NULL)
423da6c28aaSamw 		return (NT_STATUS_NO_MEMORY);
424da6c28aaSamw 
425da6c28aaSamw 	bzero(entry, (sizeof (struct samr_LocalDomainEntry) * 2));
4268d7e4166Sjose borrego 	(void) NDR_MSTRING(mxa, hostname, (ndr_mstring_t *)&entry[0].name);
4278d7e4166Sjose borrego 	(void) NDR_MSTRING(mxa, "Builtin", (ndr_mstring_t *)&entry[1].name);
428da6c28aaSamw 
4298d7e4166Sjose borrego 	info = NDR_NEW(mxa, struct samr_LocalDomainInfo);
430da6c28aaSamw 	if (info == NULL)
431da6c28aaSamw 		return (NT_STATUS_NO_MEMORY);
432da6c28aaSamw 
433da6c28aaSamw 	info->entries_read = 2;
434da6c28aaSamw 	info->entry = entry;
435da6c28aaSamw 	param->info = info;
436da6c28aaSamw 	return (NT_STATUS_SUCCESS);
437da6c28aaSamw }
438da6c28aaSamw 
439da6c28aaSamw /*
440da6c28aaSamw  * samr_s_OpenDomain
441da6c28aaSamw  *
442da6c28aaSamw  * This is a request to open a domain within the local SAM database.
443dc20a302Sas  * The caller must supply a valid connect handle.
444dc20a302Sas  * We return a handle to be used to access objects within this domain.
445da6c28aaSamw  */
446da6c28aaSamw static int
samr_s_OpenDomain(void * arg,ndr_xa_t * mxa)4478d7e4166Sjose borrego samr_s_OpenDomain(void *arg, ndr_xa_t *mxa)
448da6c28aaSamw {
449da6c28aaSamw 	struct samr_OpenDomain *param = arg;
450dc20a302Sas 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
451a0aa776eSAlan Wright 	smb_domain_t domain;
452da6c28aaSamw 
453dc20a302Sas 	if (samr_hdlookup(mxa, id, SAMR_KEY_CONNECT) == NULL) {
454da6c28aaSamw 		bzero(&param->domain_handle, sizeof (samr_handle_t));
455da6c28aaSamw 		param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
4568d7e4166Sjose borrego 		return (NDR_DRC_OK);
457da6c28aaSamw 	}
458da6c28aaSamw 
459a0aa776eSAlan Wright 	if (!smb_domain_lookup_sid((smb_sid_t *)param->sid, &domain)) {
460da6c28aaSamw 		bzero(&param->domain_handle, sizeof (samr_handle_t));
461da6c28aaSamw 		param->status = NT_SC_ERROR(NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
4628d7e4166Sjose borrego 		return (NDR_DRC_OK);
463da6c28aaSamw 	}
464da6c28aaSamw 
465a0aa776eSAlan Wright 	if ((domain.di_type != SMB_DOMAIN_BUILTIN) &&
466a0aa776eSAlan Wright 	    (domain.di_type != SMB_DOMAIN_LOCAL)) {
467dc20a302Sas 		bzero(&param->domain_handle, sizeof (samr_handle_t));
468dc20a302Sas 		param->status = NT_SC_ERROR(NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
4698d7e4166Sjose borrego 		return (NDR_DRC_OK);
470dc20a302Sas 	}
471da6c28aaSamw 
47229bd2886SAlan Wright 	id = samr_hdalloc(mxa, SAMR_KEY_DOMAIN, domain.di_type, 0);
473dc20a302Sas 	if (id) {
474dc20a302Sas 		bcopy(id, &param->domain_handle, sizeof (samr_handle_t));
475da6c28aaSamw 		param->status = 0;
476dc20a302Sas 	} else {
477da6c28aaSamw 		bzero(&param->domain_handle, sizeof (samr_handle_t));
478dc20a302Sas 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
479da6c28aaSamw 	}
480da6c28aaSamw 
4818d7e4166Sjose borrego 	return (NDR_DRC_OK);
482da6c28aaSamw }
483da6c28aaSamw 
484da6c28aaSamw /*
485da6c28aaSamw  * samr_s_QueryDomainInfo
486da6c28aaSamw  *
487da6c28aaSamw  * The caller should pass a domain handle.
488da6c28aaSamw  *
489da6c28aaSamw  * Windows 95 Server Manager sends requests for levels 6 and 7 when
490da6c28aaSamw  * the services menu item is selected. Level 2 is basically for getting
491da6c28aaSamw  * number of users, groups, and aliases in a domain.
492da6c28aaSamw  * We have no information on what the various information levels mean.
493da6c28aaSamw  */
494da6c28aaSamw static int
samr_s_QueryDomainInfo(void * arg,ndr_xa_t * mxa)4958d7e4166Sjose borrego samr_s_QueryDomainInfo(void *arg, ndr_xa_t *mxa)
496da6c28aaSamw {
497da6c28aaSamw 	struct samr_QueryDomainInfo *param = arg;
498faa1795aSjb 	struct samr_QueryDomainInfoRes *info;
499dc20a302Sas 	ndr_hdid_t *id = (ndr_hdid_t *)&param->domain_handle;
500dc20a302Sas 	ndr_handle_t *hd;
501dc20a302Sas 	samr_keydata_t *data;
502dc20a302Sas 	char *domain;
503b89a8333Snatalie li - Sun Microsystems - Irvine United States 	char hostname[NETBIOS_NAME_SZ];
5043db3f65cSamw 	int alias_cnt, user_cnt;
5053db3f65cSamw 	int rc = 0;
506da6c28aaSamw 
507dc20a302Sas 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
508dc20a302Sas 		bzero(param, sizeof (struct samr_QueryDomainInfo));
509dc20a302Sas 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
5108d7e4166Sjose borrego 		return (NDR_DRC_OK);
511dc20a302Sas 	}
512dc20a302Sas 
5138d7e4166Sjose borrego 	info = NDR_NEW(mxa, struct samr_QueryDomainInfoRes);
514faa1795aSjb 	if (info == NULL) {
515faa1795aSjb 		bzero(param, sizeof (struct samr_QueryDomainInfo));
516faa1795aSjb 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
5178d7e4166Sjose borrego 		return (NDR_DRC_OK);
518faa1795aSjb 	}
519faa1795aSjb 	info->switch_value = param->info_level;
520faa1795aSjb 	param->info = info;
521faa1795aSjb 
522dc20a302Sas 	data = (samr_keydata_t *)hd->nh_data;
523dc20a302Sas 
524dc20a302Sas 	switch (data->kd_type) {
525a0aa776eSAlan Wright 	case SMB_DOMAIN_BUILTIN:
526faa1795aSjb 		domain = "BUILTIN";
5273db3f65cSamw 		user_cnt = 0;
5287f667e74Sjose borrego 		alias_cnt = smb_sam_grp_cnt(data->kd_type);
529dc20a302Sas 		break;
530dc20a302Sas 
531a0aa776eSAlan Wright 	case SMB_DOMAIN_LOCAL:
532b89a8333Snatalie li - Sun Microsystems - Irvine United States 		rc = smb_getnetbiosname(hostname, sizeof (hostname));
5333db3f65cSamw 		if (rc == 0) {
5343db3f65cSamw 			domain = hostname;
5357f667e74Sjose borrego 			user_cnt = smb_sam_usr_cnt();
5367f667e74Sjose borrego 			alias_cnt = smb_sam_grp_cnt(data->kd_type);
537dc20a302Sas 		}
538dc20a302Sas 		break;
539dc20a302Sas 
540dc20a302Sas 	default:
541da6c28aaSamw 		bzero(param, sizeof (struct samr_QueryDomainInfo));
542da6c28aaSamw 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
5438d7e4166Sjose borrego 		return (NDR_DRC_OK);
544da6c28aaSamw 	}
545da6c28aaSamw 
5463db3f65cSamw 	if (rc != 0) {
5473db3f65cSamw 		bzero(param, sizeof (struct samr_QueryDomainInfo));
5483db3f65cSamw 		param->status = NT_SC_ERROR(NT_STATUS_INTERNAL_ERROR);
5498d7e4166Sjose borrego 		return (NDR_DRC_OK);
5503db3f65cSamw 	}
5513db3f65cSamw 
552da6c28aaSamw 	switch (param->info_level) {
553da6c28aaSamw 	case SAMR_QUERY_DOMAIN_INFO_6:
554faa1795aSjb 		info->ru.info6.unknown1 = 0x00000000;
555faa1795aSjb 		info->ru.info6.unknown2 = 0x00147FB0;
556faa1795aSjb 		info->ru.info6.unknown3 = 0x00000000;
557faa1795aSjb 		info->ru.info6.unknown4 = 0x00000000;
558faa1795aSjb 		info->ru.info6.unknown5 = 0x00000000;
559da6c28aaSamw 		param->status = NT_STATUS_SUCCESS;
560da6c28aaSamw 		break;
561da6c28aaSamw 
562da6c28aaSamw 	case SAMR_QUERY_DOMAIN_INFO_7:
563faa1795aSjb 		info->ru.info7.unknown1 = 0x00000003;
564da6c28aaSamw 		param->status = NT_STATUS_SUCCESS;
565da6c28aaSamw 		break;
566da6c28aaSamw 
567da6c28aaSamw 	case SAMR_QUERY_DOMAIN_INFO_2:
568faa1795aSjb 		info->ru.info2.unknown1 = 0x00000000;
569faa1795aSjb 		info->ru.info2.unknown2 = 0x80000000;
570da6c28aaSamw 
5718d7e4166Sjose borrego 		(void) NDR_MSTRING(mxa, "",
5728d7e4166Sjose borrego 		    (ndr_mstring_t *)&(info->ru.info2.s1));
5738d7e4166Sjose borrego 		(void) NDR_MSTRING(mxa, domain,
5748d7e4166Sjose borrego 		    (ndr_mstring_t *)&(info->ru.info2.domain));
5758d7e4166Sjose borrego 		(void) NDR_MSTRING(mxa, "",
5768d7e4166Sjose borrego 		    (ndr_mstring_t *)&(info->ru.info2.s2));
577da6c28aaSamw 
578faa1795aSjb 		info->ru.info2.sequence_num = 0x0000002B;
579faa1795aSjb 		info->ru.info2.unknown3 = 0x00000000;
580faa1795aSjb 		info->ru.info2.unknown4 = 0x00000001;
581faa1795aSjb 		info->ru.info2.unknown5 = 0x00000003;
582faa1795aSjb 		info->ru.info2.unknown6 = 0x00000001;
5833db3f65cSamw 		info->ru.info2.num_users = user_cnt;
584faa1795aSjb 		info->ru.info2.num_groups = 0;
585faa1795aSjb 		info->ru.info2.num_aliases = alias_cnt;
586da6c28aaSamw 		param->status = NT_STATUS_SUCCESS;
587da6c28aaSamw 		break;
588da6c28aaSamw 
589da6c28aaSamw 	default:
590da6c28aaSamw 		bzero(param, sizeof (struct samr_QueryDomainInfo));
5918d7e4166Sjose borrego 		return (NDR_DRC_FAULT_REQUEST_OPNUM_INVALID);
592da6c28aaSamw 	};
593da6c28aaSamw 
5948d7e4166Sjose borrego 	return (NDR_DRC_OK);
595da6c28aaSamw }
596da6c28aaSamw 
597f96bd5c8SAlan Wright /*
598f96bd5c8SAlan Wright  * QueryInfoDomain2: Identical to QueryDomainInfo.
599f96bd5c8SAlan Wright  */
600f96bd5c8SAlan Wright static int
samr_s_QueryInfoDomain2(void * arg,ndr_xa_t * mxa)601f96bd5c8SAlan Wright samr_s_QueryInfoDomain2(void *arg, ndr_xa_t *mxa)
602f96bd5c8SAlan Wright {
603f96bd5c8SAlan Wright 	return (samr_s_QueryDomainInfo(arg, mxa));
604f96bd5c8SAlan Wright }
605f96bd5c8SAlan Wright 
606da6c28aaSamw /*
6077f667e74Sjose borrego  * Looks up the given name in the specified domain which could
6087f667e74Sjose borrego  * be either the built-in or local domain.
609da6c28aaSamw  *
6107f667e74Sjose borrego  * CAVEAT: this function should be able to handle a list of
6117f667e74Sjose borrego  * names but currently it can only handle one name at a time.
612da6c28aaSamw  */
613da6c28aaSamw static int
samr_s_LookupNames(void * arg,ndr_xa_t * mxa)6148d7e4166Sjose borrego samr_s_LookupNames(void *arg, ndr_xa_t *mxa)
615da6c28aaSamw {
616da6c28aaSamw 	struct samr_LookupNames *param = arg;
617dc20a302Sas 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
618dc20a302Sas 	ndr_handle_t *hd;
619dc20a302Sas 	samr_keydata_t *data;
6207f667e74Sjose borrego 	smb_account_t account;
6216537f381Sas 	smb_wka_t *wka;
622dc20a302Sas 	uint32_t status = NT_STATUS_SUCCESS;
623da6c28aaSamw 
624dc20a302Sas 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL)
625dc20a302Sas 		status = NT_STATUS_INVALID_HANDLE;
626da6c28aaSamw 
627dc20a302Sas 	if (param->n_entry != 1)
628dc20a302Sas 		status = NT_STATUS_ACCESS_DENIED;
629da6c28aaSamw 
630da6c28aaSamw 	if (param->name.str == NULL) {
631da6c28aaSamw 		/*
632dc20a302Sas 		 * Windows NT returns NT_STATUS_NONE_MAPPED.
633da6c28aaSamw 		 * Windows 2000 returns STATUS_INVALID_ACCOUNT_NAME.
634da6c28aaSamw 		 */
635dc20a302Sas 		status = NT_STATUS_NONE_MAPPED;
636dc20a302Sas 	}
637dc20a302Sas 
638dc20a302Sas 	if (status != NT_STATUS_SUCCESS) {
639dc20a302Sas 		bzero(param, sizeof (struct samr_LookupNames));
640dc20a302Sas 		param->status = NT_SC_ERROR(status);
6418d7e4166Sjose borrego 		return (NDR_DRC_OK);
642da6c28aaSamw 	}
643da6c28aaSamw 
6448d7e4166Sjose borrego 	param->rids.rid = NDR_NEW(mxa, DWORD);
6458d7e4166Sjose borrego 	param->rid_types.rid_type = NDR_NEW(mxa, DWORD);
646da6c28aaSamw 
647dc20a302Sas 	data = (samr_keydata_t *)hd->nh_data;
648da6c28aaSamw 
649dc20a302Sas 	switch (data->kd_type) {
650a0aa776eSAlan Wright 	case SMB_DOMAIN_BUILTIN:
651f96bd5c8SAlan Wright 		wka = smb_wka_lookup_builtin((char *)param->name.str);
652dc20a302Sas 		if (wka != NULL) {
653da6c28aaSamw 			param->rids.n_entry = 1;
6546537f381Sas 			(void) smb_sid_getrid(wka->wka_binsid,
6556537f381Sas 			    &param->rids.rid[0]);
656da6c28aaSamw 			param->rid_types.n_entry = 1;
6576537f381Sas 			param->rid_types.rid_type[0] = wka->wka_type;
658da6c28aaSamw 			param->status = NT_STATUS_SUCCESS;
6598d7e4166Sjose borrego 			return (NDR_DRC_OK);
660da6c28aaSamw 		}
661dc20a302Sas 		break;
662da6c28aaSamw 
663a0aa776eSAlan Wright 	case SMB_DOMAIN_LOCAL:
6647f667e74Sjose borrego 		status = smb_sam_lookup_name(NULL, (char *)param->name.str,
6657f667e74Sjose borrego 		    SidTypeUnknown, &account);
6667f667e74Sjose borrego 		if (status == NT_STATUS_SUCCESS) {
667da6c28aaSamw 			param->rids.n_entry = 1;
6687f667e74Sjose borrego 			param->rids.rid[0] = account.a_rid;
669da6c28aaSamw 			param->rid_types.n_entry = 1;
6707f667e74Sjose borrego 			param->rid_types.rid_type[0] = account.a_type;
671da6c28aaSamw 			param->status = NT_STATUS_SUCCESS;
6727f667e74Sjose borrego 			smb_account_free(&account);
6738d7e4166Sjose borrego 			return (NDR_DRC_OK);
674da6c28aaSamw 		}
675dc20a302Sas 		break;
676da6c28aaSamw 
677dc20a302Sas 	default:
678dc20a302Sas 		bzero(param, sizeof (struct samr_LookupNames));
679dc20a302Sas 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
6808d7e4166Sjose borrego 		return (NDR_DRC_OK);
681da6c28aaSamw 	}
682da6c28aaSamw 
683da6c28aaSamw 	param->rids.n_entry = 0;
684da6c28aaSamw 	param->rid_types.n_entry = 0;
685da6c28aaSamw 	param->status = NT_SC_ERROR(NT_STATUS_NONE_MAPPED);
6868d7e4166Sjose borrego 	return (NDR_DRC_OK);
687da6c28aaSamw }
688da6c28aaSamw 
689da6c28aaSamw /*
690da6c28aaSamw  * samr_s_OpenUser
691da6c28aaSamw  *
692da6c28aaSamw  * This is a request to open a user within a specified domain in the
693da6c28aaSamw  * local SAM database. The caller must supply a valid domain handle,
694da6c28aaSamw  * obtained via a successful domain open request. The user is
695da6c28aaSamw  * specified by the rid in the request.
696da6c28aaSamw  */
697da6c28aaSamw static int
samr_s_OpenUser(void * arg,ndr_xa_t * mxa)6988d7e4166Sjose borrego samr_s_OpenUser(void *arg, ndr_xa_t *mxa)
699da6c28aaSamw {
700da6c28aaSamw 	struct samr_OpenUser *param = arg;
701dc20a302Sas 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
702dc20a302Sas 	ndr_handle_t *hd;
703dc20a302Sas 	samr_keydata_t *data;
704da6c28aaSamw 
705dc20a302Sas 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
706da6c28aaSamw 		bzero(&param->user_handle, sizeof (samr_handle_t));
707dc20a302Sas 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
7088d7e4166Sjose borrego 		return (NDR_DRC_OK);
709da6c28aaSamw 	}
710da6c28aaSamw 
711dc20a302Sas 	data = (samr_keydata_t *)hd->nh_data;
712dc20a302Sas 
713dc20a302Sas 	id = samr_hdalloc(mxa, SAMR_KEY_USER, data->kd_type, param->rid);
714dc20a302Sas 	if (id == NULL) {
715dc20a302Sas 		bzero(&param->user_handle, sizeof (samr_handle_t));
716dc20a302Sas 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
717dc20a302Sas 	} else {
718dc20a302Sas 		bcopy(id, &param->user_handle, sizeof (samr_handle_t));
719fe1c642dSBill Krier 		param->status = NT_STATUS_SUCCESS;
720dc20a302Sas 	}
721da6c28aaSamw 
7228d7e4166Sjose borrego 	return (NDR_DRC_OK);
723da6c28aaSamw }
724da6c28aaSamw 
725da6c28aaSamw /*
726da6c28aaSamw  * samr_s_DeleteUser
727da6c28aaSamw  *
728dc20a302Sas  * Request to delete a user within a specified domain in the local
729dc20a302Sas  * SAM database.  The caller should supply a valid user handle.
730da6c28aaSamw  */
731da6c28aaSamw /*ARGSUSED*/
732da6c28aaSamw static int
samr_s_DeleteUser(void * arg,ndr_xa_t * mxa)7338d7e4166Sjose borrego samr_s_DeleteUser(void *arg, ndr_xa_t *mxa)
734da6c28aaSamw {
735da6c28aaSamw 	struct samr_DeleteUser *param = arg;
736da6c28aaSamw 
737dc20a302Sas 	bzero(param, sizeof (struct samr_DeleteUser));
738da6c28aaSamw 	param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
7398d7e4166Sjose borrego 	return (NDR_DRC_OK);
740da6c28aaSamw }
741da6c28aaSamw 
742da6c28aaSamw /*
743da6c28aaSamw  * samr_s_QueryUserInfo
744da6c28aaSamw  *
745da6c28aaSamw  * Returns:
746da6c28aaSamw  * NT_STATUS_SUCCESS
747da6c28aaSamw  * NT_STATUS_ACCESS_DENIED
748da6c28aaSamw  * NT_STATUS_INVALID_INFO_CLASS
749da6c28aaSamw  */
750da6c28aaSamw /*ARGSUSED*/
751da6c28aaSamw static int
samr_s_QueryUserInfo(void * arg,ndr_xa_t * mxa)7528d7e4166Sjose borrego samr_s_QueryUserInfo(void *arg, ndr_xa_t *mxa)
753da6c28aaSamw {
754fe1c642dSBill Krier 	struct samr_QueryUserInfo	*param = arg;
755fe1c642dSBill Krier 	struct samr_QueryUserInfo21	*all_info;
756fe1c642dSBill Krier 	ndr_hdid_t			*id;
757fe1c642dSBill Krier 	ndr_handle_t			*hd;
758fe1c642dSBill Krier 	samr_keydata_t			*data;
759fe1c642dSBill Krier 	smb_domain_t			di;
760fe1c642dSBill Krier 	smb_account_t			account;
761fe1c642dSBill Krier 	smb_sid_t			*sid;
762fe1c642dSBill Krier 	uint32_t			status;
763fe1c642dSBill Krier 
764fe1c642dSBill Krier 	id = (ndr_hdid_t *)&param->user_handle;
765fe1c642dSBill Krier 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_USER)) == NULL) {
766fe1c642dSBill Krier 		status = NT_STATUS_INVALID_HANDLE;
767fe1c642dSBill Krier 		goto QueryUserInfoError;
768fe1c642dSBill Krier 	}
769fe1c642dSBill Krier 
770fe1c642dSBill Krier 	data = (samr_keydata_t *)hd->nh_data;
771fe1c642dSBill Krier 
772fe1c642dSBill Krier 	if (param->switch_value != SAMR_QUERY_USER_ALL_INFO) {
773fe1c642dSBill Krier 		status = NT_STATUS_ACCESS_DENIED;
774fe1c642dSBill Krier 		goto QueryUserInfoError;
775fe1c642dSBill Krier 	}
776da6c28aaSamw 
777fe1c642dSBill Krier 	if (!smb_domain_lookup_type(SMB_DOMAIN_LOCAL, &di)) {
778fe1c642dSBill Krier 		status = NT_STATUS_ACCESS_DENIED;
779fe1c642dSBill Krier 		goto QueryUserInfoError;
780fe1c642dSBill Krier 	}
781fe1c642dSBill Krier 
782fe1c642dSBill Krier 	if ((sid = smb_sid_splice(di.di_binsid, data->kd_rid)) == NULL) {
783fe1c642dSBill Krier 		status = NT_STATUS_ACCESS_DENIED;
784fe1c642dSBill Krier 		goto QueryUserInfoError;
785fe1c642dSBill Krier 	}
786fe1c642dSBill Krier 
787fe1c642dSBill Krier 	if (smb_sam_lookup_sid(sid, &account) != NT_STATUS_SUCCESS) {
788fe1c642dSBill Krier 		status = NT_STATUS_ACCESS_DENIED;
789fe1c642dSBill Krier 		goto QueryUserInfoError;
790fe1c642dSBill Krier 	}
791fe1c642dSBill Krier 
792fe1c642dSBill Krier 	all_info = &param->ru.info21;
793fe1c642dSBill Krier 	bzero(all_info, sizeof (struct samr_QueryUserInfo21));
794fe1c642dSBill Krier 
795*9242c919SMatt Barden 	all_info->WhichFields = SAMR_USER_ALL_USERNAME | SAMR_USER_ALL_USERID |
796*9242c919SMatt Barden 	    SAMR_USER_ALL_FULLNAME | SAMR_USER_ALL_USERACCOUNTCONTROL |
797*9242c919SMatt Barden 	    SAMR_USER_ALL_ADMINCOMMENT;
798fe1c642dSBill Krier 
799fe1c642dSBill Krier 	(void) NDR_MSTRING(mxa, account.a_name,
800fe1c642dSBill Krier 	    (ndr_mstring_t *)&all_info->UserName);
801*9242c919SMatt Barden 	(void) NDR_MSTRING(mxa, account.a_name,
802*9242c919SMatt Barden 	    (ndr_mstring_t *)&all_info->FullName);
803*9242c919SMatt Barden 	(void) NDR_MSTRING(mxa, "",
804*9242c919SMatt Barden 	    (ndr_mstring_t *)&all_info->AdminComment);
805fe1c642dSBill Krier 
806*9242c919SMatt Barden 	all_info->UserId = data->kd_rid;
807*9242c919SMatt Barden 	all_info->UserAccountControl = SAMR_AF_NORMAL_ACCOUNT |
808*9242c919SMatt Barden 	    SAMR_AF_DONT_EXPIRE_PASSWD;
809*9242c919SMatt Barden 	if ((account.a_flags & SMB_PWF_DISABLE) != 0)
810*9242c919SMatt Barden 		all_info->UserAccountControl |= SAMR_AF_ACCOUNTDISABLE;
811fe1c642dSBill Krier 
812fe1c642dSBill Krier 	param->address = 1;
813fe1c642dSBill Krier 	param->switch_index = SAMR_QUERY_USER_ALL_INFO;
814fe1c642dSBill Krier 	param->status = NT_STATUS_SUCCESS;
8159fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_account_free(&account);
8169fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_sid_free(sid);
817fe1c642dSBill Krier 	return (NDR_DRC_OK);
818fe1c642dSBill Krier 
819fe1c642dSBill Krier QueryUserInfoError:
8209fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_sid_free(sid);
821da6c28aaSamw 	bzero(param, sizeof (struct samr_QueryUserInfo));
822fe1c642dSBill Krier 	param->status = NT_SC_ERROR(status);
8238d7e4166Sjose borrego 	return (NDR_DRC_OK);
824da6c28aaSamw }
825da6c28aaSamw 
826da6c28aaSamw /*
827da6c28aaSamw  * samr_s_QueryUserGroups
828da6c28aaSamw  *
829dc20a302Sas  * Request the list of groups of which a user is a member.
830dc20a302Sas  * The user is identified from the handle, which contains an
831dc20a302Sas  * rid in the discriminator field. Note that this is a local user.
832da6c28aaSamw  */
833da6c28aaSamw static int
samr_s_QueryUserGroups(void * arg,ndr_xa_t * mxa)8348d7e4166Sjose borrego samr_s_QueryUserGroups(void *arg, ndr_xa_t *mxa)
835da6c28aaSamw {
836da6c28aaSamw 	struct samr_QueryUserGroups *param = arg;
837da6c28aaSamw 	struct samr_UserGroupInfo *info;
838dc20a302Sas 	struct samr_UserGroups *group;
839dc20a302Sas 	ndr_hdid_t *id = (ndr_hdid_t *)&param->user_handle;
840dc20a302Sas 	ndr_handle_t *hd;
841dc20a302Sas 	samr_keydata_t *data;
8426537f381Sas 	smb_sid_t *user_sid = NULL;
843dc20a302Sas 	smb_group_t grp;
844dc20a302Sas 	smb_giter_t gi;
845a0aa776eSAlan Wright 	smb_domain_t di;
846dc20a302Sas 	uint32_t status;
847dc20a302Sas 	int size;
848dc20a302Sas 	int ngrp_max;
849dc20a302Sas 
850dc20a302Sas 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_USER)) == NULL) {
851dc20a302Sas 		status = NT_STATUS_ACCESS_DENIED;
852dc20a302Sas 		goto query_error;
853dc20a302Sas 	}
854da6c28aaSamw 
855dc20a302Sas 	data = (samr_keydata_t *)hd->nh_data;
856dc20a302Sas 	switch (data->kd_type) {
857a0aa776eSAlan Wright 	case SMB_DOMAIN_BUILTIN:
858a0aa776eSAlan Wright 	case SMB_DOMAIN_LOCAL:
859a0aa776eSAlan Wright 		if (!smb_domain_lookup_type(data->kd_type, &di)) {
86029bd2886SAlan Wright 			status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
861dc20a302Sas 			goto query_error;
862dc20a302Sas 		}
863dc20a302Sas 		break;
864dc20a302Sas 	default:
865dc20a302Sas 		status = NT_STATUS_INVALID_HANDLE;
866dc20a302Sas 		goto query_error;
867dc20a302Sas 	}
868dc20a302Sas 
86929bd2886SAlan Wright 	user_sid = smb_sid_splice(di.di_binsid, data->kd_rid);
870dc20a302Sas 	if (user_sid == NULL) {
871dc20a302Sas 		status = NT_STATUS_NO_MEMORY;
872dc20a302Sas 		goto query_error;
873da6c28aaSamw 	}
874da6c28aaSamw 
8758d7e4166Sjose borrego 	info = NDR_NEW(mxa, struct samr_UserGroupInfo);
876dc20a302Sas 	if (info == NULL) {
877dc20a302Sas 		status = NT_STATUS_NO_MEMORY;
878dc20a302Sas 		goto query_error;
879dc20a302Sas 	}
880dc20a302Sas 	bzero(info, sizeof (struct samr_UserGroupInfo));
881da6c28aaSamw 
882dc20a302Sas 	size = 32 * 1024;
8838d7e4166Sjose borrego 	info->groups = NDR_MALLOC(mxa, size);
884dc20a302Sas 	if (info->groups == NULL) {
885dc20a302Sas 		status = NT_STATUS_NO_MEMORY;
886dc20a302Sas 		goto query_error;
887dc20a302Sas 	}
888dc20a302Sas 	ngrp_max = size / sizeof (struct samr_UserGroups);
889da6c28aaSamw 
890dc20a302Sas 	if (smb_lgrp_iteropen(&gi) != SMB_LGRP_SUCCESS) {
891dc20a302Sas 		status = NT_STATUS_INTERNAL_ERROR;
892dc20a302Sas 		goto query_error;
893da6c28aaSamw 	}
894da6c28aaSamw 
895dc20a302Sas 	info->n_entry = 0;
896dc20a302Sas 	group = info->groups;
897dc20a302Sas 	while ((info->n_entry < ngrp_max) &&
898dc20a302Sas 	    (smb_lgrp_iterate(&gi, &grp) == SMB_LGRP_SUCCESS)) {
899dc20a302Sas 		if (smb_lgrp_is_member(&grp, user_sid)) {
900dc20a302Sas 			group->rid = grp.sg_rid;
901dc20a302Sas 			group->attr = grp.sg_attr;
902dc20a302Sas 			group++;
903dc20a302Sas 			info->n_entry++;
904dc20a302Sas 		}
905dc20a302Sas 		smb_lgrp_free(&grp);
906dc20a302Sas 	}
907dc20a302Sas 	smb_lgrp_iterclose(&gi);
908dc20a302Sas 
909dc20a302Sas 	free(user_sid);
910dc20a302Sas 	param->info = info;
911dc20a302Sas 	param->status = NT_STATUS_SUCCESS;
9128d7e4166Sjose borrego 	return (NDR_DRC_OK);
913dc20a302Sas 
914dc20a302Sas query_error:
915dc20a302Sas 	free(user_sid);
916dc20a302Sas 	bzero(param, sizeof (struct samr_QueryUserGroups));
917dc20a302Sas 	param->status = NT_SC_ERROR(status);
9188d7e4166Sjose borrego 	return (NDR_DRC_OK);
919da6c28aaSamw }
920da6c28aaSamw 
921da6c28aaSamw /*
922da6c28aaSamw  * samr_s_OpenGroup
923da6c28aaSamw  *
924da6c28aaSamw  * This is a request to open a group within the specified domain in the
925da6c28aaSamw  * local SAM database. The caller must supply a valid domain handle,
926da6c28aaSamw  * obtained via a successful domain open request. The group is
927da6c28aaSamw  * specified by the rid in the request. If this is a local RID it
928da6c28aaSamw  * should already be encoded with type information.
929da6c28aaSamw  *
930da6c28aaSamw  * We return a handle to be used to access information about this group.
931da6c28aaSamw  */
932da6c28aaSamw static int
samr_s_OpenGroup(void * arg,ndr_xa_t * mxa)9338d7e4166Sjose borrego samr_s_OpenGroup(void *arg, ndr_xa_t *mxa)
934da6c28aaSamw {
935da6c28aaSamw 	struct samr_OpenGroup *param = arg;
936dc20a302Sas 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
937dc20a302Sas 	ndr_handle_t *hd;
938dc20a302Sas 	samr_keydata_t *data;
939da6c28aaSamw 
940dc20a302Sas 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
941da6c28aaSamw 		bzero(&param->group_handle, sizeof (samr_handle_t));
942dc20a302Sas 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
9438d7e4166Sjose borrego 		return (NDR_DRC_OK);
944da6c28aaSamw 	}
945da6c28aaSamw 
946dc20a302Sas 	data = (samr_keydata_t *)hd->nh_data;
947dc20a302Sas 	id = samr_hdalloc(mxa, SAMR_KEY_GROUP, data->kd_type, param->rid);
948dc20a302Sas 
949dc20a302Sas 	if (id) {
950dc20a302Sas 		bcopy(id, &param->group_handle, sizeof (samr_handle_t));
951dc20a302Sas 		param->status = 0;
952dc20a302Sas 	} else {
953dc20a302Sas 		bzero(&param->group_handle, sizeof (samr_handle_t));
954dc20a302Sas 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
955dc20a302Sas 	}
956da6c28aaSamw 
9578d7e4166Sjose borrego 	return (NDR_DRC_OK);
958da6c28aaSamw }
959da6c28aaSamw 
960c5866007SKeyur Desai /*
961c5866007SKeyur Desai  * samr_s_AddAliasMember
962c5866007SKeyur Desai  *
963c5866007SKeyur Desai  * Add a member to a local SAM group.
964c5866007SKeyur Desai  * The caller must supply a valid group handle.
965c5866007SKeyur Desai  * The member is specified by the sid in the request.
966c5866007SKeyur Desai  */
967c5866007SKeyur Desai static int
samr_s_AddAliasMember(void * arg,ndr_xa_t * mxa)968c5866007SKeyur Desai samr_s_AddAliasMember(void *arg, ndr_xa_t *mxa)
969c5866007SKeyur Desai {
970c5866007SKeyur Desai 	struct samr_AddAliasMember *param = arg;
971c5866007SKeyur Desai 	ndr_hdid_t *id = (ndr_hdid_t *)&param->alias_handle;
972c5866007SKeyur Desai 	ndr_handle_t *hd;
973c5866007SKeyur Desai 	samr_keydata_t *data;
974c5866007SKeyur Desai 	smb_group_t grp;
975c5866007SKeyur Desai 	uint32_t rc;
976c5866007SKeyur Desai 	uint32_t status = NT_STATUS_SUCCESS;
977c5866007SKeyur Desai 
978c5866007SKeyur Desai 	if (param->sid == NULL) {
979c5866007SKeyur Desai 		bzero(param, sizeof (struct samr_AddAliasMember));
980c5866007SKeyur Desai 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER);
981c5866007SKeyur Desai 		return (NDR_DRC_OK);
982c5866007SKeyur Desai 	}
983c5866007SKeyur Desai 
984c5866007SKeyur Desai 	if (!ndr_is_admin(mxa)) {
985c5866007SKeyur Desai 		bzero(param, sizeof (struct samr_AddAliasMember));
986c5866007SKeyur Desai 		param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
987c5866007SKeyur Desai 		return (NDR_DRC_OK);
988c5866007SKeyur Desai 	}
989c5866007SKeyur Desai 
990c5866007SKeyur Desai 
991c5866007SKeyur Desai 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_ALIAS)) == NULL) {
992c5866007SKeyur Desai 		bzero(param, sizeof (struct samr_AddAliasMember));
993c5866007SKeyur Desai 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
994c5866007SKeyur Desai 		return (NDR_DRC_OK);
995c5866007SKeyur Desai 	}
996c5866007SKeyur Desai 
997c5866007SKeyur Desai 	data = (samr_keydata_t *)hd->nh_data;
998c5866007SKeyur Desai 	rc = smb_lgrp_getbyrid(data->kd_rid, data->kd_type, &grp);
999c5866007SKeyur Desai 	if (rc != SMB_LGRP_SUCCESS) {
1000c5866007SKeyur Desai 		bzero(param, sizeof (struct samr_AddAliasMember));
1001c5866007SKeyur Desai 		status = smb_lgrp_err_to_ntstatus(rc);
1002c5866007SKeyur Desai 		param->status = NT_SC_ERROR(status);
1003c5866007SKeyur Desai 		return (NDR_DRC_OK);
1004c5866007SKeyur Desai 	}
1005c5866007SKeyur Desai 
1006c5866007SKeyur Desai 	rc = smb_lgrp_add_member(grp.sg_name,
1007c5866007SKeyur Desai 	    (smb_sid_t *)param->sid, SidTypeUser);
1008c5866007SKeyur Desai 	if (rc != SMB_LGRP_SUCCESS) {
1009c5866007SKeyur Desai 		bzero(param, sizeof (struct samr_AddAliasMember));
1010c5866007SKeyur Desai 		status = smb_lgrp_err_to_ntstatus(rc);
1011c5866007SKeyur Desai 		param->status = NT_SC_ERROR(status);
1012c5866007SKeyur Desai 	}
1013c5866007SKeyur Desai 	smb_lgrp_free(&grp);
1014c5866007SKeyur Desai 
1015c5866007SKeyur Desai 	param->status = status;
1016c5866007SKeyur Desai 	return (NDR_DRC_OK);
1017c5866007SKeyur Desai }
1018c5866007SKeyur Desai 
1019c5866007SKeyur Desai /*
1020c5866007SKeyur Desai  * samr_s_DeleteAliasMember
1021c5866007SKeyur Desai  *
1022c5866007SKeyur Desai  * Delete a member from a local SAM group.
1023c5866007SKeyur Desai  * The caller must supply a valid group handle.
1024c5866007SKeyur Desai  * The member is specified by the sid in the request.
1025c5866007SKeyur Desai  */
1026c5866007SKeyur Desai static int
samr_s_DeleteAliasMember(void * arg,ndr_xa_t * mxa)1027c5866007SKeyur Desai samr_s_DeleteAliasMember(void *arg, ndr_xa_t *mxa)
1028c5866007SKeyur Desai {
1029c5866007SKeyur Desai 	struct samr_DeleteAliasMember *param = arg;
1030c5866007SKeyur Desai 	ndr_hdid_t *id = (ndr_hdid_t *)&param->alias_handle;
1031c5866007SKeyur Desai 	ndr_handle_t *hd;
1032c5866007SKeyur Desai 	samr_keydata_t *data;
1033c5866007SKeyur Desai 	smb_group_t grp;
1034c5866007SKeyur Desai 	uint32_t rc;
1035c5866007SKeyur Desai 	uint32_t status = NT_STATUS_SUCCESS;
1036c5866007SKeyur Desai 
1037c5866007SKeyur Desai 	if (param->sid == NULL) {
1038c5866007SKeyur Desai 		bzero(param, sizeof (struct samr_DeleteAliasMember));
1039c5866007SKeyur Desai 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER);
1040c5866007SKeyur Desai 		return (NDR_DRC_OK);
1041c5866007SKeyur Desai 	}
1042c5866007SKeyur Desai 
1043c5866007SKeyur Desai 	if (!ndr_is_admin(mxa)) {
1044c5866007SKeyur Desai 		bzero(param, sizeof (struct samr_DeleteAliasMember));
1045c5866007SKeyur Desai 		param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
1046c5866007SKeyur Desai 		return (NDR_DRC_OK);
1047c5866007SKeyur Desai 	}
1048c5866007SKeyur Desai 
1049c5866007SKeyur Desai 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_ALIAS)) == NULL) {
1050c5866007SKeyur Desai 		bzero(param, sizeof (struct samr_DeleteAliasMember));
1051c5866007SKeyur Desai 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
1052c5866007SKeyur Desai 		return (NDR_DRC_OK);
1053c5866007SKeyur Desai 	}
1054c5866007SKeyur Desai 
1055c5866007SKeyur Desai 	data = (samr_keydata_t *)hd->nh_data;
1056c5866007SKeyur Desai 	rc = smb_lgrp_getbyrid(data->kd_rid, data->kd_type, &grp);
1057c5866007SKeyur Desai 	if (rc != SMB_LGRP_SUCCESS) {
1058c5866007SKeyur Desai 		bzero(param, sizeof (struct samr_DeleteAliasMember));
1059c5866007SKeyur Desai 		status = smb_lgrp_err_to_ntstatus(rc);
1060c5866007SKeyur Desai 		param->status = NT_SC_ERROR(status);
1061c5866007SKeyur Desai 		return (NDR_DRC_OK);
1062c5866007SKeyur Desai 	}
1063c5866007SKeyur Desai 
1064c5866007SKeyur Desai 	rc = smb_lgrp_del_member(grp.sg_name,
1065c5866007SKeyur Desai 	    (smb_sid_t *)param->sid, SidTypeUser);
1066c5866007SKeyur Desai 	if (rc != SMB_LGRP_SUCCESS) {
1067c5866007SKeyur Desai 		bzero(param, sizeof (struct samr_DeleteAliasMember));
1068c5866007SKeyur Desai 		status = smb_lgrp_err_to_ntstatus(rc);
1069c5866007SKeyur Desai 		param->status = NT_SC_ERROR(status);
1070c5866007SKeyur Desai 	}
1071c5866007SKeyur Desai 	smb_lgrp_free(&grp);
1072c5866007SKeyur Desai 
1073c5866007SKeyur Desai 	param->status = status;
1074c5866007SKeyur Desai 	return (NDR_DRC_OK);
1075c5866007SKeyur Desai }
1076c5866007SKeyur Desai 
1077c5866007SKeyur Desai /*
1078c5866007SKeyur Desai  * samr_s_ListAliasMembers
1079c5866007SKeyur Desai  *
1080c5866007SKeyur Desai  * List members from a local SAM group.
1081c5866007SKeyur Desai  * The caller must supply a valid group handle.
1082c5866007SKeyur Desai  * A list of user SIDs in the specified group is returned to the caller.
1083c5866007SKeyur Desai  */
1084c5866007SKeyur Desai static int
samr_s_ListAliasMembers(void * arg,ndr_xa_t * mxa)1085c5866007SKeyur Desai samr_s_ListAliasMembers(void *arg, ndr_xa_t *mxa)
1086c5866007SKeyur Desai {
1087c5866007SKeyur Desai 	struct samr_ListAliasMembers *param = arg;
1088c5866007SKeyur Desai 	ndr_hdid_t *id = (ndr_hdid_t *)&param->alias_handle;
1089c5866007SKeyur Desai 	ndr_handle_t *hd;
1090c5866007SKeyur Desai 	samr_keydata_t *data;
1091c5866007SKeyur Desai 	smb_group_t grp;
1092c5866007SKeyur Desai 	smb_gsid_t *members;
1093c5866007SKeyur Desai 	struct samr_SidInfo info;
1094c5866007SKeyur Desai 	struct samr_SidList *user;
1095c5866007SKeyur Desai 	uint32_t num = 0, size;
1096c5866007SKeyur Desai 	int i;
1097c5866007SKeyur Desai 	uint32_t rc;
1098c5866007SKeyur Desai 	uint32_t status = NT_STATUS_SUCCESS;
1099c5866007SKeyur Desai 
1100c5866007SKeyur Desai 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_ALIAS)) == NULL) {
1101c5866007SKeyur Desai 		bzero(param, sizeof (struct samr_ListAliasMembers));
1102c5866007SKeyur Desai 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
1103c5866007SKeyur Desai 		return (NDR_DRC_OK);
1104c5866007SKeyur Desai 	}
1105c5866007SKeyur Desai 
1106c5866007SKeyur Desai 	bzero(&info, sizeof (struct samr_SidInfo));
1107c5866007SKeyur Desai 	data = (samr_keydata_t *)hd->nh_data;
1108c5866007SKeyur Desai 	rc = smb_lgrp_getbyrid(data->kd_rid, data->kd_type, &grp);
1109c5866007SKeyur Desai 	if (rc != SMB_LGRP_SUCCESS) {
1110c5866007SKeyur Desai 		bzero(param, sizeof (struct samr_ListAliasMembers));
1111c5866007SKeyur Desai 		status = smb_lgrp_err_to_ntstatus(rc);
1112c5866007SKeyur Desai 		param->status = NT_SC_ERROR(status);
1113c5866007SKeyur Desai 		return (NDR_DRC_OK);
1114c5866007SKeyur Desai 	}
1115c5866007SKeyur Desai 
1116c5866007SKeyur Desai 	num = grp.sg_nmembers;
1117c5866007SKeyur Desai 	members = grp.sg_members;
1118c5866007SKeyur Desai 	size = num * sizeof (struct samr_SidList);
1119c5866007SKeyur Desai 	info.sidlist = NDR_MALLOC(mxa, size);
1120c5866007SKeyur Desai 	if (info.sidlist == NULL) {
1121c5866007SKeyur Desai 		bzero(param, sizeof (struct samr_ListAliasMembers));
1122c5866007SKeyur Desai 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1123c5866007SKeyur Desai 		smb_lgrp_free(&grp);
1124c5866007SKeyur Desai 		return (NDR_DRC_OK);
1125c5866007SKeyur Desai 	}
1126c5866007SKeyur Desai 
1127c5866007SKeyur Desai 	info.n_entry = num;
1128c5866007SKeyur Desai 	user = info.sidlist;
1129c5866007SKeyur Desai 	for (i = 0; i < num; i++) {
1130c5866007SKeyur Desai 		user->sid = (struct samr_sid *)NDR_SIDDUP(mxa,
1131c5866007SKeyur Desai 		    members[i].gs_sid);
1132c5866007SKeyur Desai 		if (user->sid == NULL) {
1133c5866007SKeyur Desai 			bzero(param, sizeof (struct samr_ListAliasMembers));
1134c5866007SKeyur Desai 			param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1135c5866007SKeyur Desai 			smb_lgrp_free(&grp);
1136c5866007SKeyur Desai 			return (NDR_DRC_OK);
1137c5866007SKeyur Desai 		}
1138c5866007SKeyur Desai 		user++;
1139c5866007SKeyur Desai 	}
1140c5866007SKeyur Desai 	smb_lgrp_free(&grp);
1141c5866007SKeyur Desai 
1142c5866007SKeyur Desai 	param->info = info;
1143c5866007SKeyur Desai 	param->status = status;
1144c5866007SKeyur Desai 	return (NDR_DRC_OK);
1145c5866007SKeyur Desai }
1146c5866007SKeyur Desai 
1147da6c28aaSamw /*
1148cb174861Sjoyce mcintosh  * samr_s_Connect2
1149da6c28aaSamw  *
1150dc20a302Sas  * This is a request to connect to the local SAM database.
1151dc20a302Sas  * We don't support any form of update request and our database doesn't
1152dc20a302Sas  * contain any private information, so there is little point in doing
1153dc20a302Sas  * any access access checking here.
1154da6c28aaSamw  *
1155da6c28aaSamw  * Return a handle for use with subsequent SAM requests.
1156da6c28aaSamw  */
1157da6c28aaSamw static int
samr_s_Connect2(void * arg,ndr_xa_t * mxa)1158cb174861Sjoyce mcintosh samr_s_Connect2(void *arg, ndr_xa_t *mxa)
1159da6c28aaSamw {
1160cb174861Sjoyce mcintosh 	struct samr_Connect2 *param = arg;
1161dc20a302Sas 	ndr_hdid_t *id;
1162da6c28aaSamw 
1163a0aa776eSAlan Wright 	id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, SMB_DOMAIN_NULL, 0);
1164dc20a302Sas 	if (id) {
1165dc20a302Sas 		bcopy(id, &param->handle, sizeof (samr_handle_t));
1166dc20a302Sas 		param->status = 0;
1167dc20a302Sas 	} else {
1168dc20a302Sas 		bzero(&param->handle, sizeof (samr_handle_t));
1169dc20a302Sas 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1170dc20a302Sas 	}
1171da6c28aaSamw 
11728d7e4166Sjose borrego 	return (NDR_DRC_OK);
1173da6c28aaSamw }
1174da6c28aaSamw 
1175da6c28aaSamw /*
1176da6c28aaSamw  * samr_s_GetUserPwInfo
1177da6c28aaSamw  *
1178f96bd5c8SAlan Wright  * Request for a user's password policy information.
1179da6c28aaSamw  */
1180da6c28aaSamw /*ARGSUSED*/
1181da6c28aaSamw static int
samr_s_GetUserPwInfo(void * arg,ndr_xa_t * mxa)11828d7e4166Sjose borrego samr_s_GetUserPwInfo(void *arg, ndr_xa_t *mxa)
1183da6c28aaSamw {
1184f96bd5c8SAlan Wright 	static samr_password_info_t	pwinfo;
1185f96bd5c8SAlan Wright 	struct samr_GetUserPwInfo	*param = arg;
1186da6c28aaSamw 
1187f96bd5c8SAlan Wright 	param->pwinfo = &pwinfo;
1188f96bd5c8SAlan Wright 	param->status = NT_STATUS_SUCCESS;
11898d7e4166Sjose borrego 	return (NDR_DRC_OK);
1190da6c28aaSamw }
1191da6c28aaSamw 
1192da6c28aaSamw /*
1193da6c28aaSamw  * samr_s_CreateUser
1194da6c28aaSamw  */
1195da6c28aaSamw /*ARGSUSED*/
1196da6c28aaSamw static int
samr_s_CreateUser(void * arg,ndr_xa_t * mxa)11978d7e4166Sjose borrego samr_s_CreateUser(void *arg, ndr_xa_t *mxa)
1198da6c28aaSamw {
1199da6c28aaSamw 	struct samr_CreateUser *param = arg;
1200da6c28aaSamw 
1201da6c28aaSamw 	bzero(&param->user_handle, sizeof (samr_handle_t));
1202da6c28aaSamw 	param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
12038d7e4166Sjose borrego 	return (NDR_DRC_OK);
1204da6c28aaSamw }
1205da6c28aaSamw 
1206da6c28aaSamw /*
12071ed6b69aSGordon Ross  * samr_s_ChangePasswordUser2
1208da6c28aaSamw  */
1209da6c28aaSamw /*ARGSUSED*/
1210da6c28aaSamw static int
samr_s_ChangePasswordUser2(void * arg,ndr_xa_t * mxa)12111ed6b69aSGordon Ross samr_s_ChangePasswordUser2(void *arg, ndr_xa_t *mxa)
1212da6c28aaSamw {
12131ed6b69aSGordon Ross 	struct samr_ChangePasswordUser2 *param = arg;
1214da6c28aaSamw 
12151ed6b69aSGordon Ross 	bzero(param, sizeof (*param));
1216da6c28aaSamw 	param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
12178d7e4166Sjose borrego 	return (NDR_DRC_OK);
1218da6c28aaSamw }
1219da6c28aaSamw 
1220da6c28aaSamw /*
1221da6c28aaSamw  * samr_s_GetDomainPwInfo
1222f96bd5c8SAlan Wright  *
1223f96bd5c8SAlan Wright  * Request for the domain password policy information.
1224da6c28aaSamw  */
1225da6c28aaSamw /*ARGSUSED*/
1226da6c28aaSamw static int
samr_s_GetDomainPwInfo(void * arg,ndr_xa_t * mxa)12278d7e4166Sjose borrego samr_s_GetDomainPwInfo(void *arg, ndr_xa_t *mxa)
1228da6c28aaSamw {
1229f96bd5c8SAlan Wright 	static samr_password_info_t	pwinfo;
1230f96bd5c8SAlan Wright 	struct samr_GetDomainPwInfo	*param = arg;
1231da6c28aaSamw 
1232f96bd5c8SAlan Wright 	param->pwinfo = &pwinfo;
1233f96bd5c8SAlan Wright 	param->status = NT_STATUS_SUCCESS;
12348d7e4166Sjose borrego 	return (NDR_DRC_OK);
1235da6c28aaSamw }
1236da6c28aaSamw 
1237da6c28aaSamw /*
1238da6c28aaSamw  * samr_s_SetUserInfo
1239da6c28aaSamw  */
1240da6c28aaSamw /*ARGSUSED*/
1241da6c28aaSamw static int
samr_s_SetUserInfo(void * arg,ndr_xa_t * mxa)12428d7e4166Sjose borrego samr_s_SetUserInfo(void *arg, ndr_xa_t *mxa)
1243da6c28aaSamw {
1244da6c28aaSamw 	struct samr_SetUserInfo *param = arg;
1245da6c28aaSamw 
1246da6c28aaSamw 	bzero(param, sizeof (struct samr_SetUserInfo));
1247da6c28aaSamw 	param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
12488d7e4166Sjose borrego 	return (NDR_DRC_OK);
1249da6c28aaSamw }
1250da6c28aaSamw 
1251da6c28aaSamw /*
1252da6c28aaSamw  * samr_s_QueryDispInfo
1253da6c28aaSamw  *
12543db3f65cSamw  * This function currently return local users' information only.
12553db3f65cSamw  * This RPC is called repeatedly until all the users info are
12563db3f65cSamw  * retrieved.
1257da6c28aaSamw  *
12583db3f65cSamw  * The total count and the returned count are returned as total size
12593db3f65cSamw  * and returned size.  The client doesn't seem to care.
1260da6c28aaSamw  */
1261da6c28aaSamw static int
samr_s_QueryDispInfo(void * arg,ndr_xa_t * mxa)12628d7e4166Sjose borrego samr_s_QueryDispInfo(void *arg, ndr_xa_t *mxa)
1263da6c28aaSamw {
1264da6c28aaSamw 	struct samr_QueryDispInfo *param = arg;
1265dc20a302Sas 	ndr_hdid_t *id = (ndr_hdid_t *)&param->domain_handle;
12663db3f65cSamw 	ndr_handle_t *hd;
12673db3f65cSamw 	samr_keydata_t *data;
12683db3f65cSamw 	DWORD status = NT_STATUS_SUCCESS;
12693db3f65cSamw 	struct user_acct_info *user;
12703db3f65cSamw 	smb_pwditer_t pwi;
12713db3f65cSamw 	smb_luser_t *uinfo;
12723db3f65cSamw 	int num_users;
12737f667e74Sjose borrego 	int start_idx;
12747f667e74Sjose borrego 	int max_retcnt, retcnt;
12757f667e74Sjose borrego 	int skip;
1276da6c28aaSamw 
12773db3f65cSamw 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
12783db3f65cSamw 		status = NT_STATUS_INVALID_HANDLE;
12793db3f65cSamw 		goto error;
1280dc20a302Sas 	}
1281da6c28aaSamw 
12823db3f65cSamw 	if (!SAMR_VALID_DISPLEVEL(param->level)) {
12833db3f65cSamw 		status = NT_STATUS_INVALID_INFO_CLASS;
12843db3f65cSamw 		goto error;
12853db3f65cSamw 	}
1286da6c28aaSamw 
12873db3f65cSamw 	if (!SAMR_SUPPORTED_DISPLEVEL(param->level)) {
12883db3f65cSamw 		status = NT_STATUS_NOT_IMPLEMENTED;
12893db3f65cSamw 		goto error;
12903db3f65cSamw 	}
1291da6c28aaSamw 
12923db3f65cSamw 	data = (samr_keydata_t *)hd->nh_data;
1293da6c28aaSamw 
12943db3f65cSamw 	switch (data->kd_type) {
1295a0aa776eSAlan Wright 	case SMB_DOMAIN_BUILTIN:
12963db3f65cSamw 		goto no_info;
1297da6c28aaSamw 
1298a0aa776eSAlan Wright 	case SMB_DOMAIN_LOCAL:
12997f667e74Sjose borrego 		num_users = smb_sam_usr_cnt();
13003db3f65cSamw 		start_idx = param->start_idx;
13013db3f65cSamw 		if ((num_users == 0) || (start_idx >= num_users))
13023db3f65cSamw 			goto no_info;
13033db3f65cSamw 
13047f667e74Sjose borrego 		max_retcnt = num_users - start_idx;
13057f667e74Sjose borrego 		if (max_retcnt > param->max_entries)
13067f667e74Sjose borrego 			max_retcnt = param->max_entries;
13078d7e4166Sjose borrego 		param->users.acct = NDR_MALLOC(mxa,
13087f667e74Sjose borrego 		    max_retcnt * sizeof (struct user_acct_info));
13093db3f65cSamw 		user = param->users.acct;
13103db3f65cSamw 		if (user == NULL) {
13113db3f65cSamw 			status = NT_STATUS_NO_MEMORY;
13123db3f65cSamw 			goto error;
13133db3f65cSamw 		}
13147f667e74Sjose borrego 		bzero(user, max_retcnt * sizeof (struct user_acct_info));
13153db3f65cSamw 
13163db3f65cSamw 		if (smb_pwd_iteropen(&pwi) != SMB_PWE_SUCCESS)
13173db3f65cSamw 			goto no_info;
13183db3f65cSamw 
13197f667e74Sjose borrego 		skip = retcnt = 0;
13203db3f65cSamw 		while ((uinfo = smb_pwd_iterate(&pwi)) != NULL) {
13217f667e74Sjose borrego 			if (skip++ < start_idx)
13223db3f65cSamw 				continue;
13233db3f65cSamw 
13247f667e74Sjose borrego 			if (retcnt++ >= max_retcnt)
13257f667e74Sjose borrego 				break;
13267f667e74Sjose borrego 
13273db3f65cSamw 			assert(uinfo->su_name != NULL);
13283db3f65cSamw 
13297f667e74Sjose borrego 			user->index = start_idx + retcnt;
13303db3f65cSamw 			user->rid = uinfo->su_rid;
13313db3f65cSamw 			user->ctrl = ACF_NORMUSER | ACF_PWDNOEXP;
13323db3f65cSamw 			if (uinfo->su_ctrl & SMB_PWF_DISABLE)
13333db3f65cSamw 				user->ctrl |= ACF_DISABLED;
13348d7e4166Sjose borrego 			if (NDR_MSTRING(mxa, uinfo->su_name,
13358d7e4166Sjose borrego 			    (ndr_mstring_t *)&user->name) == -1) {
13363db3f65cSamw 				smb_pwd_iterclose(&pwi);
13373db3f65cSamw 				status = NT_STATUS_NO_MEMORY;
13383db3f65cSamw 				goto error;
13393db3f65cSamw 			}
13408d7e4166Sjose borrego 			(void) NDR_MSTRING(mxa, uinfo->su_fullname,
13418d7e4166Sjose borrego 			    (ndr_mstring_t *)&user->fullname);
13428d7e4166Sjose borrego 			(void) NDR_MSTRING(mxa, uinfo->su_desc,
13438d7e4166Sjose borrego 			    (ndr_mstring_t *)&user->desc);
13443db3f65cSamw 			user++;
13453db3f65cSamw 		}
13463db3f65cSamw 		smb_pwd_iterclose(&pwi);
1347da6c28aaSamw 
13487f667e74Sjose borrego 		if (retcnt >= max_retcnt) {
13497f667e74Sjose borrego 			retcnt = max_retcnt;
13507f667e74Sjose borrego 			param->status = status;
13517f667e74Sjose borrego 		} else {
1352148c5f43SAlan Wright 			param->status = NT_STATUS_MORE_ENTRIES;
13537f667e74Sjose borrego 		}
13547f667e74Sjose borrego 
13553db3f65cSamw 		param->users.total_size = num_users;
13567f667e74Sjose borrego 		param->users.returned_size = retcnt;
13573db3f65cSamw 		param->users.switch_value = param->level;
13587f667e74Sjose borrego 		param->users.count = retcnt;
1359da6c28aaSamw 
13603db3f65cSamw 		break;
1361da6c28aaSamw 
13623db3f65cSamw 	default:
13633db3f65cSamw 		status = NT_STATUS_INVALID_HANDLE;
13643db3f65cSamw 		goto error;
1365da6c28aaSamw 	}
13663db3f65cSamw 
13678d7e4166Sjose borrego 	return (NDR_DRC_OK);
13683db3f65cSamw 
13693db3f65cSamw no_info:
13703db3f65cSamw 	param->users.total_size = 0;
13713db3f65cSamw 	param->users.returned_size = 0;
13723db3f65cSamw 	param->users.switch_value = param->level;
13733db3f65cSamw 	param->users.count = 0;
13743db3f65cSamw 	param->users.acct = NULL;
13753db3f65cSamw 	param->status = status;
13768d7e4166Sjose borrego 	return (NDR_DRC_OK);
13773db3f65cSamw 
13783db3f65cSamw error:
13793db3f65cSamw 	bzero(param, sizeof (struct samr_QueryDispInfo));
13803db3f65cSamw 	param->status = NT_SC_ERROR(status);
13818d7e4166Sjose borrego 	return (NDR_DRC_OK);
1382da6c28aaSamw }
1383da6c28aaSamw 
1384da6c28aaSamw /*
1385da6c28aaSamw  * samr_s_EnumDomainGroups
1386da6c28aaSamw  *
1387da6c28aaSamw  *
1388dc20a302Sas  * This function is supposed to return local group information.
1389da6c28aaSamw  * As we don't support local users, this function dosen't send
1390da6c28aaSamw  * back any information.
1391da6c28aaSamw  *
1392dc20a302Sas  * Added template that returns information for a domain group as None.
1393dc20a302Sas  * All information is hard-coded from packet captures.
1394da6c28aaSamw  */
1395da6c28aaSamw static int
samr_s_EnumDomainGroups(void * arg,ndr_xa_t * mxa)13968d7e4166Sjose borrego samr_s_EnumDomainGroups(void *arg, ndr_xa_t *mxa)
1397da6c28aaSamw {
1398da6c28aaSamw 	struct samr_EnumDomainGroups *param = arg;
1399dc20a302Sas 	ndr_hdid_t *id = (ndr_hdid_t *)&param->domain_handle;
1400da6c28aaSamw 	DWORD status = NT_STATUS_SUCCESS;
1401da6c28aaSamw 
1402dc20a302Sas 	if (samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN) == NULL)
1403da6c28aaSamw 		status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
1404da6c28aaSamw 
1405da6c28aaSamw 	param->total_size = 0;
1406da6c28aaSamw 	param->returned_size = 0;
1407da6c28aaSamw 	param->switch_value = 3;
1408da6c28aaSamw 	param->count = 0;
1409da6c28aaSamw 	param->groups = 0;
1410da6c28aaSamw 	param->status = status;
14118d7e4166Sjose borrego 	return (NDR_DRC_OK);
1412da6c28aaSamw 
1413da6c28aaSamw #ifdef SAMR_SUPPORT_GROUPS
1414da6c28aaSamw 	if ((desc->discrim != SAMR_LOCAL_DOMAIN) || (param->start_idx != 0)) {
1415da6c28aaSamw 		param->total_size = 0;
1416da6c28aaSamw 		param->returned_size = 0;
1417da6c28aaSamw 		param->switch_value = 3;
1418da6c28aaSamw 		param->count = 0;
1419da6c28aaSamw 		param->groups = 0;
1420da6c28aaSamw 	} else {
1421da6c28aaSamw 		param->total_size = 64;
1422da6c28aaSamw 		param->returned_size = 64;
1423da6c28aaSamw 		param->switch_value = 3;
1424da6c28aaSamw 		param->count = 1;
14258d7e4166Sjose borrego 		param->groups = (struct group_disp_info *)NDR_MALLOC(
1426da6c28aaSamw 		    mxa, sizeof (struct group_disp_info));
1427da6c28aaSamw 
1428da6c28aaSamw 		param->groups->count = 1;
1429da6c28aaSamw 		param->groups->acct[0].index = 1;
1430da6c28aaSamw 		param->groups->acct[0].rid = 513;
1431da6c28aaSamw 		param->groups->acct[0].ctrl = 0x7;
14328d7e4166Sjose borrego 		(void) NDR_MSTRING(mxa, "None",
14338d7e4166Sjose borrego 		    (ndr_mstring_t *)&param->groups->acct[0].name);
1434da6c28aaSamw 
14358d7e4166Sjose borrego 		(void) NDR_MSTRING(mxa, "Ordinary users",
14368d7e4166Sjose borrego 		    (ndr_mstring_t *)&param->groups->acct[0].desc);
1437da6c28aaSamw 	}
1438da6c28aaSamw 
1439da6c28aaSamw 	param->status = NT_STATUS_SUCCESS;
14408d7e4166Sjose borrego 	return (NDR_DRC_OK);
1441da6c28aaSamw #endif
1442da6c28aaSamw }
1443da6c28aaSamw 
1444da6c28aaSamw /*
1445da6c28aaSamw  * samr_s_OpenAlias
1446da6c28aaSamw  *
1447da6c28aaSamw  * Lookup for requested alias, if it exists return a handle
1448da6c28aaSamw  * for that alias. The alias domain sid should match with
1449da6c28aaSamw  * the passed domain handle.
1450da6c28aaSamw  */
1451da6c28aaSamw static int
samr_s_OpenAlias(void * arg,ndr_xa_t * mxa)14528d7e4166Sjose borrego samr_s_OpenAlias(void *arg, ndr_xa_t *mxa)
1453da6c28aaSamw {
1454da6c28aaSamw 	struct samr_OpenAlias *param = arg;
1455f96bd5c8SAlan Wright 	ndr_hdid_t	*id = (ndr_hdid_t *)&param->domain_handle;
1456f96bd5c8SAlan Wright 	ndr_handle_t	*hd;
1457f96bd5c8SAlan Wright 	samr_keydata_t	*data;
14589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_domain_type_t gd_type;
1459f96bd5c8SAlan Wright 	smb_sid_t	*sid;
1460f96bd5c8SAlan Wright 	smb_wka_t	*wka;
1461f96bd5c8SAlan Wright 	char		sidstr[SMB_SID_STRSZ];
1462f96bd5c8SAlan Wright 	uint32_t	rid;
1463f96bd5c8SAlan Wright 	uint32_t	status;
1464f96bd5c8SAlan Wright 	int		rc;
1465da6c28aaSamw 
1466dc20a302Sas 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
1467da6c28aaSamw 		status = NT_STATUS_INVALID_HANDLE;
1468da6c28aaSamw 		goto open_alias_err;
1469da6c28aaSamw 	}
1470da6c28aaSamw 
1471c5866007SKeyur Desai 	if ((param->access_mask & SAMR_ALIAS_ACCESS_ALL_ACCESS) == 0) {
1472da6c28aaSamw 		status = NT_STATUS_ACCESS_DENIED;
1473da6c28aaSamw 		goto open_alias_err;
1474da6c28aaSamw 	}
1475da6c28aaSamw 
1476dc20a302Sas 	data = (samr_keydata_t *)hd->nh_data;
14779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	gd_type = (smb_domain_type_t)data->kd_type;
1478f96bd5c8SAlan Wright 	rid = param->rid;
1479f96bd5c8SAlan Wright 
1480f96bd5c8SAlan Wright 	switch (gd_type) {
14819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	case SMB_DOMAIN_BUILTIN:
1482f96bd5c8SAlan Wright 		(void) snprintf(sidstr, SMB_SID_STRSZ, "%s-%d",
1483f96bd5c8SAlan Wright 		    NT_BUILTIN_DOMAIN_SIDSTR, rid);
1484f96bd5c8SAlan Wright 		if ((sid = smb_sid_fromstr(sidstr)) == NULL) {
1485f96bd5c8SAlan Wright 			status = NT_STATUS_NO_SUCH_ALIAS;
1486f96bd5c8SAlan Wright 			goto open_alias_err;
1487f96bd5c8SAlan Wright 		}
1488f96bd5c8SAlan Wright 
1489f96bd5c8SAlan Wright 		wka = smb_wka_lookup_sid(sid);
1490f96bd5c8SAlan Wright 		smb_sid_free(sid);
1491f96bd5c8SAlan Wright 
1492f96bd5c8SAlan Wright 		if (wka == NULL) {
1493f96bd5c8SAlan Wright 			status = NT_STATUS_NO_SUCH_ALIAS;
1494f96bd5c8SAlan Wright 			goto open_alias_err;
1495f96bd5c8SAlan Wright 		}
1496f96bd5c8SAlan Wright 		break;
1497f96bd5c8SAlan Wright 
14989fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	case SMB_DOMAIN_LOCAL:
1499f96bd5c8SAlan Wright 		rc = smb_lgrp_getbyrid(rid, gd_type, NULL);
1500f96bd5c8SAlan Wright 		if (rc != SMB_LGRP_SUCCESS) {
1501f96bd5c8SAlan Wright 			status = NT_STATUS_NO_SUCH_ALIAS;
1502f96bd5c8SAlan Wright 			goto open_alias_err;
1503f96bd5c8SAlan Wright 		}
1504f96bd5c8SAlan Wright 		break;
1505f96bd5c8SAlan Wright 
1506f96bd5c8SAlan Wright 	default:
1507da6c28aaSamw 		status = NT_STATUS_NO_SUCH_ALIAS;
1508da6c28aaSamw 		goto open_alias_err;
1509da6c28aaSamw 	}
1510da6c28aaSamw 
1511dc20a302Sas 	id = samr_hdalloc(mxa, SAMR_KEY_ALIAS, data->kd_type, param->rid);
1512dc20a302Sas 	if (id) {
1513dc20a302Sas 		bcopy(id, &param->alias_handle, sizeof (samr_handle_t));
1514dc20a302Sas 		param->status = NT_STATUS_SUCCESS;
15158d7e4166Sjose borrego 		return (NDR_DRC_OK);
1516da6c28aaSamw 	}
1517da6c28aaSamw 
1518dc20a302Sas 	status = NT_STATUS_NO_MEMORY;
1519da6c28aaSamw 
1520da6c28aaSamw open_alias_err:
1521da6c28aaSamw 	bzero(&param->alias_handle, sizeof (samr_handle_t));
1522da6c28aaSamw 	param->status = NT_SC_ERROR(status);
15238d7e4166Sjose borrego 	return (NDR_DRC_OK);
1524da6c28aaSamw }
1525da6c28aaSamw 
1526da6c28aaSamw /*
1527da6c28aaSamw  * samr_s_CreateDomainAlias
1528da6c28aaSamw  *
1529c5866007SKeyur Desai  * Create a local group in the security accounts manager (SAM) database.
1530c5866007SKeyur Desai  * A local SAM group can only be added if a Solaris group already exists
1531c5866007SKeyur Desai  * with the same name.  On success, a valid group handle is returned.
1532c5866007SKeyur Desai  *
1533c5866007SKeyur Desai  * The caller must have administrator rights to execute this function.
1534da6c28aaSamw  */
1535da6c28aaSamw static int
samr_s_CreateDomainAlias(void * arg,ndr_xa_t * mxa)15368d7e4166Sjose borrego samr_s_CreateDomainAlias(void *arg, ndr_xa_t *mxa)
1537da6c28aaSamw {
1538da6c28aaSamw 	struct samr_CreateDomainAlias *param = arg;
1539dc20a302Sas 	ndr_hdid_t *id = (ndr_hdid_t *)&param->alias_handle;
1540c5866007SKeyur Desai 	uint32_t status = NT_STATUS_SUCCESS;
1541c5866007SKeyur Desai 	smb_group_t grp;
1542c5866007SKeyur Desai 	uint32_t rc;
1543c5866007SKeyur Desai 	char *gname;
1544dc20a302Sas 
1545c5866007SKeyur Desai 	if (samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN) != NULL) {
1546dc20a302Sas 		bzero(param, sizeof (struct samr_CreateDomainAlias));
1547dc20a302Sas 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
15488d7e4166Sjose borrego 		return (NDR_DRC_OK);
1549dc20a302Sas 	}
1550dc20a302Sas 
1551c5866007SKeyur Desai 	gname = (char *)param->alias_name.str;
1552c5866007SKeyur Desai 	if (gname == NULL) {
1553c5866007SKeyur Desai 		bzero(&param->alias_handle, sizeof (samr_handle_t));
1554c5866007SKeyur Desai 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER);
1555c5866007SKeyur Desai 		return (NDR_DRC_OK);
1556da6c28aaSamw 	}
1557da6c28aaSamw 
1558c5866007SKeyur Desai 	if ((!ndr_is_admin(mxa)) ||
1559c5866007SKeyur Desai 	    ((param->access_mask & SAMR_ALIAS_ACCESS_WRITE_ACCOUNT) == 0)) {
1560c5866007SKeyur Desai 		bzero(&param->alias_handle, sizeof (samr_handle_t));
1561c5866007SKeyur Desai 		param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
1562c5866007SKeyur Desai 		return (NDR_DRC_OK);
1563c5866007SKeyur Desai 	}
1564da6c28aaSamw 
1565c5866007SKeyur Desai 	rc = smb_lgrp_add(gname, "");
1566c5866007SKeyur Desai 	if (rc != SMB_LGRP_SUCCESS) {
1567c5866007SKeyur Desai 		bzero(&param->alias_handle, sizeof (samr_handle_t));
1568c5866007SKeyur Desai 		status = smb_lgrp_err_to_ntstatus(rc);
1569c5866007SKeyur Desai 		param->status = NT_SC_ERROR(status);
1570c5866007SKeyur Desai 		return (NDR_DRC_OK);
1571da6c28aaSamw 	}
1572da6c28aaSamw 
1573c5866007SKeyur Desai 	rc = smb_lgrp_getbyname((char *)gname, &grp);
1574c5866007SKeyur Desai 	if (rc != SMB_LGRP_SUCCESS) {
1575c5866007SKeyur Desai 		bzero(&param->alias_handle, sizeof (samr_handle_t));
1576c5866007SKeyur Desai 		status = smb_lgrp_err_to_ntstatus(rc);
1577c5866007SKeyur Desai 		param->status = NT_SC_ERROR(status);
1578c5866007SKeyur Desai 		return (NDR_DRC_OK);
1579c5866007SKeyur Desai 	}
1580da6c28aaSamw 
1581c5866007SKeyur Desai 	id = samr_hdalloc(mxa, SAMR_KEY_ALIAS, SMB_DOMAIN_LOCAL, grp.sg_rid);
1582c5866007SKeyur Desai 	smb_lgrp_free(&grp);
1583c5866007SKeyur Desai 	if (id) {
1584c5866007SKeyur Desai 		bcopy(id, &param->alias_handle, sizeof (samr_handle_t));
1585c5866007SKeyur Desai 		param->status = status;
1586c5866007SKeyur Desai 	} else {
1587c5866007SKeyur Desai 		bzero(&param->alias_handle, sizeof (samr_handle_t));
1588c5866007SKeyur Desai 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1589c5866007SKeyur Desai 	}
1590da6c28aaSamw 
15918d7e4166Sjose borrego 	return (NDR_DRC_OK);
1592da6c28aaSamw }
1593da6c28aaSamw 
1594da6c28aaSamw /*
1595da6c28aaSamw  * samr_s_SetAliasInfo
1596da6c28aaSamw  *
1597dc20a302Sas  * Similar to NetLocalGroupSetInfo.
1598da6c28aaSamw  */
1599da6c28aaSamw static int
samr_s_SetAliasInfo(void * arg,ndr_xa_t * mxa)16008d7e4166Sjose borrego samr_s_SetAliasInfo(void *arg, ndr_xa_t *mxa)
1601da6c28aaSamw {
1602da6c28aaSamw 	struct samr_SetAliasInfo *param = arg;
1603dc20a302Sas 	ndr_hdid_t *id = (ndr_hdid_t *)&param->alias_handle;
1604da6c28aaSamw 	DWORD status = NT_STATUS_SUCCESS;
1605da6c28aaSamw 
1606dc20a302Sas 	if (samr_hdlookup(mxa, id, SAMR_KEY_ALIAS) == NULL)
1607da6c28aaSamw 		status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
1608da6c28aaSamw 
1609da6c28aaSamw 	param->status = status;
16108d7e4166Sjose borrego 	return (NDR_DRC_OK);
1611da6c28aaSamw }
1612da6c28aaSamw 
1613da6c28aaSamw /*
1614da6c28aaSamw  * samr_s_QueryAliasInfo
1615da6c28aaSamw  *
1616da6c28aaSamw  * Retrieves information about the specified local group account
1617da6c28aaSamw  * by given handle.
1618da6c28aaSamw  */
1619da6c28aaSamw static int
samr_s_QueryAliasInfo(void * arg,ndr_xa_t * mxa)16208d7e4166Sjose borrego samr_s_QueryAliasInfo(void *arg, ndr_xa_t *mxa)
1621da6c28aaSamw {
1622da6c28aaSamw 	struct samr_QueryAliasInfo *param = arg;
1623f96bd5c8SAlan Wright 	ndr_hdid_t	*id = (ndr_hdid_t *)&param->alias_handle;
1624f96bd5c8SAlan Wright 	ndr_handle_t	*hd;
1625f96bd5c8SAlan Wright 	samr_keydata_t	*data;
1626f96bd5c8SAlan Wright 	smb_group_t	grp;
16279fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_domain_type_t gd_type;
1628f96bd5c8SAlan Wright 	smb_sid_t	*sid;
1629f96bd5c8SAlan Wright 	smb_wka_t	*wka;
1630f96bd5c8SAlan Wright 	char		sidstr[SMB_SID_STRSZ];
1631f96bd5c8SAlan Wright 	char		*name;
1632f96bd5c8SAlan Wright 	char		*desc;
1633f96bd5c8SAlan Wright 	uint32_t	rid;
1634f96bd5c8SAlan Wright 	uint32_t	status;
1635f96bd5c8SAlan Wright 	int		rc;
1636da6c28aaSamw 
1637dc20a302Sas 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_ALIAS)) == NULL) {
1638da6c28aaSamw 		status = NT_STATUS_INVALID_HANDLE;
1639da6c28aaSamw 		goto query_alias_err;
1640da6c28aaSamw 	}
1641da6c28aaSamw 
1642dc20a302Sas 	data = (samr_keydata_t *)hd->nh_data;
16439fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	gd_type = (smb_domain_type_t)data->kd_type;
1644f96bd5c8SAlan Wright 	rid = data->kd_rid;
1645f96bd5c8SAlan Wright 
1646f96bd5c8SAlan Wright 	switch (gd_type) {
16479fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	case SMB_DOMAIN_BUILTIN:
1648f96bd5c8SAlan Wright 		(void) snprintf(sidstr, SMB_SID_STRSZ, "%s-%d",
1649f96bd5c8SAlan Wright 		    NT_BUILTIN_DOMAIN_SIDSTR, rid);
1650f96bd5c8SAlan Wright 		if ((sid = smb_sid_fromstr(sidstr)) == NULL) {
1651f96bd5c8SAlan Wright 			status = NT_STATUS_NO_SUCH_ALIAS;
1652f96bd5c8SAlan Wright 			goto query_alias_err;
1653f96bd5c8SAlan Wright 		}
1654f96bd5c8SAlan Wright 
1655f96bd5c8SAlan Wright 		wka = smb_wka_lookup_sid(sid);
1656f96bd5c8SAlan Wright 		smb_sid_free(sid);
1657f96bd5c8SAlan Wright 
1658f96bd5c8SAlan Wright 		if (wka == NULL) {
1659f96bd5c8SAlan Wright 			status = NT_STATUS_NO_SUCH_ALIAS;
1660f96bd5c8SAlan Wright 			goto query_alias_err;
1661f96bd5c8SAlan Wright 		}
1662f96bd5c8SAlan Wright 
1663f96bd5c8SAlan Wright 		name = wka->wka_name;
1664f96bd5c8SAlan Wright 		desc = (wka->wka_desc != NULL) ? wka->wka_desc : "";
1665f96bd5c8SAlan Wright 		break;
1666f96bd5c8SAlan Wright 
16679fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	case SMB_DOMAIN_LOCAL:
1668f96bd5c8SAlan Wright 		rc = smb_lgrp_getbyrid(rid, gd_type, &grp);
1669f96bd5c8SAlan Wright 		if (rc != SMB_LGRP_SUCCESS) {
1670f96bd5c8SAlan Wright 			status = NT_STATUS_NO_SUCH_ALIAS;
1671f96bd5c8SAlan Wright 			goto query_alias_err;
1672f96bd5c8SAlan Wright 		}
1673f96bd5c8SAlan Wright 		name = grp.sg_name;
1674f96bd5c8SAlan Wright 		desc = grp.sg_cmnt;
1675f96bd5c8SAlan Wright 		break;
1676f96bd5c8SAlan Wright 
1677f96bd5c8SAlan Wright 	default:
1678da6c28aaSamw 		status = NT_STATUS_NO_SUCH_ALIAS;
1679da6c28aaSamw 		goto query_alias_err;
1680da6c28aaSamw 	}
1681da6c28aaSamw 
1682da6c28aaSamw 	switch (param->level) {
1683eef90b86SGordon Ross 	case SAMR_QUERY_ALIAS_INFO_GENERAL:
1684da6c28aaSamw 		param->ru.info1.level = param->level;
1685f96bd5c8SAlan Wright 		(void) NDR_MSTRING(mxa, name,
16868d7e4166Sjose borrego 		    (ndr_mstring_t *)&param->ru.info1.name);
1687f96bd5c8SAlan Wright 		(void) NDR_MSTRING(mxa, desc,
16888d7e4166Sjose borrego 		    (ndr_mstring_t *)&param->ru.info1.desc);
1689eef90b86SGordon Ross 		param->ru.info1.member_count = 1;
1690eef90b86SGordon Ross 		break;
1691da6c28aaSamw 
1692eef90b86SGordon Ross 	case SAMR_QUERY_ALIAS_INFO_NAME:
1693eef90b86SGordon Ross 		param->ru.info2.level = param->level;
1694eef90b86SGordon Ross 		(void) NDR_MSTRING(mxa, name,
1695eef90b86SGordon Ross 		    (ndr_mstring_t *)&param->ru.info2.name);
1696da6c28aaSamw 		break;
1697da6c28aaSamw 
1698eef90b86SGordon Ross 	case SAMR_QUERY_ALIAS_INFO_COMMENT:
1699da6c28aaSamw 		param->ru.info3.level = param->level;
1700f96bd5c8SAlan Wright 		(void) NDR_MSTRING(mxa, desc,
17018d7e4166Sjose borrego 		    (ndr_mstring_t *)&param->ru.info3.desc);
1702da6c28aaSamw 		break;
1703da6c28aaSamw 
1704da6c28aaSamw 	default:
17059fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		if (gd_type == SMB_DOMAIN_LOCAL)
1706f96bd5c8SAlan Wright 			smb_lgrp_free(&grp);
1707da6c28aaSamw 		status = NT_STATUS_INVALID_INFO_CLASS;
1708da6c28aaSamw 		goto query_alias_err;
1709da6c28aaSamw 	};
1710da6c28aaSamw 
17119fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (gd_type == SMB_DOMAIN_LOCAL)
1712f96bd5c8SAlan Wright 		smb_lgrp_free(&grp);
171355bf511dSas 	param->address = (DWORD)(uintptr_t)&param->ru;
1714da6c28aaSamw 	param->status = 0;
17158d7e4166Sjose borrego 	return (NDR_DRC_OK);
1716da6c28aaSamw 
1717da6c28aaSamw query_alias_err:
1718da6c28aaSamw 	param->status = NT_SC_ERROR(status);
17198d7e4166Sjose borrego 	return (NDR_DRC_OK);
1720da6c28aaSamw }
1721da6c28aaSamw 
1722da6c28aaSamw /*
1723da6c28aaSamw  * samr_s_DeleteDomainAlias
1724da6c28aaSamw  *
1725c5866007SKeyur Desai  * Deletes a local group in the security database, which is the
1726c5866007SKeyur Desai  * security accounts manager (SAM). A valid group handle is returned
1727c5866007SKeyur Desai  * to the caller upon success.
1728da6c28aaSamw  *
1729c5866007SKeyur Desai  * The caller must have administrator rights to execute this function.
1730da6c28aaSamw  */
1731da6c28aaSamw static int
samr_s_DeleteDomainAlias(void * arg,ndr_xa_t * mxa)17328d7e4166Sjose borrego samr_s_DeleteDomainAlias(void *arg, ndr_xa_t *mxa)
1733da6c28aaSamw {
1734da6c28aaSamw 	struct samr_DeleteDomainAlias *param = arg;
1735dc20a302Sas 	ndr_hdid_t *id = (ndr_hdid_t *)&param->alias_handle;
1736c5866007SKeyur Desai 	ndr_handle_t	*hd;
1737c5866007SKeyur Desai 	smb_group_t grp;
1738c5866007SKeyur Desai 	samr_keydata_t	*data;
1739c5866007SKeyur Desai 	smb_domain_type_t	gd_type;
1740c5866007SKeyur Desai 	uint32_t	rid;
1741c5866007SKeyur Desai 	uint32_t	rc;
1742c5866007SKeyur Desai 	uint32_t	status = NT_STATUS_SUCCESS;
1743da6c28aaSamw 
1744c5866007SKeyur Desai 	if (!ndr_is_admin(mxa)) {
1745dc20a302Sas 		bzero(param, sizeof (struct samr_DeleteDomainAlias));
1746c5866007SKeyur Desai 		param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
17478d7e4166Sjose borrego 		return (NDR_DRC_OK);
1748dc20a302Sas 	}
1749da6c28aaSamw 
1750c5866007SKeyur Desai 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_ALIAS)) == NULL) {
1751c5866007SKeyur Desai 		bzero(param, sizeof (struct samr_DeleteDomainAlias));
1752c5866007SKeyur Desai 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
1753c5866007SKeyur Desai 		return (NDR_DRC_OK);
1754c5866007SKeyur Desai 	}
1755da6c28aaSamw 
1756c5866007SKeyur Desai 	data = (samr_keydata_t *)hd->nh_data;
1757c5866007SKeyur Desai 	gd_type = (smb_domain_type_t)data->kd_type;
1758c5866007SKeyur Desai 	rid = data->kd_rid;
1759da6c28aaSamw 
1760c5866007SKeyur Desai 	switch (gd_type) {
1761c5866007SKeyur Desai 	case SMB_DOMAIN_BUILTIN:
1762c5866007SKeyur Desai 		bzero(param, sizeof (struct samr_DeleteDomainAlias));
1763c5866007SKeyur Desai 		status = NT_SC_ERROR(NT_STATUS_NOT_SUPPORTED);
1764c5866007SKeyur Desai 		break;
1765da6c28aaSamw 
1766c5866007SKeyur Desai 	case SMB_DOMAIN_LOCAL:
1767c5866007SKeyur Desai 		rc = smb_lgrp_getbyrid(rid, gd_type, &grp);
1768c5866007SKeyur Desai 		if (rc != SMB_LGRP_SUCCESS) {
1769c5866007SKeyur Desai 			bzero(param, sizeof (struct samr_DeleteDomainAlias));
1770c5866007SKeyur Desai 			status = smb_lgrp_err_to_ntstatus(rc);
1771c5866007SKeyur Desai 			status = NT_SC_ERROR(status);
1772c5866007SKeyur Desai 			break;
1773c5866007SKeyur Desai 		}
1774da6c28aaSamw 
1775c5866007SKeyur Desai 		rc = smb_lgrp_delete(grp.sg_name);
1776c5866007SKeyur Desai 		if (rc != SMB_LGRP_SUCCESS) {
1777c5866007SKeyur Desai 			bzero(param, sizeof (struct samr_DeleteDomainAlias));
1778c5866007SKeyur Desai 			status = smb_lgrp_err_to_ntstatus(rc);
1779c5866007SKeyur Desai 			status = NT_SC_ERROR(status);
1780c5866007SKeyur Desai 		}
1781c5866007SKeyur Desai 		smb_lgrp_free(&grp);
1782c5866007SKeyur Desai 		break;
1783da6c28aaSamw 
1784c5866007SKeyur Desai 	default:
1785c5866007SKeyur Desai 		bzero(param, sizeof (struct samr_DeleteDomainAlias));
1786c5866007SKeyur Desai 		status = NT_SC_ERROR(NT_STATUS_NO_SUCH_ALIAS);
1787c5866007SKeyur Desai 	}
1788da6c28aaSamw 
1789c5866007SKeyur Desai 	param->status = status;
17908d7e4166Sjose borrego 	return (NDR_DRC_OK);
1791da6c28aaSamw }
1792da6c28aaSamw 
1793da6c28aaSamw /*
1794da6c28aaSamw  * samr_s_EnumDomainAliases
1795da6c28aaSamw  *
1796da6c28aaSamw  * This function sends back a list which contains all local groups' name.
1797da6c28aaSamw  */
1798da6c28aaSamw static int
samr_s_EnumDomainAliases(void * arg,ndr_xa_t * mxa)17998d7e4166Sjose borrego samr_s_EnumDomainAliases(void *arg, ndr_xa_t *mxa)
1800da6c28aaSamw {
1801da6c28aaSamw 	struct samr_EnumDomainAliases *param = arg;
1802dc20a302Sas 	ndr_hdid_t *id = (ndr_hdid_t *)&param->domain_handle;
1803dc20a302Sas 	ndr_handle_t *hd;
1804dc20a302Sas 	samr_keydata_t *data;
1805dc20a302Sas 	smb_group_t grp;
1806dc20a302Sas 	smb_giter_t gi;
1807dc20a302Sas 	int cnt, skip, i;
1808da6c28aaSamw 	struct name_rid *info;
1809da6c28aaSamw 
1810dc20a302Sas 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
1811dc20a302Sas 		bzero(param, sizeof (struct samr_EnumDomainAliases));
1812dc20a302Sas 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
18138d7e4166Sjose borrego 		return (NDR_DRC_OK);
1814da6c28aaSamw 	}
1815da6c28aaSamw 
1816dc20a302Sas 	data = (samr_keydata_t *)hd->nh_data;
1817da6c28aaSamw 
18187f667e74Sjose borrego 	cnt = smb_sam_grp_cnt(data->kd_type);
1819dc20a302Sas 	if (cnt <= param->resume_handle) {
18208d7e4166Sjose borrego 		param->aliases = (struct aliases_info *)NDR_MALLOC(mxa,
1821dc20a302Sas 		    sizeof (struct aliases_info));
1822da6c28aaSamw 
18233db3f65cSamw 		if (param->aliases == NULL) {
18243db3f65cSamw 			bzero(param, sizeof (struct samr_EnumDomainAliases));
18253db3f65cSamw 			param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
18268d7e4166Sjose borrego 			return (NDR_DRC_OK);
18273db3f65cSamw 		}
18283db3f65cSamw 
1829dc20a302Sas 		bzero(param->aliases, sizeof (struct aliases_info));
1830dc20a302Sas 		param->out_resume = 0;
1831dc20a302Sas 		param->entries = 0;
1832dc20a302Sas 		param->status = NT_STATUS_SUCCESS;
18338d7e4166Sjose borrego 		return (NDR_DRC_OK);
1834da6c28aaSamw 	}
1835da6c28aaSamw 
1836dc20a302Sas 	cnt -= param->resume_handle;
18378d7e4166Sjose borrego 	param->aliases = (struct aliases_info *)NDR_MALLOC(mxa,
1838da6c28aaSamw 	    sizeof (struct aliases_info) + (cnt-1) * sizeof (struct name_rid));
1839da6c28aaSamw 
18403db3f65cSamw 	if (param->aliases == NULL) {
18413db3f65cSamw 		bzero(param, sizeof (struct samr_EnumDomainAliases));
18423db3f65cSamw 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
18438d7e4166Sjose borrego 		return (NDR_DRC_OK);
18443db3f65cSamw 	}
18453db3f65cSamw 
1846dc20a302Sas 	if (smb_lgrp_iteropen(&gi) != SMB_LGRP_SUCCESS) {
1847dc20a302Sas 		bzero(param, sizeof (struct samr_EnumDomainAliases));
1848dc20a302Sas 		param->status = NT_SC_ERROR(NT_STATUS_INTERNAL_ERROR);
18498d7e4166Sjose borrego 		return (NDR_DRC_OK);
1850dc20a302Sas 	}
1851da6c28aaSamw 
1852dc20a302Sas 	skip = i = 0;
1853dc20a302Sas 	info = param->aliases->info;
1854dc20a302Sas 	while (smb_lgrp_iterate(&gi, &grp) == SMB_LGRP_SUCCESS) {
1855dc20a302Sas 		if ((skip++ >= param->resume_handle) &&
1856dc20a302Sas 		    (grp.sg_domain == data->kd_type) && (i++ < cnt)) {
1857dc20a302Sas 			info->rid = grp.sg_rid;
18588d7e4166Sjose borrego 			(void) NDR_MSTRING(mxa, grp.sg_name,
18598d7e4166Sjose borrego 			    (ndr_mstring_t *)&info->name);
1860da6c28aaSamw 
1861da6c28aaSamw 			info++;
1862da6c28aaSamw 		}
1863dc20a302Sas 		smb_lgrp_free(&grp);
1864da6c28aaSamw 	}
1865dc20a302Sas 	smb_lgrp_iterclose(&gi);
1866da6c28aaSamw 
1867dc20a302Sas 	param->aliases->count = i;
1868dc20a302Sas 	param->aliases->address = i;
1869da6c28aaSamw 
1870dc20a302Sas 	param->out_resume = i;
1871dc20a302Sas 	param->entries = i;
1872dc20a302Sas 	param->status = 0;
18738d7e4166Sjose borrego 	return (NDR_DRC_OK);
1874da6c28aaSamw }
1875da6c28aaSamw 
1876da6c28aaSamw /*
1877cb174861Sjoyce mcintosh  * samr_s_Connect4
1878da6c28aaSamw  */
1879da6c28aaSamw static int
samr_s_Connect4(void * arg,ndr_xa_t * mxa)1880cb174861Sjoyce mcintosh samr_s_Connect4(void *arg, ndr_xa_t *mxa)
1881da6c28aaSamw {
1882cb174861Sjoyce mcintosh 	struct samr_Connect4	*param = arg;
1883f96bd5c8SAlan Wright 	ndr_hdid_t		*id;
1884da6c28aaSamw 
1885f96bd5c8SAlan Wright 	id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, SMB_DOMAIN_NULL, 0);
1886f96bd5c8SAlan Wright 	if (id) {
1887f96bd5c8SAlan Wright 		bcopy(id, &param->handle, sizeof (samr_handle_t));
1888f96bd5c8SAlan Wright 		param->status = 0;
1889f96bd5c8SAlan Wright 	} else {
1890f96bd5c8SAlan Wright 		bzero(&param->handle, sizeof (samr_handle_t));
1891f96bd5c8SAlan Wright 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1892f96bd5c8SAlan Wright 	}
1893da6c28aaSamw 
1894f96bd5c8SAlan Wright 	return (NDR_DRC_OK);
1895f96bd5c8SAlan Wright }
1896da6c28aaSamw 
1897da6c28aaSamw /*
1898cb174861Sjoyce mcintosh  * samr_s_Connect5
1899da6c28aaSamw  *
1900cb174861Sjoyce mcintosh  * This is the connect5 form of the connect request used by Windows XP.
1901da6c28aaSamw  * Returns an RPC fault for now.
1902da6c28aaSamw  */
1903da6c28aaSamw /*ARGSUSED*/
1904da6c28aaSamw static int
samr_s_Connect5(void * arg,ndr_xa_t * mxa)1905cb174861Sjoyce mcintosh samr_s_Connect5(void *arg, ndr_xa_t *mxa)
1906da6c28aaSamw {
1907cb174861Sjoyce mcintosh 	struct samr_Connect5 *param = arg;
1908da6c28aaSamw 
1909cb174861Sjoyce mcintosh 	bzero(param, sizeof (struct samr_Connect5));
19108d7e4166Sjose borrego 	return (NDR_DRC_FAULT_REQUEST_OPNUM_INVALID);
1911da6c28aaSamw }
1912da6c28aaSamw 
19138d7e4166Sjose borrego static ndr_stub_table_t samr_stub_table[] = {
1914cb174861Sjoyce mcintosh 	{ samr_s_Connect,		SAMR_OPNUM_Connect },
1915da6c28aaSamw 	{ samr_s_CloseHandle,		SAMR_OPNUM_CloseHandle },
1916*9242c919SMatt Barden 	{ samr_s_QuerySecObject,	SAMR_OPNUM_QuerySecObject },
1917da6c28aaSamw 	{ samr_s_LookupDomain,		SAMR_OPNUM_LookupDomain },
1918da6c28aaSamw 	{ samr_s_EnumLocalDomains,	SAMR_OPNUM_EnumLocalDomains },
1919da6c28aaSamw 	{ samr_s_OpenDomain,		SAMR_OPNUM_OpenDomain },
1920da6c28aaSamw 	{ samr_s_QueryDomainInfo,	SAMR_OPNUM_QueryDomainInfo },
1921f96bd5c8SAlan Wright 	{ samr_s_QueryInfoDomain2,	SAMR_OPNUM_QueryInfoDomain2 },
1922da6c28aaSamw 	{ samr_s_LookupNames,		SAMR_OPNUM_LookupNames },
1923da6c28aaSamw 	{ samr_s_OpenUser,		SAMR_OPNUM_OpenUser },
1924da6c28aaSamw 	{ samr_s_DeleteUser,		SAMR_OPNUM_DeleteUser },
1925da6c28aaSamw 	{ samr_s_QueryUserInfo,		SAMR_OPNUM_QueryUserInfo },
1926da6c28aaSamw 	{ samr_s_QueryUserGroups,	SAMR_OPNUM_QueryUserGroups },
1927da6c28aaSamw 	{ samr_s_OpenGroup,		SAMR_OPNUM_OpenGroup },
1928cb174861Sjoyce mcintosh 	{ samr_s_Connect2,		SAMR_OPNUM_Connect2 },
1929da6c28aaSamw 	{ samr_s_GetUserPwInfo,		SAMR_OPNUM_GetUserPwInfo },
1930da6c28aaSamw 	{ samr_s_CreateUser,		SAMR_OPNUM_CreateUser },
19311ed6b69aSGordon Ross 	{ samr_s_ChangePasswordUser2,	SAMR_OPNUM_ChangePasswordUser2 },
1932da6c28aaSamw 	{ samr_s_GetDomainPwInfo,	SAMR_OPNUM_GetDomainPwInfo },
1933da6c28aaSamw 	{ samr_s_SetUserInfo,		SAMR_OPNUM_SetUserInfo },
1934da6c28aaSamw 	{ samr_s_Connect4,		SAMR_OPNUM_Connect4 },
1935cb174861Sjoyce mcintosh 	{ samr_s_Connect5,		SAMR_OPNUM_Connect5 },
1936da6c28aaSamw 	{ samr_s_QueryDispInfo,		SAMR_OPNUM_QueryDispInfo },
1937da6c28aaSamw 	{ samr_s_OpenAlias,		SAMR_OPNUM_OpenAlias },
1938da6c28aaSamw 	{ samr_s_CreateDomainAlias,	SAMR_OPNUM_CreateDomainAlias },
1939da6c28aaSamw 	{ samr_s_SetAliasInfo,		SAMR_OPNUM_SetAliasInfo },
1940da6c28aaSamw 	{ samr_s_QueryAliasInfo,	SAMR_OPNUM_QueryAliasInfo },
1941da6c28aaSamw 	{ samr_s_DeleteDomainAlias,	SAMR_OPNUM_DeleteDomainAlias },
1942da6c28aaSamw 	{ samr_s_EnumDomainAliases,	SAMR_OPNUM_EnumDomainAliases },
1943da6c28aaSamw 	{ samr_s_EnumDomainGroups,	SAMR_OPNUM_EnumDomainGroups },
1944c5866007SKeyur Desai 	{ samr_s_AddAliasMember,	SAMR_OPNUM_AddAliasMember },
1945c5866007SKeyur Desai 	{ samr_s_DeleteAliasMember,	SAMR_OPNUM_DeleteAliasMember },
1946c5866007SKeyur Desai 	{ samr_s_ListAliasMembers,	SAMR_OPNUM_ListAliasMembers },
1947da6c28aaSamw 	{0}
1948da6c28aaSamw };
1949da6c28aaSamw 
1950da6c28aaSamw /*
1951da6c28aaSamw  * There is a bug in the way that midl and the marshalling code handles
1952da6c28aaSamw  * unions so we need to fix some of the data offsets at runtime. The
1953da6c28aaSamw  * following macros and the fixup functions handle the corrections.
1954da6c28aaSamw  */
1955da6c28aaSamw 
1956da6c28aaSamw DECL_FIXUP_STRUCT(samr_QueryAliasInfo_ru);
1957da6c28aaSamw DECL_FIXUP_STRUCT(samr_QueryAliasInfoRes);
1958da6c28aaSamw DECL_FIXUP_STRUCT(samr_QueryAliasInfo);
1959da6c28aaSamw 
1960da6c28aaSamw DECL_FIXUP_STRUCT(QueryUserInfo_result_u);
1961da6c28aaSamw DECL_FIXUP_STRUCT(QueryUserInfo_result);
1962da6c28aaSamw DECL_FIXUP_STRUCT(samr_QueryUserInfo);
1963da6c28aaSamw 
1964da6c28aaSamw void
fixup_samr_QueryAliasInfo(struct samr_QueryAliasInfo * val)1965da6c28aaSamw fixup_samr_QueryAliasInfo(struct samr_QueryAliasInfo *val)
1966da6c28aaSamw {
1967da6c28aaSamw 	unsigned short size1 = 0;
1968da6c28aaSamw 	unsigned short size2 = 0;
1969da6c28aaSamw 	unsigned short size3 = 0;
1970da6c28aaSamw 
1971da6c28aaSamw 	switch (val->level) {
1972eef90b86SGordon Ross 	case SAMR_QUERY_ALIAS_INFO_GENERAL:
1973eef90b86SGordon Ross 		size1 = sizeof (struct samr_QueryAliasInfoGeneral);
1974eef90b86SGordon Ross 		break;
1975eef90b86SGordon Ross 	case SAMR_QUERY_ALIAS_INFO_NAME:
1976eef90b86SGordon Ross 		size1 = sizeof (struct samr_QueryAliasInfoName);
1977eef90b86SGordon Ross 		break;
1978eef90b86SGordon Ross 	case SAMR_QUERY_ALIAS_INFO_COMMENT:
1979eef90b86SGordon Ross 		size1 = sizeof (struct samr_QueryAliasInfoComment);
1980eef90b86SGordon Ross 		break;
1981da6c28aaSamw 
1982eef90b86SGordon Ross 	default:
1983eef90b86SGordon Ross 		return;
1984da6c28aaSamw 	};
1985da6c28aaSamw 
1986da6c28aaSamw 	size2 = size1 + (2 * sizeof (DWORD));
19872c1b14e5Sjose borrego 	size3 = size2 + sizeof (ndr_request_hdr_t) + sizeof (DWORD);
1988da6c28aaSamw 
1989da6c28aaSamw 	FIXUP_PDU_SIZE(samr_QueryAliasInfo_ru, size1);
1990da6c28aaSamw 	FIXUP_PDU_SIZE(samr_QueryAliasInfoRes, size2);
1991da6c28aaSamw 	FIXUP_PDU_SIZE(samr_QueryAliasInfo, size3);
1992da6c28aaSamw }
1993da6c28aaSamw 
1994da6c28aaSamw void
fixup_samr_QueryUserInfo(struct samr_QueryUserInfo * val)1995da6c28aaSamw fixup_samr_QueryUserInfo(struct samr_QueryUserInfo *val)
1996da6c28aaSamw {
1997da6c28aaSamw 	unsigned short size1 = 0;
1998da6c28aaSamw 	unsigned short size2 = 0;
1999da6c28aaSamw 	unsigned short size3 = 0;
2000da6c28aaSamw 
2001da6c28aaSamw 	switch (val->switch_index) {
2002da6c28aaSamw 		CASE_INFO_ENT(samr_QueryUserInfo, 1);
2003da6c28aaSamw 		CASE_INFO_ENT(samr_QueryUserInfo, 6);
2004da6c28aaSamw 		CASE_INFO_ENT(samr_QueryUserInfo, 7);
2005da6c28aaSamw 		CASE_INFO_ENT(samr_QueryUserInfo, 8);
2006da6c28aaSamw 		CASE_INFO_ENT(samr_QueryUserInfo, 9);
2007da6c28aaSamw 		CASE_INFO_ENT(samr_QueryUserInfo, 16);
2008fe1c642dSBill Krier 		CASE_INFO_ENT(samr_QueryUserInfo, 21);
2009da6c28aaSamw 
2010da6c28aaSamw 		default:
2011da6c28aaSamw 			return;
2012da6c28aaSamw 	};
2013da6c28aaSamw 
2014da6c28aaSamw 	size2 = size1 + (2 * sizeof (DWORD));
20152c1b14e5Sjose borrego 	size3 = size2 + sizeof (ndr_request_hdr_t) + sizeof (DWORD);
2016da6c28aaSamw 
2017da6c28aaSamw 	FIXUP_PDU_SIZE(QueryUserInfo_result_u, size1);
2018da6c28aaSamw 	FIXUP_PDU_SIZE(QueryUserInfo_result, size2);
2019da6c28aaSamw 	FIXUP_PDU_SIZE(samr_QueryUserInfo, size3);
2020da6c28aaSamw }
2021da6c28aaSamw 
2022da6c28aaSamw /*
2023da6c28aaSamw  * As long as there is only one entry in the union, there is no need
2024da6c28aaSamw  * to patch anything.
2025da6c28aaSamw  */
2026da6c28aaSamw /*ARGSUSED*/
2027da6c28aaSamw void
fixup_samr_QueryGroupInfo(struct samr_QueryGroupInfo * val)2028da6c28aaSamw fixup_samr_QueryGroupInfo(struct samr_QueryGroupInfo *val)
2029da6c28aaSamw {
2030da6c28aaSamw }
2031