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 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 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 * 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 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 * 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 2028 fixup_samr_QueryGroupInfo(struct samr_QueryGroupInfo *val) 2029 { 2030 } 2031