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