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