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 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 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 41 #include <smbsrv/libsmb.h> 42 #include <smbsrv/libmlrpc.h> 43 #include <smbsrv/libmlsvc.h> 44 #include <smbsrv/ntstatus.h> 45 #include <smbsrv/nterror.h> 46 #include <smbsrv/smbinfo.h> 47 #include <smbsrv/nmpipes.h> 48 #include <smbsrv/ndl/samrpc.ndl> 49 #include <samlib.h> 50 51 /* 52 * The keys associated with the various handles dispensed by the SAMR 53 * server. These keys can be used to validate client activity. 54 * These values are never passed over the wire so security shouldn't 55 * be an issue. 56 */ 57 typedef enum { 58 SAMR_KEY_NULL = 0, 59 SAMR_KEY_CONNECT, 60 SAMR_KEY_DOMAIN, 61 SAMR_KEY_USER, 62 SAMR_KEY_GROUP, 63 SAMR_KEY_ALIAS 64 } samr_key_t; 65 66 typedef struct samr_keydata { 67 samr_key_t kd_key; 68 smb_domain_type_t kd_type; 69 DWORD kd_rid; 70 } samr_keydata_t; 71 72 /* 73 * DomainDisplayUser All user objects (or those derived from user) with 74 * userAccountControl containing the UF_NORMAL_ACCOUNT bit. 75 * 76 * DomainDisplayMachine All user objects (or those derived from user) with 77 * userAccountControl containing the 78 * UF_WORKSTATION_TRUST_ACCOUNT or UF_SERVER_TRUST_ACCOUNT 79 * bit. 80 * 81 * DomainDisplayGroup All group objects (or those derived from group) with 82 * groupType equal to GROUP_TYPE_SECURITY_UNIVERSAL or 83 * GROUP_TYPE_SECURITY_ACCOUNT. 84 * 85 * DomainDisplayOemUser Same as DomainDisplayUser with OEM strings 86 * 87 * DomainDisplayOemGroup Same as DomainDisplayGroup with OEM strings 88 */ 89 typedef enum { 90 DomainDisplayUser = 1, 91 DomainDisplayMachine, 92 DomainDispalyGroup, 93 DomainDisplayOemUser, 94 DomainDisplayOemGroup 95 } samr_displvl_t; 96 97 #define SAMR_VALID_DISPLEVEL(lvl) \ 98 (((lvl) >= DomainDisplayUser) && ((lvl) <= DomainDisplayOemGroup)) 99 100 #define SAMR_SUPPORTED_DISPLEVEL(lvl) (lvl == DomainDisplayUser) 101 102 static ndr_hdid_t *samr_hdalloc(ndr_xa_t *, samr_key_t, smb_domain_type_t, 103 DWORD); 104 static void samr_hdfree(ndr_xa_t *, ndr_hdid_t *); 105 static ndr_handle_t *samr_hdlookup(ndr_xa_t *, ndr_hdid_t *, samr_key_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 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 return (ndr_hdalloc(mxa, data)); 169 } 170 171 /* 172 * Handle deallocation wrapper to free the local context. 173 */ 174 static void 175 samr_hdfree(ndr_xa_t *mxa, ndr_hdid_t *id) 176 { 177 ndr_handle_t *hd; 178 179 if ((hd = ndr_hdlookup(mxa, id)) != NULL) { 180 free(hd->nh_data); 181 ndr_hdfree(mxa, id); 182 } 183 } 184 185 /* 186 * Handle lookup wrapper to validate the local context. 187 */ 188 static ndr_handle_t * 189 samr_hdlookup(ndr_xa_t *mxa, ndr_hdid_t *id, samr_key_t key) 190 { 191 ndr_handle_t *hd; 192 samr_keydata_t *data; 193 194 if ((hd = ndr_hdlookup(mxa, id)) == NULL) 195 return (NULL); 196 197 if ((data = (samr_keydata_t *)hd->nh_data) == NULL) 198 return (NULL); 199 200 if (data->kd_key != key) 201 return (NULL); 202 203 return (hd); 204 } 205 206 /* 207 * samr_s_ConnectAnon 208 * 209 * This is a request to connect to the local SAM database. We don't 210 * support any form of update request and our database doesn't 211 * contain any private information, so there is little point in 212 * doing any access access checking here. 213 * 214 * Return a handle for use with subsequent SAM requests. 215 */ 216 static int 217 samr_s_ConnectAnon(void *arg, ndr_xa_t *mxa) 218 { 219 struct samr_ConnectAnon *param = arg; 220 ndr_hdid_t *id; 221 222 id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, SMB_DOMAIN_NULL, 0); 223 if (id) { 224 bcopy(id, ¶m->handle, sizeof (samr_handle_t)); 225 param->status = 0; 226 } else { 227 bzero(¶m->handle, sizeof (samr_handle_t)); 228 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); 229 } 230 231 return (NDR_DRC_OK); 232 } 233 234 /* 235 * samr_s_CloseHandle 236 * 237 * Close the SAM interface specified by the handle. 238 * Free the handle and zero out the result handle for the client. 239 */ 240 static int 241 samr_s_CloseHandle(void *arg, ndr_xa_t *mxa) 242 { 243 struct samr_CloseHandle *param = arg; 244 ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 245 246 samr_hdfree(mxa, id); 247 248 bzero(¶m->result_handle, sizeof (samr_handle_t)); 249 param->status = 0; 250 return (NDR_DRC_OK); 251 } 252 253 /* 254 * samr_s_LookupDomain 255 * 256 * This is a request to map a domain name to a domain SID. We can map 257 * the primary domain name, our local domain name (hostname) and the 258 * builtin domain names to the appropriate SID. Anything else will be 259 * rejected. 260 */ 261 static int 262 samr_s_LookupDomain(void *arg, ndr_xa_t *mxa) 263 { 264 struct samr_LookupDomain *param = arg; 265 char *domain_name; 266 smb_domain_t di; 267 268 if ((domain_name = (char *)param->domain_name.str) == NULL) { 269 bzero(param, sizeof (struct samr_LookupDomain)); 270 param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER); 271 return (NDR_DRC_OK); 272 } 273 274 if (!smb_domain_lookup_name(domain_name, &di)) { 275 bzero(param, sizeof (struct samr_LookupDomain)); 276 param->status = NT_SC_ERROR(NT_STATUS_NO_SUCH_DOMAIN); 277 return (NDR_DRC_OK); 278 } 279 280 param->sid = (struct samr_sid *)NDR_SIDDUP(mxa, di.di_binsid); 281 if (param->sid == NULL) { 282 bzero(param, sizeof (struct samr_LookupDomain)); 283 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); 284 return (NDR_DRC_OK); 285 } 286 287 param->status = NT_STATUS_SUCCESS; 288 return (NDR_DRC_OK); 289 } 290 291 /* 292 * samr_s_EnumLocalDomains 293 * 294 * This is a request for the local domains supported by this server. 295 * All we do here is validate the handle and set the status. The real 296 * work is done in samr_s_enum_local_domains. 297 */ 298 static int 299 samr_s_EnumLocalDomains(void *arg, ndr_xa_t *mxa) 300 { 301 struct samr_EnumLocalDomain *param = arg; 302 ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 303 DWORD status; 304 305 if (samr_hdlookup(mxa, id, SAMR_KEY_CONNECT) == NULL) 306 status = NT_STATUS_ACCESS_DENIED; 307 else 308 status = samr_s_enum_local_domains(param, mxa); 309 310 if (status == NT_STATUS_SUCCESS) { 311 param->enum_context = param->info->entries_read; 312 param->total_entries = param->info->entries_read; 313 param->status = NT_STATUS_SUCCESS; 314 } else { 315 bzero(param, sizeof (struct samr_EnumLocalDomain)); 316 param->status = NT_SC_ERROR(status); 317 } 318 319 return (NDR_DRC_OK); 320 } 321 322 323 /* 324 * samr_s_enum_local_domains 325 * 326 * This function should only be called via samr_s_EnumLocalDomains to 327 * ensure that the appropriate validation is performed. We will answer 328 * queries about two domains: the local domain, synonymous with the 329 * local hostname, and the BUILTIN domain. So we return these two 330 * strings. 331 * 332 * Returns NT status values. 333 */ 334 static DWORD 335 samr_s_enum_local_domains(struct samr_EnumLocalDomain *param, 336 ndr_xa_t *mxa) 337 { 338 struct samr_LocalDomainInfo *info; 339 struct samr_LocalDomainEntry *entry; 340 char *hostname; 341 342 hostname = NDR_MALLOC(mxa, NETBIOS_NAME_SZ); 343 if (hostname == NULL) 344 return (NT_STATUS_NO_MEMORY); 345 346 if (smb_getnetbiosname(hostname, NETBIOS_NAME_SZ) != 0) 347 return (NT_STATUS_NO_MEMORY); 348 349 entry = NDR_NEWN(mxa, struct samr_LocalDomainEntry, 2); 350 if (entry == NULL) 351 return (NT_STATUS_NO_MEMORY); 352 353 bzero(entry, (sizeof (struct samr_LocalDomainEntry) * 2)); 354 (void) NDR_MSTRING(mxa, hostname, (ndr_mstring_t *)&entry[0].name); 355 (void) NDR_MSTRING(mxa, "Builtin", (ndr_mstring_t *)&entry[1].name); 356 357 info = NDR_NEW(mxa, struct samr_LocalDomainInfo); 358 if (info == NULL) 359 return (NT_STATUS_NO_MEMORY); 360 361 info->entries_read = 2; 362 info->entry = entry; 363 param->info = info; 364 return (NT_STATUS_SUCCESS); 365 } 366 367 /* 368 * samr_s_OpenDomain 369 * 370 * This is a request to open a domain within the local SAM database. 371 * The caller must supply a valid connect handle. 372 * We return a handle to be used to access objects within this domain. 373 */ 374 static int 375 samr_s_OpenDomain(void *arg, ndr_xa_t *mxa) 376 { 377 struct samr_OpenDomain *param = arg; 378 ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 379 smb_domain_t domain; 380 381 if (samr_hdlookup(mxa, id, SAMR_KEY_CONNECT) == NULL) { 382 bzero(¶m->domain_handle, sizeof (samr_handle_t)); 383 param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); 384 return (NDR_DRC_OK); 385 } 386 387 if (!smb_domain_lookup_sid((smb_sid_t *)param->sid, &domain)) { 388 bzero(¶m->domain_handle, sizeof (samr_handle_t)); 389 param->status = NT_SC_ERROR(NT_STATUS_CANT_ACCESS_DOMAIN_INFO); 390 return (NDR_DRC_OK); 391 } 392 393 if ((domain.di_type != SMB_DOMAIN_BUILTIN) && 394 (domain.di_type != SMB_DOMAIN_LOCAL)) { 395 bzero(¶m->domain_handle, sizeof (samr_handle_t)); 396 param->status = NT_SC_ERROR(NT_STATUS_CANT_ACCESS_DOMAIN_INFO); 397 return (NDR_DRC_OK); 398 } 399 400 id = samr_hdalloc(mxa, SAMR_KEY_DOMAIN, domain.di_type, 0); 401 if (id) { 402 bcopy(id, ¶m->domain_handle, sizeof (samr_handle_t)); 403 param->status = 0; 404 } else { 405 bzero(¶m->domain_handle, sizeof (samr_handle_t)); 406 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); 407 } 408 409 return (NDR_DRC_OK); 410 } 411 412 /* 413 * samr_s_QueryDomainInfo 414 * 415 * The caller should pass a domain handle. 416 * 417 * Windows 95 Server Manager sends requests for levels 6 and 7 when 418 * the services menu item is selected. Level 2 is basically for getting 419 * number of users, groups, and aliases in a domain. 420 * We have no information on what the various information levels mean. 421 */ 422 static int 423 samr_s_QueryDomainInfo(void *arg, ndr_xa_t *mxa) 424 { 425 struct samr_QueryDomainInfo *param = arg; 426 struct samr_QueryDomainInfoRes *info; 427 ndr_hdid_t *id = (ndr_hdid_t *)¶m->domain_handle; 428 ndr_handle_t *hd; 429 samr_keydata_t *data; 430 char *domain; 431 char hostname[NETBIOS_NAME_SZ]; 432 int alias_cnt, user_cnt; 433 int rc = 0; 434 435 if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) { 436 bzero(param, sizeof (struct samr_QueryDomainInfo)); 437 param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); 438 return (NDR_DRC_OK); 439 } 440 441 info = NDR_NEW(mxa, struct samr_QueryDomainInfoRes); 442 if (info == NULL) { 443 bzero(param, sizeof (struct samr_QueryDomainInfo)); 444 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); 445 return (NDR_DRC_OK); 446 } 447 info->switch_value = param->info_level; 448 param->info = info; 449 450 data = (samr_keydata_t *)hd->nh_data; 451 452 switch (data->kd_type) { 453 case SMB_DOMAIN_BUILTIN: 454 domain = "BUILTIN"; 455 user_cnt = 0; 456 alias_cnt = smb_sam_grp_cnt(data->kd_type); 457 break; 458 459 case SMB_DOMAIN_LOCAL: 460 rc = smb_getnetbiosname(hostname, sizeof (hostname)); 461 if (rc == 0) { 462 domain = hostname; 463 user_cnt = smb_sam_usr_cnt(); 464 alias_cnt = smb_sam_grp_cnt(data->kd_type); 465 } 466 break; 467 468 default: 469 bzero(param, sizeof (struct samr_QueryDomainInfo)); 470 param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); 471 return (NDR_DRC_OK); 472 } 473 474 if (rc != 0) { 475 bzero(param, sizeof (struct samr_QueryDomainInfo)); 476 param->status = NT_SC_ERROR(NT_STATUS_INTERNAL_ERROR); 477 return (NDR_DRC_OK); 478 } 479 480 switch (param->info_level) { 481 case SAMR_QUERY_DOMAIN_INFO_6: 482 info->ru.info6.unknown1 = 0x00000000; 483 info->ru.info6.unknown2 = 0x00147FB0; 484 info->ru.info6.unknown3 = 0x00000000; 485 info->ru.info6.unknown4 = 0x00000000; 486 info->ru.info6.unknown5 = 0x00000000; 487 param->status = NT_STATUS_SUCCESS; 488 break; 489 490 case SAMR_QUERY_DOMAIN_INFO_7: 491 info->ru.info7.unknown1 = 0x00000003; 492 param->status = NT_STATUS_SUCCESS; 493 break; 494 495 case SAMR_QUERY_DOMAIN_INFO_2: 496 info->ru.info2.unknown1 = 0x00000000; 497 info->ru.info2.unknown2 = 0x80000000; 498 499 (void) NDR_MSTRING(mxa, "", 500 (ndr_mstring_t *)&(info->ru.info2.s1)); 501 (void) NDR_MSTRING(mxa, domain, 502 (ndr_mstring_t *)&(info->ru.info2.domain)); 503 (void) NDR_MSTRING(mxa, "", 504 (ndr_mstring_t *)&(info->ru.info2.s2)); 505 506 info->ru.info2.sequence_num = 0x0000002B; 507 info->ru.info2.unknown3 = 0x00000000; 508 info->ru.info2.unknown4 = 0x00000001; 509 info->ru.info2.unknown5 = 0x00000003; 510 info->ru.info2.unknown6 = 0x00000001; 511 info->ru.info2.num_users = user_cnt; 512 info->ru.info2.num_groups = 0; 513 info->ru.info2.num_aliases = alias_cnt; 514 param->status = NT_STATUS_SUCCESS; 515 break; 516 517 default: 518 bzero(param, sizeof (struct samr_QueryDomainInfo)); 519 return (NDR_DRC_FAULT_REQUEST_OPNUM_INVALID); 520 }; 521 522 return (NDR_DRC_OK); 523 } 524 525 /* 526 * Looks up the given name in the specified domain which could 527 * be either the built-in or local domain. 528 * 529 * CAVEAT: this function should be able to handle a list of 530 * names but currently it can only handle one name at a time. 531 */ 532 static int 533 samr_s_LookupNames(void *arg, ndr_xa_t *mxa) 534 { 535 struct samr_LookupNames *param = arg; 536 ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 537 ndr_handle_t *hd; 538 samr_keydata_t *data; 539 smb_account_t account; 540 smb_wka_t *wka; 541 uint32_t status = NT_STATUS_SUCCESS; 542 543 if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) 544 status = NT_STATUS_INVALID_HANDLE; 545 546 if (param->n_entry != 1) 547 status = NT_STATUS_ACCESS_DENIED; 548 549 if (param->name.str == NULL) { 550 /* 551 * Windows NT returns NT_STATUS_NONE_MAPPED. 552 * Windows 2000 returns STATUS_INVALID_ACCOUNT_NAME. 553 */ 554 status = NT_STATUS_NONE_MAPPED; 555 } 556 557 if (status != NT_STATUS_SUCCESS) { 558 bzero(param, sizeof (struct samr_LookupNames)); 559 param->status = NT_SC_ERROR(status); 560 return (NDR_DRC_OK); 561 } 562 563 param->rids.rid = NDR_NEW(mxa, DWORD); 564 param->rid_types.rid_type = NDR_NEW(mxa, DWORD); 565 566 data = (samr_keydata_t *)hd->nh_data; 567 568 switch (data->kd_type) { 569 case SMB_DOMAIN_BUILTIN: 570 wka = smb_wka_lookup_name((char *)param->name.str); 571 if (wka != NULL) { 572 param->rids.n_entry = 1; 573 (void) smb_sid_getrid(wka->wka_binsid, 574 ¶m->rids.rid[0]); 575 param->rid_types.n_entry = 1; 576 param->rid_types.rid_type[0] = wka->wka_type; 577 param->status = NT_STATUS_SUCCESS; 578 return (NDR_DRC_OK); 579 } 580 break; 581 582 case SMB_DOMAIN_LOCAL: 583 status = smb_sam_lookup_name(NULL, (char *)param->name.str, 584 SidTypeUnknown, &account); 585 if (status == NT_STATUS_SUCCESS) { 586 param->rids.n_entry = 1; 587 param->rids.rid[0] = account.a_rid; 588 param->rid_types.n_entry = 1; 589 param->rid_types.rid_type[0] = account.a_type; 590 param->status = NT_STATUS_SUCCESS; 591 smb_account_free(&account); 592 return (NDR_DRC_OK); 593 } 594 break; 595 596 default: 597 bzero(param, sizeof (struct samr_LookupNames)); 598 param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); 599 return (NDR_DRC_OK); 600 } 601 602 param->rids.n_entry = 0; 603 param->rid_types.n_entry = 0; 604 param->status = NT_SC_ERROR(NT_STATUS_NONE_MAPPED); 605 return (NDR_DRC_OK); 606 } 607 608 /* 609 * samr_s_OpenUser 610 * 611 * This is a request to open a user within a specified domain in the 612 * local SAM database. The caller must supply a valid domain handle, 613 * obtained via a successful domain open request. The user is 614 * specified by the rid in the request. 615 */ 616 static int 617 samr_s_OpenUser(void *arg, ndr_xa_t *mxa) 618 { 619 struct samr_OpenUser *param = arg; 620 ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 621 ndr_handle_t *hd; 622 samr_keydata_t *data; 623 624 if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) { 625 bzero(¶m->user_handle, sizeof (samr_handle_t)); 626 param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); 627 return (NDR_DRC_OK); 628 } 629 630 data = (samr_keydata_t *)hd->nh_data; 631 632 id = samr_hdalloc(mxa, SAMR_KEY_USER, data->kd_type, param->rid); 633 if (id == NULL) { 634 bzero(¶m->user_handle, sizeof (samr_handle_t)); 635 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); 636 } else { 637 bcopy(id, ¶m->user_handle, sizeof (samr_handle_t)); 638 param->status = NT_STATUS_SUCCESS; 639 } 640 641 return (NDR_DRC_OK); 642 } 643 644 /* 645 * samr_s_DeleteUser 646 * 647 * Request to delete a user within a specified domain in the local 648 * SAM database. The caller should supply a valid user handle. 649 */ 650 /*ARGSUSED*/ 651 static int 652 samr_s_DeleteUser(void *arg, ndr_xa_t *mxa) 653 { 654 struct samr_DeleteUser *param = arg; 655 656 bzero(param, sizeof (struct samr_DeleteUser)); 657 param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); 658 return (NDR_DRC_OK); 659 } 660 661 /* 662 * samr_s_QueryUserInfo 663 * 664 * Returns: 665 * NT_STATUS_SUCCESS 666 * NT_STATUS_ACCESS_DENIED 667 * NT_STATUS_INVALID_INFO_CLASS 668 */ 669 /*ARGSUSED*/ 670 static int 671 samr_s_QueryUserInfo(void *arg, ndr_xa_t *mxa) 672 { 673 static uint16_t owf_buf[8]; 674 static uint8_t hour_buf[SAMR_SET_USER_HOURS_SZ]; 675 struct samr_QueryUserInfo *param = arg; 676 struct samr_QueryUserInfo21 *all_info; 677 ndr_hdid_t *id; 678 ndr_handle_t *hd; 679 samr_keydata_t *data; 680 smb_domain_t di; 681 smb_account_t account; 682 smb_sid_t *sid; 683 uint32_t status; 684 685 id = (ndr_hdid_t *)¶m->user_handle; 686 if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_USER)) == NULL) { 687 status = NT_STATUS_INVALID_HANDLE; 688 goto QueryUserInfoError; 689 } 690 691 data = (samr_keydata_t *)hd->nh_data; 692 693 if (param->switch_value != SAMR_QUERY_USER_ALL_INFO) { 694 status = NT_STATUS_ACCESS_DENIED; 695 goto QueryUserInfoError; 696 } 697 698 if (!smb_domain_lookup_type(SMB_DOMAIN_LOCAL, &di)) { 699 status = NT_STATUS_ACCESS_DENIED; 700 goto QueryUserInfoError; 701 } 702 703 if ((sid = smb_sid_splice(di.di_binsid, data->kd_rid)) == NULL) { 704 status = NT_STATUS_ACCESS_DENIED; 705 goto QueryUserInfoError; 706 } 707 708 if (smb_sam_lookup_sid(sid, &account) != NT_STATUS_SUCCESS) { 709 status = NT_STATUS_ACCESS_DENIED; 710 goto QueryUserInfoError; 711 } 712 713 all_info = ¶m->ru.info21; 714 bzero(all_info, sizeof (struct samr_QueryUserInfo21)); 715 716 all_info->WhichFields = SAMR_USER_ALL_USERNAME | SAMR_USER_ALL_USERID; 717 718 (void) NDR_MSTRING(mxa, account.a_name, 719 (ndr_mstring_t *)&all_info->UserName); 720 all_info->UserId = data->kd_rid; 721 722 all_info->LmOwfPassword.length = 16; 723 all_info->LmOwfPassword.maxlen = 16; 724 all_info->LmOwfPassword.buf = owf_buf; 725 all_info->NtOwfPassword.length = 16; 726 all_info->NtOwfPassword.maxlen = 16; 727 all_info->NtOwfPassword.buf = owf_buf; 728 all_info->LogonHours.units_per_week = SAMR_HOURS_PER_WEEK; 729 all_info->LogonHours.hours = hour_buf; 730 731 param->address = 1; 732 param->switch_index = SAMR_QUERY_USER_ALL_INFO; 733 param->status = NT_STATUS_SUCCESS; 734 return (NDR_DRC_OK); 735 736 QueryUserInfoError: 737 bzero(param, sizeof (struct samr_QueryUserInfo)); 738 param->status = NT_SC_ERROR(status); 739 return (NDR_DRC_OK); 740 } 741 742 /* 743 * samr_s_QueryUserGroups 744 * 745 * Request the list of groups of which a user is a member. 746 * The user is identified from the handle, which contains an 747 * rid in the discriminator field. Note that this is a local user. 748 */ 749 static int 750 samr_s_QueryUserGroups(void *arg, ndr_xa_t *mxa) 751 { 752 struct samr_QueryUserGroups *param = arg; 753 struct samr_UserGroupInfo *info; 754 struct samr_UserGroups *group; 755 ndr_hdid_t *id = (ndr_hdid_t *)¶m->user_handle; 756 ndr_handle_t *hd; 757 samr_keydata_t *data; 758 smb_sid_t *user_sid = NULL; 759 smb_group_t grp; 760 smb_giter_t gi; 761 smb_domain_t di; 762 uint32_t status; 763 int size; 764 int ngrp_max; 765 766 if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_USER)) == NULL) { 767 status = NT_STATUS_ACCESS_DENIED; 768 goto query_error; 769 } 770 771 data = (samr_keydata_t *)hd->nh_data; 772 switch (data->kd_type) { 773 case SMB_DOMAIN_BUILTIN: 774 case SMB_DOMAIN_LOCAL: 775 if (!smb_domain_lookup_type(data->kd_type, &di)) { 776 status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; 777 goto query_error; 778 } 779 break; 780 default: 781 status = NT_STATUS_INVALID_HANDLE; 782 goto query_error; 783 } 784 785 user_sid = smb_sid_splice(di.di_binsid, data->kd_rid); 786 if (user_sid == NULL) { 787 status = NT_STATUS_NO_MEMORY; 788 goto query_error; 789 } 790 791 info = NDR_NEW(mxa, struct samr_UserGroupInfo); 792 if (info == NULL) { 793 status = NT_STATUS_NO_MEMORY; 794 goto query_error; 795 } 796 bzero(info, sizeof (struct samr_UserGroupInfo)); 797 798 size = 32 * 1024; 799 info->groups = NDR_MALLOC(mxa, size); 800 if (info->groups == NULL) { 801 status = NT_STATUS_NO_MEMORY; 802 goto query_error; 803 } 804 ngrp_max = size / sizeof (struct samr_UserGroups); 805 806 if (smb_lgrp_iteropen(&gi) != SMB_LGRP_SUCCESS) { 807 status = NT_STATUS_INTERNAL_ERROR; 808 goto query_error; 809 } 810 811 info->n_entry = 0; 812 group = info->groups; 813 while ((info->n_entry < ngrp_max) && 814 (smb_lgrp_iterate(&gi, &grp) == SMB_LGRP_SUCCESS)) { 815 if (smb_lgrp_is_member(&grp, user_sid)) { 816 group->rid = grp.sg_rid; 817 group->attr = grp.sg_attr; 818 group++; 819 info->n_entry++; 820 } 821 smb_lgrp_free(&grp); 822 } 823 smb_lgrp_iterclose(&gi); 824 825 free(user_sid); 826 param->info = info; 827 param->status = NT_STATUS_SUCCESS; 828 return (NDR_DRC_OK); 829 830 query_error: 831 free(user_sid); 832 bzero(param, sizeof (struct samr_QueryUserGroups)); 833 param->status = NT_SC_ERROR(status); 834 return (NDR_DRC_OK); 835 } 836 837 /* 838 * samr_s_OpenGroup 839 * 840 * This is a request to open a group within the specified domain in the 841 * local SAM database. The caller must supply a valid domain handle, 842 * obtained via a successful domain open request. The group is 843 * specified by the rid in the request. If this is a local RID it 844 * should already be encoded with type information. 845 * 846 * We return a handle to be used to access information about this group. 847 */ 848 static int 849 samr_s_OpenGroup(void *arg, ndr_xa_t *mxa) 850 { 851 struct samr_OpenGroup *param = arg; 852 ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 853 ndr_handle_t *hd; 854 samr_keydata_t *data; 855 856 if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) { 857 bzero(¶m->group_handle, sizeof (samr_handle_t)); 858 param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); 859 return (NDR_DRC_OK); 860 } 861 862 data = (samr_keydata_t *)hd->nh_data; 863 id = samr_hdalloc(mxa, SAMR_KEY_GROUP, data->kd_type, param->rid); 864 865 if (id) { 866 bcopy(id, ¶m->group_handle, sizeof (samr_handle_t)); 867 param->status = 0; 868 } else { 869 bzero(¶m->group_handle, sizeof (samr_handle_t)); 870 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); 871 } 872 873 return (NDR_DRC_OK); 874 } 875 876 /* 877 * samr_s_Connect 878 * 879 * This is a request to connect to the local SAM database. 880 * We don't support any form of update request and our database doesn't 881 * contain any private information, so there is little point in doing 882 * any access access checking here. 883 * 884 * Return a handle for use with subsequent SAM requests. 885 */ 886 static int 887 samr_s_Connect(void *arg, ndr_xa_t *mxa) 888 { 889 struct samr_Connect *param = arg; 890 ndr_hdid_t *id; 891 892 id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, SMB_DOMAIN_NULL, 0); 893 if (id) { 894 bcopy(id, ¶m->handle, sizeof (samr_handle_t)); 895 param->status = 0; 896 } else { 897 bzero(¶m->handle, sizeof (samr_handle_t)); 898 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); 899 } 900 901 return (NDR_DRC_OK); 902 } 903 904 /* 905 * samr_s_GetUserPwInfo 906 * 907 * This is a request to get a user's password. 908 */ 909 /*ARGSUSED*/ 910 static int 911 samr_s_GetUserPwInfo(void *arg, ndr_xa_t *mxa) 912 { 913 struct samr_GetUserPwInfo *param = arg; 914 915 bzero(param, sizeof (struct samr_GetUserPwInfo)); 916 param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); 917 return (NDR_DRC_OK); 918 } 919 920 /* 921 * samr_s_CreateUser 922 */ 923 /*ARGSUSED*/ 924 static int 925 samr_s_CreateUser(void *arg, ndr_xa_t *mxa) 926 { 927 struct samr_CreateUser *param = arg; 928 929 bzero(¶m->user_handle, sizeof (samr_handle_t)); 930 param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); 931 return (NDR_DRC_OK); 932 } 933 934 /* 935 * samr_s_ChangeUserPasswd 936 */ 937 /*ARGSUSED*/ 938 static int 939 samr_s_ChangeUserPasswd(void *arg, ndr_xa_t *mxa) 940 { 941 struct samr_ChangeUserPasswd *param = arg; 942 943 bzero(param, sizeof (struct samr_ChangeUserPasswd)); 944 param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); 945 return (NDR_DRC_OK); 946 } 947 948 /* 949 * samr_s_GetDomainPwInfo 950 */ 951 /*ARGSUSED*/ 952 static int 953 samr_s_GetDomainPwInfo(void *arg, ndr_xa_t *mxa) 954 { 955 struct samr_GetDomainPwInfo *param = arg; 956 957 bzero(param, sizeof (struct samr_GetDomainPwInfo)); 958 param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); 959 return (NDR_DRC_OK); 960 } 961 962 /* 963 * samr_s_SetUserInfo 964 */ 965 /*ARGSUSED*/ 966 static int 967 samr_s_SetUserInfo(void *arg, ndr_xa_t *mxa) 968 { 969 struct samr_SetUserInfo *param = arg; 970 971 bzero(param, sizeof (struct samr_SetUserInfo)); 972 param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); 973 return (NDR_DRC_OK); 974 } 975 976 /* 977 * samr_s_QueryDispInfo 978 * 979 * This function currently return local users' information only. 980 * This RPC is called repeatedly until all the users info are 981 * retrieved. 982 * 983 * The total count and the returned count are returned as total size 984 * and returned size. The client doesn't seem to care. 985 */ 986 static int 987 samr_s_QueryDispInfo(void *arg, ndr_xa_t *mxa) 988 { 989 struct samr_QueryDispInfo *param = arg; 990 ndr_hdid_t *id = (ndr_hdid_t *)¶m->domain_handle; 991 ndr_handle_t *hd; 992 samr_keydata_t *data; 993 DWORD status = NT_STATUS_SUCCESS; 994 struct user_acct_info *user; 995 smb_pwditer_t pwi; 996 smb_luser_t *uinfo; 997 int num_users; 998 int start_idx; 999 int max_retcnt, retcnt; 1000 int skip; 1001 1002 if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) { 1003 status = NT_STATUS_INVALID_HANDLE; 1004 goto error; 1005 } 1006 1007 if (!SAMR_VALID_DISPLEVEL(param->level)) { 1008 status = NT_STATUS_INVALID_INFO_CLASS; 1009 goto error; 1010 } 1011 1012 if (!SAMR_SUPPORTED_DISPLEVEL(param->level)) { 1013 status = NT_STATUS_NOT_IMPLEMENTED; 1014 goto error; 1015 } 1016 1017 data = (samr_keydata_t *)hd->nh_data; 1018 1019 switch (data->kd_type) { 1020 case SMB_DOMAIN_BUILTIN: 1021 goto no_info; 1022 1023 case SMB_DOMAIN_LOCAL: 1024 num_users = smb_sam_usr_cnt(); 1025 start_idx = param->start_idx; 1026 if ((num_users == 0) || (start_idx >= num_users)) 1027 goto no_info; 1028 1029 max_retcnt = num_users - start_idx; 1030 if (max_retcnt > param->max_entries) 1031 max_retcnt = param->max_entries; 1032 param->users.acct = NDR_MALLOC(mxa, 1033 max_retcnt * sizeof (struct user_acct_info)); 1034 user = param->users.acct; 1035 if (user == NULL) { 1036 status = NT_STATUS_NO_MEMORY; 1037 goto error; 1038 } 1039 bzero(user, max_retcnt * sizeof (struct user_acct_info)); 1040 1041 if (smb_pwd_iteropen(&pwi) != SMB_PWE_SUCCESS) 1042 goto no_info; 1043 1044 skip = retcnt = 0; 1045 while ((uinfo = smb_pwd_iterate(&pwi)) != NULL) { 1046 if (skip++ < start_idx) 1047 continue; 1048 1049 if (retcnt++ >= max_retcnt) 1050 break; 1051 1052 assert(uinfo->su_name != NULL); 1053 1054 user->index = start_idx + retcnt; 1055 user->rid = uinfo->su_rid; 1056 user->ctrl = ACF_NORMUSER | ACF_PWDNOEXP; 1057 if (uinfo->su_ctrl & SMB_PWF_DISABLE) 1058 user->ctrl |= ACF_DISABLED; 1059 if (NDR_MSTRING(mxa, uinfo->su_name, 1060 (ndr_mstring_t *)&user->name) == -1) { 1061 smb_pwd_iterclose(&pwi); 1062 status = NT_STATUS_NO_MEMORY; 1063 goto error; 1064 } 1065 (void) NDR_MSTRING(mxa, uinfo->su_fullname, 1066 (ndr_mstring_t *)&user->fullname); 1067 (void) NDR_MSTRING(mxa, uinfo->su_desc, 1068 (ndr_mstring_t *)&user->desc); 1069 user++; 1070 } 1071 smb_pwd_iterclose(&pwi); 1072 1073 if (retcnt >= max_retcnt) { 1074 retcnt = max_retcnt; 1075 param->status = status; 1076 } else { 1077 param->status = ERROR_MORE_ENTRIES; 1078 } 1079 1080 param->users.total_size = num_users; 1081 param->users.returned_size = retcnt; 1082 param->users.switch_value = param->level; 1083 param->users.count = retcnt; 1084 1085 break; 1086 1087 default: 1088 status = NT_STATUS_INVALID_HANDLE; 1089 goto error; 1090 } 1091 1092 return (NDR_DRC_OK); 1093 1094 no_info: 1095 param->users.total_size = 0; 1096 param->users.returned_size = 0; 1097 param->users.switch_value = param->level; 1098 param->users.count = 0; 1099 param->users.acct = NULL; 1100 param->status = status; 1101 return (NDR_DRC_OK); 1102 1103 error: 1104 bzero(param, sizeof (struct samr_QueryDispInfo)); 1105 param->status = NT_SC_ERROR(status); 1106 return (NDR_DRC_OK); 1107 } 1108 1109 /* 1110 * samr_s_EnumDomainGroups 1111 * 1112 * 1113 * This function is supposed to return local group information. 1114 * As we don't support local users, this function dosen't send 1115 * back any information. 1116 * 1117 * Added template that returns information for a domain group as None. 1118 * All information is hard-coded from packet captures. 1119 */ 1120 static int 1121 samr_s_EnumDomainGroups(void *arg, ndr_xa_t *mxa) 1122 { 1123 struct samr_EnumDomainGroups *param = arg; 1124 ndr_hdid_t *id = (ndr_hdid_t *)¶m->domain_handle; 1125 DWORD status = NT_STATUS_SUCCESS; 1126 1127 if (samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN) == NULL) 1128 status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); 1129 1130 param->total_size = 0; 1131 param->returned_size = 0; 1132 param->switch_value = 3; 1133 param->count = 0; 1134 param->groups = 0; 1135 param->status = status; 1136 return (NDR_DRC_OK); 1137 1138 #ifdef SAMR_SUPPORT_GROUPS 1139 if ((desc->discrim != SAMR_LOCAL_DOMAIN) || (param->start_idx != 0)) { 1140 param->total_size = 0; 1141 param->returned_size = 0; 1142 param->switch_value = 3; 1143 param->count = 0; 1144 param->groups = 0; 1145 } else { 1146 param->total_size = 64; 1147 param->returned_size = 64; 1148 param->switch_value = 3; 1149 param->count = 1; 1150 param->groups = (struct group_disp_info *)NDR_MALLOC( 1151 mxa, sizeof (struct group_disp_info)); 1152 1153 param->groups->count = 1; 1154 param->groups->acct[0].index = 1; 1155 param->groups->acct[0].rid = 513; 1156 param->groups->acct[0].ctrl = 0x7; 1157 (void) NDR_MSTRING(mxa, "None", 1158 (ndr_mstring_t *)¶m->groups->acct[0].name); 1159 1160 (void) NDR_MSTRING(mxa, "Ordinary users", 1161 (ndr_mstring_t *)¶m->groups->acct[0].desc); 1162 } 1163 1164 param->status = NT_STATUS_SUCCESS; 1165 return (NDR_DRC_OK); 1166 #endif 1167 } 1168 1169 /* 1170 * samr_s_OpenAlias 1171 * 1172 * Lookup for requested alias, if it exists return a handle 1173 * for that alias. The alias domain sid should match with 1174 * the passed domain handle. 1175 */ 1176 static int 1177 samr_s_OpenAlias(void *arg, ndr_xa_t *mxa) 1178 { 1179 struct samr_OpenAlias *param = arg; 1180 ndr_hdid_t *id = (ndr_hdid_t *)¶m->domain_handle; 1181 ndr_handle_t *hd; 1182 uint32_t status; 1183 samr_keydata_t *data; 1184 int rc; 1185 1186 if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) { 1187 status = NT_STATUS_INVALID_HANDLE; 1188 goto open_alias_err; 1189 } 1190 1191 if (param->access_mask != SAMR_ALIAS_ACCESS_GET_INFO) { 1192 status = NT_STATUS_ACCESS_DENIED; 1193 goto open_alias_err; 1194 } 1195 1196 data = (samr_keydata_t *)hd->nh_data; 1197 rc = smb_lgrp_getbyrid(param->rid, (smb_gdomain_t)data->kd_type, NULL); 1198 if (rc != SMB_LGRP_SUCCESS) { 1199 status = NT_STATUS_NO_SUCH_ALIAS; 1200 goto open_alias_err; 1201 } 1202 1203 id = samr_hdalloc(mxa, SAMR_KEY_ALIAS, data->kd_type, param->rid); 1204 if (id) { 1205 bcopy(id, ¶m->alias_handle, sizeof (samr_handle_t)); 1206 param->status = NT_STATUS_SUCCESS; 1207 return (NDR_DRC_OK); 1208 } 1209 1210 status = NT_STATUS_NO_MEMORY; 1211 1212 open_alias_err: 1213 bzero(¶m->alias_handle, sizeof (samr_handle_t)); 1214 param->status = NT_SC_ERROR(status); 1215 return (NDR_DRC_OK); 1216 } 1217 1218 /* 1219 * samr_s_CreateDomainAlias 1220 * 1221 * Creates a local group in the security database, which is the 1222 * security accounts manager (SAM) 1223 * For more information you can look at MSDN page for NetLocalGroupAdd. 1224 * This RPC is used by CMC and right now it returns access denied. 1225 * The peice of code that creates a local group doesn't get compiled. 1226 */ 1227 /*ARGSUSED*/ 1228 static int 1229 samr_s_CreateDomainAlias(void *arg, ndr_xa_t *mxa) 1230 { 1231 struct samr_CreateDomainAlias *param = arg; 1232 ndr_hdid_t *id = (ndr_hdid_t *)¶m->alias_handle; 1233 1234 if (samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN) == NULL) { 1235 bzero(param, sizeof (struct samr_CreateDomainAlias)); 1236 param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); 1237 return (NDR_DRC_OK); 1238 } 1239 1240 bzero(param, sizeof (struct samr_CreateDomainAlias)); 1241 param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); 1242 return (NDR_DRC_OK); 1243 1244 #ifdef SAMR_SUPPORT_ADD_ALIAS 1245 DWORD status = NT_STATUS_SUCCESS; 1246 nt_group_t *grp; 1247 char *alias_name; 1248 1249 alias_name = param->alias_name.str; 1250 if (alias_name == 0) { 1251 status = NT_STATUS_INVALID_PARAMETER; 1252 goto create_alias_err; 1253 } 1254 1255 /* 1256 * Check access mask. User should be member of 1257 * Administrators or Account Operators local group. 1258 */ 1259 status = nt_group_add(alias_name, 0, 1260 NT_GROUP_AF_ADD | NT_GROUP_AF_LOCAL); 1261 1262 if (status != NT_STATUS_SUCCESS) 1263 goto create_alias_err; 1264 1265 grp = nt_group_getinfo(alias_name, RWLOCK_READER); 1266 if (grp == NULL) { 1267 status = NT_STATUS_INTERNAL_ERROR; 1268 goto create_alias_err; 1269 } 1270 1271 (void) smb_sid_getrid(grp->sid, ¶m->rid); 1272 nt_group_putinfo(grp); 1273 handle = mlsvc_get_handle(MLSVC_IFSPEC_SAMR, SAMR_ALIAS_KEY, 1274 param->rid); 1275 bcopy(handle, ¶m->alias_handle, sizeof (samr_handle_t)); 1276 1277 param->status = 0; 1278 return (NDR_DRC_OK); 1279 1280 create_alias_err: 1281 bzero(¶m->alias_handle, sizeof (samr_handle_t)); 1282 param->status = NT_SC_ERROR(status); 1283 return (NDR_DRC_OK); 1284 #endif 1285 } 1286 1287 /* 1288 * samr_s_SetAliasInfo 1289 * 1290 * Similar to NetLocalGroupSetInfo. 1291 */ 1292 static int 1293 samr_s_SetAliasInfo(void *arg, ndr_xa_t *mxa) 1294 { 1295 struct samr_SetAliasInfo *param = arg; 1296 ndr_hdid_t *id = (ndr_hdid_t *)¶m->alias_handle; 1297 DWORD status = NT_STATUS_SUCCESS; 1298 1299 if (samr_hdlookup(mxa, id, SAMR_KEY_ALIAS) == NULL) 1300 status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); 1301 1302 param->status = status; 1303 return (NDR_DRC_OK); 1304 } 1305 1306 /* 1307 * samr_s_QueryAliasInfo 1308 * 1309 * Retrieves information about the specified local group account 1310 * by given handle. 1311 */ 1312 static int 1313 samr_s_QueryAliasInfo(void *arg, ndr_xa_t *mxa) 1314 { 1315 struct samr_QueryAliasInfo *param = arg; 1316 ndr_hdid_t *id = (ndr_hdid_t *)¶m->alias_handle; 1317 ndr_handle_t *hd; 1318 samr_keydata_t *data; 1319 smb_group_t grp; 1320 uint32_t status; 1321 int rc; 1322 1323 if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_ALIAS)) == NULL) { 1324 status = NT_STATUS_INVALID_HANDLE; 1325 goto query_alias_err; 1326 } 1327 1328 data = (samr_keydata_t *)hd->nh_data; 1329 rc = smb_lgrp_getbyrid(data->kd_rid, (smb_gdomain_t)data->kd_type, 1330 &grp); 1331 if (rc != SMB_LGRP_SUCCESS) { 1332 status = NT_STATUS_NO_SUCH_ALIAS; 1333 goto query_alias_err; 1334 } 1335 1336 switch (param->level) { 1337 case SAMR_QUERY_ALIAS_INFO_1: 1338 param->ru.info1.level = param->level; 1339 (void) NDR_MSTRING(mxa, grp.sg_name, 1340 (ndr_mstring_t *)¶m->ru.info1.name); 1341 1342 (void) NDR_MSTRING(mxa, grp.sg_cmnt, 1343 (ndr_mstring_t *)¶m->ru.info1.desc); 1344 1345 param->ru.info1.unknown = 1; 1346 break; 1347 1348 case SAMR_QUERY_ALIAS_INFO_3: 1349 param->ru.info3.level = param->level; 1350 (void) NDR_MSTRING(mxa, grp.sg_cmnt, 1351 (ndr_mstring_t *)¶m->ru.info3.desc); 1352 break; 1353 1354 default: 1355 smb_lgrp_free(&grp); 1356 status = NT_STATUS_INVALID_INFO_CLASS; 1357 goto query_alias_err; 1358 }; 1359 1360 smb_lgrp_free(&grp); 1361 param->address = (DWORD)(uintptr_t)¶m->ru; 1362 param->status = 0; 1363 return (NDR_DRC_OK); 1364 1365 query_alias_err: 1366 param->status = NT_SC_ERROR(status); 1367 return (NDR_DRC_OK); 1368 } 1369 1370 /* 1371 * samr_s_DeleteDomainAlias 1372 * 1373 * Deletes a local group account and all its members from the 1374 * security database, which is the security accounts manager (SAM) database. 1375 * Only members of the Administrators or Account Operators local group can 1376 * execute this function. 1377 * For more information you can look at MSDN page for NetLocalGroupSetInfo. 1378 * 1379 * This RPC is used by CMC and right now it returns access denied. 1380 * The peice of code that removes a local group doesn't get compiled. 1381 */ 1382 static int 1383 samr_s_DeleteDomainAlias(void *arg, ndr_xa_t *mxa) 1384 { 1385 struct samr_DeleteDomainAlias *param = arg; 1386 ndr_hdid_t *id = (ndr_hdid_t *)¶m->alias_handle; 1387 1388 if (samr_hdlookup(mxa, id, SAMR_KEY_ALIAS) == NULL) { 1389 bzero(param, sizeof (struct samr_DeleteDomainAlias)); 1390 param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); 1391 return (NDR_DRC_OK); 1392 } 1393 1394 bzero(param, sizeof (struct samr_DeleteDomainAlias)); 1395 param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); 1396 return (NDR_DRC_OK); 1397 1398 #ifdef SAMR_SUPPORT_DEL_ALIAS 1399 nt_group_t *grp; 1400 char *alias_name; 1401 DWORD status; 1402 1403 grp = nt_groups_lookup_rid(desc->discrim); 1404 if (grp == 0) { 1405 status = NT_STATUS_NO_SUCH_ALIAS; 1406 goto delete_alias_err; 1407 } 1408 1409 alias_name = strdup(grp->name); 1410 if (alias_name == 0) { 1411 status = NT_STATUS_NO_MEMORY; 1412 goto delete_alias_err; 1413 } 1414 1415 status = nt_group_delete(alias_name); 1416 free(alias_name); 1417 if (status != NT_STATUS_SUCCESS) 1418 goto delete_alias_err; 1419 1420 param->status = 0; 1421 return (NDR_DRC_OK); 1422 1423 delete_alias_err: 1424 param->status = NT_SC_ERROR(status); 1425 return (NDR_DRC_OK); 1426 #endif 1427 } 1428 1429 /* 1430 * samr_s_EnumDomainAliases 1431 * 1432 * This function sends back a list which contains all local groups' name. 1433 */ 1434 static int 1435 samr_s_EnumDomainAliases(void *arg, ndr_xa_t *mxa) 1436 { 1437 struct samr_EnumDomainAliases *param = arg; 1438 ndr_hdid_t *id = (ndr_hdid_t *)¶m->domain_handle; 1439 ndr_handle_t *hd; 1440 samr_keydata_t *data; 1441 smb_group_t grp; 1442 smb_giter_t gi; 1443 int cnt, skip, i; 1444 struct name_rid *info; 1445 1446 if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) { 1447 bzero(param, sizeof (struct samr_EnumDomainAliases)); 1448 param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); 1449 return (NDR_DRC_OK); 1450 } 1451 1452 data = (samr_keydata_t *)hd->nh_data; 1453 1454 cnt = smb_sam_grp_cnt(data->kd_type); 1455 if (cnt <= param->resume_handle) { 1456 param->aliases = (struct aliases_info *)NDR_MALLOC(mxa, 1457 sizeof (struct aliases_info)); 1458 1459 if (param->aliases == NULL) { 1460 bzero(param, sizeof (struct samr_EnumDomainAliases)); 1461 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); 1462 return (NDR_DRC_OK); 1463 } 1464 1465 bzero(param->aliases, sizeof (struct aliases_info)); 1466 param->out_resume = 0; 1467 param->entries = 0; 1468 param->status = NT_STATUS_SUCCESS; 1469 return (NDR_DRC_OK); 1470 } 1471 1472 cnt -= param->resume_handle; 1473 param->aliases = (struct aliases_info *)NDR_MALLOC(mxa, 1474 sizeof (struct aliases_info) + (cnt-1) * sizeof (struct name_rid)); 1475 1476 if (param->aliases == NULL) { 1477 bzero(param, sizeof (struct samr_EnumDomainAliases)); 1478 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); 1479 return (NDR_DRC_OK); 1480 } 1481 1482 if (smb_lgrp_iteropen(&gi) != SMB_LGRP_SUCCESS) { 1483 bzero(param, sizeof (struct samr_EnumDomainAliases)); 1484 param->status = NT_SC_ERROR(NT_STATUS_INTERNAL_ERROR); 1485 return (NDR_DRC_OK); 1486 } 1487 1488 skip = i = 0; 1489 info = param->aliases->info; 1490 while (smb_lgrp_iterate(&gi, &grp) == SMB_LGRP_SUCCESS) { 1491 if ((skip++ >= param->resume_handle) && 1492 (grp.sg_domain == data->kd_type) && (i++ < cnt)) { 1493 info->rid = grp.sg_rid; 1494 (void) NDR_MSTRING(mxa, grp.sg_name, 1495 (ndr_mstring_t *)&info->name); 1496 1497 info++; 1498 } 1499 smb_lgrp_free(&grp); 1500 } 1501 smb_lgrp_iterclose(&gi); 1502 1503 param->aliases->count = i; 1504 param->aliases->address = i; 1505 1506 param->out_resume = i; 1507 param->entries = i; 1508 param->status = 0; 1509 return (NDR_DRC_OK); 1510 } 1511 1512 /* 1513 * samr_s_Connect3 1514 * 1515 * This is the connect3 form of the connect request. It contains an 1516 * extra parameter over samr_Connect. See samr_s_Connect for other 1517 * details. NT returns an RPC fault - so we can do the same for now. 1518 * Doing it this way should avoid the unsupported opnum error message 1519 * appearing in the log. 1520 */ 1521 /*ARGSUSED*/ 1522 static int 1523 samr_s_Connect3(void *arg, ndr_xa_t *mxa) 1524 { 1525 struct samr_Connect3 *param = arg; 1526 1527 bzero(param, sizeof (struct samr_Connect3)); 1528 return (NDR_DRC_FAULT_REQUEST_OPNUM_INVALID); 1529 } 1530 1531 1532 /* 1533 * samr_s_Connect4 1534 * 1535 * This is the connect4 form of the connect request used by Windows XP. 1536 * Returns an RPC fault for now. 1537 */ 1538 /*ARGSUSED*/ 1539 static int 1540 samr_s_Connect4(void *arg, ndr_xa_t *mxa) 1541 { 1542 struct samr_Connect4 *param = arg; 1543 1544 bzero(param, sizeof (struct samr_Connect4)); 1545 return (NDR_DRC_FAULT_REQUEST_OPNUM_INVALID); 1546 } 1547 1548 static ndr_stub_table_t samr_stub_table[] = { 1549 { samr_s_ConnectAnon, SAMR_OPNUM_ConnectAnon }, 1550 { samr_s_CloseHandle, SAMR_OPNUM_CloseHandle }, 1551 { samr_s_LookupDomain, SAMR_OPNUM_LookupDomain }, 1552 { samr_s_EnumLocalDomains, SAMR_OPNUM_EnumLocalDomains }, 1553 { samr_s_OpenDomain, SAMR_OPNUM_OpenDomain }, 1554 { samr_s_QueryDomainInfo, SAMR_OPNUM_QueryDomainInfo }, 1555 { samr_s_LookupNames, SAMR_OPNUM_LookupNames }, 1556 { samr_s_OpenUser, SAMR_OPNUM_OpenUser }, 1557 { samr_s_DeleteUser, SAMR_OPNUM_DeleteUser }, 1558 { samr_s_QueryUserInfo, SAMR_OPNUM_QueryUserInfo }, 1559 { samr_s_QueryUserGroups, SAMR_OPNUM_QueryUserGroups }, 1560 { samr_s_OpenGroup, SAMR_OPNUM_OpenGroup }, 1561 { samr_s_Connect, SAMR_OPNUM_Connect }, 1562 { samr_s_GetUserPwInfo, SAMR_OPNUM_GetUserPwInfo }, 1563 { samr_s_CreateUser, SAMR_OPNUM_CreateUser }, 1564 { samr_s_ChangeUserPasswd, SAMR_OPNUM_ChangeUserPasswd }, 1565 { samr_s_GetDomainPwInfo, SAMR_OPNUM_GetDomainPwInfo }, 1566 { samr_s_SetUserInfo, SAMR_OPNUM_SetUserInfo }, 1567 { samr_s_Connect3, SAMR_OPNUM_Connect3 }, 1568 { samr_s_Connect4, SAMR_OPNUM_Connect4 }, 1569 { samr_s_QueryDispInfo, SAMR_OPNUM_QueryDispInfo }, 1570 { samr_s_OpenAlias, SAMR_OPNUM_OpenAlias }, 1571 { samr_s_CreateDomainAlias, SAMR_OPNUM_CreateDomainAlias }, 1572 { samr_s_SetAliasInfo, SAMR_OPNUM_SetAliasInfo }, 1573 { samr_s_QueryAliasInfo, SAMR_OPNUM_QueryAliasInfo }, 1574 { samr_s_DeleteDomainAlias, SAMR_OPNUM_DeleteDomainAlias }, 1575 { samr_s_EnumDomainAliases, SAMR_OPNUM_EnumDomainAliases }, 1576 { samr_s_EnumDomainGroups, SAMR_OPNUM_EnumDomainGroups }, 1577 {0} 1578 }; 1579 1580 /* 1581 * There is a bug in the way that midl and the marshalling code handles 1582 * unions so we need to fix some of the data offsets at runtime. The 1583 * following macros and the fixup functions handle the corrections. 1584 */ 1585 1586 DECL_FIXUP_STRUCT(samr_QueryAliasInfo_ru); 1587 DECL_FIXUP_STRUCT(samr_QueryAliasInfoRes); 1588 DECL_FIXUP_STRUCT(samr_QueryAliasInfo); 1589 1590 DECL_FIXUP_STRUCT(QueryUserInfo_result_u); 1591 DECL_FIXUP_STRUCT(QueryUserInfo_result); 1592 DECL_FIXUP_STRUCT(samr_QueryUserInfo); 1593 1594 void 1595 fixup_samr_QueryAliasInfo(struct samr_QueryAliasInfo *val) 1596 { 1597 unsigned short size1 = 0; 1598 unsigned short size2 = 0; 1599 unsigned short size3 = 0; 1600 1601 switch (val->level) { 1602 CASE_INFO_ENT(samr_QueryAliasInfo, 1); 1603 CASE_INFO_ENT(samr_QueryAliasInfo, 3); 1604 1605 default: 1606 return; 1607 }; 1608 1609 size2 = size1 + (2 * sizeof (DWORD)); 1610 size3 = size2 + sizeof (ndr_request_hdr_t) + sizeof (DWORD); 1611 1612 FIXUP_PDU_SIZE(samr_QueryAliasInfo_ru, size1); 1613 FIXUP_PDU_SIZE(samr_QueryAliasInfoRes, size2); 1614 FIXUP_PDU_SIZE(samr_QueryAliasInfo, size3); 1615 } 1616 1617 void 1618 fixup_samr_QueryUserInfo(struct samr_QueryUserInfo *val) 1619 { 1620 unsigned short size1 = 0; 1621 unsigned short size2 = 0; 1622 unsigned short size3 = 0; 1623 1624 switch (val->switch_index) { 1625 CASE_INFO_ENT(samr_QueryUserInfo, 1); 1626 CASE_INFO_ENT(samr_QueryUserInfo, 6); 1627 CASE_INFO_ENT(samr_QueryUserInfo, 7); 1628 CASE_INFO_ENT(samr_QueryUserInfo, 8); 1629 CASE_INFO_ENT(samr_QueryUserInfo, 9); 1630 CASE_INFO_ENT(samr_QueryUserInfo, 16); 1631 CASE_INFO_ENT(samr_QueryUserInfo, 21); 1632 1633 default: 1634 return; 1635 }; 1636 1637 size2 = size1 + (2 * sizeof (DWORD)); 1638 size3 = size2 + sizeof (ndr_request_hdr_t) + sizeof (DWORD); 1639 1640 FIXUP_PDU_SIZE(QueryUserInfo_result_u, size1); 1641 FIXUP_PDU_SIZE(QueryUserInfo_result, size2); 1642 FIXUP_PDU_SIZE(samr_QueryUserInfo, size3); 1643 } 1644 1645 /* 1646 * As long as there is only one entry in the union, there is no need 1647 * to patch anything. 1648 */ 1649 /*ARGSUSED*/ 1650 void 1651 fixup_samr_QueryGroupInfo(struct samr_QueryGroupInfo *val) 1652 { 1653 } 1654