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