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