xref: /illumos-gate/usr/src/lib/smbsrv/libmlsvc/common/samr_svc.c (revision 9242c9192f9f0f5745fbfc92d13edb32c9bcb8c3)
1fe1c642dSBill Krier /*
2fe1c642dSBill Krier  * CDDL HEADER START
3fe1c642dSBill Krier  *
4fe1c642dSBill Krier  * The contents of this file are subject to the terms of the
5fe1c642dSBill Krier  * Common Development and Distribution License (the "License").
6fe1c642dSBill Krier  * You may not use this file except in compliance with the License.
7fe1c642dSBill Krier  *
8fe1c642dSBill Krier  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fe1c642dSBill Krier  * or http://www.opensolaris.org/os/licensing.
10fe1c642dSBill Krier  * See the License for the specific language governing permissions
11fe1c642dSBill Krier  * and limitations under the License.
12fe1c642dSBill Krier  *
13fe1c642dSBill Krier  * When distributing Covered Code, include this CDDL HEADER in each
14fe1c642dSBill Krier  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fe1c642dSBill Krier  * If applicable, add the following below this CDDL HEADER, with the
16fe1c642dSBill Krier  * fields enclosed by brackets "[]" replaced with your own identifying
17fe1c642dSBill Krier  * information: Portions Copyright [yyyy] [name of copyright owner]
18fe1c642dSBill Krier  *
19fe1c642dSBill Krier  * CDDL HEADER END
20fe1c642dSBill Krier  */
21148c5f43SAlan Wright 
22fe1c642dSBill Krier /*
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.
25fe1c642dSBill Krier  */
26fe1c642dSBill Krier 
27fe1c642dSBill Krier /*
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.
35fe1c642dSBill Krier  */
36fe1c642dSBill Krier 
37fe1c642dSBill Krier #include <strings.h>
38fe1c642dSBill Krier #include <unistd.h>
39fe1c642dSBill Krier #include <netdb.h>
40fe1c642dSBill Krier #include <assert.h>
41c5866007SKeyur Desai #include <grp.h>
423299f39fSGordon Ross #include <libmlrpc/libmlrpc.h>
43fe1c642dSBill Krier #include <smbsrv/libsmb.h>
44fe1c642dSBill Krier #include <smbsrv/libmlsvc.h>
45fe1c642dSBill Krier #include <smbsrv/smbinfo.h>
46fe1c642dSBill Krier #include <smbsrv/nmpipes.h>
47fe1c642dSBill Krier #include <smbsrv/ndl/samrpc.ndl>
48fe1c642dSBill Krier #include <samlib.h>
49fe1c642dSBill Krier 
50fe1c642dSBill Krier /*
51fe1c642dSBill Krier  * The keys associated with the various handles dispensed by the SAMR
52fe1c642dSBill Krier  * server.  These keys can be used to validate client activity.
53fe1c642dSBill Krier  * These values are never passed over the wire so security shouldn't
54fe1c642dSBill Krier  * be an issue.
55fe1c642dSBill Krier  */
56fe1c642dSBill Krier typedef enum {
57fe1c642dSBill Krier 	SAMR_KEY_NULL = 0,
58fe1c642dSBill Krier 	SAMR_KEY_CONNECT,
59fe1c642dSBill Krier 	SAMR_KEY_DOMAIN,
60fe1c642dSBill Krier 	SAMR_KEY_USER,
61fe1c642dSBill Krier 	SAMR_KEY_GROUP,
62fe1c642dSBill Krier 	SAMR_KEY_ALIAS
63fe1c642dSBill Krier } samr_key_t;
64fe1c642dSBill Krier 
65fe1c642dSBill Krier typedef struct samr_keydata {
66fe1c642dSBill Krier 	samr_key_t kd_key;
67fe1c642dSBill Krier 	smb_domain_type_t kd_type;
68fe1c642dSBill Krier 	DWORD kd_rid;
69fe1c642dSBill Krier } samr_keydata_t;
70fe1c642dSBill Krier 
71fe1c642dSBill Krier /*
72fe1c642dSBill Krier  * DomainDisplayUser	All user objects (or those derived from user) with
73fe1c642dSBill Krier  *			userAccountControl containing the UF_NORMAL_ACCOUNT bit.
74fe1c642dSBill Krier  *
75fe1c642dSBill Krier  * DomainDisplayMachine	All user objects (or those derived from user) with
76fe1c642dSBill Krier  *			userAccountControl containing the
77fe1c642dSBill Krier  *			UF_WORKSTATION_TRUST_ACCOUNT or UF_SERVER_TRUST_ACCOUNT
78fe1c642dSBill Krier  *			bit.
79fe1c642dSBill Krier  *
80fe1c642dSBill Krier  * DomainDisplayGroup	All group objects (or those derived from group) with
81fe1c642dSBill Krier  *			groupType equal to GROUP_TYPE_SECURITY_UNIVERSAL or
82fe1c642dSBill Krier  *			GROUP_TYPE_SECURITY_ACCOUNT.
83fe1c642dSBill Krier  *
84fe1c642dSBill Krier  * DomainDisplayOemUser	Same as DomainDisplayUser with OEM strings
85fe1c642dSBill Krier  *
86fe1c642dSBill Krier  * DomainDisplayOemGroup Same as DomainDisplayGroup with OEM strings
87fe1c642dSBill Krier  */
88fe1c642dSBill Krier typedef enum {
89fe1c642dSBill Krier 	DomainDisplayUser = 1,
90fe1c642dSBill Krier 	DomainDisplayMachine,
91fe1c642dSBill Krier 	DomainDispalyGroup,
92fe1c642dSBill Krier 	DomainDisplayOemUser,
93fe1c642dSBill Krier 	DomainDisplayOemGroup
94fe1c642dSBill Krier } samr_displvl_t;
95fe1c642dSBill Krier 
96fe1c642dSBill Krier #define	SAMR_VALID_DISPLEVEL(lvl) \
97fe1c642dSBill Krier 	(((lvl) >= DomainDisplayUser) && ((lvl) <= DomainDisplayOemGroup))
98fe1c642dSBill Krier 
99fe1c642dSBill Krier #define	SAMR_SUPPORTED_DISPLEVEL(lvl) (lvl == DomainDisplayUser)
100fe1c642dSBill Krier 
101fe1c642dSBill Krier static ndr_hdid_t *samr_hdalloc(ndr_xa_t *, samr_key_t, smb_domain_type_t,
102fe1c642dSBill Krier     DWORD);
103fe1c642dSBill Krier static void samr_hdfree(ndr_xa_t *, ndr_hdid_t *);
104fe1c642dSBill Krier 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 *);
106fe1c642dSBill Krier static int samr_call_stub(ndr_xa_t *mxa);
107fe1c642dSBill Krier static DWORD samr_s_enum_local_domains(struct samr_EnumLocalDomain *,
108fe1c642dSBill Krier     ndr_xa_t *);
109fe1c642dSBill Krier 
110fe1c642dSBill Krier static ndr_stub_table_t samr_stub_table[];
111fe1c642dSBill Krier 
112fe1c642dSBill Krier static ndr_service_t samr_service = {
113fe1c642dSBill Krier 	"SAMR",				/* name */
114fe1c642dSBill Krier 	"Security Accounts Manager",	/* desc */
115fe1c642dSBill Krier 	"\\samr",			/* endpoint */
116fe1c642dSBill Krier 	PIPE_LSASS,			/* sec_addr_port */
117fe1c642dSBill Krier 	"12345778-1234-abcd-ef00-0123456789ac", 1,	/* abstract */
118fe1c642dSBill Krier 	NDR_TRANSFER_SYNTAX_UUID,		2,	/* transfer */
119fe1c642dSBill Krier 	0,				/* no bind_instance_size */
120fe1c642dSBill Krier 	NULL,				/* no bind_req() */
121fe1c642dSBill Krier 	NULL,				/* no unbind_and_close() */
122fe1c642dSBill Krier 	samr_call_stub,			/* call_stub() */
123fe1c642dSBill Krier 	&TYPEINFO(samr_interface),	/* interface ti */
124fe1c642dSBill Krier 	samr_stub_table			/* stub_table */
125fe1c642dSBill Krier };
126fe1c642dSBill Krier 
127fe1c642dSBill Krier /*
128fe1c642dSBill Krier  * samr_initialize
129fe1c642dSBill Krier  *
130fe1c642dSBill Krier  * This function registers the SAM RPC interface with the RPC runtime
131fe1c642dSBill Krier  * library. It must be called in order to use either the client side
132fe1c642dSBill Krier  * or the server side functions.
133fe1c642dSBill Krier  */
134fe1c642dSBill Krier void
samr_initialize(void)135fe1c642dSBill Krier samr_initialize(void)
136fe1c642dSBill Krier {
137fe1c642dSBill Krier 	(void) ndr_svc_register(&samr_service);
138fe1c642dSBill Krier }
139fe1c642dSBill Krier 
140fe1c642dSBill Krier /*
141fe1c642dSBill Krier  * Custom call_stub to set the stream string policy.
142fe1c642dSBill Krier  */
143fe1c642dSBill Krier static int
samr_call_stub(ndr_xa_t * mxa)144fe1c642dSBill Krier samr_call_stub(ndr_xa_t *mxa)
145fe1c642dSBill Krier {
146fe1c642dSBill Krier 	NDS_SETF(&mxa->send_nds, NDS_F_NOTERM);
147fe1c642dSBill Krier 	NDS_SETF(&mxa->recv_nds, NDS_F_NOTERM);
148fe1c642dSBill Krier 
149fe1c642dSBill Krier 	return (ndr_generic_call_stub(mxa));
150fe1c642dSBill Krier }
151fe1c642dSBill Krier 
152fe1c642dSBill Krier /*
153fe1c642dSBill Krier  * Handle allocation wrapper to setup the local context.
154fe1c642dSBill Krier  */
155fe1c642dSBill Krier static ndr_hdid_t *
samr_hdalloc(ndr_xa_t * mxa,samr_key_t key,smb_domain_type_t domain_type,DWORD rid)156fe1c642dSBill Krier samr_hdalloc(ndr_xa_t *mxa, samr_key_t key, smb_domain_type_t domain_type,
157fe1c642dSBill Krier     DWORD rid)
158fe1c642dSBill Krier {
1599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	ndr_handle_t	*hd;
1609fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	ndr_hdid_t	*id;
161fe1c642dSBill Krier 	samr_keydata_t	*data;
162fe1c642dSBill Krier 
163fe1c642dSBill Krier 	if ((data = malloc(sizeof (samr_keydata_t))) == NULL)
164fe1c642dSBill Krier 		return (NULL);
165fe1c642dSBill Krier 
166fe1c642dSBill Krier 	data->kd_key = key;
167fe1c642dSBill Krier 	data->kd_type = domain_type;
168fe1c642dSBill Krier 	data->kd_rid = rid;
169fe1c642dSBill Krier 
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);
179fe1c642dSBill Krier }
180fe1c642dSBill Krier 
181fe1c642dSBill Krier /*
182fe1c642dSBill Krier  * Handle deallocation wrapper to free the local context.
183fe1c642dSBill Krier  */
184fe1c642dSBill Krier static void
samr_hdfree(ndr_xa_t * mxa,ndr_hdid_t * id)185fe1c642dSBill Krier samr_hdfree(ndr_xa_t *mxa, ndr_hdid_t *id)
186fe1c642dSBill Krier {
187fe1c642dSBill Krier 	ndr_handle_t *hd;
188fe1c642dSBill Krier 
189fe1c642dSBill Krier 	if ((hd = ndr_hdlookup(mxa, id)) != NULL) {
190fe1c642dSBill Krier 		free(hd->nh_data);
1919fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		hd->nh_data = NULL;
192fe1c642dSBill Krier 		ndr_hdfree(mxa, id);
193fe1c642dSBill Krier 	}
194fe1c642dSBill Krier }
195fe1c642dSBill Krier 
196fe1c642dSBill Krier /*
197fe1c642dSBill Krier  * Handle lookup wrapper to validate the local context.
198fe1c642dSBill Krier  */
199fe1c642dSBill Krier static ndr_handle_t *
samr_hdlookup(ndr_xa_t * mxa,ndr_hdid_t * id,samr_key_t key)200fe1c642dSBill Krier samr_hdlookup(ndr_xa_t *mxa, ndr_hdid_t *id, samr_key_t key)
201fe1c642dSBill Krier {
202fe1c642dSBill Krier 	ndr_handle_t *hd;
203fe1c642dSBill Krier 	samr_keydata_t *data;
204fe1c642dSBill Krier 
205fe1c642dSBill Krier 	if ((hd = ndr_hdlookup(mxa, id)) == NULL)
206fe1c642dSBill Krier 		return (NULL);
207fe1c642dSBill Krier 
208fe1c642dSBill Krier 	if ((data = (samr_keydata_t *)hd->nh_data) == NULL)
209fe1c642dSBill Krier 		return (NULL);
210fe1c642dSBill Krier 
211fe1c642dSBill Krier 	if (data->kd_key != key)
212fe1c642dSBill Krier 		return (NULL);
213fe1c642dSBill Krier 
214fe1c642dSBill Krier 	return (hd);
215fe1c642dSBill Krier }
216fe1c642dSBill Krier 
217fe1c642dSBill Krier /*
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 
235*9242c919SMatt Barden /*
236cb174861Sjoyce mcintosh  * samr_s_Connect
237fe1c642dSBill Krier  *
238fe1c642dSBill Krier  * This is a request to connect to the local SAM database. We don't
239fe1c642dSBill Krier  * support any form of update request and our database doesn't
240fe1c642dSBill Krier  * contain any private information, so there is little point in
241fe1c642dSBill Krier  * doing any access access checking here.
242fe1c642dSBill Krier  *
243fe1c642dSBill Krier  * Return a handle for use with subsequent SAM requests.
244fe1c642dSBill Krier  */
245fe1c642dSBill Krier static int
samr_s_Connect(void * arg,ndr_xa_t * mxa)246cb174861Sjoyce mcintosh samr_s_Connect(void *arg, ndr_xa_t *mxa)
247fe1c642dSBill Krier {
248cb174861Sjoyce mcintosh 	struct samr_Connect *param = arg;
249fe1c642dSBill Krier 	ndr_hdid_t *id;
250fe1c642dSBill Krier 
251fe1c642dSBill Krier 	id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, SMB_DOMAIN_NULL, 0);
252fe1c642dSBill Krier 	if (id) {
253fe1c642dSBill Krier 		bcopy(id, &param->handle, sizeof (samr_handle_t));
254fe1c642dSBill Krier 		param->status = 0;
255fe1c642dSBill Krier 	} else {
256fe1c642dSBill Krier 		bzero(&param->handle, sizeof (samr_handle_t));
257fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
258fe1c642dSBill Krier 	}
259fe1c642dSBill Krier 
260fe1c642dSBill Krier 	return (NDR_DRC_OK);
261fe1c642dSBill Krier }
262fe1c642dSBill Krier 
263fe1c642dSBill Krier /*
264fe1c642dSBill Krier  * samr_s_CloseHandle
265fe1c642dSBill Krier  *
266fe1c642dSBill Krier  * Close the SAM interface specified by the handle.
267fe1c642dSBill Krier  * Free the handle and zero out the result handle for the client.
268fe1c642dSBill Krier  */
269fe1c642dSBill Krier static int
samr_s_CloseHandle(void * arg,ndr_xa_t * mxa)270fe1c642dSBill Krier samr_s_CloseHandle(void *arg, ndr_xa_t *mxa)
271fe1c642dSBill Krier {
272fe1c642dSBill Krier 	struct samr_CloseHandle *param = arg;
273fe1c642dSBill Krier 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
274fe1c642dSBill Krier 
275fe1c642dSBill Krier 	samr_hdfree(mxa, id);
276fe1c642dSBill Krier 
277fe1c642dSBill Krier 	bzero(&param->result_handle, sizeof (samr_handle_t));
278fe1c642dSBill Krier 	param->status = 0;
279fe1c642dSBill Krier 	return (NDR_DRC_OK);
280fe1c642dSBill Krier }
281fe1c642dSBill Krier 
282fe1c642dSBill Krier /*
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 
325*9242c919SMatt Barden /*
326fe1c642dSBill Krier  * samr_s_LookupDomain
327fe1c642dSBill Krier  *
328fe1c642dSBill Krier  * This is a request to map a domain name to a domain SID. We can map
329fe1c642dSBill Krier  * the primary domain name, our local domain name (hostname) and the
330fe1c642dSBill Krier  * builtin domain names to the appropriate SID. Anything else will be
331fe1c642dSBill Krier  * rejected.
332fe1c642dSBill Krier  */
333fe1c642dSBill Krier static int
samr_s_LookupDomain(void * arg,ndr_xa_t * mxa)334fe1c642dSBill Krier samr_s_LookupDomain(void *arg, ndr_xa_t *mxa)
335fe1c642dSBill Krier {
336fe1c642dSBill Krier 	struct samr_LookupDomain *param = arg;
337fe1c642dSBill Krier 	char *domain_name;
338fe1c642dSBill Krier 	smb_domain_t di;
339fe1c642dSBill Krier 
340fe1c642dSBill Krier 	if ((domain_name = (char *)param->domain_name.str) == NULL) {
341fe1c642dSBill Krier 		bzero(param, sizeof (struct samr_LookupDomain));
342fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER);
343fe1c642dSBill Krier 		return (NDR_DRC_OK);
344fe1c642dSBill Krier 	}
345fe1c642dSBill Krier 
346fe1c642dSBill Krier 	if (!smb_domain_lookup_name(domain_name, &di)) {
347fe1c642dSBill Krier 		bzero(param, sizeof (struct samr_LookupDomain));
348fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_NO_SUCH_DOMAIN);
349fe1c642dSBill Krier 		return (NDR_DRC_OK);
350fe1c642dSBill Krier 	}
351fe1c642dSBill Krier 
352fe1c642dSBill Krier 	param->sid = (struct samr_sid *)NDR_SIDDUP(mxa, di.di_binsid);
353fe1c642dSBill Krier 	if (param->sid == NULL) {
354fe1c642dSBill Krier 		bzero(param, sizeof (struct samr_LookupDomain));
355fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
356fe1c642dSBill Krier 		return (NDR_DRC_OK);
357fe1c642dSBill Krier 	}
358fe1c642dSBill Krier 
359fe1c642dSBill Krier 	param->status = NT_STATUS_SUCCESS;
360fe1c642dSBill Krier 	return (NDR_DRC_OK);
361fe1c642dSBill Krier }
362fe1c642dSBill Krier 
363fe1c642dSBill Krier /*
364fe1c642dSBill Krier  * samr_s_EnumLocalDomains
365fe1c642dSBill Krier  *
366fe1c642dSBill Krier  * This is a request for the local domains supported by this server.
367fe1c642dSBill Krier  * All we do here is validate the handle and set the status. The real
368fe1c642dSBill Krier  * work is done in samr_s_enum_local_domains.
369fe1c642dSBill Krier  */
370fe1c642dSBill Krier static int
samr_s_EnumLocalDomains(void * arg,ndr_xa_t * mxa)371fe1c642dSBill Krier samr_s_EnumLocalDomains(void *arg, ndr_xa_t *mxa)
372fe1c642dSBill Krier {
373fe1c642dSBill Krier 	struct samr_EnumLocalDomain *param = arg;
374fe1c642dSBill Krier 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
375fe1c642dSBill Krier 	DWORD status;
376fe1c642dSBill Krier 
377fe1c642dSBill Krier 	if (samr_hdlookup(mxa, id, SAMR_KEY_CONNECT) == NULL)
378fe1c642dSBill Krier 		status = NT_STATUS_ACCESS_DENIED;
379fe1c642dSBill Krier 	else
380fe1c642dSBill Krier 		status = samr_s_enum_local_domains(param, mxa);
381fe1c642dSBill Krier 
382fe1c642dSBill Krier 	if (status == NT_STATUS_SUCCESS) {
383fe1c642dSBill Krier 		param->enum_context = param->info->entries_read;
384fe1c642dSBill Krier 		param->total_entries = param->info->entries_read;
385fe1c642dSBill Krier 		param->status = NT_STATUS_SUCCESS;
386fe1c642dSBill Krier 	} else {
387fe1c642dSBill Krier 		bzero(param, sizeof (struct samr_EnumLocalDomain));
388fe1c642dSBill Krier 		param->status = NT_SC_ERROR(status);
389fe1c642dSBill Krier 	}
390fe1c642dSBill Krier 
391fe1c642dSBill Krier 	return (NDR_DRC_OK);
392fe1c642dSBill Krier }
393fe1c642dSBill Krier 
394fe1c642dSBill Krier 
395fe1c642dSBill Krier /*
396fe1c642dSBill Krier  * samr_s_enum_local_domains
397fe1c642dSBill Krier  *
398fe1c642dSBill Krier  * This function should only be called via samr_s_EnumLocalDomains to
399fe1c642dSBill Krier  * ensure that the appropriate validation is performed. We will answer
400fe1c642dSBill Krier  * queries about two domains: the local domain, synonymous with the
401fe1c642dSBill Krier  * local hostname, and the BUILTIN domain. So we return these two
402fe1c642dSBill Krier  * strings.
403fe1c642dSBill Krier  *
404fe1c642dSBill Krier  * Returns NT status values.
405fe1c642dSBill Krier  */
406fe1c642dSBill Krier static DWORD
samr_s_enum_local_domains(struct samr_EnumLocalDomain * param,ndr_xa_t * mxa)407fe1c642dSBill Krier samr_s_enum_local_domains(struct samr_EnumLocalDomain *param,
408fe1c642dSBill Krier     ndr_xa_t *mxa)
409fe1c642dSBill Krier {
410fe1c642dSBill Krier 	struct samr_LocalDomainInfo *info;
411fe1c642dSBill Krier 	struct samr_LocalDomainEntry *entry;
412fe1c642dSBill Krier 	char *hostname;
413fe1c642dSBill Krier 
414fe1c642dSBill Krier 	hostname = NDR_MALLOC(mxa, NETBIOS_NAME_SZ);
415fe1c642dSBill Krier 	if (hostname == NULL)
416fe1c642dSBill Krier 		return (NT_STATUS_NO_MEMORY);
417fe1c642dSBill Krier 
418fe1c642dSBill Krier 	if (smb_getnetbiosname(hostname, NETBIOS_NAME_SZ) != 0)
419fe1c642dSBill Krier 		return (NT_STATUS_NO_MEMORY);
420fe1c642dSBill Krier 
421fe1c642dSBill Krier 	entry = NDR_NEWN(mxa, struct samr_LocalDomainEntry, 2);
422fe1c642dSBill Krier 	if (entry == NULL)
423fe1c642dSBill Krier 		return (NT_STATUS_NO_MEMORY);
424fe1c642dSBill Krier 
425fe1c642dSBill Krier 	bzero(entry, (sizeof (struct samr_LocalDomainEntry) * 2));
426fe1c642dSBill Krier 	(void) NDR_MSTRING(mxa, hostname, (ndr_mstring_t *)&entry[0].name);
427fe1c642dSBill Krier 	(void) NDR_MSTRING(mxa, "Builtin", (ndr_mstring_t *)&entry[1].name);
428fe1c642dSBill Krier 
429fe1c642dSBill Krier 	info = NDR_NEW(mxa, struct samr_LocalDomainInfo);
430fe1c642dSBill Krier 	if (info == NULL)
431fe1c642dSBill Krier 		return (NT_STATUS_NO_MEMORY);
432fe1c642dSBill Krier 
433fe1c642dSBill Krier 	info->entries_read = 2;
434fe1c642dSBill Krier 	info->entry = entry;
435fe1c642dSBill Krier 	param->info = info;
436fe1c642dSBill Krier 	return (NT_STATUS_SUCCESS);
437fe1c642dSBill Krier }
438fe1c642dSBill Krier 
439fe1c642dSBill Krier /*
440fe1c642dSBill Krier  * samr_s_OpenDomain
441fe1c642dSBill Krier  *
442fe1c642dSBill Krier  * This is a request to open a domain within the local SAM database.
443fe1c642dSBill Krier  * The caller must supply a valid connect handle.
444fe1c642dSBill Krier  * We return a handle to be used to access objects within this domain.
445fe1c642dSBill Krier  */
446fe1c642dSBill Krier static int
samr_s_OpenDomain(void * arg,ndr_xa_t * mxa)447fe1c642dSBill Krier samr_s_OpenDomain(void *arg, ndr_xa_t *mxa)
448fe1c642dSBill Krier {
449fe1c642dSBill Krier 	struct samr_OpenDomain *param = arg;
450fe1c642dSBill Krier 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
451fe1c642dSBill Krier 	smb_domain_t domain;
452fe1c642dSBill Krier 
453fe1c642dSBill Krier 	if (samr_hdlookup(mxa, id, SAMR_KEY_CONNECT) == NULL) {
454fe1c642dSBill Krier 		bzero(&param->domain_handle, sizeof (samr_handle_t));
455fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
456fe1c642dSBill Krier 		return (NDR_DRC_OK);
457fe1c642dSBill Krier 	}
458fe1c642dSBill Krier 
459fe1c642dSBill Krier 	if (!smb_domain_lookup_sid((smb_sid_t *)param->sid, &domain)) {
460fe1c642dSBill Krier 		bzero(&param->domain_handle, sizeof (samr_handle_t));
461fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
462fe1c642dSBill Krier 		return (NDR_DRC_OK);
463fe1c642dSBill Krier 	}
464fe1c642dSBill Krier 
465fe1c642dSBill Krier 	if ((domain.di_type != SMB_DOMAIN_BUILTIN) &&
466fe1c642dSBill Krier 	    (domain.di_type != SMB_DOMAIN_LOCAL)) {
467fe1c642dSBill Krier 		bzero(&param->domain_handle, sizeof (samr_handle_t));
468fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
469fe1c642dSBill Krier 		return (NDR_DRC_OK);
470fe1c642dSBill Krier 	}
471fe1c642dSBill Krier 
472fe1c642dSBill Krier 	id = samr_hdalloc(mxa, SAMR_KEY_DOMAIN, domain.di_type, 0);
473fe1c642dSBill Krier 	if (id) {
474fe1c642dSBill Krier 		bcopy(id, &param->domain_handle, sizeof (samr_handle_t));
475fe1c642dSBill Krier 		param->status = 0;
476fe1c642dSBill Krier 	} else {
477fe1c642dSBill Krier 		bzero(&param->domain_handle, sizeof (samr_handle_t));
478fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
479fe1c642dSBill Krier 	}
480fe1c642dSBill Krier 
481fe1c642dSBill Krier 	return (NDR_DRC_OK);
482fe1c642dSBill Krier }
483fe1c642dSBill Krier 
484fe1c642dSBill Krier /*
485fe1c642dSBill Krier  * samr_s_QueryDomainInfo
486fe1c642dSBill Krier  *
487fe1c642dSBill Krier  * The caller should pass a domain handle.
488fe1c642dSBill Krier  *
489fe1c642dSBill Krier  * Windows 95 Server Manager sends requests for levels 6 and 7 when
490fe1c642dSBill Krier  * the services menu item is selected. Level 2 is basically for getting
491fe1c642dSBill Krier  * number of users, groups, and aliases in a domain.
492fe1c642dSBill Krier  * We have no information on what the various information levels mean.
493fe1c642dSBill Krier  */
494fe1c642dSBill Krier static int
samr_s_QueryDomainInfo(void * arg,ndr_xa_t * mxa)495fe1c642dSBill Krier samr_s_QueryDomainInfo(void *arg, ndr_xa_t *mxa)
496fe1c642dSBill Krier {
497fe1c642dSBill Krier 	struct samr_QueryDomainInfo *param = arg;
498fe1c642dSBill Krier 	struct samr_QueryDomainInfoRes *info;
499fe1c642dSBill Krier 	ndr_hdid_t *id = (ndr_hdid_t *)&param->domain_handle;
500fe1c642dSBill Krier 	ndr_handle_t *hd;
501fe1c642dSBill Krier 	samr_keydata_t *data;
502fe1c642dSBill Krier 	char *domain;
503fe1c642dSBill Krier 	char hostname[NETBIOS_NAME_SZ];
504fe1c642dSBill Krier 	int alias_cnt, user_cnt;
505fe1c642dSBill Krier 	int rc = 0;
506fe1c642dSBill Krier 
507fe1c642dSBill Krier 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
508fe1c642dSBill Krier 		bzero(param, sizeof (struct samr_QueryDomainInfo));
509fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
510fe1c642dSBill Krier 		return (NDR_DRC_OK);
511fe1c642dSBill Krier 	}
512fe1c642dSBill Krier 
513fe1c642dSBill Krier 	info = NDR_NEW(mxa, struct samr_QueryDomainInfoRes);
514fe1c642dSBill Krier 	if (info == NULL) {
515fe1c642dSBill Krier 		bzero(param, sizeof (struct samr_QueryDomainInfo));
516fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
517fe1c642dSBill Krier 		return (NDR_DRC_OK);
518fe1c642dSBill Krier 	}
519fe1c642dSBill Krier 	info->switch_value = param->info_level;
520fe1c642dSBill Krier 	param->info = info;
521fe1c642dSBill Krier 
522fe1c642dSBill Krier 	data = (samr_keydata_t *)hd->nh_data;
523fe1c642dSBill Krier 
524fe1c642dSBill Krier 	switch (data->kd_type) {
525fe1c642dSBill Krier 	case SMB_DOMAIN_BUILTIN:
526fe1c642dSBill Krier 		domain = "BUILTIN";
527fe1c642dSBill Krier 		user_cnt = 0;
528fe1c642dSBill Krier 		alias_cnt = smb_sam_grp_cnt(data->kd_type);
529fe1c642dSBill Krier 		break;
530fe1c642dSBill Krier 
531fe1c642dSBill Krier 	case SMB_DOMAIN_LOCAL:
532fe1c642dSBill Krier 		rc = smb_getnetbiosname(hostname, sizeof (hostname));
533fe1c642dSBill Krier 		if (rc == 0) {
534fe1c642dSBill Krier 			domain = hostname;
535fe1c642dSBill Krier 			user_cnt = smb_sam_usr_cnt();
536fe1c642dSBill Krier 			alias_cnt = smb_sam_grp_cnt(data->kd_type);
537fe1c642dSBill Krier 		}
538fe1c642dSBill Krier 		break;
539fe1c642dSBill Krier 
540fe1c642dSBill Krier 	default:
541fe1c642dSBill Krier 		bzero(param, sizeof (struct samr_QueryDomainInfo));
542fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
543fe1c642dSBill Krier 		return (NDR_DRC_OK);
544fe1c642dSBill Krier 	}
545fe1c642dSBill Krier 
546fe1c642dSBill Krier 	if (rc != 0) {
547fe1c642dSBill Krier 		bzero(param, sizeof (struct samr_QueryDomainInfo));
548fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_INTERNAL_ERROR);
549fe1c642dSBill Krier 		return (NDR_DRC_OK);
550fe1c642dSBill Krier 	}
551fe1c642dSBill Krier 
552fe1c642dSBill Krier 	switch (param->info_level) {
553fe1c642dSBill Krier 	case SAMR_QUERY_DOMAIN_INFO_6:
554fe1c642dSBill Krier 		info->ru.info6.unknown1 = 0x00000000;
555fe1c642dSBill Krier 		info->ru.info6.unknown2 = 0x00147FB0;
556fe1c642dSBill Krier 		info->ru.info6.unknown3 = 0x00000000;
557fe1c642dSBill Krier 		info->ru.info6.unknown4 = 0x00000000;
558fe1c642dSBill Krier 		info->ru.info6.unknown5 = 0x00000000;
559fe1c642dSBill Krier 		param->status = NT_STATUS_SUCCESS;
560fe1c642dSBill Krier 		break;
561fe1c642dSBill Krier 
562fe1c642dSBill Krier 	case SAMR_QUERY_DOMAIN_INFO_7:
563fe1c642dSBill Krier 		info->ru.info7.unknown1 = 0x00000003;
564fe1c642dSBill Krier 		param->status = NT_STATUS_SUCCESS;
565fe1c642dSBill Krier 		break;
566fe1c642dSBill Krier 
567fe1c642dSBill Krier 	case SAMR_QUERY_DOMAIN_INFO_2:
568fe1c642dSBill Krier 		info->ru.info2.unknown1 = 0x00000000;
569fe1c642dSBill Krier 		info->ru.info2.unknown2 = 0x80000000;
570fe1c642dSBill Krier 
571fe1c642dSBill Krier 		(void) NDR_MSTRING(mxa, "",
572fe1c642dSBill Krier 		    (ndr_mstring_t *)&(info->ru.info2.s1));
573fe1c642dSBill Krier 		(void) NDR_MSTRING(mxa, domain,
574fe1c642dSBill Krier 		    (ndr_mstring_t *)&(info->ru.info2.domain));
575fe1c642dSBill Krier 		(void) NDR_MSTRING(mxa, "",
576fe1c642dSBill Krier 		    (ndr_mstring_t *)&(info->ru.info2.s2));
577fe1c642dSBill Krier 
578fe1c642dSBill Krier 		info->ru.info2.sequence_num = 0x0000002B;
579fe1c642dSBill Krier 		info->ru.info2.unknown3 = 0x00000000;
580fe1c642dSBill Krier 		info->ru.info2.unknown4 = 0x00000001;
581fe1c642dSBill Krier 		info->ru.info2.unknown5 = 0x00000003;
582fe1c642dSBill Krier 		info->ru.info2.unknown6 = 0x00000001;
583fe1c642dSBill Krier 		info->ru.info2.num_users = user_cnt;
584fe1c642dSBill Krier 		info->ru.info2.num_groups = 0;
585fe1c642dSBill Krier 		info->ru.info2.num_aliases = alias_cnt;
586fe1c642dSBill Krier 		param->status = NT_STATUS_SUCCESS;
587fe1c642dSBill Krier 		break;
588fe1c642dSBill Krier 
589fe1c642dSBill Krier 	default:
590fe1c642dSBill Krier 		bzero(param, sizeof (struct samr_QueryDomainInfo));
591fe1c642dSBill Krier 		return (NDR_DRC_FAULT_REQUEST_OPNUM_INVALID);
592fe1c642dSBill Krier 	};
593fe1c642dSBill Krier 
594fe1c642dSBill Krier 	return (NDR_DRC_OK);
595fe1c642dSBill Krier }
596fe1c642dSBill Krier 
597fe1c642dSBill Krier /*
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 
606f96bd5c8SAlan Wright /*
607fe1c642dSBill Krier  * Looks up the given name in the specified domain which could
608fe1c642dSBill Krier  * be either the built-in or local domain.
609fe1c642dSBill Krier  *
610fe1c642dSBill Krier  * CAVEAT: this function should be able to handle a list of
611fe1c642dSBill Krier  * names but currently it can only handle one name at a time.
612fe1c642dSBill Krier  */
613fe1c642dSBill Krier static int
samr_s_LookupNames(void * arg,ndr_xa_t * mxa)614fe1c642dSBill Krier samr_s_LookupNames(void *arg, ndr_xa_t *mxa)
615fe1c642dSBill Krier {
616fe1c642dSBill Krier 	struct samr_LookupNames *param = arg;
617fe1c642dSBill Krier 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
618fe1c642dSBill Krier 	ndr_handle_t *hd;
619fe1c642dSBill Krier 	samr_keydata_t *data;
620fe1c642dSBill Krier 	smb_account_t account;
621fe1c642dSBill Krier 	smb_wka_t *wka;
622fe1c642dSBill Krier 	uint32_t status = NT_STATUS_SUCCESS;
623fe1c642dSBill Krier 
624fe1c642dSBill Krier 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL)
625fe1c642dSBill Krier 		status = NT_STATUS_INVALID_HANDLE;
626fe1c642dSBill Krier 
627fe1c642dSBill Krier 	if (param->n_entry != 1)
628fe1c642dSBill Krier 		status = NT_STATUS_ACCESS_DENIED;
629fe1c642dSBill Krier 
630fe1c642dSBill Krier 	if (param->name.str == NULL) {
631fe1c642dSBill Krier 		/*
632fe1c642dSBill Krier 		 * Windows NT returns NT_STATUS_NONE_MAPPED.
633fe1c642dSBill Krier 		 * Windows 2000 returns STATUS_INVALID_ACCOUNT_NAME.
634fe1c642dSBill Krier 		 */
635fe1c642dSBill Krier 		status = NT_STATUS_NONE_MAPPED;
636fe1c642dSBill Krier 	}
637fe1c642dSBill Krier 
638fe1c642dSBill Krier 	if (status != NT_STATUS_SUCCESS) {
639fe1c642dSBill Krier 		bzero(param, sizeof (struct samr_LookupNames));
640fe1c642dSBill Krier 		param->status = NT_SC_ERROR(status);
641fe1c642dSBill Krier 		return (NDR_DRC_OK);
642fe1c642dSBill Krier 	}
643fe1c642dSBill Krier 
644fe1c642dSBill Krier 	param->rids.rid = NDR_NEW(mxa, DWORD);
645fe1c642dSBill Krier 	param->rid_types.rid_type = NDR_NEW(mxa, DWORD);
646fe1c642dSBill Krier 
647fe1c642dSBill Krier 	data = (samr_keydata_t *)hd->nh_data;
648fe1c642dSBill Krier 
649fe1c642dSBill Krier 	switch (data->kd_type) {
650fe1c642dSBill Krier 	case SMB_DOMAIN_BUILTIN:
651f96bd5c8SAlan Wright 		wka = smb_wka_lookup_builtin((char *)param->name.str);
652fe1c642dSBill Krier 		if (wka != NULL) {
653fe1c642dSBill Krier 			param->rids.n_entry = 1;
654fe1c642dSBill Krier 			(void) smb_sid_getrid(wka->wka_binsid,
655fe1c642dSBill Krier 			    &param->rids.rid[0]);
656fe1c642dSBill Krier 			param->rid_types.n_entry = 1;
657fe1c642dSBill Krier 			param->rid_types.rid_type[0] = wka->wka_type;
658fe1c642dSBill Krier 			param->status = NT_STATUS_SUCCESS;
659fe1c642dSBill Krier 			return (NDR_DRC_OK);
660fe1c642dSBill Krier 		}
661fe1c642dSBill Krier 		break;
662fe1c642dSBill Krier 
663fe1c642dSBill Krier 	case SMB_DOMAIN_LOCAL:
664fe1c642dSBill Krier 		status = smb_sam_lookup_name(NULL, (char *)param->name.str,
665fe1c642dSBill Krier 		    SidTypeUnknown, &account);
666fe1c642dSBill Krier 		if (status == NT_STATUS_SUCCESS) {
667fe1c642dSBill Krier 			param->rids.n_entry = 1;
668fe1c642dSBill Krier 			param->rids.rid[0] = account.a_rid;
669fe1c642dSBill Krier 			param->rid_types.n_entry = 1;
670fe1c642dSBill Krier 			param->rid_types.rid_type[0] = account.a_type;
671fe1c642dSBill Krier 			param->status = NT_STATUS_SUCCESS;
672fe1c642dSBill Krier 			smb_account_free(&account);
673fe1c642dSBill Krier 			return (NDR_DRC_OK);
674fe1c642dSBill Krier 		}
675fe1c642dSBill Krier 		break;
676fe1c642dSBill Krier 
677fe1c642dSBill Krier 	default:
678fe1c642dSBill Krier 		bzero(param, sizeof (struct samr_LookupNames));
679fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
680fe1c642dSBill Krier 		return (NDR_DRC_OK);
681fe1c642dSBill Krier 	}
682fe1c642dSBill Krier 
683fe1c642dSBill Krier 	param->rids.n_entry = 0;
684fe1c642dSBill Krier 	param->rid_types.n_entry = 0;
685fe1c642dSBill Krier 	param->status = NT_SC_ERROR(NT_STATUS_NONE_MAPPED);
686fe1c642dSBill Krier 	return (NDR_DRC_OK);
687fe1c642dSBill Krier }
688fe1c642dSBill Krier 
689fe1c642dSBill Krier /*
690fe1c642dSBill Krier  * samr_s_OpenUser
691fe1c642dSBill Krier  *
692fe1c642dSBill Krier  * This is a request to open a user within a specified domain in the
693fe1c642dSBill Krier  * local SAM database. The caller must supply a valid domain handle,
694fe1c642dSBill Krier  * obtained via a successful domain open request. The user is
695fe1c642dSBill Krier  * specified by the rid in the request.
696fe1c642dSBill Krier  */
697fe1c642dSBill Krier static int
samr_s_OpenUser(void * arg,ndr_xa_t * mxa)698fe1c642dSBill Krier samr_s_OpenUser(void *arg, ndr_xa_t *mxa)
699fe1c642dSBill Krier {
700fe1c642dSBill Krier 	struct samr_OpenUser *param = arg;
701fe1c642dSBill Krier 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
702fe1c642dSBill Krier 	ndr_handle_t *hd;
703fe1c642dSBill Krier 	samr_keydata_t *data;
704fe1c642dSBill Krier 
705fe1c642dSBill Krier 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
706fe1c642dSBill Krier 		bzero(&param->user_handle, sizeof (samr_handle_t));
707fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
708fe1c642dSBill Krier 		return (NDR_DRC_OK);
709fe1c642dSBill Krier 	}
710fe1c642dSBill Krier 
711fe1c642dSBill Krier 	data = (samr_keydata_t *)hd->nh_data;
712fe1c642dSBill Krier 
713fe1c642dSBill Krier 	id = samr_hdalloc(mxa, SAMR_KEY_USER, data->kd_type, param->rid);
714fe1c642dSBill Krier 	if (id == NULL) {
715fe1c642dSBill Krier 		bzero(&param->user_handle, sizeof (samr_handle_t));
716fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
717fe1c642dSBill Krier 	} else {
718fe1c642dSBill Krier 		bcopy(id, &param->user_handle, sizeof (samr_handle_t));
719fe1c642dSBill Krier 		param->status = NT_STATUS_SUCCESS;
720fe1c642dSBill Krier 	}
721fe1c642dSBill Krier 
722fe1c642dSBill Krier 	return (NDR_DRC_OK);
723fe1c642dSBill Krier }
724fe1c642dSBill Krier 
725fe1c642dSBill Krier /*
726fe1c642dSBill Krier  * samr_s_DeleteUser
727fe1c642dSBill Krier  *
728fe1c642dSBill Krier  * Request to delete a user within a specified domain in the local
729fe1c642dSBill Krier  * SAM database.  The caller should supply a valid user handle.
730fe1c642dSBill Krier  */
731fe1c642dSBill Krier /*ARGSUSED*/
732fe1c642dSBill Krier static int
samr_s_DeleteUser(void * arg,ndr_xa_t * mxa)733fe1c642dSBill Krier samr_s_DeleteUser(void *arg, ndr_xa_t *mxa)
734fe1c642dSBill Krier {
735fe1c642dSBill Krier 	struct samr_DeleteUser *param = arg;
736fe1c642dSBill Krier 
737fe1c642dSBill Krier 	bzero(param, sizeof (struct samr_DeleteUser));
738fe1c642dSBill Krier 	param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
739fe1c642dSBill Krier 	return (NDR_DRC_OK);
740fe1c642dSBill Krier }
741fe1c642dSBill Krier 
742fe1c642dSBill Krier /*
743fe1c642dSBill Krier  * samr_s_QueryUserInfo
744fe1c642dSBill Krier  *
745fe1c642dSBill Krier  * Returns:
746fe1c642dSBill Krier  * NT_STATUS_SUCCESS
747fe1c642dSBill Krier  * NT_STATUS_ACCESS_DENIED
748fe1c642dSBill Krier  * NT_STATUS_INVALID_INFO_CLASS
749fe1c642dSBill Krier  */
750fe1c642dSBill Krier /*ARGSUSED*/
751fe1c642dSBill Krier static int
samr_s_QueryUserInfo(void * arg,ndr_xa_t * mxa)752fe1c642dSBill Krier samr_s_QueryUserInfo(void *arg, ndr_xa_t *mxa)
753fe1c642dSBill Krier {
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 	}
776fe1c642dSBill Krier 
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);
821fe1c642dSBill Krier 	bzero(param, sizeof (struct samr_QueryUserInfo));
822fe1c642dSBill Krier 	param->status = NT_SC_ERROR(status);
823fe1c642dSBill Krier 	return (NDR_DRC_OK);
824fe1c642dSBill Krier }
825fe1c642dSBill Krier 
826fe1c642dSBill Krier /*
827fe1c642dSBill Krier  * samr_s_QueryUserGroups
828fe1c642dSBill Krier  *
829fe1c642dSBill Krier  * Request the list of groups of which a user is a member.
830fe1c642dSBill Krier  * The user is identified from the handle, which contains an
831fe1c642dSBill Krier  * rid in the discriminator field. Note that this is a local user.
832fe1c642dSBill Krier  */
833fe1c642dSBill Krier static int
samr_s_QueryUserGroups(void * arg,ndr_xa_t * mxa)834fe1c642dSBill Krier samr_s_QueryUserGroups(void *arg, ndr_xa_t *mxa)
835fe1c642dSBill Krier {
836fe1c642dSBill Krier 	struct samr_QueryUserGroups *param = arg;
837fe1c642dSBill Krier 	struct samr_UserGroupInfo *info;
838fe1c642dSBill Krier 	struct samr_UserGroups *group;
839fe1c642dSBill Krier 	ndr_hdid_t *id = (ndr_hdid_t *)&param->user_handle;
840fe1c642dSBill Krier 	ndr_handle_t *hd;
841fe1c642dSBill Krier 	samr_keydata_t *data;
842fe1c642dSBill Krier 	smb_sid_t *user_sid = NULL;
843fe1c642dSBill Krier 	smb_group_t grp;
844fe1c642dSBill Krier 	smb_giter_t gi;
845fe1c642dSBill Krier 	smb_domain_t di;
846fe1c642dSBill Krier 	uint32_t status;
847fe1c642dSBill Krier 	int size;
848fe1c642dSBill Krier 	int ngrp_max;
849fe1c642dSBill Krier 
850fe1c642dSBill Krier 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_USER)) == NULL) {
851fe1c642dSBill Krier 		status = NT_STATUS_ACCESS_DENIED;
852fe1c642dSBill Krier 		goto query_error;
853fe1c642dSBill Krier 	}
854fe1c642dSBill Krier 
855fe1c642dSBill Krier 	data = (samr_keydata_t *)hd->nh_data;
856fe1c642dSBill Krier 	switch (data->kd_type) {
857fe1c642dSBill Krier 	case SMB_DOMAIN_BUILTIN:
858fe1c642dSBill Krier 	case SMB_DOMAIN_LOCAL:
859fe1c642dSBill Krier 		if (!smb_domain_lookup_type(data->kd_type, &di)) {
860fe1c642dSBill Krier 			status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
861fe1c642dSBill Krier 			goto query_error;
862fe1c642dSBill Krier 		}
863fe1c642dSBill Krier 		break;
864fe1c642dSBill Krier 	default:
865fe1c642dSBill Krier 		status = NT_STATUS_INVALID_HANDLE;
866fe1c642dSBill Krier 		goto query_error;
867fe1c642dSBill Krier 	}
868fe1c642dSBill Krier 
869fe1c642dSBill Krier 	user_sid = smb_sid_splice(di.di_binsid, data->kd_rid);
870fe1c642dSBill Krier 	if (user_sid == NULL) {
871fe1c642dSBill Krier 		status = NT_STATUS_NO_MEMORY;
872fe1c642dSBill Krier 		goto query_error;
873fe1c642dSBill Krier 	}
874fe1c642dSBill Krier 
875fe1c642dSBill Krier 	info = NDR_NEW(mxa, struct samr_UserGroupInfo);
876fe1c642dSBill Krier 	if (info == NULL) {
877fe1c642dSBill Krier 		status = NT_STATUS_NO_MEMORY;
878fe1c642dSBill Krier 		goto query_error;
879fe1c642dSBill Krier 	}
880fe1c642dSBill Krier 	bzero(info, sizeof (struct samr_UserGroupInfo));
881fe1c642dSBill Krier 
882fe1c642dSBill Krier 	size = 32 * 1024;
883fe1c642dSBill Krier 	info->groups = NDR_MALLOC(mxa, size);
884fe1c642dSBill Krier 	if (info->groups == NULL) {
885fe1c642dSBill Krier 		status = NT_STATUS_NO_MEMORY;
886fe1c642dSBill Krier 		goto query_error;
887fe1c642dSBill Krier 	}
888fe1c642dSBill Krier 	ngrp_max = size / sizeof (struct samr_UserGroups);
889fe1c642dSBill Krier 
890fe1c642dSBill Krier 	if (smb_lgrp_iteropen(&gi) != SMB_LGRP_SUCCESS) {
891fe1c642dSBill Krier 		status = NT_STATUS_INTERNAL_ERROR;
892fe1c642dSBill Krier 		goto query_error;
893fe1c642dSBill Krier 	}
894fe1c642dSBill Krier 
895fe1c642dSBill Krier 	info->n_entry = 0;
896fe1c642dSBill Krier 	group = info->groups;
897fe1c642dSBill Krier 	while ((info->n_entry < ngrp_max) &&
898fe1c642dSBill Krier 	    (smb_lgrp_iterate(&gi, &grp) == SMB_LGRP_SUCCESS)) {
899fe1c642dSBill Krier 		if (smb_lgrp_is_member(&grp, user_sid)) {
900fe1c642dSBill Krier 			group->rid = grp.sg_rid;
901fe1c642dSBill Krier 			group->attr = grp.sg_attr;
902fe1c642dSBill Krier 			group++;
903fe1c642dSBill Krier 			info->n_entry++;
904fe1c642dSBill Krier 		}
905fe1c642dSBill Krier 		smb_lgrp_free(&grp);
906fe1c642dSBill Krier 	}
907fe1c642dSBill Krier 	smb_lgrp_iterclose(&gi);
908fe1c642dSBill Krier 
909fe1c642dSBill Krier 	free(user_sid);
910fe1c642dSBill Krier 	param->info = info;
911fe1c642dSBill Krier 	param->status = NT_STATUS_SUCCESS;
912fe1c642dSBill Krier 	return (NDR_DRC_OK);
913fe1c642dSBill Krier 
914fe1c642dSBill Krier query_error:
915fe1c642dSBill Krier 	free(user_sid);
916fe1c642dSBill Krier 	bzero(param, sizeof (struct samr_QueryUserGroups));
917fe1c642dSBill Krier 	param->status = NT_SC_ERROR(status);
918fe1c642dSBill Krier 	return (NDR_DRC_OK);
919fe1c642dSBill Krier }
920fe1c642dSBill Krier 
921fe1c642dSBill Krier /*
922fe1c642dSBill Krier  * samr_s_OpenGroup
923fe1c642dSBill Krier  *
924fe1c642dSBill Krier  * This is a request to open a group within the specified domain in the
925fe1c642dSBill Krier  * local SAM database. The caller must supply a valid domain handle,
926fe1c642dSBill Krier  * obtained via a successful domain open request. The group is
927fe1c642dSBill Krier  * specified by the rid in the request. If this is a local RID it
928fe1c642dSBill Krier  * should already be encoded with type information.
929fe1c642dSBill Krier  *
930fe1c642dSBill Krier  * We return a handle to be used to access information about this group.
931fe1c642dSBill Krier  */
932fe1c642dSBill Krier static int
samr_s_OpenGroup(void * arg,ndr_xa_t * mxa)933fe1c642dSBill Krier samr_s_OpenGroup(void *arg, ndr_xa_t *mxa)
934fe1c642dSBill Krier {
935fe1c642dSBill Krier 	struct samr_OpenGroup *param = arg;
936fe1c642dSBill Krier 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
937fe1c642dSBill Krier 	ndr_handle_t *hd;
938fe1c642dSBill Krier 	samr_keydata_t *data;
939fe1c642dSBill Krier 
940fe1c642dSBill Krier 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
941fe1c642dSBill Krier 		bzero(&param->group_handle, sizeof (samr_handle_t));
942fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
943fe1c642dSBill Krier 		return (NDR_DRC_OK);
944fe1c642dSBill Krier 	}
945fe1c642dSBill Krier 
946fe1c642dSBill Krier 	data = (samr_keydata_t *)hd->nh_data;
947fe1c642dSBill Krier 	id = samr_hdalloc(mxa, SAMR_KEY_GROUP, data->kd_type, param->rid);
948fe1c642dSBill Krier 
949fe1c642dSBill Krier 	if (id) {
950fe1c642dSBill Krier 		bcopy(id, &param->group_handle, sizeof (samr_handle_t));
951fe1c642dSBill Krier 		param->status = 0;
952fe1c642dSBill Krier 	} else {
953fe1c642dSBill Krier 		bzero(&param->group_handle, sizeof (samr_handle_t));
954fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
955fe1c642dSBill Krier 	}
956fe1c642dSBill Krier 
957fe1c642dSBill Krier 	return (NDR_DRC_OK);
958fe1c642dSBill Krier }
959fe1c642dSBill Krier 
960fe1c642dSBill Krier /*
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 
1147c5866007SKeyur Desai /*
1148cb174861Sjoyce mcintosh  * samr_s_Connect2
1149fe1c642dSBill Krier  *
1150fe1c642dSBill Krier  * This is a request to connect to the local SAM database.
1151fe1c642dSBill Krier  * We don't support any form of update request and our database doesn't
1152fe1c642dSBill Krier  * contain any private information, so there is little point in doing
1153fe1c642dSBill Krier  * any access access checking here.
1154fe1c642dSBill Krier  *
1155fe1c642dSBill Krier  * Return a handle for use with subsequent SAM requests.
1156fe1c642dSBill Krier  */
1157fe1c642dSBill Krier static int
samr_s_Connect2(void * arg,ndr_xa_t * mxa)1158cb174861Sjoyce mcintosh samr_s_Connect2(void *arg, ndr_xa_t *mxa)
1159fe1c642dSBill Krier {
1160cb174861Sjoyce mcintosh 	struct samr_Connect2 *param = arg;
1161fe1c642dSBill Krier 	ndr_hdid_t *id;
1162fe1c642dSBill Krier 
1163fe1c642dSBill Krier 	id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, SMB_DOMAIN_NULL, 0);
1164fe1c642dSBill Krier 	if (id) {
1165fe1c642dSBill Krier 		bcopy(id, &param->handle, sizeof (samr_handle_t));
1166fe1c642dSBill Krier 		param->status = 0;
1167fe1c642dSBill Krier 	} else {
1168fe1c642dSBill Krier 		bzero(&param->handle, sizeof (samr_handle_t));
1169fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1170fe1c642dSBill Krier 	}
1171fe1c642dSBill Krier 
1172fe1c642dSBill Krier 	return (NDR_DRC_OK);
1173fe1c642dSBill Krier }
1174fe1c642dSBill Krier 
1175fe1c642dSBill Krier /*
1176fe1c642dSBill Krier  * samr_s_GetUserPwInfo
1177fe1c642dSBill Krier  *
1178f96bd5c8SAlan Wright  * Request for a user's password policy information.
1179fe1c642dSBill Krier  */
1180fe1c642dSBill Krier /*ARGSUSED*/
1181fe1c642dSBill Krier static int
samr_s_GetUserPwInfo(void * arg,ndr_xa_t * mxa)1182fe1c642dSBill Krier samr_s_GetUserPwInfo(void *arg, ndr_xa_t *mxa)
1183fe1c642dSBill Krier {
1184f96bd5c8SAlan Wright 	static samr_password_info_t	pwinfo;
1185fe1c642dSBill Krier 	struct samr_GetUserPwInfo	*param = arg;
1186fe1c642dSBill Krier 
1187f96bd5c8SAlan Wright 	param->pwinfo = &pwinfo;
1188f96bd5c8SAlan Wright 	param->status = NT_STATUS_SUCCESS;
1189fe1c642dSBill Krier 	return (NDR_DRC_OK);
1190fe1c642dSBill Krier }
1191fe1c642dSBill Krier 
1192fe1c642dSBill Krier /*
1193fe1c642dSBill Krier  * samr_s_CreateUser
1194fe1c642dSBill Krier  */
1195fe1c642dSBill Krier /*ARGSUSED*/
1196fe1c642dSBill Krier static int
samr_s_CreateUser(void * arg,ndr_xa_t * mxa)1197fe1c642dSBill Krier samr_s_CreateUser(void *arg, ndr_xa_t *mxa)
1198fe1c642dSBill Krier {
1199fe1c642dSBill Krier 	struct samr_CreateUser *param = arg;
1200fe1c642dSBill Krier 
1201fe1c642dSBill Krier 	bzero(&param->user_handle, sizeof (samr_handle_t));
1202fe1c642dSBill Krier 	param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
1203fe1c642dSBill Krier 	return (NDR_DRC_OK);
1204fe1c642dSBill Krier }
1205fe1c642dSBill Krier 
1206fe1c642dSBill Krier /*
12071ed6b69aSGordon Ross  * samr_s_ChangePasswordUser2
1208fe1c642dSBill Krier  */
1209fe1c642dSBill Krier /*ARGSUSED*/
1210fe1c642dSBill Krier static int
samr_s_ChangePasswordUser2(void * arg,ndr_xa_t * mxa)12111ed6b69aSGordon Ross samr_s_ChangePasswordUser2(void *arg, ndr_xa_t *mxa)
1212fe1c642dSBill Krier {
12131ed6b69aSGordon Ross 	struct samr_ChangePasswordUser2 *param = arg;
1214fe1c642dSBill Krier 
12151ed6b69aSGordon Ross 	bzero(param, sizeof (*param));
1216fe1c642dSBill Krier 	param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
1217fe1c642dSBill Krier 	return (NDR_DRC_OK);
1218fe1c642dSBill Krier }
1219fe1c642dSBill Krier 
1220fe1c642dSBill Krier /*
1221fe1c642dSBill Krier  * samr_s_GetDomainPwInfo
1222f96bd5c8SAlan Wright  *
1223f96bd5c8SAlan Wright  * Request for the domain password policy information.
1224fe1c642dSBill Krier  */
1225fe1c642dSBill Krier /*ARGSUSED*/
1226fe1c642dSBill Krier static int
samr_s_GetDomainPwInfo(void * arg,ndr_xa_t * mxa)1227fe1c642dSBill Krier samr_s_GetDomainPwInfo(void *arg, ndr_xa_t *mxa)
1228fe1c642dSBill Krier {
1229f96bd5c8SAlan Wright 	static samr_password_info_t	pwinfo;
1230fe1c642dSBill Krier 	struct samr_GetDomainPwInfo	*param = arg;
1231fe1c642dSBill Krier 
1232f96bd5c8SAlan Wright 	param->pwinfo = &pwinfo;
1233f96bd5c8SAlan Wright 	param->status = NT_STATUS_SUCCESS;
1234fe1c642dSBill Krier 	return (NDR_DRC_OK);
1235fe1c642dSBill Krier }
1236fe1c642dSBill Krier 
1237fe1c642dSBill Krier /*
1238fe1c642dSBill Krier  * samr_s_SetUserInfo
1239fe1c642dSBill Krier  */
1240fe1c642dSBill Krier /*ARGSUSED*/
1241fe1c642dSBill Krier static int
samr_s_SetUserInfo(void * arg,ndr_xa_t * mxa)1242fe1c642dSBill Krier samr_s_SetUserInfo(void *arg, ndr_xa_t *mxa)
1243fe1c642dSBill Krier {
1244fe1c642dSBill Krier 	struct samr_SetUserInfo *param = arg;
1245fe1c642dSBill Krier 
1246fe1c642dSBill Krier 	bzero(param, sizeof (struct samr_SetUserInfo));
1247fe1c642dSBill Krier 	param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
1248fe1c642dSBill Krier 	return (NDR_DRC_OK);
1249fe1c642dSBill Krier }
1250fe1c642dSBill Krier 
1251fe1c642dSBill Krier /*
1252fe1c642dSBill Krier  * samr_s_QueryDispInfo
1253fe1c642dSBill Krier  *
1254fe1c642dSBill Krier  * This function currently return local users' information only.
1255fe1c642dSBill Krier  * This RPC is called repeatedly until all the users info are
1256fe1c642dSBill Krier  * retrieved.
1257fe1c642dSBill Krier  *
1258fe1c642dSBill Krier  * The total count and the returned count are returned as total size
1259fe1c642dSBill Krier  * and returned size.  The client doesn't seem to care.
1260fe1c642dSBill Krier  */
1261fe1c642dSBill Krier static int
samr_s_QueryDispInfo(void * arg,ndr_xa_t * mxa)1262fe1c642dSBill Krier samr_s_QueryDispInfo(void *arg, ndr_xa_t *mxa)
1263fe1c642dSBill Krier {
1264fe1c642dSBill Krier 	struct samr_QueryDispInfo *param = arg;
1265fe1c642dSBill Krier 	ndr_hdid_t *id = (ndr_hdid_t *)&param->domain_handle;
1266fe1c642dSBill Krier 	ndr_handle_t *hd;
1267fe1c642dSBill Krier 	samr_keydata_t *data;
1268fe1c642dSBill Krier 	DWORD status = NT_STATUS_SUCCESS;
1269fe1c642dSBill Krier 	struct user_acct_info *user;
1270fe1c642dSBill Krier 	smb_pwditer_t pwi;
1271fe1c642dSBill Krier 	smb_luser_t *uinfo;
1272fe1c642dSBill Krier 	int num_users;
1273fe1c642dSBill Krier 	int start_idx;
1274fe1c642dSBill Krier 	int max_retcnt, retcnt;
1275fe1c642dSBill Krier 	int skip;
1276fe1c642dSBill Krier 
1277fe1c642dSBill Krier 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
1278fe1c642dSBill Krier 		status = NT_STATUS_INVALID_HANDLE;
1279fe1c642dSBill Krier 		goto error;
1280fe1c642dSBill Krier 	}
1281fe1c642dSBill Krier 
1282fe1c642dSBill Krier 	if (!SAMR_VALID_DISPLEVEL(param->level)) {
1283fe1c642dSBill Krier 		status = NT_STATUS_INVALID_INFO_CLASS;
1284fe1c642dSBill Krier 		goto error;
1285fe1c642dSBill Krier 	}
1286fe1c642dSBill Krier 
1287fe1c642dSBill Krier 	if (!SAMR_SUPPORTED_DISPLEVEL(param->level)) {
1288fe1c642dSBill Krier 		status = NT_STATUS_NOT_IMPLEMENTED;
1289fe1c642dSBill Krier 		goto error;
1290fe1c642dSBill Krier 	}
1291fe1c642dSBill Krier 
1292fe1c642dSBill Krier 	data = (samr_keydata_t *)hd->nh_data;
1293fe1c642dSBill Krier 
1294fe1c642dSBill Krier 	switch (data->kd_type) {
1295fe1c642dSBill Krier 	case SMB_DOMAIN_BUILTIN:
1296fe1c642dSBill Krier 		goto no_info;
1297fe1c642dSBill Krier 
1298fe1c642dSBill Krier 	case SMB_DOMAIN_LOCAL:
1299fe1c642dSBill Krier 		num_users = smb_sam_usr_cnt();
1300fe1c642dSBill Krier 		start_idx = param->start_idx;
1301fe1c642dSBill Krier 		if ((num_users == 0) || (start_idx >= num_users))
1302fe1c642dSBill Krier 			goto no_info;
1303fe1c642dSBill Krier 
1304fe1c642dSBill Krier 		max_retcnt = num_users - start_idx;
1305fe1c642dSBill Krier 		if (max_retcnt > param->max_entries)
1306fe1c642dSBill Krier 			max_retcnt = param->max_entries;
1307fe1c642dSBill Krier 		param->users.acct = NDR_MALLOC(mxa,
1308fe1c642dSBill Krier 		    max_retcnt * sizeof (struct user_acct_info));
1309fe1c642dSBill Krier 		user = param->users.acct;
1310fe1c642dSBill Krier 		if (user == NULL) {
1311fe1c642dSBill Krier 			status = NT_STATUS_NO_MEMORY;
1312fe1c642dSBill Krier 			goto error;
1313fe1c642dSBill Krier 		}
1314fe1c642dSBill Krier 		bzero(user, max_retcnt * sizeof (struct user_acct_info));
1315fe1c642dSBill Krier 
1316fe1c642dSBill Krier 		if (smb_pwd_iteropen(&pwi) != SMB_PWE_SUCCESS)
1317fe1c642dSBill Krier 			goto no_info;
1318fe1c642dSBill Krier 
1319fe1c642dSBill Krier 		skip = retcnt = 0;
1320fe1c642dSBill Krier 		while ((uinfo = smb_pwd_iterate(&pwi)) != NULL) {
1321fe1c642dSBill Krier 			if (skip++ < start_idx)
1322fe1c642dSBill Krier 				continue;
1323fe1c642dSBill Krier 
1324fe1c642dSBill Krier 			if (retcnt++ >= max_retcnt)
1325fe1c642dSBill Krier 				break;
1326fe1c642dSBill Krier 
1327fe1c642dSBill Krier 			assert(uinfo->su_name != NULL);
1328fe1c642dSBill Krier 
1329fe1c642dSBill Krier 			user->index = start_idx + retcnt;
1330fe1c642dSBill Krier 			user->rid = uinfo->su_rid;
1331fe1c642dSBill Krier 			user->ctrl = ACF_NORMUSER | ACF_PWDNOEXP;
1332fe1c642dSBill Krier 			if (uinfo->su_ctrl & SMB_PWF_DISABLE)
1333fe1c642dSBill Krier 				user->ctrl |= ACF_DISABLED;
1334fe1c642dSBill Krier 			if (NDR_MSTRING(mxa, uinfo->su_name,
1335fe1c642dSBill Krier 			    (ndr_mstring_t *)&user->name) == -1) {
1336fe1c642dSBill Krier 				smb_pwd_iterclose(&pwi);
1337fe1c642dSBill Krier 				status = NT_STATUS_NO_MEMORY;
1338fe1c642dSBill Krier 				goto error;
1339fe1c642dSBill Krier 			}
1340fe1c642dSBill Krier 			(void) NDR_MSTRING(mxa, uinfo->su_fullname,
1341fe1c642dSBill Krier 			    (ndr_mstring_t *)&user->fullname);
1342fe1c642dSBill Krier 			(void) NDR_MSTRING(mxa, uinfo->su_desc,
1343fe1c642dSBill Krier 			    (ndr_mstring_t *)&user->desc);
1344fe1c642dSBill Krier 			user++;
1345fe1c642dSBill Krier 		}
1346fe1c642dSBill Krier 		smb_pwd_iterclose(&pwi);
1347fe1c642dSBill Krier 
1348fe1c642dSBill Krier 		if (retcnt >= max_retcnt) {
1349fe1c642dSBill Krier 			retcnt = max_retcnt;
1350fe1c642dSBill Krier 			param->status = status;
1351fe1c642dSBill Krier 		} else {
1352148c5f43SAlan Wright 			param->status = NT_STATUS_MORE_ENTRIES;
1353fe1c642dSBill Krier 		}
1354fe1c642dSBill Krier 
1355fe1c642dSBill Krier 		param->users.total_size = num_users;
1356fe1c642dSBill Krier 		param->users.returned_size = retcnt;
1357fe1c642dSBill Krier 		param->users.switch_value = param->level;
1358fe1c642dSBill Krier 		param->users.count = retcnt;
1359fe1c642dSBill Krier 
1360fe1c642dSBill Krier 		break;
1361fe1c642dSBill Krier 
1362fe1c642dSBill Krier 	default:
1363fe1c642dSBill Krier 		status = NT_STATUS_INVALID_HANDLE;
1364fe1c642dSBill Krier 		goto error;
1365fe1c642dSBill Krier 	}
1366fe1c642dSBill Krier 
1367fe1c642dSBill Krier 	return (NDR_DRC_OK);
1368fe1c642dSBill Krier 
1369fe1c642dSBill Krier no_info:
1370fe1c642dSBill Krier 	param->users.total_size = 0;
1371fe1c642dSBill Krier 	param->users.returned_size = 0;
1372fe1c642dSBill Krier 	param->users.switch_value = param->level;
1373fe1c642dSBill Krier 	param->users.count = 0;
1374fe1c642dSBill Krier 	param->users.acct = NULL;
1375fe1c642dSBill Krier 	param->status = status;
1376fe1c642dSBill Krier 	return (NDR_DRC_OK);
1377fe1c642dSBill Krier 
1378fe1c642dSBill Krier error:
1379fe1c642dSBill Krier 	bzero(param, sizeof (struct samr_QueryDispInfo));
1380fe1c642dSBill Krier 	param->status = NT_SC_ERROR(status);
1381fe1c642dSBill Krier 	return (NDR_DRC_OK);
1382fe1c642dSBill Krier }
1383fe1c642dSBill Krier 
1384fe1c642dSBill Krier /*
1385fe1c642dSBill Krier  * samr_s_EnumDomainGroups
1386fe1c642dSBill Krier  *
1387fe1c642dSBill Krier  *
1388fe1c642dSBill Krier  * This function is supposed to return local group information.
1389fe1c642dSBill Krier  * As we don't support local users, this function dosen't send
1390fe1c642dSBill Krier  * back any information.
1391fe1c642dSBill Krier  *
1392fe1c642dSBill Krier  * Added template that returns information for a domain group as None.
1393fe1c642dSBill Krier  * All information is hard-coded from packet captures.
1394fe1c642dSBill Krier  */
1395fe1c642dSBill Krier static int
samr_s_EnumDomainGroups(void * arg,ndr_xa_t * mxa)1396fe1c642dSBill Krier samr_s_EnumDomainGroups(void *arg, ndr_xa_t *mxa)
1397fe1c642dSBill Krier {
1398fe1c642dSBill Krier 	struct samr_EnumDomainGroups *param = arg;
1399fe1c642dSBill Krier 	ndr_hdid_t *id = (ndr_hdid_t *)&param->domain_handle;
1400fe1c642dSBill Krier 	DWORD status = NT_STATUS_SUCCESS;
1401fe1c642dSBill Krier 
1402fe1c642dSBill Krier 	if (samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN) == NULL)
1403fe1c642dSBill Krier 		status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
1404fe1c642dSBill Krier 
1405fe1c642dSBill Krier 	param->total_size = 0;
1406fe1c642dSBill Krier 	param->returned_size = 0;
1407fe1c642dSBill Krier 	param->switch_value = 3;
1408fe1c642dSBill Krier 	param->count = 0;
1409fe1c642dSBill Krier 	param->groups = 0;
1410fe1c642dSBill Krier 	param->status = status;
1411fe1c642dSBill Krier 	return (NDR_DRC_OK);
1412fe1c642dSBill Krier 
1413fe1c642dSBill Krier #ifdef SAMR_SUPPORT_GROUPS
1414fe1c642dSBill Krier 	if ((desc->discrim != SAMR_LOCAL_DOMAIN) || (param->start_idx != 0)) {
1415fe1c642dSBill Krier 		param->total_size = 0;
1416fe1c642dSBill Krier 		param->returned_size = 0;
1417fe1c642dSBill Krier 		param->switch_value = 3;
1418fe1c642dSBill Krier 		param->count = 0;
1419fe1c642dSBill Krier 		param->groups = 0;
1420fe1c642dSBill Krier 	} else {
1421fe1c642dSBill Krier 		param->total_size = 64;
1422fe1c642dSBill Krier 		param->returned_size = 64;
1423fe1c642dSBill Krier 		param->switch_value = 3;
1424fe1c642dSBill Krier 		param->count = 1;
1425fe1c642dSBill Krier 		param->groups = (struct group_disp_info *)NDR_MALLOC(
1426fe1c642dSBill Krier 		    mxa, sizeof (struct group_disp_info));
1427fe1c642dSBill Krier 
1428fe1c642dSBill Krier 		param->groups->count = 1;
1429fe1c642dSBill Krier 		param->groups->acct[0].index = 1;
1430fe1c642dSBill Krier 		param->groups->acct[0].rid = 513;
1431fe1c642dSBill Krier 		param->groups->acct[0].ctrl = 0x7;
1432fe1c642dSBill Krier 		(void) NDR_MSTRING(mxa, "None",
1433fe1c642dSBill Krier 		    (ndr_mstring_t *)&param->groups->acct[0].name);
1434fe1c642dSBill Krier 
1435fe1c642dSBill Krier 		(void) NDR_MSTRING(mxa, "Ordinary users",
1436fe1c642dSBill Krier 		    (ndr_mstring_t *)&param->groups->acct[0].desc);
1437fe1c642dSBill Krier 	}
1438fe1c642dSBill Krier 
1439fe1c642dSBill Krier 	param->status = NT_STATUS_SUCCESS;
1440fe1c642dSBill Krier 	return (NDR_DRC_OK);
1441fe1c642dSBill Krier #endif
1442fe1c642dSBill Krier }
1443fe1c642dSBill Krier 
1444fe1c642dSBill Krier /*
1445fe1c642dSBill Krier  * samr_s_OpenAlias
1446fe1c642dSBill Krier  *
1447fe1c642dSBill Krier  * Lookup for requested alias, if it exists return a handle
1448fe1c642dSBill Krier  * for that alias. The alias domain sid should match with
1449fe1c642dSBill Krier  * the passed domain handle.
1450fe1c642dSBill Krier  */
1451fe1c642dSBill Krier static int
samr_s_OpenAlias(void * arg,ndr_xa_t * mxa)1452fe1c642dSBill Krier samr_s_OpenAlias(void *arg, ndr_xa_t *mxa)
1453fe1c642dSBill Krier {
1454fe1c642dSBill Krier 	struct samr_OpenAlias *param = arg;
1455fe1c642dSBill Krier 	ndr_hdid_t	*id = (ndr_hdid_t *)&param->domain_handle;
1456fe1c642dSBill Krier 	ndr_handle_t	*hd;
1457fe1c642dSBill Krier 	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;
1464fe1c642dSBill Krier 	int		rc;
1465fe1c642dSBill Krier 
1466fe1c642dSBill Krier 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
1467fe1c642dSBill Krier 		status = NT_STATUS_INVALID_HANDLE;
1468fe1c642dSBill Krier 		goto open_alias_err;
1469fe1c642dSBill Krier 	}
1470fe1c642dSBill Krier 
1471c5866007SKeyur Desai 	if ((param->access_mask & SAMR_ALIAS_ACCESS_ALL_ACCESS) == 0) {
1472fe1c642dSBill Krier 		status = NT_STATUS_ACCESS_DENIED;
1473fe1c642dSBill Krier 		goto open_alias_err;
1474fe1c642dSBill Krier 	}
1475fe1c642dSBill Krier 
1476fe1c642dSBill Krier 	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);
1500fe1c642dSBill Krier 		if (rc != SMB_LGRP_SUCCESS) {
1501fe1c642dSBill Krier 			status = NT_STATUS_NO_SUCH_ALIAS;
1502fe1c642dSBill Krier 			goto open_alias_err;
1503fe1c642dSBill Krier 		}
1504f96bd5c8SAlan Wright 		break;
1505f96bd5c8SAlan Wright 
1506f96bd5c8SAlan Wright 	default:
1507f96bd5c8SAlan Wright 		status = NT_STATUS_NO_SUCH_ALIAS;
1508f96bd5c8SAlan Wright 		goto open_alias_err;
1509f96bd5c8SAlan Wright 	}
1510fe1c642dSBill Krier 
1511fe1c642dSBill Krier 	id = samr_hdalloc(mxa, SAMR_KEY_ALIAS, data->kd_type, param->rid);
1512fe1c642dSBill Krier 	if (id) {
1513fe1c642dSBill Krier 		bcopy(id, &param->alias_handle, sizeof (samr_handle_t));
1514fe1c642dSBill Krier 		param->status = NT_STATUS_SUCCESS;
1515fe1c642dSBill Krier 		return (NDR_DRC_OK);
1516fe1c642dSBill Krier 	}
1517fe1c642dSBill Krier 
1518fe1c642dSBill Krier 	status = NT_STATUS_NO_MEMORY;
1519fe1c642dSBill Krier 
1520fe1c642dSBill Krier open_alias_err:
1521fe1c642dSBill Krier 	bzero(&param->alias_handle, sizeof (samr_handle_t));
1522fe1c642dSBill Krier 	param->status = NT_SC_ERROR(status);
1523fe1c642dSBill Krier 	return (NDR_DRC_OK);
1524fe1c642dSBill Krier }
1525fe1c642dSBill Krier 
1526fe1c642dSBill Krier /*
1527fe1c642dSBill Krier  * samr_s_CreateDomainAlias
1528fe1c642dSBill Krier  *
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.
1534fe1c642dSBill Krier  */
1535fe1c642dSBill Krier static int
samr_s_CreateDomainAlias(void * arg,ndr_xa_t * mxa)1536fe1c642dSBill Krier samr_s_CreateDomainAlias(void *arg, ndr_xa_t *mxa)
1537fe1c642dSBill Krier {
1538fe1c642dSBill Krier 	struct samr_CreateDomainAlias *param = arg;
1539fe1c642dSBill Krier 	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;
1544fe1c642dSBill Krier 
1545c5866007SKeyur Desai 	if (samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN) != NULL) {
1546fe1c642dSBill Krier 		bzero(param, sizeof (struct samr_CreateDomainAlias));
1547fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
1548fe1c642dSBill Krier 		return (NDR_DRC_OK);
1549fe1c642dSBill Krier 	}
1550fe1c642dSBill Krier 
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);
1556c5866007SKeyur Desai 	}
1557c5866007SKeyur Desai 
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));
1561fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
1562fe1c642dSBill Krier 		return (NDR_DRC_OK);
1563fe1c642dSBill Krier 	}
1564fe1c642dSBill Krier 
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);
1569fe1c642dSBill Krier 		param->status = NT_SC_ERROR(status);
1570fe1c642dSBill Krier 		return (NDR_DRC_OK);
1571c5866007SKeyur Desai 	}
1572c5866007SKeyur Desai 
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 	}
1580c5866007SKeyur Desai 
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 	}
1590c5866007SKeyur Desai 
1591c5866007SKeyur Desai 	return (NDR_DRC_OK);
1592fe1c642dSBill Krier }
1593fe1c642dSBill Krier 
1594fe1c642dSBill Krier /*
1595fe1c642dSBill Krier  * samr_s_SetAliasInfo
1596fe1c642dSBill Krier  *
1597fe1c642dSBill Krier  * Similar to NetLocalGroupSetInfo.
1598fe1c642dSBill Krier  */
1599fe1c642dSBill Krier static int
samr_s_SetAliasInfo(void * arg,ndr_xa_t * mxa)1600fe1c642dSBill Krier samr_s_SetAliasInfo(void *arg, ndr_xa_t *mxa)
1601fe1c642dSBill Krier {
1602fe1c642dSBill Krier 	struct samr_SetAliasInfo *param = arg;
1603fe1c642dSBill Krier 	ndr_hdid_t *id = (ndr_hdid_t *)&param->alias_handle;
1604fe1c642dSBill Krier 	DWORD status = NT_STATUS_SUCCESS;
1605fe1c642dSBill Krier 
1606fe1c642dSBill Krier 	if (samr_hdlookup(mxa, id, SAMR_KEY_ALIAS) == NULL)
1607fe1c642dSBill Krier 		status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
1608fe1c642dSBill Krier 
1609fe1c642dSBill Krier 	param->status = status;
1610fe1c642dSBill Krier 	return (NDR_DRC_OK);
1611fe1c642dSBill Krier }
1612fe1c642dSBill Krier 
1613fe1c642dSBill Krier /*
1614fe1c642dSBill Krier  * samr_s_QueryAliasInfo
1615fe1c642dSBill Krier  *
1616fe1c642dSBill Krier  * Retrieves information about the specified local group account
1617fe1c642dSBill Krier  * by given handle.
1618fe1c642dSBill Krier  */
1619fe1c642dSBill Krier static int
samr_s_QueryAliasInfo(void * arg,ndr_xa_t * mxa)1620fe1c642dSBill Krier samr_s_QueryAliasInfo(void *arg, ndr_xa_t *mxa)
1621fe1c642dSBill Krier {
1622fe1c642dSBill Krier 	struct samr_QueryAliasInfo *param = arg;
1623fe1c642dSBill Krier 	ndr_hdid_t	*id = (ndr_hdid_t *)&param->alias_handle;
1624fe1c642dSBill Krier 	ndr_handle_t	*hd;
1625fe1c642dSBill Krier 	samr_keydata_t	*data;
1626fe1c642dSBill Krier 	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;
1634fe1c642dSBill Krier 	uint32_t	status;
1635fe1c642dSBill Krier 	int		rc;
1636fe1c642dSBill Krier 
1637fe1c642dSBill Krier 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_ALIAS)) == NULL) {
1638fe1c642dSBill Krier 		status = NT_STATUS_INVALID_HANDLE;
1639fe1c642dSBill Krier 		goto query_alias_err;
1640fe1c642dSBill Krier 	}
1641fe1c642dSBill Krier 
1642fe1c642dSBill Krier 	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);
1669fe1c642dSBill Krier 		if (rc != SMB_LGRP_SUCCESS) {
1670fe1c642dSBill Krier 			status = NT_STATUS_NO_SUCH_ALIAS;
1671fe1c642dSBill Krier 			goto query_alias_err;
1672fe1c642dSBill Krier 		}
1673f96bd5c8SAlan Wright 		name = grp.sg_name;
1674f96bd5c8SAlan Wright 		desc = grp.sg_cmnt;
1675f96bd5c8SAlan Wright 		break;
1676f96bd5c8SAlan Wright 
1677f96bd5c8SAlan Wright 	default:
1678f96bd5c8SAlan Wright 		status = NT_STATUS_NO_SUCH_ALIAS;
1679f96bd5c8SAlan Wright 		goto query_alias_err;
1680f96bd5c8SAlan Wright 	}
1681fe1c642dSBill Krier 
1682fe1c642dSBill Krier 	switch (param->level) {
1683eef90b86SGordon Ross 	case SAMR_QUERY_ALIAS_INFO_GENERAL:
1684fe1c642dSBill Krier 		param->ru.info1.level = param->level;
1685f96bd5c8SAlan Wright 		(void) NDR_MSTRING(mxa, name,
1686fe1c642dSBill Krier 		    (ndr_mstring_t *)&param->ru.info1.name);
1687f96bd5c8SAlan Wright 		(void) NDR_MSTRING(mxa, desc,
1688fe1c642dSBill Krier 		    (ndr_mstring_t *)&param->ru.info1.desc);
1689eef90b86SGordon Ross 		param->ru.info1.member_count = 1;
1690fe1c642dSBill Krier 		break;
1691fe1c642dSBill Krier 
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);
1696eef90b86SGordon Ross 		break;
1697eef90b86SGordon Ross 
1698eef90b86SGordon Ross 	case SAMR_QUERY_ALIAS_INFO_COMMENT:
1699fe1c642dSBill Krier 		param->ru.info3.level = param->level;
1700f96bd5c8SAlan Wright 		(void) NDR_MSTRING(mxa, desc,
1701fe1c642dSBill Krier 		    (ndr_mstring_t *)&param->ru.info3.desc);
1702fe1c642dSBill Krier 		break;
1703fe1c642dSBill Krier 
1704fe1c642dSBill Krier 	default:
17059fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		if (gd_type == SMB_DOMAIN_LOCAL)
1706fe1c642dSBill Krier 			smb_lgrp_free(&grp);
1707fe1c642dSBill Krier 		status = NT_STATUS_INVALID_INFO_CLASS;
1708fe1c642dSBill Krier 		goto query_alias_err;
1709fe1c642dSBill Krier 	};
1710fe1c642dSBill Krier 
17119fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (gd_type == SMB_DOMAIN_LOCAL)
1712fe1c642dSBill Krier 		smb_lgrp_free(&grp);
1713fe1c642dSBill Krier 	param->address = (DWORD)(uintptr_t)&param->ru;
1714fe1c642dSBill Krier 	param->status = 0;
1715fe1c642dSBill Krier 	return (NDR_DRC_OK);
1716fe1c642dSBill Krier 
1717fe1c642dSBill Krier query_alias_err:
1718fe1c642dSBill Krier 	param->status = NT_SC_ERROR(status);
1719fe1c642dSBill Krier 	return (NDR_DRC_OK);
1720fe1c642dSBill Krier }
1721fe1c642dSBill Krier 
1722fe1c642dSBill Krier /*
1723fe1c642dSBill Krier  * samr_s_DeleteDomainAlias
1724fe1c642dSBill Krier  *
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.
1728fe1c642dSBill Krier  *
1729c5866007SKeyur Desai  * The caller must have administrator rights to execute this function.
1730fe1c642dSBill Krier  */
1731fe1c642dSBill Krier static int
samr_s_DeleteDomainAlias(void * arg,ndr_xa_t * mxa)1732fe1c642dSBill Krier samr_s_DeleteDomainAlias(void *arg, ndr_xa_t *mxa)
1733fe1c642dSBill Krier {
1734fe1c642dSBill Krier 	struct samr_DeleteDomainAlias *param = arg;
1735fe1c642dSBill Krier 	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;
1743fe1c642dSBill Krier 
1744c5866007SKeyur Desai 	if (!ndr_is_admin(mxa)) {
1745c5866007SKeyur Desai 		bzero(param, sizeof (struct samr_DeleteDomainAlias));
1746c5866007SKeyur Desai 		param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
1747c5866007SKeyur Desai 		return (NDR_DRC_OK);
1748c5866007SKeyur Desai 	}
1749c5866007SKeyur Desai 
1750c5866007SKeyur Desai 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_ALIAS)) == NULL) {
1751fe1c642dSBill Krier 		bzero(param, sizeof (struct samr_DeleteDomainAlias));
1752fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
1753fe1c642dSBill Krier 		return (NDR_DRC_OK);
1754fe1c642dSBill Krier 	}
1755fe1c642dSBill Krier 
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;
1759c5866007SKeyur Desai 
1760c5866007SKeyur Desai 	switch (gd_type) {
1761c5866007SKeyur Desai 	case SMB_DOMAIN_BUILTIN:
1762fe1c642dSBill Krier 		bzero(param, sizeof (struct samr_DeleteDomainAlias));
1763c5866007SKeyur Desai 		status = NT_SC_ERROR(NT_STATUS_NOT_SUPPORTED);
1764c5866007SKeyur Desai 		break;
1765fe1c642dSBill Krier 
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;
1773fe1c642dSBill Krier 		}
1774fe1c642dSBill Krier 
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;
1783c5866007SKeyur Desai 
1784c5866007SKeyur Desai 	default:
1785c5866007SKeyur Desai 		bzero(param, sizeof (struct samr_DeleteDomainAlias));
1786c5866007SKeyur Desai 		status = NT_SC_ERROR(NT_STATUS_NO_SUCH_ALIAS);
1787fe1c642dSBill Krier 	}
1788fe1c642dSBill Krier 
1789c5866007SKeyur Desai 	param->status = status;
1790fe1c642dSBill Krier 	return (NDR_DRC_OK);
1791fe1c642dSBill Krier }
1792fe1c642dSBill Krier 
1793fe1c642dSBill Krier /*
1794fe1c642dSBill Krier  * samr_s_EnumDomainAliases
1795fe1c642dSBill Krier  *
1796fe1c642dSBill Krier  * This function sends back a list which contains all local groups' name.
1797fe1c642dSBill Krier  */
1798fe1c642dSBill Krier static int
samr_s_EnumDomainAliases(void * arg,ndr_xa_t * mxa)1799fe1c642dSBill Krier samr_s_EnumDomainAliases(void *arg, ndr_xa_t *mxa)
1800fe1c642dSBill Krier {
1801fe1c642dSBill Krier 	struct samr_EnumDomainAliases *param = arg;
1802fe1c642dSBill Krier 	ndr_hdid_t *id = (ndr_hdid_t *)&param->domain_handle;
1803fe1c642dSBill Krier 	ndr_handle_t *hd;
1804fe1c642dSBill Krier 	samr_keydata_t *data;
1805fe1c642dSBill Krier 	smb_group_t grp;
1806fe1c642dSBill Krier 	smb_giter_t gi;
1807fe1c642dSBill Krier 	int cnt, skip, i;
1808fe1c642dSBill Krier 	struct name_rid *info;
1809fe1c642dSBill Krier 
1810fe1c642dSBill Krier 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
1811fe1c642dSBill Krier 		bzero(param, sizeof (struct samr_EnumDomainAliases));
1812fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
1813fe1c642dSBill Krier 		return (NDR_DRC_OK);
1814fe1c642dSBill Krier 	}
1815fe1c642dSBill Krier 
1816fe1c642dSBill Krier 	data = (samr_keydata_t *)hd->nh_data;
1817fe1c642dSBill Krier 
1818fe1c642dSBill Krier 	cnt = smb_sam_grp_cnt(data->kd_type);
1819fe1c642dSBill Krier 	if (cnt <= param->resume_handle) {
1820fe1c642dSBill Krier 		param->aliases = (struct aliases_info *)NDR_MALLOC(mxa,
1821fe1c642dSBill Krier 		    sizeof (struct aliases_info));
1822fe1c642dSBill Krier 
1823fe1c642dSBill Krier 		if (param->aliases == NULL) {
1824fe1c642dSBill Krier 			bzero(param, sizeof (struct samr_EnumDomainAliases));
1825fe1c642dSBill Krier 			param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1826fe1c642dSBill Krier 			return (NDR_DRC_OK);
1827fe1c642dSBill Krier 		}
1828fe1c642dSBill Krier 
1829fe1c642dSBill Krier 		bzero(param->aliases, sizeof (struct aliases_info));
1830fe1c642dSBill Krier 		param->out_resume = 0;
1831fe1c642dSBill Krier 		param->entries = 0;
1832fe1c642dSBill Krier 		param->status = NT_STATUS_SUCCESS;
1833fe1c642dSBill Krier 		return (NDR_DRC_OK);
1834fe1c642dSBill Krier 	}
1835fe1c642dSBill Krier 
1836fe1c642dSBill Krier 	cnt -= param->resume_handle;
1837fe1c642dSBill Krier 	param->aliases = (struct aliases_info *)NDR_MALLOC(mxa,
1838fe1c642dSBill Krier 	    sizeof (struct aliases_info) + (cnt-1) * sizeof (struct name_rid));
1839fe1c642dSBill Krier 
1840fe1c642dSBill Krier 	if (param->aliases == NULL) {
1841fe1c642dSBill Krier 		bzero(param, sizeof (struct samr_EnumDomainAliases));
1842fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1843fe1c642dSBill Krier 		return (NDR_DRC_OK);
1844fe1c642dSBill Krier 	}
1845fe1c642dSBill Krier 
1846fe1c642dSBill Krier 	if (smb_lgrp_iteropen(&gi) != SMB_LGRP_SUCCESS) {
1847fe1c642dSBill Krier 		bzero(param, sizeof (struct samr_EnumDomainAliases));
1848fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_INTERNAL_ERROR);
1849fe1c642dSBill Krier 		return (NDR_DRC_OK);
1850fe1c642dSBill Krier 	}
1851fe1c642dSBill Krier 
1852fe1c642dSBill Krier 	skip = i = 0;
1853fe1c642dSBill Krier 	info = param->aliases->info;
1854fe1c642dSBill Krier 	while (smb_lgrp_iterate(&gi, &grp) == SMB_LGRP_SUCCESS) {
1855fe1c642dSBill Krier 		if ((skip++ >= param->resume_handle) &&
1856fe1c642dSBill Krier 		    (grp.sg_domain == data->kd_type) && (i++ < cnt)) {
1857fe1c642dSBill Krier 			info->rid = grp.sg_rid;
1858fe1c642dSBill Krier 			(void) NDR_MSTRING(mxa, grp.sg_name,
1859fe1c642dSBill Krier 			    (ndr_mstring_t *)&info->name);
1860fe1c642dSBill Krier 
1861fe1c642dSBill Krier 			info++;
1862fe1c642dSBill Krier 		}
1863fe1c642dSBill Krier 		smb_lgrp_free(&grp);
1864fe1c642dSBill Krier 	}
1865fe1c642dSBill Krier 	smb_lgrp_iterclose(&gi);
1866fe1c642dSBill Krier 
1867fe1c642dSBill Krier 	param->aliases->count = i;
1868fe1c642dSBill Krier 	param->aliases->address = i;
1869fe1c642dSBill Krier 
1870fe1c642dSBill Krier 	param->out_resume = i;
1871fe1c642dSBill Krier 	param->entries = i;
1872fe1c642dSBill Krier 	param->status = 0;
1873fe1c642dSBill Krier 	return (NDR_DRC_OK);
1874fe1c642dSBill Krier }
1875fe1c642dSBill Krier 
1876fe1c642dSBill Krier /*
1877cb174861Sjoyce mcintosh  * samr_s_Connect4
1878fe1c642dSBill Krier  */
1879fe1c642dSBill Krier static int
samr_s_Connect4(void * arg,ndr_xa_t * mxa)1880cb174861Sjoyce mcintosh samr_s_Connect4(void *arg, ndr_xa_t *mxa)
1881fe1c642dSBill Krier {
1882cb174861Sjoyce mcintosh 	struct samr_Connect4	*param = arg;
1883f96bd5c8SAlan Wright 	ndr_hdid_t		*id;
1884fe1c642dSBill Krier 
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);
1892fe1c642dSBill Krier 	}
1893fe1c642dSBill Krier 
1894f96bd5c8SAlan Wright 	return (NDR_DRC_OK);
1895f96bd5c8SAlan Wright }
1896fe1c642dSBill Krier 
1897fe1c642dSBill Krier /*
1898cb174861Sjoyce mcintosh  * samr_s_Connect5
1899fe1c642dSBill Krier  *
1900cb174861Sjoyce mcintosh  * This is the connect5 form of the connect request used by Windows XP.
1901fe1c642dSBill Krier  * Returns an RPC fault for now.
1902fe1c642dSBill Krier  */
1903fe1c642dSBill Krier /*ARGSUSED*/
1904fe1c642dSBill Krier static int
samr_s_Connect5(void * arg,ndr_xa_t * mxa)1905cb174861Sjoyce mcintosh samr_s_Connect5(void *arg, ndr_xa_t *mxa)
1906fe1c642dSBill Krier {
1907cb174861Sjoyce mcintosh 	struct samr_Connect5 *param = arg;
1908fe1c642dSBill Krier 
1909cb174861Sjoyce mcintosh 	bzero(param, sizeof (struct samr_Connect5));
1910fe1c642dSBill Krier 	return (NDR_DRC_FAULT_REQUEST_OPNUM_INVALID);
1911fe1c642dSBill Krier }
1912fe1c642dSBill Krier 
1913fe1c642dSBill Krier static ndr_stub_table_t samr_stub_table[] = {
1914cb174861Sjoyce mcintosh 	{ samr_s_Connect,		SAMR_OPNUM_Connect },
1915fe1c642dSBill Krier 	{ samr_s_CloseHandle,		SAMR_OPNUM_CloseHandle },
1916*9242c919SMatt Barden 	{ samr_s_QuerySecObject,	SAMR_OPNUM_QuerySecObject },
1917fe1c642dSBill Krier 	{ samr_s_LookupDomain,		SAMR_OPNUM_LookupDomain },
1918fe1c642dSBill Krier 	{ samr_s_EnumLocalDomains,	SAMR_OPNUM_EnumLocalDomains },
1919fe1c642dSBill Krier 	{ samr_s_OpenDomain,		SAMR_OPNUM_OpenDomain },
1920fe1c642dSBill Krier 	{ samr_s_QueryDomainInfo,	SAMR_OPNUM_QueryDomainInfo },
1921f96bd5c8SAlan Wright 	{ samr_s_QueryInfoDomain2,	SAMR_OPNUM_QueryInfoDomain2 },
1922fe1c642dSBill Krier 	{ samr_s_LookupNames,		SAMR_OPNUM_LookupNames },
1923fe1c642dSBill Krier 	{ samr_s_OpenUser,		SAMR_OPNUM_OpenUser },
1924fe1c642dSBill Krier 	{ samr_s_DeleteUser,		SAMR_OPNUM_DeleteUser },
1925fe1c642dSBill Krier 	{ samr_s_QueryUserInfo,		SAMR_OPNUM_QueryUserInfo },
1926fe1c642dSBill Krier 	{ samr_s_QueryUserGroups,	SAMR_OPNUM_QueryUserGroups },
1927fe1c642dSBill Krier 	{ samr_s_OpenGroup,		SAMR_OPNUM_OpenGroup },
1928cb174861Sjoyce mcintosh 	{ samr_s_Connect2,		SAMR_OPNUM_Connect2 },
1929fe1c642dSBill Krier 	{ samr_s_GetUserPwInfo,		SAMR_OPNUM_GetUserPwInfo },
1930fe1c642dSBill Krier 	{ samr_s_CreateUser,		SAMR_OPNUM_CreateUser },
19311ed6b69aSGordon Ross 	{ samr_s_ChangePasswordUser2,	SAMR_OPNUM_ChangePasswordUser2 },
1932fe1c642dSBill Krier 	{ samr_s_GetDomainPwInfo,	SAMR_OPNUM_GetDomainPwInfo },
1933fe1c642dSBill Krier 	{ samr_s_SetUserInfo,		SAMR_OPNUM_SetUserInfo },
1934fe1c642dSBill Krier 	{ samr_s_Connect4,		SAMR_OPNUM_Connect4 },
1935cb174861Sjoyce mcintosh 	{ samr_s_Connect5,		SAMR_OPNUM_Connect5 },
1936fe1c642dSBill Krier 	{ samr_s_QueryDispInfo,		SAMR_OPNUM_QueryDispInfo },
1937fe1c642dSBill Krier 	{ samr_s_OpenAlias,		SAMR_OPNUM_OpenAlias },
1938fe1c642dSBill Krier 	{ samr_s_CreateDomainAlias,	SAMR_OPNUM_CreateDomainAlias },
1939fe1c642dSBill Krier 	{ samr_s_SetAliasInfo,		SAMR_OPNUM_SetAliasInfo },
1940fe1c642dSBill Krier 	{ samr_s_QueryAliasInfo,	SAMR_OPNUM_QueryAliasInfo },
1941fe1c642dSBill Krier 	{ samr_s_DeleteDomainAlias,	SAMR_OPNUM_DeleteDomainAlias },
1942fe1c642dSBill Krier 	{ samr_s_EnumDomainAliases,	SAMR_OPNUM_EnumDomainAliases },
1943fe1c642dSBill Krier 	{ 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 },
1947fe1c642dSBill Krier 	{0}
1948fe1c642dSBill Krier };
1949fe1c642dSBill Krier 
1950fe1c642dSBill Krier /*
1951fe1c642dSBill Krier  * There is a bug in the way that midl and the marshalling code handles
1952fe1c642dSBill Krier  * unions so we need to fix some of the data offsets at runtime. The
1953fe1c642dSBill Krier  * following macros and the fixup functions handle the corrections.
1954fe1c642dSBill Krier  */
1955fe1c642dSBill Krier 
1956fe1c642dSBill Krier DECL_FIXUP_STRUCT(samr_QueryAliasInfo_ru);
1957fe1c642dSBill Krier DECL_FIXUP_STRUCT(samr_QueryAliasInfoRes);
1958fe1c642dSBill Krier DECL_FIXUP_STRUCT(samr_QueryAliasInfo);
1959fe1c642dSBill Krier 
1960fe1c642dSBill Krier DECL_FIXUP_STRUCT(QueryUserInfo_result_u);
1961fe1c642dSBill Krier DECL_FIXUP_STRUCT(QueryUserInfo_result);
1962fe1c642dSBill Krier DECL_FIXUP_STRUCT(samr_QueryUserInfo);
1963fe1c642dSBill Krier 
1964fe1c642dSBill Krier void
fixup_samr_QueryAliasInfo(struct samr_QueryAliasInfo * val)1965fe1c642dSBill Krier fixup_samr_QueryAliasInfo(struct samr_QueryAliasInfo *val)
1966fe1c642dSBill Krier {
1967fe1c642dSBill Krier 	unsigned short size1 = 0;
1968fe1c642dSBill Krier 	unsigned short size2 = 0;
1969fe1c642dSBill Krier 	unsigned short size3 = 0;
1970fe1c642dSBill Krier 
1971fe1c642dSBill Krier 	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;
1981fe1c642dSBill Krier 
1982fe1c642dSBill Krier 	default:
1983fe1c642dSBill Krier 		return;
1984fe1c642dSBill Krier 	};
1985fe1c642dSBill Krier 
1986fe1c642dSBill Krier 	size2 = size1 + (2 * sizeof (DWORD));
1987fe1c642dSBill Krier 	size3 = size2 + sizeof (ndr_request_hdr_t) + sizeof (DWORD);
1988fe1c642dSBill Krier 
1989fe1c642dSBill Krier 	FIXUP_PDU_SIZE(samr_QueryAliasInfo_ru, size1);
1990fe1c642dSBill Krier 	FIXUP_PDU_SIZE(samr_QueryAliasInfoRes, size2);
1991fe1c642dSBill Krier 	FIXUP_PDU_SIZE(samr_QueryAliasInfo, size3);
1992fe1c642dSBill Krier }
1993fe1c642dSBill Krier 
1994fe1c642dSBill Krier void
fixup_samr_QueryUserInfo(struct samr_QueryUserInfo * val)1995fe1c642dSBill Krier fixup_samr_QueryUserInfo(struct samr_QueryUserInfo *val)
1996fe1c642dSBill Krier {
1997fe1c642dSBill Krier 	unsigned short size1 = 0;
1998fe1c642dSBill Krier 	unsigned short size2 = 0;
1999fe1c642dSBill Krier 	unsigned short size3 = 0;
2000fe1c642dSBill Krier 
2001fe1c642dSBill Krier 	switch (val->switch_index) {
2002fe1c642dSBill Krier 		CASE_INFO_ENT(samr_QueryUserInfo, 1);
2003fe1c642dSBill Krier 		CASE_INFO_ENT(samr_QueryUserInfo, 6);
2004fe1c642dSBill Krier 		CASE_INFO_ENT(samr_QueryUserInfo, 7);
2005fe1c642dSBill Krier 		CASE_INFO_ENT(samr_QueryUserInfo, 8);
2006fe1c642dSBill Krier 		CASE_INFO_ENT(samr_QueryUserInfo, 9);
2007fe1c642dSBill Krier 		CASE_INFO_ENT(samr_QueryUserInfo, 16);
2008fe1c642dSBill Krier 		CASE_INFO_ENT(samr_QueryUserInfo, 21);
2009fe1c642dSBill Krier 
2010fe1c642dSBill Krier 		default:
2011fe1c642dSBill Krier 			return;
2012fe1c642dSBill Krier 	};
2013fe1c642dSBill Krier 
2014fe1c642dSBill Krier 	size2 = size1 + (2 * sizeof (DWORD));
2015fe1c642dSBill Krier 	size3 = size2 + sizeof (ndr_request_hdr_t) + sizeof (DWORD);
2016fe1c642dSBill Krier 
2017fe1c642dSBill Krier 	FIXUP_PDU_SIZE(QueryUserInfo_result_u, size1);
2018fe1c642dSBill Krier 	FIXUP_PDU_SIZE(QueryUserInfo_result, size2);
2019fe1c642dSBill Krier 	FIXUP_PDU_SIZE(samr_QueryUserInfo, size3);
2020fe1c642dSBill Krier }
2021fe1c642dSBill Krier 
2022fe1c642dSBill Krier /*
2023fe1c642dSBill Krier  * As long as there is only one entry in the union, there is no need
2024fe1c642dSBill Krier  * to patch anything.
2025fe1c642dSBill Krier  */
2026fe1c642dSBill Krier /*ARGSUSED*/
2027fe1c642dSBill Krier void
fixup_samr_QueryGroupInfo(struct samr_QueryGroupInfo * val)2028fe1c642dSBill Krier fixup_samr_QueryGroupInfo(struct samr_QueryGroupInfo *val)
2029fe1c642dSBill Krier {
2030fe1c642dSBill Krier }
2031