xref: /illumos-gate/usr/src/lib/smbsrv/libmlsvc/common/samr_svc.c (revision 3299f39fdcbdab4be7a9c70daa3873f2b78a398d)
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.
24eef90b86SGordon Ross  * Copyright 2015 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>
42*3299f39fSGordon 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);
105fe1c642dSBill Krier static int samr_call_stub(ndr_xa_t *mxa);
106fe1c642dSBill Krier static DWORD samr_s_enum_local_domains(struct samr_EnumLocalDomain *,
107fe1c642dSBill Krier     ndr_xa_t *);
108fe1c642dSBill Krier 
109fe1c642dSBill Krier static ndr_stub_table_t samr_stub_table[];
110fe1c642dSBill Krier 
111fe1c642dSBill Krier static ndr_service_t samr_service = {
112fe1c642dSBill Krier 	"SAMR",				/* name */
113fe1c642dSBill Krier 	"Security Accounts Manager",	/* desc */
114fe1c642dSBill Krier 	"\\samr",			/* endpoint */
115fe1c642dSBill Krier 	PIPE_LSASS,			/* sec_addr_port */
116fe1c642dSBill Krier 	"12345778-1234-abcd-ef00-0123456789ac", 1,	/* abstract */
117fe1c642dSBill Krier 	NDR_TRANSFER_SYNTAX_UUID,		2,	/* transfer */
118fe1c642dSBill Krier 	0,				/* no bind_instance_size */
119fe1c642dSBill Krier 	NULL,				/* no bind_req() */
120fe1c642dSBill Krier 	NULL,				/* no unbind_and_close() */
121fe1c642dSBill Krier 	samr_call_stub,			/* call_stub() */
122fe1c642dSBill Krier 	&TYPEINFO(samr_interface),	/* interface ti */
123fe1c642dSBill Krier 	samr_stub_table			/* stub_table */
124fe1c642dSBill Krier };
125fe1c642dSBill Krier 
126fe1c642dSBill Krier /*
127fe1c642dSBill Krier  * samr_initialize
128fe1c642dSBill Krier  *
129fe1c642dSBill Krier  * This function registers the SAM RPC interface with the RPC runtime
130fe1c642dSBill Krier  * library. It must be called in order to use either the client side
131fe1c642dSBill Krier  * or the server side functions.
132fe1c642dSBill Krier  */
133fe1c642dSBill Krier void
134fe1c642dSBill Krier samr_initialize(void)
135fe1c642dSBill Krier {
136fe1c642dSBill Krier 	(void) ndr_svc_register(&samr_service);
137fe1c642dSBill Krier }
138fe1c642dSBill Krier 
139fe1c642dSBill Krier /*
140fe1c642dSBill Krier  * Custom call_stub to set the stream string policy.
141fe1c642dSBill Krier  */
142fe1c642dSBill Krier static int
143fe1c642dSBill Krier samr_call_stub(ndr_xa_t *mxa)
144fe1c642dSBill Krier {
145fe1c642dSBill Krier 	NDS_SETF(&mxa->send_nds, NDS_F_NOTERM);
146fe1c642dSBill Krier 	NDS_SETF(&mxa->recv_nds, NDS_F_NOTERM);
147fe1c642dSBill Krier 
148fe1c642dSBill Krier 	return (ndr_generic_call_stub(mxa));
149fe1c642dSBill Krier }
150fe1c642dSBill Krier 
151fe1c642dSBill Krier /*
152fe1c642dSBill Krier  * Handle allocation wrapper to setup the local context.
153fe1c642dSBill Krier  */
154fe1c642dSBill Krier static ndr_hdid_t *
155fe1c642dSBill Krier samr_hdalloc(ndr_xa_t *mxa, samr_key_t key, smb_domain_type_t domain_type,
156fe1c642dSBill Krier     DWORD rid)
157fe1c642dSBill Krier {
1589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	ndr_handle_t	*hd;
1599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	ndr_hdid_t	*id;
160fe1c642dSBill Krier 	samr_keydata_t	*data;
161fe1c642dSBill Krier 
162fe1c642dSBill Krier 	if ((data = malloc(sizeof (samr_keydata_t))) == NULL)
163fe1c642dSBill Krier 		return (NULL);
164fe1c642dSBill Krier 
165fe1c642dSBill Krier 	data->kd_key = key;
166fe1c642dSBill Krier 	data->kd_type = domain_type;
167fe1c642dSBill Krier 	data->kd_rid = rid;
168fe1c642dSBill Krier 
1699fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if ((id = ndr_hdalloc(mxa, data)) == NULL) {
1709fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		free(data);
1719fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (NULL);
1729fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
1739fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
1749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if ((hd = ndr_hdlookup(mxa, id)) != NULL)
1759fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		hd->nh_data_free = free;
1769fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
1779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	return (id);
178fe1c642dSBill Krier }
179fe1c642dSBill Krier 
180fe1c642dSBill Krier /*
181fe1c642dSBill Krier  * Handle deallocation wrapper to free the local context.
182fe1c642dSBill Krier  */
183fe1c642dSBill Krier static void
184fe1c642dSBill Krier samr_hdfree(ndr_xa_t *mxa, ndr_hdid_t *id)
185fe1c642dSBill Krier {
186fe1c642dSBill Krier 	ndr_handle_t *hd;
187fe1c642dSBill Krier 
188fe1c642dSBill Krier 	if ((hd = ndr_hdlookup(mxa, id)) != NULL) {
189fe1c642dSBill Krier 		free(hd->nh_data);
1909fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		hd->nh_data = NULL;
191fe1c642dSBill Krier 		ndr_hdfree(mxa, id);
192fe1c642dSBill Krier 	}
193fe1c642dSBill Krier }
194fe1c642dSBill Krier 
195fe1c642dSBill Krier /*
196fe1c642dSBill Krier  * Handle lookup wrapper to validate the local context.
197fe1c642dSBill Krier  */
198fe1c642dSBill Krier static ndr_handle_t *
199fe1c642dSBill Krier samr_hdlookup(ndr_xa_t *mxa, ndr_hdid_t *id, samr_key_t key)
200fe1c642dSBill Krier {
201fe1c642dSBill Krier 	ndr_handle_t *hd;
202fe1c642dSBill Krier 	samr_keydata_t *data;
203fe1c642dSBill Krier 
204fe1c642dSBill Krier 	if ((hd = ndr_hdlookup(mxa, id)) == NULL)
205fe1c642dSBill Krier 		return (NULL);
206fe1c642dSBill Krier 
207fe1c642dSBill Krier 	if ((data = (samr_keydata_t *)hd->nh_data) == NULL)
208fe1c642dSBill Krier 		return (NULL);
209fe1c642dSBill Krier 
210fe1c642dSBill Krier 	if (data->kd_key != key)
211fe1c642dSBill Krier 		return (NULL);
212fe1c642dSBill Krier 
213fe1c642dSBill Krier 	return (hd);
214fe1c642dSBill Krier }
215fe1c642dSBill Krier 
216fe1c642dSBill Krier /*
217cb174861Sjoyce mcintosh  * samr_s_Connect
218fe1c642dSBill Krier  *
219fe1c642dSBill Krier  * This is a request to connect to the local SAM database. We don't
220fe1c642dSBill Krier  * support any form of update request and our database doesn't
221fe1c642dSBill Krier  * contain any private information, so there is little point in
222fe1c642dSBill Krier  * doing any access access checking here.
223fe1c642dSBill Krier  *
224fe1c642dSBill Krier  * Return a handle for use with subsequent SAM requests.
225fe1c642dSBill Krier  */
226fe1c642dSBill Krier static int
227cb174861Sjoyce mcintosh samr_s_Connect(void *arg, ndr_xa_t *mxa)
228fe1c642dSBill Krier {
229cb174861Sjoyce mcintosh 	struct samr_Connect *param = arg;
230fe1c642dSBill Krier 	ndr_hdid_t *id;
231fe1c642dSBill Krier 
232fe1c642dSBill Krier 	id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, SMB_DOMAIN_NULL, 0);
233fe1c642dSBill Krier 	if (id) {
234fe1c642dSBill Krier 		bcopy(id, &param->handle, sizeof (samr_handle_t));
235fe1c642dSBill Krier 		param->status = 0;
236fe1c642dSBill Krier 	} else {
237fe1c642dSBill Krier 		bzero(&param->handle, sizeof (samr_handle_t));
238fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
239fe1c642dSBill Krier 	}
240fe1c642dSBill Krier 
241fe1c642dSBill Krier 	return (NDR_DRC_OK);
242fe1c642dSBill Krier }
243fe1c642dSBill Krier 
244fe1c642dSBill Krier /*
245fe1c642dSBill Krier  * samr_s_CloseHandle
246fe1c642dSBill Krier  *
247fe1c642dSBill Krier  * Close the SAM interface specified by the handle.
248fe1c642dSBill Krier  * Free the handle and zero out the result handle for the client.
249fe1c642dSBill Krier  */
250fe1c642dSBill Krier static int
251fe1c642dSBill Krier samr_s_CloseHandle(void *arg, ndr_xa_t *mxa)
252fe1c642dSBill Krier {
253fe1c642dSBill Krier 	struct samr_CloseHandle *param = arg;
254fe1c642dSBill Krier 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
255fe1c642dSBill Krier 
256fe1c642dSBill Krier 	samr_hdfree(mxa, id);
257fe1c642dSBill Krier 
258fe1c642dSBill Krier 	bzero(&param->result_handle, sizeof (samr_handle_t));
259fe1c642dSBill Krier 	param->status = 0;
260fe1c642dSBill Krier 	return (NDR_DRC_OK);
261fe1c642dSBill Krier }
262fe1c642dSBill Krier 
263fe1c642dSBill Krier /*
264fe1c642dSBill Krier  * samr_s_LookupDomain
265fe1c642dSBill Krier  *
266fe1c642dSBill Krier  * This is a request to map a domain name to a domain SID. We can map
267fe1c642dSBill Krier  * the primary domain name, our local domain name (hostname) and the
268fe1c642dSBill Krier  * builtin domain names to the appropriate SID. Anything else will be
269fe1c642dSBill Krier  * rejected.
270fe1c642dSBill Krier  */
271fe1c642dSBill Krier static int
272fe1c642dSBill Krier samr_s_LookupDomain(void *arg, ndr_xa_t *mxa)
273fe1c642dSBill Krier {
274fe1c642dSBill Krier 	struct samr_LookupDomain *param = arg;
275fe1c642dSBill Krier 	char *domain_name;
276fe1c642dSBill Krier 	smb_domain_t di;
277fe1c642dSBill Krier 
278fe1c642dSBill Krier 	if ((domain_name = (char *)param->domain_name.str) == NULL) {
279fe1c642dSBill Krier 		bzero(param, sizeof (struct samr_LookupDomain));
280fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER);
281fe1c642dSBill Krier 		return (NDR_DRC_OK);
282fe1c642dSBill Krier 	}
283fe1c642dSBill Krier 
284fe1c642dSBill Krier 	if (!smb_domain_lookup_name(domain_name, &di)) {
285fe1c642dSBill Krier 		bzero(param, sizeof (struct samr_LookupDomain));
286fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_NO_SUCH_DOMAIN);
287fe1c642dSBill Krier 		return (NDR_DRC_OK);
288fe1c642dSBill Krier 	}
289fe1c642dSBill Krier 
290fe1c642dSBill Krier 	param->sid = (struct samr_sid *)NDR_SIDDUP(mxa, di.di_binsid);
291fe1c642dSBill Krier 	if (param->sid == NULL) {
292fe1c642dSBill Krier 		bzero(param, sizeof (struct samr_LookupDomain));
293fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
294fe1c642dSBill Krier 		return (NDR_DRC_OK);
295fe1c642dSBill Krier 	}
296fe1c642dSBill Krier 
297fe1c642dSBill Krier 	param->status = NT_STATUS_SUCCESS;
298fe1c642dSBill Krier 	return (NDR_DRC_OK);
299fe1c642dSBill Krier }
300fe1c642dSBill Krier 
301fe1c642dSBill Krier /*
302fe1c642dSBill Krier  * samr_s_EnumLocalDomains
303fe1c642dSBill Krier  *
304fe1c642dSBill Krier  * This is a request for the local domains supported by this server.
305fe1c642dSBill Krier  * All we do here is validate the handle and set the status. The real
306fe1c642dSBill Krier  * work is done in samr_s_enum_local_domains.
307fe1c642dSBill Krier  */
308fe1c642dSBill Krier static int
309fe1c642dSBill Krier samr_s_EnumLocalDomains(void *arg, ndr_xa_t *mxa)
310fe1c642dSBill Krier {
311fe1c642dSBill Krier 	struct samr_EnumLocalDomain *param = arg;
312fe1c642dSBill Krier 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
313fe1c642dSBill Krier 	DWORD status;
314fe1c642dSBill Krier 
315fe1c642dSBill Krier 	if (samr_hdlookup(mxa, id, SAMR_KEY_CONNECT) == NULL)
316fe1c642dSBill Krier 		status = NT_STATUS_ACCESS_DENIED;
317fe1c642dSBill Krier 	else
318fe1c642dSBill Krier 		status = samr_s_enum_local_domains(param, mxa);
319fe1c642dSBill Krier 
320fe1c642dSBill Krier 	if (status == NT_STATUS_SUCCESS) {
321fe1c642dSBill Krier 		param->enum_context = param->info->entries_read;
322fe1c642dSBill Krier 		param->total_entries = param->info->entries_read;
323fe1c642dSBill Krier 		param->status = NT_STATUS_SUCCESS;
324fe1c642dSBill Krier 	} else {
325fe1c642dSBill Krier 		bzero(param, sizeof (struct samr_EnumLocalDomain));
326fe1c642dSBill Krier 		param->status = NT_SC_ERROR(status);
327fe1c642dSBill Krier 	}
328fe1c642dSBill Krier 
329fe1c642dSBill Krier 	return (NDR_DRC_OK);
330fe1c642dSBill Krier }
331fe1c642dSBill Krier 
332fe1c642dSBill Krier 
333fe1c642dSBill Krier /*
334fe1c642dSBill Krier  * samr_s_enum_local_domains
335fe1c642dSBill Krier  *
336fe1c642dSBill Krier  * This function should only be called via samr_s_EnumLocalDomains to
337fe1c642dSBill Krier  * ensure that the appropriate validation is performed. We will answer
338fe1c642dSBill Krier  * queries about two domains: the local domain, synonymous with the
339fe1c642dSBill Krier  * local hostname, and the BUILTIN domain. So we return these two
340fe1c642dSBill Krier  * strings.
341fe1c642dSBill Krier  *
342fe1c642dSBill Krier  * Returns NT status values.
343fe1c642dSBill Krier  */
344fe1c642dSBill Krier static DWORD
345fe1c642dSBill Krier samr_s_enum_local_domains(struct samr_EnumLocalDomain *param,
346fe1c642dSBill Krier     ndr_xa_t *mxa)
347fe1c642dSBill Krier {
348fe1c642dSBill Krier 	struct samr_LocalDomainInfo *info;
349fe1c642dSBill Krier 	struct samr_LocalDomainEntry *entry;
350fe1c642dSBill Krier 	char *hostname;
351fe1c642dSBill Krier 
352fe1c642dSBill Krier 	hostname = NDR_MALLOC(mxa, NETBIOS_NAME_SZ);
353fe1c642dSBill Krier 	if (hostname == NULL)
354fe1c642dSBill Krier 		return (NT_STATUS_NO_MEMORY);
355fe1c642dSBill Krier 
356fe1c642dSBill Krier 	if (smb_getnetbiosname(hostname, NETBIOS_NAME_SZ) != 0)
357fe1c642dSBill Krier 		return (NT_STATUS_NO_MEMORY);
358fe1c642dSBill Krier 
359fe1c642dSBill Krier 	entry = NDR_NEWN(mxa, struct samr_LocalDomainEntry, 2);
360fe1c642dSBill Krier 	if (entry == NULL)
361fe1c642dSBill Krier 		return (NT_STATUS_NO_MEMORY);
362fe1c642dSBill Krier 
363fe1c642dSBill Krier 	bzero(entry, (sizeof (struct samr_LocalDomainEntry) * 2));
364fe1c642dSBill Krier 	(void) NDR_MSTRING(mxa, hostname, (ndr_mstring_t *)&entry[0].name);
365fe1c642dSBill Krier 	(void) NDR_MSTRING(mxa, "Builtin", (ndr_mstring_t *)&entry[1].name);
366fe1c642dSBill Krier 
367fe1c642dSBill Krier 	info = NDR_NEW(mxa, struct samr_LocalDomainInfo);
368fe1c642dSBill Krier 	if (info == NULL)
369fe1c642dSBill Krier 		return (NT_STATUS_NO_MEMORY);
370fe1c642dSBill Krier 
371fe1c642dSBill Krier 	info->entries_read = 2;
372fe1c642dSBill Krier 	info->entry = entry;
373fe1c642dSBill Krier 	param->info = info;
374fe1c642dSBill Krier 	return (NT_STATUS_SUCCESS);
375fe1c642dSBill Krier }
376fe1c642dSBill Krier 
377fe1c642dSBill Krier /*
378fe1c642dSBill Krier  * samr_s_OpenDomain
379fe1c642dSBill Krier  *
380fe1c642dSBill Krier  * This is a request to open a domain within the local SAM database.
381fe1c642dSBill Krier  * The caller must supply a valid connect handle.
382fe1c642dSBill Krier  * We return a handle to be used to access objects within this domain.
383fe1c642dSBill Krier  */
384fe1c642dSBill Krier static int
385fe1c642dSBill Krier samr_s_OpenDomain(void *arg, ndr_xa_t *mxa)
386fe1c642dSBill Krier {
387fe1c642dSBill Krier 	struct samr_OpenDomain *param = arg;
388fe1c642dSBill Krier 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
389fe1c642dSBill Krier 	smb_domain_t domain;
390fe1c642dSBill Krier 
391fe1c642dSBill Krier 	if (samr_hdlookup(mxa, id, SAMR_KEY_CONNECT) == NULL) {
392fe1c642dSBill Krier 		bzero(&param->domain_handle, sizeof (samr_handle_t));
393fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
394fe1c642dSBill Krier 		return (NDR_DRC_OK);
395fe1c642dSBill Krier 	}
396fe1c642dSBill Krier 
397fe1c642dSBill Krier 	if (!smb_domain_lookup_sid((smb_sid_t *)param->sid, &domain)) {
398fe1c642dSBill Krier 		bzero(&param->domain_handle, sizeof (samr_handle_t));
399fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
400fe1c642dSBill Krier 		return (NDR_DRC_OK);
401fe1c642dSBill Krier 	}
402fe1c642dSBill Krier 
403fe1c642dSBill Krier 	if ((domain.di_type != SMB_DOMAIN_BUILTIN) &&
404fe1c642dSBill Krier 	    (domain.di_type != SMB_DOMAIN_LOCAL)) {
405fe1c642dSBill Krier 		bzero(&param->domain_handle, sizeof (samr_handle_t));
406fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
407fe1c642dSBill Krier 		return (NDR_DRC_OK);
408fe1c642dSBill Krier 	}
409fe1c642dSBill Krier 
410fe1c642dSBill Krier 	id = samr_hdalloc(mxa, SAMR_KEY_DOMAIN, domain.di_type, 0);
411fe1c642dSBill Krier 	if (id) {
412fe1c642dSBill Krier 		bcopy(id, &param->domain_handle, sizeof (samr_handle_t));
413fe1c642dSBill Krier 		param->status = 0;
414fe1c642dSBill Krier 	} else {
415fe1c642dSBill Krier 		bzero(&param->domain_handle, sizeof (samr_handle_t));
416fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
417fe1c642dSBill Krier 	}
418fe1c642dSBill Krier 
419fe1c642dSBill Krier 	return (NDR_DRC_OK);
420fe1c642dSBill Krier }
421fe1c642dSBill Krier 
422fe1c642dSBill Krier /*
423fe1c642dSBill Krier  * samr_s_QueryDomainInfo
424fe1c642dSBill Krier  *
425fe1c642dSBill Krier  * The caller should pass a domain handle.
426fe1c642dSBill Krier  *
427fe1c642dSBill Krier  * Windows 95 Server Manager sends requests for levels 6 and 7 when
428fe1c642dSBill Krier  * the services menu item is selected. Level 2 is basically for getting
429fe1c642dSBill Krier  * number of users, groups, and aliases in a domain.
430fe1c642dSBill Krier  * We have no information on what the various information levels mean.
431fe1c642dSBill Krier  */
432fe1c642dSBill Krier static int
433fe1c642dSBill Krier samr_s_QueryDomainInfo(void *arg, ndr_xa_t *mxa)
434fe1c642dSBill Krier {
435fe1c642dSBill Krier 	struct samr_QueryDomainInfo *param = arg;
436fe1c642dSBill Krier 	struct samr_QueryDomainInfoRes *info;
437fe1c642dSBill Krier 	ndr_hdid_t *id = (ndr_hdid_t *)&param->domain_handle;
438fe1c642dSBill Krier 	ndr_handle_t *hd;
439fe1c642dSBill Krier 	samr_keydata_t *data;
440fe1c642dSBill Krier 	char *domain;
441fe1c642dSBill Krier 	char hostname[NETBIOS_NAME_SZ];
442fe1c642dSBill Krier 	int alias_cnt, user_cnt;
443fe1c642dSBill Krier 	int rc = 0;
444fe1c642dSBill Krier 
445fe1c642dSBill Krier 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
446fe1c642dSBill Krier 		bzero(param, sizeof (struct samr_QueryDomainInfo));
447fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
448fe1c642dSBill Krier 		return (NDR_DRC_OK);
449fe1c642dSBill Krier 	}
450fe1c642dSBill Krier 
451fe1c642dSBill Krier 	info = NDR_NEW(mxa, struct samr_QueryDomainInfoRes);
452fe1c642dSBill Krier 	if (info == NULL) {
453fe1c642dSBill Krier 		bzero(param, sizeof (struct samr_QueryDomainInfo));
454fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
455fe1c642dSBill Krier 		return (NDR_DRC_OK);
456fe1c642dSBill Krier 	}
457fe1c642dSBill Krier 	info->switch_value = param->info_level;
458fe1c642dSBill Krier 	param->info = info;
459fe1c642dSBill Krier 
460fe1c642dSBill Krier 	data = (samr_keydata_t *)hd->nh_data;
461fe1c642dSBill Krier 
462fe1c642dSBill Krier 	switch (data->kd_type) {
463fe1c642dSBill Krier 	case SMB_DOMAIN_BUILTIN:
464fe1c642dSBill Krier 		domain = "BUILTIN";
465fe1c642dSBill Krier 		user_cnt = 0;
466fe1c642dSBill Krier 		alias_cnt = smb_sam_grp_cnt(data->kd_type);
467fe1c642dSBill Krier 		break;
468fe1c642dSBill Krier 
469fe1c642dSBill Krier 	case SMB_DOMAIN_LOCAL:
470fe1c642dSBill Krier 		rc = smb_getnetbiosname(hostname, sizeof (hostname));
471fe1c642dSBill Krier 		if (rc == 0) {
472fe1c642dSBill Krier 			domain = hostname;
473fe1c642dSBill Krier 			user_cnt = smb_sam_usr_cnt();
474fe1c642dSBill Krier 			alias_cnt = smb_sam_grp_cnt(data->kd_type);
475fe1c642dSBill Krier 		}
476fe1c642dSBill Krier 		break;
477fe1c642dSBill Krier 
478fe1c642dSBill Krier 	default:
479fe1c642dSBill Krier 		bzero(param, sizeof (struct samr_QueryDomainInfo));
480fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
481fe1c642dSBill Krier 		return (NDR_DRC_OK);
482fe1c642dSBill Krier 	}
483fe1c642dSBill Krier 
484fe1c642dSBill Krier 	if (rc != 0) {
485fe1c642dSBill Krier 		bzero(param, sizeof (struct samr_QueryDomainInfo));
486fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_INTERNAL_ERROR);
487fe1c642dSBill Krier 		return (NDR_DRC_OK);
488fe1c642dSBill Krier 	}
489fe1c642dSBill Krier 
490fe1c642dSBill Krier 	switch (param->info_level) {
491fe1c642dSBill Krier 	case SAMR_QUERY_DOMAIN_INFO_6:
492fe1c642dSBill Krier 		info->ru.info6.unknown1 = 0x00000000;
493fe1c642dSBill Krier 		info->ru.info6.unknown2 = 0x00147FB0;
494fe1c642dSBill Krier 		info->ru.info6.unknown3 = 0x00000000;
495fe1c642dSBill Krier 		info->ru.info6.unknown4 = 0x00000000;
496fe1c642dSBill Krier 		info->ru.info6.unknown5 = 0x00000000;
497fe1c642dSBill Krier 		param->status = NT_STATUS_SUCCESS;
498fe1c642dSBill Krier 		break;
499fe1c642dSBill Krier 
500fe1c642dSBill Krier 	case SAMR_QUERY_DOMAIN_INFO_7:
501fe1c642dSBill Krier 		info->ru.info7.unknown1 = 0x00000003;
502fe1c642dSBill Krier 		param->status = NT_STATUS_SUCCESS;
503fe1c642dSBill Krier 		break;
504fe1c642dSBill Krier 
505fe1c642dSBill Krier 	case SAMR_QUERY_DOMAIN_INFO_2:
506fe1c642dSBill Krier 		info->ru.info2.unknown1 = 0x00000000;
507fe1c642dSBill Krier 		info->ru.info2.unknown2 = 0x80000000;
508fe1c642dSBill Krier 
509fe1c642dSBill Krier 		(void) NDR_MSTRING(mxa, "",
510fe1c642dSBill Krier 		    (ndr_mstring_t *)&(info->ru.info2.s1));
511fe1c642dSBill Krier 		(void) NDR_MSTRING(mxa, domain,
512fe1c642dSBill Krier 		    (ndr_mstring_t *)&(info->ru.info2.domain));
513fe1c642dSBill Krier 		(void) NDR_MSTRING(mxa, "",
514fe1c642dSBill Krier 		    (ndr_mstring_t *)&(info->ru.info2.s2));
515fe1c642dSBill Krier 
516fe1c642dSBill Krier 		info->ru.info2.sequence_num = 0x0000002B;
517fe1c642dSBill Krier 		info->ru.info2.unknown3 = 0x00000000;
518fe1c642dSBill Krier 		info->ru.info2.unknown4 = 0x00000001;
519fe1c642dSBill Krier 		info->ru.info2.unknown5 = 0x00000003;
520fe1c642dSBill Krier 		info->ru.info2.unknown6 = 0x00000001;
521fe1c642dSBill Krier 		info->ru.info2.num_users = user_cnt;
522fe1c642dSBill Krier 		info->ru.info2.num_groups = 0;
523fe1c642dSBill Krier 		info->ru.info2.num_aliases = alias_cnt;
524fe1c642dSBill Krier 		param->status = NT_STATUS_SUCCESS;
525fe1c642dSBill Krier 		break;
526fe1c642dSBill Krier 
527fe1c642dSBill Krier 	default:
528fe1c642dSBill Krier 		bzero(param, sizeof (struct samr_QueryDomainInfo));
529fe1c642dSBill Krier 		return (NDR_DRC_FAULT_REQUEST_OPNUM_INVALID);
530fe1c642dSBill Krier 	};
531fe1c642dSBill Krier 
532fe1c642dSBill Krier 	return (NDR_DRC_OK);
533fe1c642dSBill Krier }
534fe1c642dSBill Krier 
535fe1c642dSBill Krier /*
536f96bd5c8SAlan Wright  * QueryInfoDomain2: Identical to QueryDomainInfo.
537f96bd5c8SAlan Wright  */
538f96bd5c8SAlan Wright static int
539f96bd5c8SAlan Wright samr_s_QueryInfoDomain2(void *arg, ndr_xa_t *mxa)
540f96bd5c8SAlan Wright {
541f96bd5c8SAlan Wright 	return (samr_s_QueryDomainInfo(arg, mxa));
542f96bd5c8SAlan Wright }
543f96bd5c8SAlan Wright 
544f96bd5c8SAlan Wright /*
545fe1c642dSBill Krier  * Looks up the given name in the specified domain which could
546fe1c642dSBill Krier  * be either the built-in or local domain.
547fe1c642dSBill Krier  *
548fe1c642dSBill Krier  * CAVEAT: this function should be able to handle a list of
549fe1c642dSBill Krier  * names but currently it can only handle one name at a time.
550fe1c642dSBill Krier  */
551fe1c642dSBill Krier static int
552fe1c642dSBill Krier samr_s_LookupNames(void *arg, ndr_xa_t *mxa)
553fe1c642dSBill Krier {
554fe1c642dSBill Krier 	struct samr_LookupNames *param = arg;
555fe1c642dSBill Krier 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
556fe1c642dSBill Krier 	ndr_handle_t *hd;
557fe1c642dSBill Krier 	samr_keydata_t *data;
558fe1c642dSBill Krier 	smb_account_t account;
559fe1c642dSBill Krier 	smb_wka_t *wka;
560fe1c642dSBill Krier 	uint32_t status = NT_STATUS_SUCCESS;
561fe1c642dSBill Krier 
562fe1c642dSBill Krier 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL)
563fe1c642dSBill Krier 		status = NT_STATUS_INVALID_HANDLE;
564fe1c642dSBill Krier 
565fe1c642dSBill Krier 	if (param->n_entry != 1)
566fe1c642dSBill Krier 		status = NT_STATUS_ACCESS_DENIED;
567fe1c642dSBill Krier 
568fe1c642dSBill Krier 	if (param->name.str == NULL) {
569fe1c642dSBill Krier 		/*
570fe1c642dSBill Krier 		 * Windows NT returns NT_STATUS_NONE_MAPPED.
571fe1c642dSBill Krier 		 * Windows 2000 returns STATUS_INVALID_ACCOUNT_NAME.
572fe1c642dSBill Krier 		 */
573fe1c642dSBill Krier 		status = NT_STATUS_NONE_MAPPED;
574fe1c642dSBill Krier 	}
575fe1c642dSBill Krier 
576fe1c642dSBill Krier 	if (status != NT_STATUS_SUCCESS) {
577fe1c642dSBill Krier 		bzero(param, sizeof (struct samr_LookupNames));
578fe1c642dSBill Krier 		param->status = NT_SC_ERROR(status);
579fe1c642dSBill Krier 		return (NDR_DRC_OK);
580fe1c642dSBill Krier 	}
581fe1c642dSBill Krier 
582fe1c642dSBill Krier 	param->rids.rid = NDR_NEW(mxa, DWORD);
583fe1c642dSBill Krier 	param->rid_types.rid_type = NDR_NEW(mxa, DWORD);
584fe1c642dSBill Krier 
585fe1c642dSBill Krier 	data = (samr_keydata_t *)hd->nh_data;
586fe1c642dSBill Krier 
587fe1c642dSBill Krier 	switch (data->kd_type) {
588fe1c642dSBill Krier 	case SMB_DOMAIN_BUILTIN:
589f96bd5c8SAlan Wright 		wka = smb_wka_lookup_builtin((char *)param->name.str);
590fe1c642dSBill Krier 		if (wka != NULL) {
591fe1c642dSBill Krier 			param->rids.n_entry = 1;
592fe1c642dSBill Krier 			(void) smb_sid_getrid(wka->wka_binsid,
593fe1c642dSBill Krier 			    &param->rids.rid[0]);
594fe1c642dSBill Krier 			param->rid_types.n_entry = 1;
595fe1c642dSBill Krier 			param->rid_types.rid_type[0] = wka->wka_type;
596fe1c642dSBill Krier 			param->status = NT_STATUS_SUCCESS;
597fe1c642dSBill Krier 			return (NDR_DRC_OK);
598fe1c642dSBill Krier 		}
599fe1c642dSBill Krier 		break;
600fe1c642dSBill Krier 
601fe1c642dSBill Krier 	case SMB_DOMAIN_LOCAL:
602fe1c642dSBill Krier 		status = smb_sam_lookup_name(NULL, (char *)param->name.str,
603fe1c642dSBill Krier 		    SidTypeUnknown, &account);
604fe1c642dSBill Krier 		if (status == NT_STATUS_SUCCESS) {
605fe1c642dSBill Krier 			param->rids.n_entry = 1;
606fe1c642dSBill Krier 			param->rids.rid[0] = account.a_rid;
607fe1c642dSBill Krier 			param->rid_types.n_entry = 1;
608fe1c642dSBill Krier 			param->rid_types.rid_type[0] = account.a_type;
609fe1c642dSBill Krier 			param->status = NT_STATUS_SUCCESS;
610fe1c642dSBill Krier 			smb_account_free(&account);
611fe1c642dSBill Krier 			return (NDR_DRC_OK);
612fe1c642dSBill Krier 		}
613fe1c642dSBill Krier 		break;
614fe1c642dSBill Krier 
615fe1c642dSBill Krier 	default:
616fe1c642dSBill Krier 		bzero(param, sizeof (struct samr_LookupNames));
617fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
618fe1c642dSBill Krier 		return (NDR_DRC_OK);
619fe1c642dSBill Krier 	}
620fe1c642dSBill Krier 
621fe1c642dSBill Krier 	param->rids.n_entry = 0;
622fe1c642dSBill Krier 	param->rid_types.n_entry = 0;
623fe1c642dSBill Krier 	param->status = NT_SC_ERROR(NT_STATUS_NONE_MAPPED);
624fe1c642dSBill Krier 	return (NDR_DRC_OK);
625fe1c642dSBill Krier }
626fe1c642dSBill Krier 
627fe1c642dSBill Krier /*
628fe1c642dSBill Krier  * samr_s_OpenUser
629fe1c642dSBill Krier  *
630fe1c642dSBill Krier  * This is a request to open a user within a specified domain in the
631fe1c642dSBill Krier  * local SAM database. The caller must supply a valid domain handle,
632fe1c642dSBill Krier  * obtained via a successful domain open request. The user is
633fe1c642dSBill Krier  * specified by the rid in the request.
634fe1c642dSBill Krier  */
635fe1c642dSBill Krier static int
636fe1c642dSBill Krier samr_s_OpenUser(void *arg, ndr_xa_t *mxa)
637fe1c642dSBill Krier {
638fe1c642dSBill Krier 	struct samr_OpenUser *param = arg;
639fe1c642dSBill Krier 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
640fe1c642dSBill Krier 	ndr_handle_t *hd;
641fe1c642dSBill Krier 	samr_keydata_t *data;
642fe1c642dSBill Krier 
643fe1c642dSBill Krier 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
644fe1c642dSBill Krier 		bzero(&param->user_handle, sizeof (samr_handle_t));
645fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
646fe1c642dSBill Krier 		return (NDR_DRC_OK);
647fe1c642dSBill Krier 	}
648fe1c642dSBill Krier 
649fe1c642dSBill Krier 	data = (samr_keydata_t *)hd->nh_data;
650fe1c642dSBill Krier 
651fe1c642dSBill Krier 	id = samr_hdalloc(mxa, SAMR_KEY_USER, data->kd_type, param->rid);
652fe1c642dSBill Krier 	if (id == NULL) {
653fe1c642dSBill Krier 		bzero(&param->user_handle, sizeof (samr_handle_t));
654fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
655fe1c642dSBill Krier 	} else {
656fe1c642dSBill Krier 		bcopy(id, &param->user_handle, sizeof (samr_handle_t));
657fe1c642dSBill Krier 		param->status = NT_STATUS_SUCCESS;
658fe1c642dSBill Krier 	}
659fe1c642dSBill Krier 
660fe1c642dSBill Krier 	return (NDR_DRC_OK);
661fe1c642dSBill Krier }
662fe1c642dSBill Krier 
663fe1c642dSBill Krier /*
664fe1c642dSBill Krier  * samr_s_DeleteUser
665fe1c642dSBill Krier  *
666fe1c642dSBill Krier  * Request to delete a user within a specified domain in the local
667fe1c642dSBill Krier  * SAM database.  The caller should supply a valid user handle.
668fe1c642dSBill Krier  */
669fe1c642dSBill Krier /*ARGSUSED*/
670fe1c642dSBill Krier static int
671fe1c642dSBill Krier samr_s_DeleteUser(void *arg, ndr_xa_t *mxa)
672fe1c642dSBill Krier {
673fe1c642dSBill Krier 	struct samr_DeleteUser *param = arg;
674fe1c642dSBill Krier 
675fe1c642dSBill Krier 	bzero(param, sizeof (struct samr_DeleteUser));
676fe1c642dSBill Krier 	param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
677fe1c642dSBill Krier 	return (NDR_DRC_OK);
678fe1c642dSBill Krier }
679fe1c642dSBill Krier 
680fe1c642dSBill Krier /*
681fe1c642dSBill Krier  * samr_s_QueryUserInfo
682fe1c642dSBill Krier  *
683fe1c642dSBill Krier  * Returns:
684fe1c642dSBill Krier  * NT_STATUS_SUCCESS
685fe1c642dSBill Krier  * NT_STATUS_ACCESS_DENIED
686fe1c642dSBill Krier  * NT_STATUS_INVALID_INFO_CLASS
687fe1c642dSBill Krier  */
688fe1c642dSBill Krier /*ARGSUSED*/
689fe1c642dSBill Krier static int
690fe1c642dSBill Krier samr_s_QueryUserInfo(void *arg, ndr_xa_t *mxa)
691fe1c642dSBill Krier {
692fe1c642dSBill Krier 	static uint16_t			owf_buf[8];
693fe1c642dSBill Krier 	static uint8_t			hour_buf[SAMR_SET_USER_HOURS_SZ];
694fe1c642dSBill Krier 	struct samr_QueryUserInfo	*param = arg;
695fe1c642dSBill Krier 	struct samr_QueryUserInfo21	*all_info;
696fe1c642dSBill Krier 	ndr_hdid_t			*id;
697fe1c642dSBill Krier 	ndr_handle_t			*hd;
698fe1c642dSBill Krier 	samr_keydata_t			*data;
699fe1c642dSBill Krier 	smb_domain_t			di;
700fe1c642dSBill Krier 	smb_account_t			account;
701fe1c642dSBill Krier 	smb_sid_t			*sid;
702fe1c642dSBill Krier 	uint32_t			status;
703fe1c642dSBill Krier 
704fe1c642dSBill Krier 	id = (ndr_hdid_t *)&param->user_handle;
705fe1c642dSBill Krier 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_USER)) == NULL) {
706fe1c642dSBill Krier 		status = NT_STATUS_INVALID_HANDLE;
707fe1c642dSBill Krier 		goto QueryUserInfoError;
708fe1c642dSBill Krier 	}
709fe1c642dSBill Krier 
710fe1c642dSBill Krier 	data = (samr_keydata_t *)hd->nh_data;
711fe1c642dSBill Krier 
712fe1c642dSBill Krier 	if (param->switch_value != SAMR_QUERY_USER_ALL_INFO) {
713fe1c642dSBill Krier 		status = NT_STATUS_ACCESS_DENIED;
714fe1c642dSBill Krier 		goto QueryUserInfoError;
715fe1c642dSBill Krier 	}
716fe1c642dSBill Krier 
717fe1c642dSBill Krier 	if (!smb_domain_lookup_type(SMB_DOMAIN_LOCAL, &di)) {
718fe1c642dSBill Krier 		status = NT_STATUS_ACCESS_DENIED;
719fe1c642dSBill Krier 		goto QueryUserInfoError;
720fe1c642dSBill Krier 	}
721fe1c642dSBill Krier 
722fe1c642dSBill Krier 	if ((sid = smb_sid_splice(di.di_binsid, data->kd_rid)) == NULL) {
723fe1c642dSBill Krier 		status = NT_STATUS_ACCESS_DENIED;
724fe1c642dSBill Krier 		goto QueryUserInfoError;
725fe1c642dSBill Krier 	}
726fe1c642dSBill Krier 
727fe1c642dSBill Krier 	if (smb_sam_lookup_sid(sid, &account) != NT_STATUS_SUCCESS) {
728fe1c642dSBill Krier 		status = NT_STATUS_ACCESS_DENIED;
729fe1c642dSBill Krier 		goto QueryUserInfoError;
730fe1c642dSBill Krier 	}
731fe1c642dSBill Krier 
732fe1c642dSBill Krier 	all_info = &param->ru.info21;
733fe1c642dSBill Krier 	bzero(all_info, sizeof (struct samr_QueryUserInfo21));
734fe1c642dSBill Krier 
735fe1c642dSBill Krier 	all_info->WhichFields = SAMR_USER_ALL_USERNAME | SAMR_USER_ALL_USERID;
736fe1c642dSBill Krier 
737fe1c642dSBill Krier 	(void) NDR_MSTRING(mxa, account.a_name,
738fe1c642dSBill Krier 	    (ndr_mstring_t *)&all_info->UserName);
739fe1c642dSBill Krier 	all_info->UserId = data->kd_rid;
740fe1c642dSBill Krier 
741fe1c642dSBill Krier 	all_info->LmOwfPassword.length = 16;
742fe1c642dSBill Krier 	all_info->LmOwfPassword.maxlen = 16;
743fe1c642dSBill Krier 	all_info->LmOwfPassword.buf = owf_buf;
744fe1c642dSBill Krier 	all_info->NtOwfPassword.length = 16;
745fe1c642dSBill Krier 	all_info->NtOwfPassword.maxlen = 16;
746fe1c642dSBill Krier 	all_info->NtOwfPassword.buf = owf_buf;
747fe1c642dSBill Krier 	all_info->LogonHours.units_per_week = SAMR_HOURS_PER_WEEK;
748fe1c642dSBill Krier 	all_info->LogonHours.hours = hour_buf;
749fe1c642dSBill Krier 
750fe1c642dSBill Krier 	param->address = 1;
751fe1c642dSBill Krier 	param->switch_index = SAMR_QUERY_USER_ALL_INFO;
752fe1c642dSBill Krier 	param->status = NT_STATUS_SUCCESS;
7539fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_account_free(&account);
7549fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_sid_free(sid);
755fe1c642dSBill Krier 	return (NDR_DRC_OK);
756fe1c642dSBill Krier 
757fe1c642dSBill Krier QueryUserInfoError:
7589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_sid_free(sid);
759fe1c642dSBill Krier 	bzero(param, sizeof (struct samr_QueryUserInfo));
760fe1c642dSBill Krier 	param->status = NT_SC_ERROR(status);
761fe1c642dSBill Krier 	return (NDR_DRC_OK);
762fe1c642dSBill Krier }
763fe1c642dSBill Krier 
764fe1c642dSBill Krier /*
765fe1c642dSBill Krier  * samr_s_QueryUserGroups
766fe1c642dSBill Krier  *
767fe1c642dSBill Krier  * Request the list of groups of which a user is a member.
768fe1c642dSBill Krier  * The user is identified from the handle, which contains an
769fe1c642dSBill Krier  * rid in the discriminator field. Note that this is a local user.
770fe1c642dSBill Krier  */
771fe1c642dSBill Krier static int
772fe1c642dSBill Krier samr_s_QueryUserGroups(void *arg, ndr_xa_t *mxa)
773fe1c642dSBill Krier {
774fe1c642dSBill Krier 	struct samr_QueryUserGroups *param = arg;
775fe1c642dSBill Krier 	struct samr_UserGroupInfo *info;
776fe1c642dSBill Krier 	struct samr_UserGroups *group;
777fe1c642dSBill Krier 	ndr_hdid_t *id = (ndr_hdid_t *)&param->user_handle;
778fe1c642dSBill Krier 	ndr_handle_t *hd;
779fe1c642dSBill Krier 	samr_keydata_t *data;
780fe1c642dSBill Krier 	smb_sid_t *user_sid = NULL;
781fe1c642dSBill Krier 	smb_group_t grp;
782fe1c642dSBill Krier 	smb_giter_t gi;
783fe1c642dSBill Krier 	smb_domain_t di;
784fe1c642dSBill Krier 	uint32_t status;
785fe1c642dSBill Krier 	int size;
786fe1c642dSBill Krier 	int ngrp_max;
787fe1c642dSBill Krier 
788fe1c642dSBill Krier 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_USER)) == NULL) {
789fe1c642dSBill Krier 		status = NT_STATUS_ACCESS_DENIED;
790fe1c642dSBill Krier 		goto query_error;
791fe1c642dSBill Krier 	}
792fe1c642dSBill Krier 
793fe1c642dSBill Krier 	data = (samr_keydata_t *)hd->nh_data;
794fe1c642dSBill Krier 	switch (data->kd_type) {
795fe1c642dSBill Krier 	case SMB_DOMAIN_BUILTIN:
796fe1c642dSBill Krier 	case SMB_DOMAIN_LOCAL:
797fe1c642dSBill Krier 		if (!smb_domain_lookup_type(data->kd_type, &di)) {
798fe1c642dSBill Krier 			status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
799fe1c642dSBill Krier 			goto query_error;
800fe1c642dSBill Krier 		}
801fe1c642dSBill Krier 		break;
802fe1c642dSBill Krier 	default:
803fe1c642dSBill Krier 		status = NT_STATUS_INVALID_HANDLE;
804fe1c642dSBill Krier 		goto query_error;
805fe1c642dSBill Krier 	}
806fe1c642dSBill Krier 
807fe1c642dSBill Krier 	user_sid = smb_sid_splice(di.di_binsid, data->kd_rid);
808fe1c642dSBill Krier 	if (user_sid == NULL) {
809fe1c642dSBill Krier 		status = NT_STATUS_NO_MEMORY;
810fe1c642dSBill Krier 		goto query_error;
811fe1c642dSBill Krier 	}
812fe1c642dSBill Krier 
813fe1c642dSBill Krier 	info = NDR_NEW(mxa, struct samr_UserGroupInfo);
814fe1c642dSBill Krier 	if (info == NULL) {
815fe1c642dSBill Krier 		status = NT_STATUS_NO_MEMORY;
816fe1c642dSBill Krier 		goto query_error;
817fe1c642dSBill Krier 	}
818fe1c642dSBill Krier 	bzero(info, sizeof (struct samr_UserGroupInfo));
819fe1c642dSBill Krier 
820fe1c642dSBill Krier 	size = 32 * 1024;
821fe1c642dSBill Krier 	info->groups = NDR_MALLOC(mxa, size);
822fe1c642dSBill Krier 	if (info->groups == NULL) {
823fe1c642dSBill Krier 		status = NT_STATUS_NO_MEMORY;
824fe1c642dSBill Krier 		goto query_error;
825fe1c642dSBill Krier 	}
826fe1c642dSBill Krier 	ngrp_max = size / sizeof (struct samr_UserGroups);
827fe1c642dSBill Krier 
828fe1c642dSBill Krier 	if (smb_lgrp_iteropen(&gi) != SMB_LGRP_SUCCESS) {
829fe1c642dSBill Krier 		status = NT_STATUS_INTERNAL_ERROR;
830fe1c642dSBill Krier 		goto query_error;
831fe1c642dSBill Krier 	}
832fe1c642dSBill Krier 
833fe1c642dSBill Krier 	info->n_entry = 0;
834fe1c642dSBill Krier 	group = info->groups;
835fe1c642dSBill Krier 	while ((info->n_entry < ngrp_max) &&
836fe1c642dSBill Krier 	    (smb_lgrp_iterate(&gi, &grp) == SMB_LGRP_SUCCESS)) {
837fe1c642dSBill Krier 		if (smb_lgrp_is_member(&grp, user_sid)) {
838fe1c642dSBill Krier 			group->rid = grp.sg_rid;
839fe1c642dSBill Krier 			group->attr = grp.sg_attr;
840fe1c642dSBill Krier 			group++;
841fe1c642dSBill Krier 			info->n_entry++;
842fe1c642dSBill Krier 		}
843fe1c642dSBill Krier 		smb_lgrp_free(&grp);
844fe1c642dSBill Krier 	}
845fe1c642dSBill Krier 	smb_lgrp_iterclose(&gi);
846fe1c642dSBill Krier 
847fe1c642dSBill Krier 	free(user_sid);
848fe1c642dSBill Krier 	param->info = info;
849fe1c642dSBill Krier 	param->status = NT_STATUS_SUCCESS;
850fe1c642dSBill Krier 	return (NDR_DRC_OK);
851fe1c642dSBill Krier 
852fe1c642dSBill Krier query_error:
853fe1c642dSBill Krier 	free(user_sid);
854fe1c642dSBill Krier 	bzero(param, sizeof (struct samr_QueryUserGroups));
855fe1c642dSBill Krier 	param->status = NT_SC_ERROR(status);
856fe1c642dSBill Krier 	return (NDR_DRC_OK);
857fe1c642dSBill Krier }
858fe1c642dSBill Krier 
859fe1c642dSBill Krier /*
860fe1c642dSBill Krier  * samr_s_OpenGroup
861fe1c642dSBill Krier  *
862fe1c642dSBill Krier  * This is a request to open a group within the specified domain in the
863fe1c642dSBill Krier  * local SAM database. The caller must supply a valid domain handle,
864fe1c642dSBill Krier  * obtained via a successful domain open request. The group is
865fe1c642dSBill Krier  * specified by the rid in the request. If this is a local RID it
866fe1c642dSBill Krier  * should already be encoded with type information.
867fe1c642dSBill Krier  *
868fe1c642dSBill Krier  * We return a handle to be used to access information about this group.
869fe1c642dSBill Krier  */
870fe1c642dSBill Krier static int
871fe1c642dSBill Krier samr_s_OpenGroup(void *arg, ndr_xa_t *mxa)
872fe1c642dSBill Krier {
873fe1c642dSBill Krier 	struct samr_OpenGroup *param = arg;
874fe1c642dSBill Krier 	ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
875fe1c642dSBill Krier 	ndr_handle_t *hd;
876fe1c642dSBill Krier 	samr_keydata_t *data;
877fe1c642dSBill Krier 
878fe1c642dSBill Krier 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
879fe1c642dSBill Krier 		bzero(&param->group_handle, sizeof (samr_handle_t));
880fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
881fe1c642dSBill Krier 		return (NDR_DRC_OK);
882fe1c642dSBill Krier 	}
883fe1c642dSBill Krier 
884fe1c642dSBill Krier 	data = (samr_keydata_t *)hd->nh_data;
885fe1c642dSBill Krier 	id = samr_hdalloc(mxa, SAMR_KEY_GROUP, data->kd_type, param->rid);
886fe1c642dSBill Krier 
887fe1c642dSBill Krier 	if (id) {
888fe1c642dSBill Krier 		bcopy(id, &param->group_handle, sizeof (samr_handle_t));
889fe1c642dSBill Krier 		param->status = 0;
890fe1c642dSBill Krier 	} else {
891fe1c642dSBill Krier 		bzero(&param->group_handle, sizeof (samr_handle_t));
892fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
893fe1c642dSBill Krier 	}
894fe1c642dSBill Krier 
895fe1c642dSBill Krier 	return (NDR_DRC_OK);
896fe1c642dSBill Krier }
897fe1c642dSBill Krier 
898fe1c642dSBill Krier /*
899c5866007SKeyur Desai  * samr_s_AddAliasMember
900c5866007SKeyur Desai  *
901c5866007SKeyur Desai  * Add a member to a local SAM group.
902c5866007SKeyur Desai  * The caller must supply a valid group handle.
903c5866007SKeyur Desai  * The member is specified by the sid in the request.
904c5866007SKeyur Desai  */
905c5866007SKeyur Desai static int
906c5866007SKeyur Desai samr_s_AddAliasMember(void *arg, ndr_xa_t *mxa)
907c5866007SKeyur Desai {
908c5866007SKeyur Desai 	struct samr_AddAliasMember *param = arg;
909c5866007SKeyur Desai 	ndr_hdid_t *id = (ndr_hdid_t *)&param->alias_handle;
910c5866007SKeyur Desai 	ndr_handle_t *hd;
911c5866007SKeyur Desai 	samr_keydata_t *data;
912c5866007SKeyur Desai 	smb_group_t grp;
913c5866007SKeyur Desai 	uint32_t rc;
914c5866007SKeyur Desai 	uint32_t status = NT_STATUS_SUCCESS;
915c5866007SKeyur Desai 
916c5866007SKeyur Desai 	if (param->sid == NULL) {
917c5866007SKeyur Desai 		bzero(param, sizeof (struct samr_AddAliasMember));
918c5866007SKeyur Desai 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER);
919c5866007SKeyur Desai 		return (NDR_DRC_OK);
920c5866007SKeyur Desai 	}
921c5866007SKeyur Desai 
922c5866007SKeyur Desai 	if (!ndr_is_admin(mxa)) {
923c5866007SKeyur Desai 		bzero(param, sizeof (struct samr_AddAliasMember));
924c5866007SKeyur Desai 		param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
925c5866007SKeyur Desai 		return (NDR_DRC_OK);
926c5866007SKeyur Desai 	}
927c5866007SKeyur Desai 
928c5866007SKeyur Desai 
929c5866007SKeyur Desai 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_ALIAS)) == NULL) {
930c5866007SKeyur Desai 		bzero(param, sizeof (struct samr_AddAliasMember));
931c5866007SKeyur Desai 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
932c5866007SKeyur Desai 		return (NDR_DRC_OK);
933c5866007SKeyur Desai 	}
934c5866007SKeyur Desai 
935c5866007SKeyur Desai 	data = (samr_keydata_t *)hd->nh_data;
936c5866007SKeyur Desai 	rc = smb_lgrp_getbyrid(data->kd_rid, data->kd_type, &grp);
937c5866007SKeyur Desai 	if (rc != SMB_LGRP_SUCCESS) {
938c5866007SKeyur Desai 		bzero(param, sizeof (struct samr_AddAliasMember));
939c5866007SKeyur Desai 		status = smb_lgrp_err_to_ntstatus(rc);
940c5866007SKeyur Desai 		param->status = NT_SC_ERROR(status);
941c5866007SKeyur Desai 		return (NDR_DRC_OK);
942c5866007SKeyur Desai 	}
943c5866007SKeyur Desai 
944c5866007SKeyur Desai 	rc = smb_lgrp_add_member(grp.sg_name,
945c5866007SKeyur Desai 	    (smb_sid_t *)param->sid, SidTypeUser);
946c5866007SKeyur Desai 	if (rc != SMB_LGRP_SUCCESS) {
947c5866007SKeyur Desai 		bzero(param, sizeof (struct samr_AddAliasMember));
948c5866007SKeyur Desai 		status = smb_lgrp_err_to_ntstatus(rc);
949c5866007SKeyur Desai 		param->status = NT_SC_ERROR(status);
950c5866007SKeyur Desai 	}
951c5866007SKeyur Desai 	smb_lgrp_free(&grp);
952c5866007SKeyur Desai 
953c5866007SKeyur Desai 	param->status = status;
954c5866007SKeyur Desai 	return (NDR_DRC_OK);
955c5866007SKeyur Desai }
956c5866007SKeyur Desai 
957c5866007SKeyur Desai /*
958c5866007SKeyur Desai  * samr_s_DeleteAliasMember
959c5866007SKeyur Desai  *
960c5866007SKeyur Desai  * Delete a member from a local SAM group.
961c5866007SKeyur Desai  * The caller must supply a valid group handle.
962c5866007SKeyur Desai  * The member is specified by the sid in the request.
963c5866007SKeyur Desai  */
964c5866007SKeyur Desai static int
965c5866007SKeyur Desai samr_s_DeleteAliasMember(void *arg, ndr_xa_t *mxa)
966c5866007SKeyur Desai {
967c5866007SKeyur Desai 	struct samr_DeleteAliasMember *param = arg;
968c5866007SKeyur Desai 	ndr_hdid_t *id = (ndr_hdid_t *)&param->alias_handle;
969c5866007SKeyur Desai 	ndr_handle_t *hd;
970c5866007SKeyur Desai 	samr_keydata_t *data;
971c5866007SKeyur Desai 	smb_group_t grp;
972c5866007SKeyur Desai 	uint32_t rc;
973c5866007SKeyur Desai 	uint32_t status = NT_STATUS_SUCCESS;
974c5866007SKeyur Desai 
975c5866007SKeyur Desai 	if (param->sid == NULL) {
976c5866007SKeyur Desai 		bzero(param, sizeof (struct samr_DeleteAliasMember));
977c5866007SKeyur Desai 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER);
978c5866007SKeyur Desai 		return (NDR_DRC_OK);
979c5866007SKeyur Desai 	}
980c5866007SKeyur Desai 
981c5866007SKeyur Desai 	if (!ndr_is_admin(mxa)) {
982c5866007SKeyur Desai 		bzero(param, sizeof (struct samr_DeleteAliasMember));
983c5866007SKeyur Desai 		param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
984c5866007SKeyur Desai 		return (NDR_DRC_OK);
985c5866007SKeyur Desai 	}
986c5866007SKeyur Desai 
987c5866007SKeyur Desai 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_ALIAS)) == NULL) {
988c5866007SKeyur Desai 		bzero(param, sizeof (struct samr_DeleteAliasMember));
989c5866007SKeyur Desai 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
990c5866007SKeyur Desai 		return (NDR_DRC_OK);
991c5866007SKeyur Desai 	}
992c5866007SKeyur Desai 
993c5866007SKeyur Desai 	data = (samr_keydata_t *)hd->nh_data;
994c5866007SKeyur Desai 	rc = smb_lgrp_getbyrid(data->kd_rid, data->kd_type, &grp);
995c5866007SKeyur Desai 	if (rc != SMB_LGRP_SUCCESS) {
996c5866007SKeyur Desai 		bzero(param, sizeof (struct samr_DeleteAliasMember));
997c5866007SKeyur Desai 		status = smb_lgrp_err_to_ntstatus(rc);
998c5866007SKeyur Desai 		param->status = NT_SC_ERROR(status);
999c5866007SKeyur Desai 		return (NDR_DRC_OK);
1000c5866007SKeyur Desai 	}
1001c5866007SKeyur Desai 
1002c5866007SKeyur Desai 	rc = smb_lgrp_del_member(grp.sg_name,
1003c5866007SKeyur Desai 	    (smb_sid_t *)param->sid, SidTypeUser);
1004c5866007SKeyur Desai 	if (rc != SMB_LGRP_SUCCESS) {
1005c5866007SKeyur Desai 		bzero(param, sizeof (struct samr_DeleteAliasMember));
1006c5866007SKeyur Desai 		status = smb_lgrp_err_to_ntstatus(rc);
1007c5866007SKeyur Desai 		param->status = NT_SC_ERROR(status);
1008c5866007SKeyur Desai 	}
1009c5866007SKeyur Desai 	smb_lgrp_free(&grp);
1010c5866007SKeyur Desai 
1011c5866007SKeyur Desai 	param->status = status;
1012c5866007SKeyur Desai 	return (NDR_DRC_OK);
1013c5866007SKeyur Desai }
1014c5866007SKeyur Desai 
1015c5866007SKeyur Desai /*
1016c5866007SKeyur Desai  * samr_s_ListAliasMembers
1017c5866007SKeyur Desai  *
1018c5866007SKeyur Desai  * List members from a local SAM group.
1019c5866007SKeyur Desai  * The caller must supply a valid group handle.
1020c5866007SKeyur Desai  * A list of user SIDs in the specified group is returned to the caller.
1021c5866007SKeyur Desai  */
1022c5866007SKeyur Desai static int
1023c5866007SKeyur Desai samr_s_ListAliasMembers(void *arg, ndr_xa_t *mxa)
1024c5866007SKeyur Desai {
1025c5866007SKeyur Desai 	struct samr_ListAliasMembers *param = arg;
1026c5866007SKeyur Desai 	ndr_hdid_t *id = (ndr_hdid_t *)&param->alias_handle;
1027c5866007SKeyur Desai 	ndr_handle_t *hd;
1028c5866007SKeyur Desai 	samr_keydata_t *data;
1029c5866007SKeyur Desai 	smb_group_t grp;
1030c5866007SKeyur Desai 	smb_gsid_t *members;
1031c5866007SKeyur Desai 	struct samr_SidInfo info;
1032c5866007SKeyur Desai 	struct samr_SidList *user;
1033c5866007SKeyur Desai 	uint32_t num = 0, size;
1034c5866007SKeyur Desai 	int i;
1035c5866007SKeyur Desai 	uint32_t rc;
1036c5866007SKeyur Desai 	uint32_t status = NT_STATUS_SUCCESS;
1037c5866007SKeyur Desai 
1038c5866007SKeyur Desai 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_ALIAS)) == NULL) {
1039c5866007SKeyur Desai 		bzero(param, sizeof (struct samr_ListAliasMembers));
1040c5866007SKeyur Desai 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
1041c5866007SKeyur Desai 		return (NDR_DRC_OK);
1042c5866007SKeyur Desai 	}
1043c5866007SKeyur Desai 
1044c5866007SKeyur Desai 	bzero(&info, sizeof (struct samr_SidInfo));
1045c5866007SKeyur Desai 	data = (samr_keydata_t *)hd->nh_data;
1046c5866007SKeyur Desai 	rc = smb_lgrp_getbyrid(data->kd_rid, data->kd_type, &grp);
1047c5866007SKeyur Desai 	if (rc != SMB_LGRP_SUCCESS) {
1048c5866007SKeyur Desai 		bzero(param, sizeof (struct samr_ListAliasMembers));
1049c5866007SKeyur Desai 		status = smb_lgrp_err_to_ntstatus(rc);
1050c5866007SKeyur Desai 		param->status = NT_SC_ERROR(status);
1051c5866007SKeyur Desai 		return (NDR_DRC_OK);
1052c5866007SKeyur Desai 	}
1053c5866007SKeyur Desai 
1054c5866007SKeyur Desai 	num = grp.sg_nmembers;
1055c5866007SKeyur Desai 	members = grp.sg_members;
1056c5866007SKeyur Desai 	size = num * sizeof (struct samr_SidList);
1057c5866007SKeyur Desai 	info.sidlist = NDR_MALLOC(mxa, size);
1058c5866007SKeyur Desai 	if (info.sidlist == NULL) {
1059c5866007SKeyur Desai 		bzero(param, sizeof (struct samr_ListAliasMembers));
1060c5866007SKeyur Desai 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1061c5866007SKeyur Desai 		smb_lgrp_free(&grp);
1062c5866007SKeyur Desai 		return (NDR_DRC_OK);
1063c5866007SKeyur Desai 	}
1064c5866007SKeyur Desai 
1065c5866007SKeyur Desai 	info.n_entry = num;
1066c5866007SKeyur Desai 	user = info.sidlist;
1067c5866007SKeyur Desai 	for (i = 0; i < num; i++) {
1068c5866007SKeyur Desai 		user->sid = (struct samr_sid *)NDR_SIDDUP(mxa,
1069c5866007SKeyur Desai 		    members[i].gs_sid);
1070c5866007SKeyur Desai 		if (user->sid == NULL) {
1071c5866007SKeyur Desai 			bzero(param, sizeof (struct samr_ListAliasMembers));
1072c5866007SKeyur Desai 			param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1073c5866007SKeyur Desai 			smb_lgrp_free(&grp);
1074c5866007SKeyur Desai 			return (NDR_DRC_OK);
1075c5866007SKeyur Desai 		}
1076c5866007SKeyur Desai 		user++;
1077c5866007SKeyur Desai 	}
1078c5866007SKeyur Desai 	smb_lgrp_free(&grp);
1079c5866007SKeyur Desai 
1080c5866007SKeyur Desai 	param->info = info;
1081c5866007SKeyur Desai 	param->status = status;
1082c5866007SKeyur Desai 	return (NDR_DRC_OK);
1083c5866007SKeyur Desai }
1084c5866007SKeyur Desai 
1085c5866007SKeyur Desai /*
1086cb174861Sjoyce mcintosh  * samr_s_Connect2
1087fe1c642dSBill Krier  *
1088fe1c642dSBill Krier  * This is a request to connect to the local SAM database.
1089fe1c642dSBill Krier  * We don't support any form of update request and our database doesn't
1090fe1c642dSBill Krier  * contain any private information, so there is little point in doing
1091fe1c642dSBill Krier  * any access access checking here.
1092fe1c642dSBill Krier  *
1093fe1c642dSBill Krier  * Return a handle for use with subsequent SAM requests.
1094fe1c642dSBill Krier  */
1095fe1c642dSBill Krier static int
1096cb174861Sjoyce mcintosh samr_s_Connect2(void *arg, ndr_xa_t *mxa)
1097fe1c642dSBill Krier {
1098cb174861Sjoyce mcintosh 	struct samr_Connect2 *param = arg;
1099fe1c642dSBill Krier 	ndr_hdid_t *id;
1100fe1c642dSBill Krier 
1101fe1c642dSBill Krier 	id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, SMB_DOMAIN_NULL, 0);
1102fe1c642dSBill Krier 	if (id) {
1103fe1c642dSBill Krier 		bcopy(id, &param->handle, sizeof (samr_handle_t));
1104fe1c642dSBill Krier 		param->status = 0;
1105fe1c642dSBill Krier 	} else {
1106fe1c642dSBill Krier 		bzero(&param->handle, sizeof (samr_handle_t));
1107fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1108fe1c642dSBill Krier 	}
1109fe1c642dSBill Krier 
1110fe1c642dSBill Krier 	return (NDR_DRC_OK);
1111fe1c642dSBill Krier }
1112fe1c642dSBill Krier 
1113fe1c642dSBill Krier /*
1114fe1c642dSBill Krier  * samr_s_GetUserPwInfo
1115fe1c642dSBill Krier  *
1116f96bd5c8SAlan Wright  * Request for a user's password policy information.
1117fe1c642dSBill Krier  */
1118fe1c642dSBill Krier /*ARGSUSED*/
1119fe1c642dSBill Krier static int
1120fe1c642dSBill Krier samr_s_GetUserPwInfo(void *arg, ndr_xa_t *mxa)
1121fe1c642dSBill Krier {
1122f96bd5c8SAlan Wright 	static samr_password_info_t	pwinfo;
1123fe1c642dSBill Krier 	struct samr_GetUserPwInfo	*param = arg;
1124fe1c642dSBill Krier 
1125f96bd5c8SAlan Wright 	param->pwinfo = &pwinfo;
1126f96bd5c8SAlan Wright 	param->status = NT_STATUS_SUCCESS;
1127fe1c642dSBill Krier 	return (NDR_DRC_OK);
1128fe1c642dSBill Krier }
1129fe1c642dSBill Krier 
1130fe1c642dSBill Krier /*
1131fe1c642dSBill Krier  * samr_s_CreateUser
1132fe1c642dSBill Krier  */
1133fe1c642dSBill Krier /*ARGSUSED*/
1134fe1c642dSBill Krier static int
1135fe1c642dSBill Krier samr_s_CreateUser(void *arg, ndr_xa_t *mxa)
1136fe1c642dSBill Krier {
1137fe1c642dSBill Krier 	struct samr_CreateUser *param = arg;
1138fe1c642dSBill Krier 
1139fe1c642dSBill Krier 	bzero(&param->user_handle, sizeof (samr_handle_t));
1140fe1c642dSBill Krier 	param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
1141fe1c642dSBill Krier 	return (NDR_DRC_OK);
1142fe1c642dSBill Krier }
1143fe1c642dSBill Krier 
1144fe1c642dSBill Krier /*
11451ed6b69aSGordon Ross  * samr_s_ChangePasswordUser2
1146fe1c642dSBill Krier  */
1147fe1c642dSBill Krier /*ARGSUSED*/
1148fe1c642dSBill Krier static int
11491ed6b69aSGordon Ross samr_s_ChangePasswordUser2(void *arg, ndr_xa_t *mxa)
1150fe1c642dSBill Krier {
11511ed6b69aSGordon Ross 	struct samr_ChangePasswordUser2 *param = arg;
1152fe1c642dSBill Krier 
11531ed6b69aSGordon Ross 	bzero(param, sizeof (*param));
1154fe1c642dSBill Krier 	param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
1155fe1c642dSBill Krier 	return (NDR_DRC_OK);
1156fe1c642dSBill Krier }
1157fe1c642dSBill Krier 
1158fe1c642dSBill Krier /*
1159fe1c642dSBill Krier  * samr_s_GetDomainPwInfo
1160f96bd5c8SAlan Wright  *
1161f96bd5c8SAlan Wright  * Request for the domain password policy information.
1162fe1c642dSBill Krier  */
1163fe1c642dSBill Krier /*ARGSUSED*/
1164fe1c642dSBill Krier static int
1165fe1c642dSBill Krier samr_s_GetDomainPwInfo(void *arg, ndr_xa_t *mxa)
1166fe1c642dSBill Krier {
1167f96bd5c8SAlan Wright 	static samr_password_info_t	pwinfo;
1168fe1c642dSBill Krier 	struct samr_GetDomainPwInfo	*param = arg;
1169fe1c642dSBill Krier 
1170f96bd5c8SAlan Wright 	param->pwinfo = &pwinfo;
1171f96bd5c8SAlan Wright 	param->status = NT_STATUS_SUCCESS;
1172fe1c642dSBill Krier 	return (NDR_DRC_OK);
1173fe1c642dSBill Krier }
1174fe1c642dSBill Krier 
1175fe1c642dSBill Krier /*
1176fe1c642dSBill Krier  * samr_s_SetUserInfo
1177fe1c642dSBill Krier  */
1178fe1c642dSBill Krier /*ARGSUSED*/
1179fe1c642dSBill Krier static int
1180fe1c642dSBill Krier samr_s_SetUserInfo(void *arg, ndr_xa_t *mxa)
1181fe1c642dSBill Krier {
1182fe1c642dSBill Krier 	struct samr_SetUserInfo *param = arg;
1183fe1c642dSBill Krier 
1184fe1c642dSBill Krier 	bzero(param, sizeof (struct samr_SetUserInfo));
1185fe1c642dSBill Krier 	param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
1186fe1c642dSBill Krier 	return (NDR_DRC_OK);
1187fe1c642dSBill Krier }
1188fe1c642dSBill Krier 
1189fe1c642dSBill Krier /*
1190fe1c642dSBill Krier  * samr_s_QueryDispInfo
1191fe1c642dSBill Krier  *
1192fe1c642dSBill Krier  * This function currently return local users' information only.
1193fe1c642dSBill Krier  * This RPC is called repeatedly until all the users info are
1194fe1c642dSBill Krier  * retrieved.
1195fe1c642dSBill Krier  *
1196fe1c642dSBill Krier  * The total count and the returned count are returned as total size
1197fe1c642dSBill Krier  * and returned size.  The client doesn't seem to care.
1198fe1c642dSBill Krier  */
1199fe1c642dSBill Krier static int
1200fe1c642dSBill Krier samr_s_QueryDispInfo(void *arg, ndr_xa_t *mxa)
1201fe1c642dSBill Krier {
1202fe1c642dSBill Krier 	struct samr_QueryDispInfo *param = arg;
1203fe1c642dSBill Krier 	ndr_hdid_t *id = (ndr_hdid_t *)&param->domain_handle;
1204fe1c642dSBill Krier 	ndr_handle_t *hd;
1205fe1c642dSBill Krier 	samr_keydata_t *data;
1206fe1c642dSBill Krier 	DWORD status = NT_STATUS_SUCCESS;
1207fe1c642dSBill Krier 	struct user_acct_info *user;
1208fe1c642dSBill Krier 	smb_pwditer_t pwi;
1209fe1c642dSBill Krier 	smb_luser_t *uinfo;
1210fe1c642dSBill Krier 	int num_users;
1211fe1c642dSBill Krier 	int start_idx;
1212fe1c642dSBill Krier 	int max_retcnt, retcnt;
1213fe1c642dSBill Krier 	int skip;
1214fe1c642dSBill Krier 
1215fe1c642dSBill Krier 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
1216fe1c642dSBill Krier 		status = NT_STATUS_INVALID_HANDLE;
1217fe1c642dSBill Krier 		goto error;
1218fe1c642dSBill Krier 	}
1219fe1c642dSBill Krier 
1220fe1c642dSBill Krier 	if (!SAMR_VALID_DISPLEVEL(param->level)) {
1221fe1c642dSBill Krier 		status = NT_STATUS_INVALID_INFO_CLASS;
1222fe1c642dSBill Krier 		goto error;
1223fe1c642dSBill Krier 	}
1224fe1c642dSBill Krier 
1225fe1c642dSBill Krier 	if (!SAMR_SUPPORTED_DISPLEVEL(param->level)) {
1226fe1c642dSBill Krier 		status = NT_STATUS_NOT_IMPLEMENTED;
1227fe1c642dSBill Krier 		goto error;
1228fe1c642dSBill Krier 	}
1229fe1c642dSBill Krier 
1230fe1c642dSBill Krier 	data = (samr_keydata_t *)hd->nh_data;
1231fe1c642dSBill Krier 
1232fe1c642dSBill Krier 	switch (data->kd_type) {
1233fe1c642dSBill Krier 	case SMB_DOMAIN_BUILTIN:
1234fe1c642dSBill Krier 		goto no_info;
1235fe1c642dSBill Krier 
1236fe1c642dSBill Krier 	case SMB_DOMAIN_LOCAL:
1237fe1c642dSBill Krier 		num_users = smb_sam_usr_cnt();
1238fe1c642dSBill Krier 		start_idx = param->start_idx;
1239fe1c642dSBill Krier 		if ((num_users == 0) || (start_idx >= num_users))
1240fe1c642dSBill Krier 			goto no_info;
1241fe1c642dSBill Krier 
1242fe1c642dSBill Krier 		max_retcnt = num_users - start_idx;
1243fe1c642dSBill Krier 		if (max_retcnt > param->max_entries)
1244fe1c642dSBill Krier 			max_retcnt = param->max_entries;
1245fe1c642dSBill Krier 		param->users.acct = NDR_MALLOC(mxa,
1246fe1c642dSBill Krier 		    max_retcnt * sizeof (struct user_acct_info));
1247fe1c642dSBill Krier 		user = param->users.acct;
1248fe1c642dSBill Krier 		if (user == NULL) {
1249fe1c642dSBill Krier 			status = NT_STATUS_NO_MEMORY;
1250fe1c642dSBill Krier 			goto error;
1251fe1c642dSBill Krier 		}
1252fe1c642dSBill Krier 		bzero(user, max_retcnt * sizeof (struct user_acct_info));
1253fe1c642dSBill Krier 
1254fe1c642dSBill Krier 		if (smb_pwd_iteropen(&pwi) != SMB_PWE_SUCCESS)
1255fe1c642dSBill Krier 			goto no_info;
1256fe1c642dSBill Krier 
1257fe1c642dSBill Krier 		skip = retcnt = 0;
1258fe1c642dSBill Krier 		while ((uinfo = smb_pwd_iterate(&pwi)) != NULL) {
1259fe1c642dSBill Krier 			if (skip++ < start_idx)
1260fe1c642dSBill Krier 				continue;
1261fe1c642dSBill Krier 
1262fe1c642dSBill Krier 			if (retcnt++ >= max_retcnt)
1263fe1c642dSBill Krier 				break;
1264fe1c642dSBill Krier 
1265fe1c642dSBill Krier 			assert(uinfo->su_name != NULL);
1266fe1c642dSBill Krier 
1267fe1c642dSBill Krier 			user->index = start_idx + retcnt;
1268fe1c642dSBill Krier 			user->rid = uinfo->su_rid;
1269fe1c642dSBill Krier 			user->ctrl = ACF_NORMUSER | ACF_PWDNOEXP;
1270fe1c642dSBill Krier 			if (uinfo->su_ctrl & SMB_PWF_DISABLE)
1271fe1c642dSBill Krier 				user->ctrl |= ACF_DISABLED;
1272fe1c642dSBill Krier 			if (NDR_MSTRING(mxa, uinfo->su_name,
1273fe1c642dSBill Krier 			    (ndr_mstring_t *)&user->name) == -1) {
1274fe1c642dSBill Krier 				smb_pwd_iterclose(&pwi);
1275fe1c642dSBill Krier 				status = NT_STATUS_NO_MEMORY;
1276fe1c642dSBill Krier 				goto error;
1277fe1c642dSBill Krier 			}
1278fe1c642dSBill Krier 			(void) NDR_MSTRING(mxa, uinfo->su_fullname,
1279fe1c642dSBill Krier 			    (ndr_mstring_t *)&user->fullname);
1280fe1c642dSBill Krier 			(void) NDR_MSTRING(mxa, uinfo->su_desc,
1281fe1c642dSBill Krier 			    (ndr_mstring_t *)&user->desc);
1282fe1c642dSBill Krier 			user++;
1283fe1c642dSBill Krier 		}
1284fe1c642dSBill Krier 		smb_pwd_iterclose(&pwi);
1285fe1c642dSBill Krier 
1286fe1c642dSBill Krier 		if (retcnt >= max_retcnt) {
1287fe1c642dSBill Krier 			retcnt = max_retcnt;
1288fe1c642dSBill Krier 			param->status = status;
1289fe1c642dSBill Krier 		} else {
1290148c5f43SAlan Wright 			param->status = NT_STATUS_MORE_ENTRIES;
1291fe1c642dSBill Krier 		}
1292fe1c642dSBill Krier 
1293fe1c642dSBill Krier 		param->users.total_size = num_users;
1294fe1c642dSBill Krier 		param->users.returned_size = retcnt;
1295fe1c642dSBill Krier 		param->users.switch_value = param->level;
1296fe1c642dSBill Krier 		param->users.count = retcnt;
1297fe1c642dSBill Krier 
1298fe1c642dSBill Krier 		break;
1299fe1c642dSBill Krier 
1300fe1c642dSBill Krier 	default:
1301fe1c642dSBill Krier 		status = NT_STATUS_INVALID_HANDLE;
1302fe1c642dSBill Krier 		goto error;
1303fe1c642dSBill Krier 	}
1304fe1c642dSBill Krier 
1305fe1c642dSBill Krier 	return (NDR_DRC_OK);
1306fe1c642dSBill Krier 
1307fe1c642dSBill Krier no_info:
1308fe1c642dSBill Krier 	param->users.total_size = 0;
1309fe1c642dSBill Krier 	param->users.returned_size = 0;
1310fe1c642dSBill Krier 	param->users.switch_value = param->level;
1311fe1c642dSBill Krier 	param->users.count = 0;
1312fe1c642dSBill Krier 	param->users.acct = NULL;
1313fe1c642dSBill Krier 	param->status = status;
1314fe1c642dSBill Krier 	return (NDR_DRC_OK);
1315fe1c642dSBill Krier 
1316fe1c642dSBill Krier error:
1317fe1c642dSBill Krier 	bzero(param, sizeof (struct samr_QueryDispInfo));
1318fe1c642dSBill Krier 	param->status = NT_SC_ERROR(status);
1319fe1c642dSBill Krier 	return (NDR_DRC_OK);
1320fe1c642dSBill Krier }
1321fe1c642dSBill Krier 
1322fe1c642dSBill Krier /*
1323fe1c642dSBill Krier  * samr_s_EnumDomainGroups
1324fe1c642dSBill Krier  *
1325fe1c642dSBill Krier  *
1326fe1c642dSBill Krier  * This function is supposed to return local group information.
1327fe1c642dSBill Krier  * As we don't support local users, this function dosen't send
1328fe1c642dSBill Krier  * back any information.
1329fe1c642dSBill Krier  *
1330fe1c642dSBill Krier  * Added template that returns information for a domain group as None.
1331fe1c642dSBill Krier  * All information is hard-coded from packet captures.
1332fe1c642dSBill Krier  */
1333fe1c642dSBill Krier static int
1334fe1c642dSBill Krier samr_s_EnumDomainGroups(void *arg, ndr_xa_t *mxa)
1335fe1c642dSBill Krier {
1336fe1c642dSBill Krier 	struct samr_EnumDomainGroups *param = arg;
1337fe1c642dSBill Krier 	ndr_hdid_t *id = (ndr_hdid_t *)&param->domain_handle;
1338fe1c642dSBill Krier 	DWORD status = NT_STATUS_SUCCESS;
1339fe1c642dSBill Krier 
1340fe1c642dSBill Krier 	if (samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN) == NULL)
1341fe1c642dSBill Krier 		status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
1342fe1c642dSBill Krier 
1343fe1c642dSBill Krier 	param->total_size = 0;
1344fe1c642dSBill Krier 	param->returned_size = 0;
1345fe1c642dSBill Krier 	param->switch_value = 3;
1346fe1c642dSBill Krier 	param->count = 0;
1347fe1c642dSBill Krier 	param->groups = 0;
1348fe1c642dSBill Krier 	param->status = status;
1349fe1c642dSBill Krier 	return (NDR_DRC_OK);
1350fe1c642dSBill Krier 
1351fe1c642dSBill Krier #ifdef SAMR_SUPPORT_GROUPS
1352fe1c642dSBill Krier 	if ((desc->discrim != SAMR_LOCAL_DOMAIN) || (param->start_idx != 0)) {
1353fe1c642dSBill Krier 		param->total_size = 0;
1354fe1c642dSBill Krier 		param->returned_size = 0;
1355fe1c642dSBill Krier 		param->switch_value = 3;
1356fe1c642dSBill Krier 		param->count = 0;
1357fe1c642dSBill Krier 		param->groups = 0;
1358fe1c642dSBill Krier 	} else {
1359fe1c642dSBill Krier 		param->total_size = 64;
1360fe1c642dSBill Krier 		param->returned_size = 64;
1361fe1c642dSBill Krier 		param->switch_value = 3;
1362fe1c642dSBill Krier 		param->count = 1;
1363fe1c642dSBill Krier 		param->groups = (struct group_disp_info *)NDR_MALLOC(
1364fe1c642dSBill Krier 		    mxa, sizeof (struct group_disp_info));
1365fe1c642dSBill Krier 
1366fe1c642dSBill Krier 		param->groups->count = 1;
1367fe1c642dSBill Krier 		param->groups->acct[0].index = 1;
1368fe1c642dSBill Krier 		param->groups->acct[0].rid = 513;
1369fe1c642dSBill Krier 		param->groups->acct[0].ctrl = 0x7;
1370fe1c642dSBill Krier 		(void) NDR_MSTRING(mxa, "None",
1371fe1c642dSBill Krier 		    (ndr_mstring_t *)&param->groups->acct[0].name);
1372fe1c642dSBill Krier 
1373fe1c642dSBill Krier 		(void) NDR_MSTRING(mxa, "Ordinary users",
1374fe1c642dSBill Krier 		    (ndr_mstring_t *)&param->groups->acct[0].desc);
1375fe1c642dSBill Krier 	}
1376fe1c642dSBill Krier 
1377fe1c642dSBill Krier 	param->status = NT_STATUS_SUCCESS;
1378fe1c642dSBill Krier 	return (NDR_DRC_OK);
1379fe1c642dSBill Krier #endif
1380fe1c642dSBill Krier }
1381fe1c642dSBill Krier 
1382fe1c642dSBill Krier /*
1383fe1c642dSBill Krier  * samr_s_OpenAlias
1384fe1c642dSBill Krier  *
1385fe1c642dSBill Krier  * Lookup for requested alias, if it exists return a handle
1386fe1c642dSBill Krier  * for that alias. The alias domain sid should match with
1387fe1c642dSBill Krier  * the passed domain handle.
1388fe1c642dSBill Krier  */
1389fe1c642dSBill Krier static int
1390fe1c642dSBill Krier samr_s_OpenAlias(void *arg, ndr_xa_t *mxa)
1391fe1c642dSBill Krier {
1392fe1c642dSBill Krier 	struct samr_OpenAlias *param = arg;
1393fe1c642dSBill Krier 	ndr_hdid_t	*id = (ndr_hdid_t *)&param->domain_handle;
1394fe1c642dSBill Krier 	ndr_handle_t	*hd;
1395fe1c642dSBill Krier 	samr_keydata_t	*data;
13969fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_domain_type_t gd_type;
1397f96bd5c8SAlan Wright 	smb_sid_t	*sid;
1398f96bd5c8SAlan Wright 	smb_wka_t	*wka;
1399f96bd5c8SAlan Wright 	char		sidstr[SMB_SID_STRSZ];
1400f96bd5c8SAlan Wright 	uint32_t	rid;
1401f96bd5c8SAlan Wright 	uint32_t	status;
1402fe1c642dSBill Krier 	int		rc;
1403fe1c642dSBill Krier 
1404fe1c642dSBill Krier 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
1405fe1c642dSBill Krier 		status = NT_STATUS_INVALID_HANDLE;
1406fe1c642dSBill Krier 		goto open_alias_err;
1407fe1c642dSBill Krier 	}
1408fe1c642dSBill Krier 
1409c5866007SKeyur Desai 	if ((param->access_mask & SAMR_ALIAS_ACCESS_ALL_ACCESS) == 0) {
1410fe1c642dSBill Krier 		status = NT_STATUS_ACCESS_DENIED;
1411fe1c642dSBill Krier 		goto open_alias_err;
1412fe1c642dSBill Krier 	}
1413fe1c642dSBill Krier 
1414fe1c642dSBill Krier 	data = (samr_keydata_t *)hd->nh_data;
14159fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	gd_type = (smb_domain_type_t)data->kd_type;
1416f96bd5c8SAlan Wright 	rid = param->rid;
1417f96bd5c8SAlan Wright 
1418f96bd5c8SAlan Wright 	switch (gd_type) {
14199fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	case SMB_DOMAIN_BUILTIN:
1420f96bd5c8SAlan Wright 		(void) snprintf(sidstr, SMB_SID_STRSZ, "%s-%d",
1421f96bd5c8SAlan Wright 		    NT_BUILTIN_DOMAIN_SIDSTR, rid);
1422f96bd5c8SAlan Wright 		if ((sid = smb_sid_fromstr(sidstr)) == NULL) {
1423f96bd5c8SAlan Wright 			status = NT_STATUS_NO_SUCH_ALIAS;
1424f96bd5c8SAlan Wright 			goto open_alias_err;
1425f96bd5c8SAlan Wright 		}
1426f96bd5c8SAlan Wright 
1427f96bd5c8SAlan Wright 		wka = smb_wka_lookup_sid(sid);
1428f96bd5c8SAlan Wright 		smb_sid_free(sid);
1429f96bd5c8SAlan Wright 
1430f96bd5c8SAlan Wright 		if (wka == NULL) {
1431f96bd5c8SAlan Wright 			status = NT_STATUS_NO_SUCH_ALIAS;
1432f96bd5c8SAlan Wright 			goto open_alias_err;
1433f96bd5c8SAlan Wright 		}
1434f96bd5c8SAlan Wright 		break;
1435f96bd5c8SAlan Wright 
14369fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	case SMB_DOMAIN_LOCAL:
1437f96bd5c8SAlan Wright 		rc = smb_lgrp_getbyrid(rid, gd_type, NULL);
1438fe1c642dSBill Krier 		if (rc != SMB_LGRP_SUCCESS) {
1439fe1c642dSBill Krier 			status = NT_STATUS_NO_SUCH_ALIAS;
1440fe1c642dSBill Krier 			goto open_alias_err;
1441fe1c642dSBill Krier 		}
1442f96bd5c8SAlan Wright 		break;
1443f96bd5c8SAlan Wright 
1444f96bd5c8SAlan Wright 	default:
1445f96bd5c8SAlan Wright 		status = NT_STATUS_NO_SUCH_ALIAS;
1446f96bd5c8SAlan Wright 		goto open_alias_err;
1447f96bd5c8SAlan Wright 	}
1448fe1c642dSBill Krier 
1449fe1c642dSBill Krier 	id = samr_hdalloc(mxa, SAMR_KEY_ALIAS, data->kd_type, param->rid);
1450fe1c642dSBill Krier 	if (id) {
1451fe1c642dSBill Krier 		bcopy(id, &param->alias_handle, sizeof (samr_handle_t));
1452fe1c642dSBill Krier 		param->status = NT_STATUS_SUCCESS;
1453fe1c642dSBill Krier 		return (NDR_DRC_OK);
1454fe1c642dSBill Krier 	}
1455fe1c642dSBill Krier 
1456fe1c642dSBill Krier 	status = NT_STATUS_NO_MEMORY;
1457fe1c642dSBill Krier 
1458fe1c642dSBill Krier open_alias_err:
1459fe1c642dSBill Krier 	bzero(&param->alias_handle, sizeof (samr_handle_t));
1460fe1c642dSBill Krier 	param->status = NT_SC_ERROR(status);
1461fe1c642dSBill Krier 	return (NDR_DRC_OK);
1462fe1c642dSBill Krier }
1463fe1c642dSBill Krier 
1464fe1c642dSBill Krier /*
1465fe1c642dSBill Krier  * samr_s_CreateDomainAlias
1466fe1c642dSBill Krier  *
1467c5866007SKeyur Desai  * Create a local group in the security accounts manager (SAM) database.
1468c5866007SKeyur Desai  * A local SAM group can only be added if a Solaris group already exists
1469c5866007SKeyur Desai  * with the same name.  On success, a valid group handle is returned.
1470c5866007SKeyur Desai  *
1471c5866007SKeyur Desai  * The caller must have administrator rights to execute this function.
1472fe1c642dSBill Krier  */
1473fe1c642dSBill Krier static int
1474fe1c642dSBill Krier samr_s_CreateDomainAlias(void *arg, ndr_xa_t *mxa)
1475fe1c642dSBill Krier {
1476fe1c642dSBill Krier 	struct samr_CreateDomainAlias *param = arg;
1477fe1c642dSBill Krier 	ndr_hdid_t *id = (ndr_hdid_t *)&param->alias_handle;
1478c5866007SKeyur Desai 	uint32_t status = NT_STATUS_SUCCESS;
1479c5866007SKeyur Desai 	smb_group_t grp;
1480c5866007SKeyur Desai 	uint32_t rc;
1481c5866007SKeyur Desai 	char *gname;
1482fe1c642dSBill Krier 
1483c5866007SKeyur Desai 	if (samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN) != NULL) {
1484fe1c642dSBill Krier 		bzero(param, sizeof (struct samr_CreateDomainAlias));
1485fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
1486fe1c642dSBill Krier 		return (NDR_DRC_OK);
1487fe1c642dSBill Krier 	}
1488fe1c642dSBill Krier 
1489c5866007SKeyur Desai 	gname = (char *)param->alias_name.str;
1490c5866007SKeyur Desai 	if (gname == NULL) {
1491c5866007SKeyur Desai 		bzero(&param->alias_handle, sizeof (samr_handle_t));
1492c5866007SKeyur Desai 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER);
1493c5866007SKeyur Desai 		return (NDR_DRC_OK);
1494c5866007SKeyur Desai 	}
1495c5866007SKeyur Desai 
1496c5866007SKeyur Desai 	if ((!ndr_is_admin(mxa)) ||
1497c5866007SKeyur Desai 	    ((param->access_mask & SAMR_ALIAS_ACCESS_WRITE_ACCOUNT) == 0)) {
1498c5866007SKeyur Desai 		bzero(&param->alias_handle, sizeof (samr_handle_t));
1499fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
1500fe1c642dSBill Krier 		return (NDR_DRC_OK);
1501fe1c642dSBill Krier 	}
1502fe1c642dSBill Krier 
1503c5866007SKeyur Desai 	rc = smb_lgrp_add(gname, "");
1504c5866007SKeyur Desai 	if (rc != SMB_LGRP_SUCCESS) {
1505c5866007SKeyur Desai 		bzero(&param->alias_handle, sizeof (samr_handle_t));
1506c5866007SKeyur Desai 		status = smb_lgrp_err_to_ntstatus(rc);
1507fe1c642dSBill Krier 		param->status = NT_SC_ERROR(status);
1508fe1c642dSBill Krier 		return (NDR_DRC_OK);
1509c5866007SKeyur Desai 	}
1510c5866007SKeyur Desai 
1511c5866007SKeyur Desai 	rc = smb_lgrp_getbyname((char *)gname, &grp);
1512c5866007SKeyur Desai 	if (rc != SMB_LGRP_SUCCESS) {
1513c5866007SKeyur Desai 		bzero(&param->alias_handle, sizeof (samr_handle_t));
1514c5866007SKeyur Desai 		status = smb_lgrp_err_to_ntstatus(rc);
1515c5866007SKeyur Desai 		param->status = NT_SC_ERROR(status);
1516c5866007SKeyur Desai 		return (NDR_DRC_OK);
1517c5866007SKeyur Desai 	}
1518c5866007SKeyur Desai 
1519c5866007SKeyur Desai 	id = samr_hdalloc(mxa, SAMR_KEY_ALIAS, SMB_DOMAIN_LOCAL, grp.sg_rid);
1520c5866007SKeyur Desai 	smb_lgrp_free(&grp);
1521c5866007SKeyur Desai 	if (id) {
1522c5866007SKeyur Desai 		bcopy(id, &param->alias_handle, sizeof (samr_handle_t));
1523c5866007SKeyur Desai 		param->status = status;
1524c5866007SKeyur Desai 	} else {
1525c5866007SKeyur Desai 		bzero(&param->alias_handle, sizeof (samr_handle_t));
1526c5866007SKeyur Desai 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1527c5866007SKeyur Desai 	}
1528c5866007SKeyur Desai 
1529c5866007SKeyur Desai 	return (NDR_DRC_OK);
1530fe1c642dSBill Krier }
1531fe1c642dSBill Krier 
1532fe1c642dSBill Krier /*
1533fe1c642dSBill Krier  * samr_s_SetAliasInfo
1534fe1c642dSBill Krier  *
1535fe1c642dSBill Krier  * Similar to NetLocalGroupSetInfo.
1536fe1c642dSBill Krier  */
1537fe1c642dSBill Krier static int
1538fe1c642dSBill Krier samr_s_SetAliasInfo(void *arg, ndr_xa_t *mxa)
1539fe1c642dSBill Krier {
1540fe1c642dSBill Krier 	struct samr_SetAliasInfo *param = arg;
1541fe1c642dSBill Krier 	ndr_hdid_t *id = (ndr_hdid_t *)&param->alias_handle;
1542fe1c642dSBill Krier 	DWORD status = NT_STATUS_SUCCESS;
1543fe1c642dSBill Krier 
1544fe1c642dSBill Krier 	if (samr_hdlookup(mxa, id, SAMR_KEY_ALIAS) == NULL)
1545fe1c642dSBill Krier 		status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
1546fe1c642dSBill Krier 
1547fe1c642dSBill Krier 	param->status = status;
1548fe1c642dSBill Krier 	return (NDR_DRC_OK);
1549fe1c642dSBill Krier }
1550fe1c642dSBill Krier 
1551fe1c642dSBill Krier /*
1552fe1c642dSBill Krier  * samr_s_QueryAliasInfo
1553fe1c642dSBill Krier  *
1554fe1c642dSBill Krier  * Retrieves information about the specified local group account
1555fe1c642dSBill Krier  * by given handle.
1556fe1c642dSBill Krier  */
1557fe1c642dSBill Krier static int
1558fe1c642dSBill Krier samr_s_QueryAliasInfo(void *arg, ndr_xa_t *mxa)
1559fe1c642dSBill Krier {
1560fe1c642dSBill Krier 	struct samr_QueryAliasInfo *param = arg;
1561fe1c642dSBill Krier 	ndr_hdid_t	*id = (ndr_hdid_t *)&param->alias_handle;
1562fe1c642dSBill Krier 	ndr_handle_t	*hd;
1563fe1c642dSBill Krier 	samr_keydata_t	*data;
1564fe1c642dSBill Krier 	smb_group_t	grp;
15659fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_domain_type_t gd_type;
1566f96bd5c8SAlan Wright 	smb_sid_t	*sid;
1567f96bd5c8SAlan Wright 	smb_wka_t	*wka;
1568f96bd5c8SAlan Wright 	char		sidstr[SMB_SID_STRSZ];
1569f96bd5c8SAlan Wright 	char		*name;
1570f96bd5c8SAlan Wright 	char		*desc;
1571f96bd5c8SAlan Wright 	uint32_t	rid;
1572fe1c642dSBill Krier 	uint32_t	status;
1573fe1c642dSBill Krier 	int		rc;
1574fe1c642dSBill Krier 
1575fe1c642dSBill Krier 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_ALIAS)) == NULL) {
1576fe1c642dSBill Krier 		status = NT_STATUS_INVALID_HANDLE;
1577fe1c642dSBill Krier 		goto query_alias_err;
1578fe1c642dSBill Krier 	}
1579fe1c642dSBill Krier 
1580fe1c642dSBill Krier 	data = (samr_keydata_t *)hd->nh_data;
15819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	gd_type = (smb_domain_type_t)data->kd_type;
1582f96bd5c8SAlan Wright 	rid = data->kd_rid;
1583f96bd5c8SAlan Wright 
1584f96bd5c8SAlan Wright 	switch (gd_type) {
15859fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	case SMB_DOMAIN_BUILTIN:
1586f96bd5c8SAlan Wright 		(void) snprintf(sidstr, SMB_SID_STRSZ, "%s-%d",
1587f96bd5c8SAlan Wright 		    NT_BUILTIN_DOMAIN_SIDSTR, rid);
1588f96bd5c8SAlan Wright 		if ((sid = smb_sid_fromstr(sidstr)) == NULL) {
1589f96bd5c8SAlan Wright 			status = NT_STATUS_NO_SUCH_ALIAS;
1590f96bd5c8SAlan Wright 			goto query_alias_err;
1591f96bd5c8SAlan Wright 		}
1592f96bd5c8SAlan Wright 
1593f96bd5c8SAlan Wright 		wka = smb_wka_lookup_sid(sid);
1594f96bd5c8SAlan Wright 		smb_sid_free(sid);
1595f96bd5c8SAlan Wright 
1596f96bd5c8SAlan Wright 		if (wka == NULL) {
1597f96bd5c8SAlan Wright 			status = NT_STATUS_NO_SUCH_ALIAS;
1598f96bd5c8SAlan Wright 			goto query_alias_err;
1599f96bd5c8SAlan Wright 		}
1600f96bd5c8SAlan Wright 
1601f96bd5c8SAlan Wright 		name = wka->wka_name;
1602f96bd5c8SAlan Wright 		desc = (wka->wka_desc != NULL) ? wka->wka_desc : "";
1603f96bd5c8SAlan Wright 		break;
1604f96bd5c8SAlan Wright 
16059fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	case SMB_DOMAIN_LOCAL:
1606f96bd5c8SAlan Wright 		rc = smb_lgrp_getbyrid(rid, gd_type, &grp);
1607fe1c642dSBill Krier 		if (rc != SMB_LGRP_SUCCESS) {
1608fe1c642dSBill Krier 			status = NT_STATUS_NO_SUCH_ALIAS;
1609fe1c642dSBill Krier 			goto query_alias_err;
1610fe1c642dSBill Krier 		}
1611f96bd5c8SAlan Wright 		name = grp.sg_name;
1612f96bd5c8SAlan Wright 		desc = grp.sg_cmnt;
1613f96bd5c8SAlan Wright 		break;
1614f96bd5c8SAlan Wright 
1615f96bd5c8SAlan Wright 	default:
1616f96bd5c8SAlan Wright 		status = NT_STATUS_NO_SUCH_ALIAS;
1617f96bd5c8SAlan Wright 		goto query_alias_err;
1618f96bd5c8SAlan Wright 	}
1619fe1c642dSBill Krier 
1620fe1c642dSBill Krier 	switch (param->level) {
1621eef90b86SGordon Ross 	case SAMR_QUERY_ALIAS_INFO_GENERAL:
1622fe1c642dSBill Krier 		param->ru.info1.level = param->level;
1623f96bd5c8SAlan Wright 		(void) NDR_MSTRING(mxa, name,
1624fe1c642dSBill Krier 		    (ndr_mstring_t *)&param->ru.info1.name);
1625f96bd5c8SAlan Wright 		(void) NDR_MSTRING(mxa, desc,
1626fe1c642dSBill Krier 		    (ndr_mstring_t *)&param->ru.info1.desc);
1627eef90b86SGordon Ross 		param->ru.info1.member_count = 1;
1628fe1c642dSBill Krier 		break;
1629fe1c642dSBill Krier 
1630eef90b86SGordon Ross 	case SAMR_QUERY_ALIAS_INFO_NAME:
1631eef90b86SGordon Ross 		param->ru.info2.level = param->level;
1632eef90b86SGordon Ross 		(void) NDR_MSTRING(mxa, name,
1633eef90b86SGordon Ross 		    (ndr_mstring_t *)&param->ru.info2.name);
1634eef90b86SGordon Ross 		break;
1635eef90b86SGordon Ross 
1636eef90b86SGordon Ross 	case SAMR_QUERY_ALIAS_INFO_COMMENT:
1637fe1c642dSBill Krier 		param->ru.info3.level = param->level;
1638f96bd5c8SAlan Wright 		(void) NDR_MSTRING(mxa, desc,
1639fe1c642dSBill Krier 		    (ndr_mstring_t *)&param->ru.info3.desc);
1640fe1c642dSBill Krier 		break;
1641fe1c642dSBill Krier 
1642fe1c642dSBill Krier 	default:
16439fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		if (gd_type == SMB_DOMAIN_LOCAL)
1644fe1c642dSBill Krier 			smb_lgrp_free(&grp);
1645fe1c642dSBill Krier 		status = NT_STATUS_INVALID_INFO_CLASS;
1646fe1c642dSBill Krier 		goto query_alias_err;
1647fe1c642dSBill Krier 	};
1648fe1c642dSBill Krier 
16499fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (gd_type == SMB_DOMAIN_LOCAL)
1650fe1c642dSBill Krier 		smb_lgrp_free(&grp);
1651fe1c642dSBill Krier 	param->address = (DWORD)(uintptr_t)&param->ru;
1652fe1c642dSBill Krier 	param->status = 0;
1653fe1c642dSBill Krier 	return (NDR_DRC_OK);
1654fe1c642dSBill Krier 
1655fe1c642dSBill Krier query_alias_err:
1656fe1c642dSBill Krier 	param->status = NT_SC_ERROR(status);
1657fe1c642dSBill Krier 	return (NDR_DRC_OK);
1658fe1c642dSBill Krier }
1659fe1c642dSBill Krier 
1660fe1c642dSBill Krier /*
1661fe1c642dSBill Krier  * samr_s_DeleteDomainAlias
1662fe1c642dSBill Krier  *
1663c5866007SKeyur Desai  * Deletes a local group in the security database, which is the
1664c5866007SKeyur Desai  * security accounts manager (SAM). A valid group handle is returned
1665c5866007SKeyur Desai  * to the caller upon success.
1666fe1c642dSBill Krier  *
1667c5866007SKeyur Desai  * The caller must have administrator rights to execute this function.
1668fe1c642dSBill Krier  */
1669fe1c642dSBill Krier static int
1670fe1c642dSBill Krier samr_s_DeleteDomainAlias(void *arg, ndr_xa_t *mxa)
1671fe1c642dSBill Krier {
1672fe1c642dSBill Krier 	struct samr_DeleteDomainAlias *param = arg;
1673fe1c642dSBill Krier 	ndr_hdid_t *id = (ndr_hdid_t *)&param->alias_handle;
1674c5866007SKeyur Desai 	ndr_handle_t	*hd;
1675c5866007SKeyur Desai 	smb_group_t grp;
1676c5866007SKeyur Desai 	samr_keydata_t	*data;
1677c5866007SKeyur Desai 	smb_domain_type_t	gd_type;
1678c5866007SKeyur Desai 	uint32_t	rid;
1679c5866007SKeyur Desai 	uint32_t	rc;
1680c5866007SKeyur Desai 	uint32_t	status = NT_STATUS_SUCCESS;
1681fe1c642dSBill Krier 
1682c5866007SKeyur Desai 	if (!ndr_is_admin(mxa)) {
1683c5866007SKeyur Desai 		bzero(param, sizeof (struct samr_DeleteDomainAlias));
1684c5866007SKeyur Desai 		param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
1685c5866007SKeyur Desai 		return (NDR_DRC_OK);
1686c5866007SKeyur Desai 	}
1687c5866007SKeyur Desai 
1688c5866007SKeyur Desai 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_ALIAS)) == NULL) {
1689fe1c642dSBill Krier 		bzero(param, sizeof (struct samr_DeleteDomainAlias));
1690fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
1691fe1c642dSBill Krier 		return (NDR_DRC_OK);
1692fe1c642dSBill Krier 	}
1693fe1c642dSBill Krier 
1694c5866007SKeyur Desai 	data = (samr_keydata_t *)hd->nh_data;
1695c5866007SKeyur Desai 	gd_type = (smb_domain_type_t)data->kd_type;
1696c5866007SKeyur Desai 	rid = data->kd_rid;
1697c5866007SKeyur Desai 
1698c5866007SKeyur Desai 	switch (gd_type) {
1699c5866007SKeyur Desai 	case SMB_DOMAIN_BUILTIN:
1700fe1c642dSBill Krier 		bzero(param, sizeof (struct samr_DeleteDomainAlias));
1701c5866007SKeyur Desai 		status = NT_SC_ERROR(NT_STATUS_NOT_SUPPORTED);
1702c5866007SKeyur Desai 		break;
1703fe1c642dSBill Krier 
1704c5866007SKeyur Desai 	case SMB_DOMAIN_LOCAL:
1705c5866007SKeyur Desai 		rc = smb_lgrp_getbyrid(rid, gd_type, &grp);
1706c5866007SKeyur Desai 		if (rc != SMB_LGRP_SUCCESS) {
1707c5866007SKeyur Desai 			bzero(param, sizeof (struct samr_DeleteDomainAlias));
1708c5866007SKeyur Desai 			status = smb_lgrp_err_to_ntstatus(rc);
1709c5866007SKeyur Desai 			status = NT_SC_ERROR(status);
1710c5866007SKeyur Desai 			break;
1711fe1c642dSBill Krier 		}
1712fe1c642dSBill Krier 
1713c5866007SKeyur Desai 		rc = smb_lgrp_delete(grp.sg_name);
1714c5866007SKeyur Desai 		if (rc != SMB_LGRP_SUCCESS) {
1715c5866007SKeyur Desai 			bzero(param, sizeof (struct samr_DeleteDomainAlias));
1716c5866007SKeyur Desai 			status = smb_lgrp_err_to_ntstatus(rc);
1717c5866007SKeyur Desai 			status = NT_SC_ERROR(status);
1718c5866007SKeyur Desai 		}
1719c5866007SKeyur Desai 		smb_lgrp_free(&grp);
1720c5866007SKeyur Desai 		break;
1721c5866007SKeyur Desai 
1722c5866007SKeyur Desai 	default:
1723c5866007SKeyur Desai 		bzero(param, sizeof (struct samr_DeleteDomainAlias));
1724c5866007SKeyur Desai 		status = NT_SC_ERROR(NT_STATUS_NO_SUCH_ALIAS);
1725fe1c642dSBill Krier 	}
1726fe1c642dSBill Krier 
1727c5866007SKeyur Desai 	param->status = status;
1728fe1c642dSBill Krier 	return (NDR_DRC_OK);
1729fe1c642dSBill Krier }
1730fe1c642dSBill Krier 
1731fe1c642dSBill Krier /*
1732fe1c642dSBill Krier  * samr_s_EnumDomainAliases
1733fe1c642dSBill Krier  *
1734fe1c642dSBill Krier  * This function sends back a list which contains all local groups' name.
1735fe1c642dSBill Krier  */
1736fe1c642dSBill Krier static int
1737fe1c642dSBill Krier samr_s_EnumDomainAliases(void *arg, ndr_xa_t *mxa)
1738fe1c642dSBill Krier {
1739fe1c642dSBill Krier 	struct samr_EnumDomainAliases *param = arg;
1740fe1c642dSBill Krier 	ndr_hdid_t *id = (ndr_hdid_t *)&param->domain_handle;
1741fe1c642dSBill Krier 	ndr_handle_t *hd;
1742fe1c642dSBill Krier 	samr_keydata_t *data;
1743fe1c642dSBill Krier 	smb_group_t grp;
1744fe1c642dSBill Krier 	smb_giter_t gi;
1745fe1c642dSBill Krier 	int cnt, skip, i;
1746fe1c642dSBill Krier 	struct name_rid *info;
1747fe1c642dSBill Krier 
1748fe1c642dSBill Krier 	if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
1749fe1c642dSBill Krier 		bzero(param, sizeof (struct samr_EnumDomainAliases));
1750fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
1751fe1c642dSBill Krier 		return (NDR_DRC_OK);
1752fe1c642dSBill Krier 	}
1753fe1c642dSBill Krier 
1754fe1c642dSBill Krier 	data = (samr_keydata_t *)hd->nh_data;
1755fe1c642dSBill Krier 
1756fe1c642dSBill Krier 	cnt = smb_sam_grp_cnt(data->kd_type);
1757fe1c642dSBill Krier 	if (cnt <= param->resume_handle) {
1758fe1c642dSBill Krier 		param->aliases = (struct aliases_info *)NDR_MALLOC(mxa,
1759fe1c642dSBill Krier 		    sizeof (struct aliases_info));
1760fe1c642dSBill Krier 
1761fe1c642dSBill Krier 		if (param->aliases == NULL) {
1762fe1c642dSBill Krier 			bzero(param, sizeof (struct samr_EnumDomainAliases));
1763fe1c642dSBill Krier 			param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1764fe1c642dSBill Krier 			return (NDR_DRC_OK);
1765fe1c642dSBill Krier 		}
1766fe1c642dSBill Krier 
1767fe1c642dSBill Krier 		bzero(param->aliases, sizeof (struct aliases_info));
1768fe1c642dSBill Krier 		param->out_resume = 0;
1769fe1c642dSBill Krier 		param->entries = 0;
1770fe1c642dSBill Krier 		param->status = NT_STATUS_SUCCESS;
1771fe1c642dSBill Krier 		return (NDR_DRC_OK);
1772fe1c642dSBill Krier 	}
1773fe1c642dSBill Krier 
1774fe1c642dSBill Krier 	cnt -= param->resume_handle;
1775fe1c642dSBill Krier 	param->aliases = (struct aliases_info *)NDR_MALLOC(mxa,
1776fe1c642dSBill Krier 	    sizeof (struct aliases_info) + (cnt-1) * sizeof (struct name_rid));
1777fe1c642dSBill Krier 
1778fe1c642dSBill Krier 	if (param->aliases == NULL) {
1779fe1c642dSBill Krier 		bzero(param, sizeof (struct samr_EnumDomainAliases));
1780fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1781fe1c642dSBill Krier 		return (NDR_DRC_OK);
1782fe1c642dSBill Krier 	}
1783fe1c642dSBill Krier 
1784fe1c642dSBill Krier 	if (smb_lgrp_iteropen(&gi) != SMB_LGRP_SUCCESS) {
1785fe1c642dSBill Krier 		bzero(param, sizeof (struct samr_EnumDomainAliases));
1786fe1c642dSBill Krier 		param->status = NT_SC_ERROR(NT_STATUS_INTERNAL_ERROR);
1787fe1c642dSBill Krier 		return (NDR_DRC_OK);
1788fe1c642dSBill Krier 	}
1789fe1c642dSBill Krier 
1790fe1c642dSBill Krier 	skip = i = 0;
1791fe1c642dSBill Krier 	info = param->aliases->info;
1792fe1c642dSBill Krier 	while (smb_lgrp_iterate(&gi, &grp) == SMB_LGRP_SUCCESS) {
1793fe1c642dSBill Krier 		if ((skip++ >= param->resume_handle) &&
1794fe1c642dSBill Krier 		    (grp.sg_domain == data->kd_type) && (i++ < cnt)) {
1795fe1c642dSBill Krier 			info->rid = grp.sg_rid;
1796fe1c642dSBill Krier 			(void) NDR_MSTRING(mxa, grp.sg_name,
1797fe1c642dSBill Krier 			    (ndr_mstring_t *)&info->name);
1798fe1c642dSBill Krier 
1799fe1c642dSBill Krier 			info++;
1800fe1c642dSBill Krier 		}
1801fe1c642dSBill Krier 		smb_lgrp_free(&grp);
1802fe1c642dSBill Krier 	}
1803fe1c642dSBill Krier 	smb_lgrp_iterclose(&gi);
1804fe1c642dSBill Krier 
1805fe1c642dSBill Krier 	param->aliases->count = i;
1806fe1c642dSBill Krier 	param->aliases->address = i;
1807fe1c642dSBill Krier 
1808fe1c642dSBill Krier 	param->out_resume = i;
1809fe1c642dSBill Krier 	param->entries = i;
1810fe1c642dSBill Krier 	param->status = 0;
1811fe1c642dSBill Krier 	return (NDR_DRC_OK);
1812fe1c642dSBill Krier }
1813fe1c642dSBill Krier 
1814fe1c642dSBill Krier /*
1815cb174861Sjoyce mcintosh  * samr_s_Connect4
1816fe1c642dSBill Krier  */
1817fe1c642dSBill Krier static int
1818cb174861Sjoyce mcintosh samr_s_Connect4(void *arg, ndr_xa_t *mxa)
1819fe1c642dSBill Krier {
1820cb174861Sjoyce mcintosh 	struct samr_Connect4	*param = arg;
1821f96bd5c8SAlan Wright 	ndr_hdid_t		*id;
1822fe1c642dSBill Krier 
1823f96bd5c8SAlan Wright 	id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, SMB_DOMAIN_NULL, 0);
1824f96bd5c8SAlan Wright 	if (id) {
1825f96bd5c8SAlan Wright 		bcopy(id, &param->handle, sizeof (samr_handle_t));
1826f96bd5c8SAlan Wright 		param->status = 0;
1827f96bd5c8SAlan Wright 	} else {
1828f96bd5c8SAlan Wright 		bzero(&param->handle, sizeof (samr_handle_t));
1829f96bd5c8SAlan Wright 		param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1830fe1c642dSBill Krier 	}
1831fe1c642dSBill Krier 
1832f96bd5c8SAlan Wright 	return (NDR_DRC_OK);
1833f96bd5c8SAlan Wright }
1834fe1c642dSBill Krier 
1835fe1c642dSBill Krier /*
1836cb174861Sjoyce mcintosh  * samr_s_Connect5
1837fe1c642dSBill Krier  *
1838cb174861Sjoyce mcintosh  * This is the connect5 form of the connect request used by Windows XP.
1839fe1c642dSBill Krier  * Returns an RPC fault for now.
1840fe1c642dSBill Krier  */
1841fe1c642dSBill Krier /*ARGSUSED*/
1842fe1c642dSBill Krier static int
1843cb174861Sjoyce mcintosh samr_s_Connect5(void *arg, ndr_xa_t *mxa)
1844fe1c642dSBill Krier {
1845cb174861Sjoyce mcintosh 	struct samr_Connect5 *param = arg;
1846fe1c642dSBill Krier 
1847cb174861Sjoyce mcintosh 	bzero(param, sizeof (struct samr_Connect5));
1848fe1c642dSBill Krier 	return (NDR_DRC_FAULT_REQUEST_OPNUM_INVALID);
1849fe1c642dSBill Krier }
1850fe1c642dSBill Krier 
1851fe1c642dSBill Krier static ndr_stub_table_t samr_stub_table[] = {
1852cb174861Sjoyce mcintosh 	{ samr_s_Connect,		SAMR_OPNUM_Connect },
1853fe1c642dSBill Krier 	{ samr_s_CloseHandle,		SAMR_OPNUM_CloseHandle },
1854fe1c642dSBill Krier 	{ samr_s_LookupDomain,		SAMR_OPNUM_LookupDomain },
1855fe1c642dSBill Krier 	{ samr_s_EnumLocalDomains,	SAMR_OPNUM_EnumLocalDomains },
1856fe1c642dSBill Krier 	{ samr_s_OpenDomain,		SAMR_OPNUM_OpenDomain },
1857fe1c642dSBill Krier 	{ samr_s_QueryDomainInfo,	SAMR_OPNUM_QueryDomainInfo },
1858f96bd5c8SAlan Wright 	{ samr_s_QueryInfoDomain2,	SAMR_OPNUM_QueryInfoDomain2 },
1859fe1c642dSBill Krier 	{ samr_s_LookupNames,		SAMR_OPNUM_LookupNames },
1860fe1c642dSBill Krier 	{ samr_s_OpenUser,		SAMR_OPNUM_OpenUser },
1861fe1c642dSBill Krier 	{ samr_s_DeleteUser,		SAMR_OPNUM_DeleteUser },
1862fe1c642dSBill Krier 	{ samr_s_QueryUserInfo,		SAMR_OPNUM_QueryUserInfo },
1863fe1c642dSBill Krier 	{ samr_s_QueryUserGroups,	SAMR_OPNUM_QueryUserGroups },
1864fe1c642dSBill Krier 	{ samr_s_OpenGroup,		SAMR_OPNUM_OpenGroup },
1865cb174861Sjoyce mcintosh 	{ samr_s_Connect2,		SAMR_OPNUM_Connect2 },
1866fe1c642dSBill Krier 	{ samr_s_GetUserPwInfo,		SAMR_OPNUM_GetUserPwInfo },
1867fe1c642dSBill Krier 	{ samr_s_CreateUser,		SAMR_OPNUM_CreateUser },
18681ed6b69aSGordon Ross 	{ samr_s_ChangePasswordUser2,	SAMR_OPNUM_ChangePasswordUser2 },
1869fe1c642dSBill Krier 	{ samr_s_GetDomainPwInfo,	SAMR_OPNUM_GetDomainPwInfo },
1870fe1c642dSBill Krier 	{ samr_s_SetUserInfo,		SAMR_OPNUM_SetUserInfo },
1871fe1c642dSBill Krier 	{ samr_s_Connect4,		SAMR_OPNUM_Connect4 },
1872cb174861Sjoyce mcintosh 	{ samr_s_Connect5,		SAMR_OPNUM_Connect5 },
1873fe1c642dSBill Krier 	{ samr_s_QueryDispInfo,		SAMR_OPNUM_QueryDispInfo },
1874fe1c642dSBill Krier 	{ samr_s_OpenAlias,		SAMR_OPNUM_OpenAlias },
1875fe1c642dSBill Krier 	{ samr_s_CreateDomainAlias,	SAMR_OPNUM_CreateDomainAlias },
1876fe1c642dSBill Krier 	{ samr_s_SetAliasInfo,		SAMR_OPNUM_SetAliasInfo },
1877fe1c642dSBill Krier 	{ samr_s_QueryAliasInfo,	SAMR_OPNUM_QueryAliasInfo },
1878fe1c642dSBill Krier 	{ samr_s_DeleteDomainAlias,	SAMR_OPNUM_DeleteDomainAlias },
1879fe1c642dSBill Krier 	{ samr_s_EnumDomainAliases,	SAMR_OPNUM_EnumDomainAliases },
1880fe1c642dSBill Krier 	{ samr_s_EnumDomainGroups,	SAMR_OPNUM_EnumDomainGroups },
1881c5866007SKeyur Desai 	{ samr_s_AddAliasMember,	SAMR_OPNUM_AddAliasMember },
1882c5866007SKeyur Desai 	{ samr_s_DeleteAliasMember,	SAMR_OPNUM_DeleteAliasMember },
1883c5866007SKeyur Desai 	{ samr_s_ListAliasMembers,	SAMR_OPNUM_ListAliasMembers },
1884fe1c642dSBill Krier 	{0}
1885fe1c642dSBill Krier };
1886fe1c642dSBill Krier 
1887fe1c642dSBill Krier /*
1888fe1c642dSBill Krier  * There is a bug in the way that midl and the marshalling code handles
1889fe1c642dSBill Krier  * unions so we need to fix some of the data offsets at runtime. The
1890fe1c642dSBill Krier  * following macros and the fixup functions handle the corrections.
1891fe1c642dSBill Krier  */
1892fe1c642dSBill Krier 
1893fe1c642dSBill Krier DECL_FIXUP_STRUCT(samr_QueryAliasInfo_ru);
1894fe1c642dSBill Krier DECL_FIXUP_STRUCT(samr_QueryAliasInfoRes);
1895fe1c642dSBill Krier DECL_FIXUP_STRUCT(samr_QueryAliasInfo);
1896fe1c642dSBill Krier 
1897fe1c642dSBill Krier DECL_FIXUP_STRUCT(QueryUserInfo_result_u);
1898fe1c642dSBill Krier DECL_FIXUP_STRUCT(QueryUserInfo_result);
1899fe1c642dSBill Krier DECL_FIXUP_STRUCT(samr_QueryUserInfo);
1900fe1c642dSBill Krier 
1901fe1c642dSBill Krier void
1902fe1c642dSBill Krier fixup_samr_QueryAliasInfo(struct samr_QueryAliasInfo *val)
1903fe1c642dSBill Krier {
1904fe1c642dSBill Krier 	unsigned short size1 = 0;
1905fe1c642dSBill Krier 	unsigned short size2 = 0;
1906fe1c642dSBill Krier 	unsigned short size3 = 0;
1907fe1c642dSBill Krier 
1908fe1c642dSBill Krier 	switch (val->level) {
1909eef90b86SGordon Ross 	case SAMR_QUERY_ALIAS_INFO_GENERAL:
1910eef90b86SGordon Ross 		size1 = sizeof (struct samr_QueryAliasInfoGeneral);
1911eef90b86SGordon Ross 		break;
1912eef90b86SGordon Ross 	case SAMR_QUERY_ALIAS_INFO_NAME:
1913eef90b86SGordon Ross 		size1 = sizeof (struct samr_QueryAliasInfoName);
1914eef90b86SGordon Ross 		break;
1915eef90b86SGordon Ross 	case SAMR_QUERY_ALIAS_INFO_COMMENT:
1916eef90b86SGordon Ross 		size1 = sizeof (struct samr_QueryAliasInfoComment);
1917eef90b86SGordon Ross 		break;
1918fe1c642dSBill Krier 
1919fe1c642dSBill Krier 	default:
1920fe1c642dSBill Krier 		return;
1921fe1c642dSBill Krier 	};
1922fe1c642dSBill Krier 
1923fe1c642dSBill Krier 	size2 = size1 + (2 * sizeof (DWORD));
1924fe1c642dSBill Krier 	size3 = size2 + sizeof (ndr_request_hdr_t) + sizeof (DWORD);
1925fe1c642dSBill Krier 
1926fe1c642dSBill Krier 	FIXUP_PDU_SIZE(samr_QueryAliasInfo_ru, size1);
1927fe1c642dSBill Krier 	FIXUP_PDU_SIZE(samr_QueryAliasInfoRes, size2);
1928fe1c642dSBill Krier 	FIXUP_PDU_SIZE(samr_QueryAliasInfo, size3);
1929fe1c642dSBill Krier }
1930fe1c642dSBill Krier 
1931fe1c642dSBill Krier void
1932fe1c642dSBill Krier fixup_samr_QueryUserInfo(struct samr_QueryUserInfo *val)
1933fe1c642dSBill Krier {
1934fe1c642dSBill Krier 	unsigned short size1 = 0;
1935fe1c642dSBill Krier 	unsigned short size2 = 0;
1936fe1c642dSBill Krier 	unsigned short size3 = 0;
1937fe1c642dSBill Krier 
1938fe1c642dSBill Krier 	switch (val->switch_index) {
1939fe1c642dSBill Krier 		CASE_INFO_ENT(samr_QueryUserInfo, 1);
1940fe1c642dSBill Krier 		CASE_INFO_ENT(samr_QueryUserInfo, 6);
1941fe1c642dSBill Krier 		CASE_INFO_ENT(samr_QueryUserInfo, 7);
1942fe1c642dSBill Krier 		CASE_INFO_ENT(samr_QueryUserInfo, 8);
1943fe1c642dSBill Krier 		CASE_INFO_ENT(samr_QueryUserInfo, 9);
1944fe1c642dSBill Krier 		CASE_INFO_ENT(samr_QueryUserInfo, 16);
1945fe1c642dSBill Krier 		CASE_INFO_ENT(samr_QueryUserInfo, 21);
1946fe1c642dSBill Krier 
1947fe1c642dSBill Krier 		default:
1948fe1c642dSBill Krier 			return;
1949fe1c642dSBill Krier 	};
1950fe1c642dSBill Krier 
1951fe1c642dSBill Krier 	size2 = size1 + (2 * sizeof (DWORD));
1952fe1c642dSBill Krier 	size3 = size2 + sizeof (ndr_request_hdr_t) + sizeof (DWORD);
1953fe1c642dSBill Krier 
1954fe1c642dSBill Krier 	FIXUP_PDU_SIZE(QueryUserInfo_result_u, size1);
1955fe1c642dSBill Krier 	FIXUP_PDU_SIZE(QueryUserInfo_result, size2);
1956fe1c642dSBill Krier 	FIXUP_PDU_SIZE(samr_QueryUserInfo, size3);
1957fe1c642dSBill Krier }
1958fe1c642dSBill Krier 
1959fe1c642dSBill Krier /*
1960fe1c642dSBill Krier  * As long as there is only one entry in the union, there is no need
1961fe1c642dSBill Krier  * to patch anything.
1962fe1c642dSBill Krier  */
1963fe1c642dSBill Krier /*ARGSUSED*/
1964fe1c642dSBill Krier void
1965fe1c642dSBill Krier fixup_samr_QueryGroupInfo(struct samr_QueryGroupInfo *val)
1966fe1c642dSBill Krier {
1967fe1c642dSBill Krier }
1968