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