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