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 * This module provides the high level interface to the LSA RPC functions. 28 */ 29 30 #include <strings.h> 31 #include <unistd.h> 32 33 #include <smbsrv/libsmb.h> 34 #include <smbsrv/libmlsvc.h> 35 #include <smbsrv/libsmbrdr.h> 36 #include <smbsrv/ntstatus.h> 37 #include <smbsrv/smbinfo.h> 38 #include <smbsrv/smb_token.h> 39 40 #include <lsalib.h> 41 42 static uint32_t lsa_lookup_name_builtin(char *, char *, smb_userinfo_t *); 43 static uint32_t lsa_lookup_name_local(char *, char *, uint16_t, 44 smb_userinfo_t *); 45 static uint32_t lsa_lookup_name_domain(char *, smb_userinfo_t *); 46 static uint32_t lsa_lookup_name_lusr(char *, smb_sid_t **); 47 static uint32_t lsa_lookup_name_lgrp(char *, smb_sid_t **); 48 49 static uint32_t lsa_lookup_sid_builtin(smb_sid_t *, smb_userinfo_t *); 50 static uint32_t lsa_lookup_sid_local(smb_sid_t *, smb_userinfo_t *); 51 static uint32_t lsa_lookup_sid_domain(smb_sid_t *, smb_userinfo_t *); 52 53 static int lsa_list_accounts(mlsvc_handle_t *); 54 55 /* 56 * Lookup the given account and returns the account information 57 * in the passed smb_userinfo_t structure. 58 * 59 * The lookup is performed in the following order: 60 * well known accounts 61 * local accounts 62 * domain accounts 63 * 64 * If it's established the given account is well know or local 65 * but the lookup fails for some reason, the next step(s) won't be 66 * performed. 67 * 68 * If the name is a domain account, it may refer to a user, group or 69 * alias. If it is a local account, its type should be specified 70 * in the sid_type parameter. In case the account type is unknown 71 * sid_type should be set to SidTypeUnknown. 72 * 73 * account argument could be either [domain\]name or [domain/]name. 74 * 75 * Return status: 76 * 77 * NT_STATUS_SUCCESS Account is successfully translated 78 * NT_STATUS_NONE_MAPPED Couldn't translate the account 79 */ 80 uint32_t 81 lsa_lookup_name(char *account, uint16_t sid_type, smb_userinfo_t *info) 82 { 83 char nambuf[SMB_USERNAME_MAXLEN]; 84 char dombuf[SMB_PI_MAX_DOMAIN]; 85 char *name, *domain; 86 uint32_t status; 87 char *slash; 88 89 (void) strsubst(account, '/', '\\'); 90 (void) strcanon(account, "\\"); 91 /* \john -> john */ 92 account += strspn(account, "\\"); 93 94 if ((slash = strchr(account, '\\')) != NULL) { 95 *slash = '\0'; 96 (void) strlcpy(dombuf, account, sizeof (dombuf)); 97 (void) strlcpy(nambuf, slash + 1, sizeof (nambuf)); 98 *slash = '\\'; 99 name = nambuf; 100 domain = dombuf; 101 } else { 102 name = account; 103 domain = NULL; 104 } 105 106 status = lsa_lookup_name_builtin(domain, name, info); 107 if (status == NT_STATUS_NOT_FOUND) { 108 status = lsa_lookup_name_local(domain, name, sid_type, info); 109 if (status == NT_STATUS_SUCCESS) 110 return (status); 111 112 if ((domain == NULL) || (status == NT_STATUS_NOT_FOUND)) 113 status = lsa_lookup_name_domain(account, info); 114 } 115 116 return ((status == NT_STATUS_SUCCESS) ? status : NT_STATUS_NONE_MAPPED); 117 } 118 119 uint32_t 120 lsa_lookup_sid(smb_sid_t *sid, smb_userinfo_t *ainfo) 121 { 122 if (!smb_sid_isvalid(sid)) 123 return (NT_STATUS_INVALID_SID); 124 125 if (smb_sid_islocal(sid)) 126 return (lsa_lookup_sid_local(sid, ainfo)); 127 128 if (smb_wka_lookup_sid(sid, NULL)) 129 return (lsa_lookup_sid_builtin(sid, ainfo)); 130 131 return (lsa_lookup_sid_domain(sid, ainfo)); 132 } 133 134 /* 135 * lsa_query_primary_domain_info 136 * 137 * Obtains the primary domain SID and name from the specified server 138 * (domain controller). The information is stored in the NT domain 139 * database by the lower level lsar_query_info_policy call. The caller 140 * should query the database to obtain a reference to the primary 141 * domain information. 142 * 143 * The requested information will be returned via 'info' argument. 144 * Caller must call lsa_free_info() when done. 145 * 146 * Returns NT status codes. 147 */ 148 DWORD 149 lsa_query_primary_domain_info(char *server, char *domain, lsa_info_t *info) 150 { 151 mlsvc_handle_t domain_handle; 152 DWORD status; 153 char *user = smbrdr_ipc_get_user(); 154 155 if ((lsar_open(server, domain, user, &domain_handle)) != 0) 156 return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); 157 158 status = lsar_query_info_policy(&domain_handle, 159 MSLSA_POLICY_PRIMARY_DOMAIN_INFO, info); 160 161 (void) lsar_close(&domain_handle); 162 return (status); 163 } 164 165 /* 166 * lsa_query_account_domain_info 167 * 168 * Obtains the account domain SID and name from the current server 169 * (domain controller). The information is stored in the NT domain 170 * database by the lower level lsar_query_info_policy call. The caller 171 * should query the database to obtain a reference to the account 172 * domain information. 173 * 174 * The requested information will be returned via 'info' argument. 175 * Caller must invoke lsa_free_info() to when done. 176 * 177 * Returns NT status codes. 178 */ 179 DWORD 180 lsa_query_account_domain_info(char *server, char *domain, lsa_info_t *info) 181 { 182 mlsvc_handle_t domain_handle; 183 DWORD status; 184 char *user = smbrdr_ipc_get_user(); 185 186 if ((lsar_open(server, domain, user, &domain_handle)) != 0) 187 return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); 188 189 status = lsar_query_info_policy(&domain_handle, 190 MSLSA_POLICY_ACCOUNT_DOMAIN_INFO, info); 191 192 (void) lsar_close(&domain_handle); 193 return (status); 194 } 195 196 /* 197 * lsa_query_dns_domain_info 198 * 199 * Obtains the DNS domain info from the specified server 200 * (domain controller). 201 * 202 * The requested information will be returned via 'info' argument. 203 * Caller must call lsa_free_info() when done. 204 * 205 * Returns NT status codes. 206 */ 207 DWORD 208 lsa_query_dns_domain_info(char *server, char *domain, lsa_info_t *info) 209 { 210 mlsvc_handle_t domain_handle; 211 DWORD status; 212 char *user = smbrdr_ipc_get_user(); 213 214 if ((lsar_open(server, domain, user, &domain_handle)) != 0) 215 return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); 216 217 status = lsar_query_info_policy(&domain_handle, 218 MSLSA_POLICY_DNS_DOMAIN_INFO, info); 219 220 (void) lsar_close(&domain_handle); 221 return (status); 222 } 223 224 /* 225 * lsa_enum_trusted_domains 226 * 227 * Enumerate the trusted domains in our primary domain. The information 228 * is stored in the NT domain database by the lower level 229 * lsar_enum_trusted_domains call. The caller should query the database 230 * to obtain a reference to the trusted domain information. 231 * 232 * The requested information will be returned via 'info' argument. 233 * Caller must call lsa_free_info() when done. 234 * 235 * Returns NT status codes. 236 */ 237 DWORD 238 lsa_enum_trusted_domains(char *server, char *domain, lsa_info_t *info) 239 { 240 mlsvc_handle_t domain_handle; 241 DWORD enum_context; 242 DWORD status; 243 char *user = smbrdr_ipc_get_user(); 244 245 if ((lsar_open(server, domain, user, &domain_handle)) != 0) 246 return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); 247 248 enum_context = 0; 249 250 status = lsar_enum_trusted_domains(&domain_handle, &enum_context, info); 251 if (status == MLSVC_NO_MORE_DATA) { 252 /* 253 * MLSVC_NO_MORE_DATA indicates that we 254 * have all of the available information. 255 */ 256 status = NT_STATUS_SUCCESS; 257 } 258 259 (void) lsar_close(&domain_handle); 260 return (status); 261 } 262 263 /* 264 * lsa_free_info 265 */ 266 void 267 lsa_free_info(lsa_info_t *info) 268 { 269 lsa_trusted_domainlist_t *list; 270 int i; 271 272 if (!info) 273 return; 274 275 switch (info->i_type) { 276 case LSA_INFO_PRIMARY_DOMAIN: 277 smb_sid_free(info->i_domain.di_primary.n_sid); 278 break; 279 280 case LSA_INFO_ACCOUNT_DOMAIN: 281 smb_sid_free(info->i_domain.di_account.n_sid); 282 break; 283 284 case LSA_INFO_DNS_DOMAIN: 285 smb_sid_free(info->i_domain.di_dns.d_sid); 286 break; 287 288 case LSA_INFO_TRUSTED_DOMAINS: 289 list = &info->i_domain.di_trust; 290 for (i = 0; i < list->t_num; i++) 291 smb_sid_free(list->t_domains[i].n_sid); 292 free(list->t_domains); 293 break; 294 295 case LSA_INFO_NONE: 296 break; 297 } 298 } 299 300 /* 301 * Lookup well known accounts table 302 * 303 * Return status: 304 * 305 * NT_STATUS_SUCCESS Account is translated successfully 306 * NT_STATUS_NOT_FOUND This is not a well known account 307 * NT_STATUS_NONE_MAPPED Account is found but domains don't match 308 * NT_STATUS_NO_MEMORY Memory shortage 309 * NT_STATUS_INTERNAL_ERROR Internal error/unexpected failure 310 */ 311 static uint32_t 312 lsa_lookup_name_builtin(char *domain, char *name, smb_userinfo_t *info) 313 { 314 smb_wka_t *wka; 315 char *wkadom; 316 317 if ((wka = smb_wka_lookup(name)) == NULL) 318 return (NT_STATUS_NOT_FOUND); 319 320 if ((wkadom = smb_wka_get_domain(wka->wka_domidx)) == NULL) 321 return (NT_STATUS_INTERNAL_ERROR); 322 323 if ((domain != NULL) && (utf8_strcasecmp(domain, wkadom) != 0)) 324 return (NT_STATUS_NONE_MAPPED); 325 326 info->user_sid = smb_sid_dup(wka->wka_binsid); 327 info->domain_sid = smb_sid_dup(wka->wka_binsid); 328 info->domain_name = strdup(wkadom); 329 330 if ((info->user_sid == NULL) || (info->domain_sid == NULL) || 331 (info->domain_name == NULL)) 332 return (NT_STATUS_NO_MEMORY); 333 334 if (smb_sid_split(info->domain_sid, &info->rid) < 0) 335 return (NT_STATUS_INTERNAL_ERROR); 336 337 info->sid_name_use = wka->wka_type; 338 return (NT_STATUS_SUCCESS); 339 } 340 341 /* 342 * Obtains the infomation for the given local account name if it 343 * can be found. The type of account is specified by sid_type, 344 * which can be of user, group or unknown type. If the caller 345 * doesn't know whether the name is a user or group name then 346 * SidTypeUnknown should be passed, in which case this 347 * function first tries to find a user and then a group match. 348 * 349 * Return status: 350 * 351 * NT_STATUS_NOT_FOUND This is not a local account 352 * NT_STATUS_NONE_MAPPED It's a local account but cannot be 353 * translated. 354 * other error status codes. 355 */ 356 static uint32_t 357 lsa_lookup_name_local(char *domain, char *name, uint16_t sid_type, 358 smb_userinfo_t *info) 359 { 360 char hostname[MAXHOSTNAMELEN]; 361 smb_sid_t *sid; 362 uint32_t status; 363 364 (void) smb_getnetbiosname(hostname, sizeof (hostname)); 365 366 if (domain != NULL) { 367 if (!smb_ishostname(domain)) 368 return (NT_STATUS_NOT_FOUND); 369 370 /* Only Netbios hostname is accepted */ 371 if (utf8_strcasecmp(domain, hostname) != 0) 372 return (NT_STATUS_NONE_MAPPED); 373 } 374 375 if ((info->domain_name = strdup(hostname)) == NULL) 376 return (NT_STATUS_NO_MEMORY); 377 378 switch (sid_type) { 379 case SidTypeUser: 380 status = lsa_lookup_name_lusr(name, &sid); 381 if (status != NT_STATUS_SUCCESS) 382 return (status); 383 break; 384 385 case SidTypeGroup: 386 case SidTypeAlias: 387 status = lsa_lookup_name_lgrp(name, &sid); 388 if (status != NT_STATUS_SUCCESS) 389 return (status); 390 break; 391 392 case SidTypeUnknown: 393 sid_type = SidTypeUser; 394 status = lsa_lookup_name_lusr(name, &sid); 395 if (status == NT_STATUS_SUCCESS) 396 break; 397 398 if (status == NT_STATUS_NONE_MAPPED) 399 return (status); 400 401 sid_type = SidTypeAlias; 402 status = lsa_lookup_name_lgrp(name, &sid); 403 if (status != NT_STATUS_SUCCESS) 404 return (status); 405 break; 406 407 default: 408 return (NT_STATUS_INVALID_PARAMETER); 409 } 410 411 info->sid_name_use = sid_type; 412 info->user_sid = sid; 413 info->domain_sid = smb_sid_dup(sid); 414 if (info->domain_sid == NULL) 415 return (NT_STATUS_NO_MEMORY); 416 417 (void) smb_sid_split(info->domain_sid, &info->rid); 418 return (NT_STATUS_SUCCESS); 419 } 420 421 /* 422 * Lookup the given account in domain. 423 * 424 * The information is returned in the user_info structure. 425 * The caller is responsible for allocating and releasing 426 * this structure. 427 */ 428 static uint32_t 429 lsa_lookup_name_domain(char *account_name, smb_userinfo_t *user_info) 430 { 431 mlsvc_handle_t domain_handle; 432 smb_domain_t dinfo; 433 char *user = smbrdr_ipc_get_user(); 434 uint32_t status; 435 436 if (!smb_domain_getinfo(&dinfo)) 437 return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); 438 439 if (lsar_open(dinfo.d_dc, dinfo.d_nbdomain, user, &domain_handle) != 0) 440 return (NT_STATUS_INVALID_PARAMETER); 441 442 status = lsar_lookup_names2(&domain_handle, account_name, user_info); 443 if (status == NT_STATUS_REVISION_MISMATCH) { 444 /* 445 * Not a Windows 2000 domain controller: 446 * use the NT compatible call. 447 */ 448 status = lsar_lookup_names(&domain_handle, account_name, 449 user_info); 450 } 451 452 (void) lsar_close(&domain_handle); 453 return (status); 454 } 455 456 /* 457 * lsa_lookup_privs 458 * 459 * Request the privileges associated with the specified account. In 460 * order to get the privileges, we first have to lookup the name on 461 * the specified domain controller and obtain the appropriate SID. 462 * The SID can then be used to open the account and obtain the 463 * account privileges. The results from both the name lookup and the 464 * privileges are returned in the user_info structure. The caller is 465 * responsible for allocating and releasing this structure. 466 * 467 * On success 0 is returned. Otherwise a -ve error code. 468 */ 469 /*ARGSUSED*/ 470 int 471 lsa_lookup_privs(char *account_name, char *target_name, 472 smb_userinfo_t *user_info) 473 { 474 mlsvc_handle_t domain_handle; 475 int rc; 476 char *user = smbrdr_ipc_get_user(); 477 smb_domain_t dinfo; 478 479 if (!smb_domain_getinfo(&dinfo)) 480 return (-1); 481 482 if ((lsar_open(dinfo.d_dc, dinfo.d_nbdomain, user, 483 &domain_handle)) != 0) 484 return (-1); 485 486 rc = lsa_list_accounts(&domain_handle); 487 (void) lsar_close(&domain_handle); 488 return (rc); 489 } 490 491 /* 492 * lsa_list_privs 493 * 494 * List the privileges supported by the specified server. 495 * This function is only intended for diagnostics. 496 * 497 * Returns NT status codes. 498 */ 499 DWORD 500 lsa_list_privs(char *server, char *domain) 501 { 502 static char name[128]; 503 static struct ms_luid luid; 504 mlsvc_handle_t domain_handle; 505 int rc; 506 int i; 507 char *user = smbrdr_ipc_get_user(); 508 509 rc = lsar_open(server, domain, user, &domain_handle); 510 if (rc != 0) 511 return (NT_STATUS_INVALID_PARAMETER); 512 513 for (i = 0; i < 30; ++i) { 514 luid.low_part = i; 515 rc = lsar_lookup_priv_name(&domain_handle, &luid, name, 128); 516 if (rc != 0) 517 continue; 518 519 (void) lsar_lookup_priv_value(&domain_handle, name, &luid); 520 (void) lsar_lookup_priv_display_name(&domain_handle, name, 521 name, 128); 522 } 523 524 (void) lsar_close(&domain_handle); 525 return (NT_STATUS_SUCCESS); 526 } 527 528 /* 529 * lsa_test 530 * 531 * LSA test routine: open and close the LSA interface. 532 * 533 * On success 0 is returned. Otherwise a -ve error code. 534 */ 535 int 536 lsa_test(char *server, char *domain) 537 { 538 mlsvc_handle_t domain_handle; 539 int rc; 540 char *user = smbrdr_ipc_get_user(); 541 542 rc = lsar_open(server, domain, user, &domain_handle); 543 if (rc != 0) 544 return (-1); 545 546 if (lsar_close(&domain_handle) != 0) 547 return (-1); 548 549 return (0); 550 } 551 552 /* 553 * lsa_list_accounts 554 * 555 * This function can be used to list the accounts in the specified 556 * domain. For now the SIDs are just listed in the system log. 557 * 558 * On success 0 is returned. Otherwise a -ve error code. 559 */ 560 static int 561 lsa_list_accounts(mlsvc_handle_t *domain_handle) 562 { 563 mlsvc_handle_t account_handle; 564 struct mslsa_EnumAccountBuf accounts; 565 struct mslsa_sid *sid; 566 char *name; 567 WORD sid_name_use; 568 smb_userinfo_t *user_info; 569 DWORD enum_context = 0; 570 int rc; 571 int i; 572 573 user_info = mlsvc_alloc_user_info(); 574 bzero(&accounts, sizeof (struct mslsa_EnumAccountBuf)); 575 576 do { 577 rc = lsar_enum_accounts(domain_handle, &enum_context, 578 &accounts); 579 if (rc != 0) 580 return (rc); 581 582 for (i = 0; i < accounts.entries_read; ++i) { 583 sid = accounts.info[i].sid; 584 585 name = smb_wka_lookup_sid((smb_sid_t *)sid, 586 &sid_name_use); 587 588 if (name == 0) { 589 if (lsar_lookup_sids(domain_handle, sid, 590 user_info) == 0) { 591 name = user_info->name; 592 sid_name_use = user_info->sid_name_use; 593 } else { 594 name = "unknown"; 595 sid_name_use = SidTypeUnknown; 596 } 597 } 598 599 if (lsar_open_account(domain_handle, sid, 600 &account_handle) == 0) { 601 (void) lsar_enum_privs_account(&account_handle, 602 user_info); 603 (void) lsar_close(&account_handle); 604 } 605 606 free(accounts.info[i].sid); 607 mlsvc_release_user_info(user_info); 608 } 609 610 if (accounts.info) 611 free(accounts.info); 612 } while (rc == 0 && accounts.entries_read != 0); 613 614 mlsvc_free_user_info(user_info); 615 return (0); 616 } 617 618 /* 619 * Lookup local SMB user account database (/var/smb/smbpasswd) 620 * if there's a match query its SID from idmap service and make 621 * sure the SID is a local SID. 622 * 623 * The memory for the returned SID must be freed by the caller. 624 */ 625 static uint32_t 626 lsa_lookup_name_lusr(char *name, smb_sid_t **sid) 627 { 628 smb_passwd_t smbpw; 629 630 if (smb_pwd_getpwnam(name, &smbpw) == NULL) 631 return (NT_STATUS_NO_SUCH_USER); 632 633 if (smb_idmap_getsid(smbpw.pw_uid, SMB_IDMAP_USER, sid) 634 != IDMAP_SUCCESS) 635 return (NT_STATUS_NONE_MAPPED); 636 637 if (!smb_sid_islocal(*sid)) { 638 smb_sid_free(*sid); 639 return (NT_STATUS_NONE_MAPPED); 640 } 641 642 return (NT_STATUS_SUCCESS); 643 } 644 645 /* 646 * Lookup local SMB group account database (/var/smb/smbgroup.db) 647 * The memory for the returned SID must be freed by the caller. 648 */ 649 static uint32_t 650 lsa_lookup_name_lgrp(char *name, smb_sid_t **sid) 651 { 652 smb_group_t grp; 653 654 if (smb_lgrp_getbyname(name, &grp) != SMB_LGRP_SUCCESS) 655 return (NT_STATUS_NO_SUCH_ALIAS); 656 657 *sid = smb_sid_dup(grp.sg_id.gs_sid); 658 smb_lgrp_free(&grp); 659 660 return ((*sid == NULL) ? NT_STATUS_NO_MEMORY : NT_STATUS_SUCCESS); 661 } 662 663 static uint32_t 664 lsa_lookup_sid_local(smb_sid_t *sid, smb_userinfo_t *ainfo) 665 { 666 char hostname[MAXHOSTNAMELEN]; 667 smb_passwd_t smbpw; 668 smb_group_t grp; 669 uint32_t rid; 670 uid_t id; 671 int id_type; 672 int rc; 673 674 id_type = SMB_IDMAP_UNKNOWN; 675 if (smb_idmap_getid(sid, &id, &id_type) != IDMAP_SUCCESS) 676 return (NT_STATUS_NONE_MAPPED); 677 678 switch (id_type) { 679 case SMB_IDMAP_USER: 680 ainfo->sid_name_use = SidTypeUser; 681 if (smb_pwd_getpwuid(id, &smbpw) == NULL) 682 return (NT_STATUS_NO_SUCH_USER); 683 684 ainfo->name = strdup(smbpw.pw_name); 685 break; 686 687 case SMB_IDMAP_GROUP: 688 ainfo->sid_name_use = SidTypeAlias; 689 (void) smb_sid_getrid(sid, &rid); 690 rc = smb_lgrp_getbyrid(rid, SMB_LGRP_LOCAL, &grp); 691 if (rc != SMB_LGRP_SUCCESS) 692 return (NT_STATUS_NO_SUCH_ALIAS); 693 694 ainfo->name = strdup(grp.sg_name); 695 smb_lgrp_free(&grp); 696 break; 697 698 default: 699 return (NT_STATUS_NONE_MAPPED); 700 } 701 702 if (ainfo->name == NULL) 703 return (NT_STATUS_NO_MEMORY); 704 705 ainfo->domain_sid = smb_sid_dup(sid); 706 if (smb_sid_split(ainfo->domain_sid, &ainfo->rid) < 0) 707 return (NT_STATUS_INTERNAL_ERROR); 708 *hostname = '\0'; 709 (void) smb_getnetbiosname(hostname, MAXHOSTNAMELEN); 710 if ((ainfo->domain_name = strdup(hostname)) == NULL) 711 return (NT_STATUS_NO_MEMORY); 712 713 return (NT_STATUS_SUCCESS); 714 } 715 716 static uint32_t 717 lsa_lookup_sid_builtin(smb_sid_t *sid, smb_userinfo_t *ainfo) 718 { 719 char *name; 720 WORD sid_name_use; 721 722 if ((name = smb_wka_lookup_sid(sid, &sid_name_use)) == NULL) 723 return (NT_STATUS_NONE_MAPPED); 724 725 ainfo->sid_name_use = sid_name_use; 726 ainfo->name = strdup(name); 727 ainfo->domain_sid = smb_sid_dup(sid); 728 729 if (ainfo->name == NULL || ainfo->domain_sid == NULL) 730 return (NT_STATUS_NO_MEMORY); 731 732 if (sid_name_use != SidTypeDomain) 733 (void) smb_sid_split(ainfo->domain_sid, &ainfo->rid); 734 735 if ((name = smb_wka_lookup_domain(ainfo->name)) != NULL) 736 ainfo->domain_name = strdup(name); 737 else 738 ainfo->domain_name = strdup("UNKNOWN"); 739 740 if (ainfo->domain_name == NULL) 741 return (NT_STATUS_NO_MEMORY); 742 743 return (NT_STATUS_SUCCESS); 744 } 745 746 static uint32_t 747 lsa_lookup_sid_domain(smb_sid_t *sid, smb_userinfo_t *ainfo) 748 { 749 mlsvc_handle_t domain_handle; 750 char *user = smbrdr_ipc_get_user(); 751 uint32_t status; 752 smb_domain_t dinfo; 753 754 if (!smb_domain_getinfo(&dinfo)) 755 return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); 756 757 if (lsar_open(dinfo.d_dc, dinfo.d_nbdomain, user, &domain_handle) != 0) 758 return (NT_STATUS_INVALID_PARAMETER); 759 760 status = lsar_lookup_sids2(&domain_handle, 761 (struct mslsa_sid *)sid, ainfo); 762 763 if (status == NT_STATUS_REVISION_MISMATCH) { 764 /* 765 * Not a Windows 2000 domain controller: 766 * use the NT compatible call. 767 */ 768 status = lsar_lookup_sids(&domain_handle, 769 (struct mslsa_sid *)sid, ainfo); 770 } 771 772 (void) lsar_close(&domain_handle); 773 return (status); 774 } 775