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