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