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