1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 24 * Copyright 2015 Nexenta Systems, Inc. All rights reserved. 25 */ 26 27 /* 28 * Local Security Authority RPC (LSAR) client-side interface. 29 */ 30 31 #include <sys/errno.h> 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <strings.h> 35 36 #include <smbsrv/libsmb.h> 37 #include <smbsrv/libmlsvc.h> 38 #include <smbsrv/smbinfo.h> 39 #include <smbsrv/ntaccess.h> 40 #include <smbsrv/ntlocale.h> 41 #include <smbsrv/string.h> 42 #include <lsalib.h> 43 44 /* 45 * The maximum number of bytes we are prepared to deal with in a 46 * response. 47 */ 48 #define MLSVC_MAX_RESPONSE_LEN 1024 49 50 /* 51 * This structure is used when looking up names. We only lookup one 52 * name at a time but the structure will allow for more. 53 */ 54 typedef struct lsa_names { 55 uint32_t n_entry; 56 mslsa_string_t name[8]; 57 } lsa_names_t; 58 59 typedef DWORD (*lsar_nameop_t)(mlsvc_handle_t *, lsa_names_t *, 60 smb_account_t *); 61 62 static uint32_t lsar_lookup_names1(mlsvc_handle_t *, lsa_names_t *, 63 smb_account_t *); 64 static uint32_t lsar_lookup_names2(mlsvc_handle_t *, lsa_names_t *, 65 smb_account_t *); 66 static uint32_t lsar_lookup_names3(mlsvc_handle_t *, lsa_names_t *, 67 smb_account_t *); 68 static uint32_t lsar_lookup_sids1(mlsvc_handle_t *, lsa_sid_t *, 69 smb_account_t *); 70 static uint32_t lsar_lookup_sids2(mlsvc_handle_t *, lsa_sid_t *, 71 smb_account_t *account); 72 73 static char *lsar_get_username(const char *); 74 static void smb_account_trace(const smb_account_t *); 75 76 static void lsar_set_trusted_domains_ex(struct mslsa_EnumTrustedDomainBufEx *, 77 smb_trusted_domains_t *); 78 static void lsar_set_trusted_domains(struct mslsa_EnumTrustedDomainBuf *, 79 smb_trusted_domains_t *); 80 81 /* 82 * lsar_open 83 * 84 * This is a wrapper round lsar_open_policy2 to ensure that we connect 85 * using the appropriate domain information. 86 * 87 * If username argument is NULL, an anonymous connection will be established. 88 * Otherwise, an authenticated connection will be established. 89 * 90 * Returns 0 or NT status (Raw, not LSA-ized) 91 */ 92 DWORD 93 lsar_open(char *server, char *domain, char *username, 94 mlsvc_handle_t *domain_handle) 95 { 96 DWORD status; 97 98 if (server == NULL || domain == NULL) 99 return (NT_STATUS_INTERNAL_ERROR); 100 101 if (username == NULL) 102 username = MLSVC_ANON_USER; 103 104 status = lsar_open_policy2(server, domain, username, domain_handle); 105 106 return (status); 107 } 108 109 /* 110 * lsar_open_policy2 111 * 112 * Obtain an LSA policy handle. A policy handle is required to access 113 * LSA resources on a remote server. The server name supplied here does 114 * not need the double backslash prefix; it is added here. Call this 115 * function via lsar_open to ensure that the appropriate connection is 116 * in place. 117 * 118 * Returns 0 or NT status (Raw, not LSA-ized) 119 */ 120 DWORD 121 lsar_open_policy2(char *server, char *domain, char *user, 122 mlsvc_handle_t *lsa_handle) 123 { 124 struct mslsa_OpenPolicy2 arg; 125 DWORD status; 126 int opnum; 127 int len; 128 129 status = ndr_rpc_bind(lsa_handle, server, domain, user, "LSARPC"); 130 if (status != 0) 131 return (status); 132 133 opnum = LSARPC_OPNUM_OpenPolicy2; 134 bzero(&arg, sizeof (struct mslsa_OpenPolicy2)); 135 136 len = strlen(server) + 4; 137 arg.servername = ndr_rpc_malloc(lsa_handle, len); 138 if (arg.servername == NULL) { 139 status = NT_STATUS_NO_MEMORY; 140 goto out; 141 } 142 143 (void) snprintf((char *)arg.servername, len, "\\\\%s", server); 144 arg.attributes.length = sizeof (struct mslsa_object_attributes); 145 arg.desiredAccess = MAXIMUM_ALLOWED; 146 147 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) { 148 status = RPC_NT_CALL_FAILED; 149 goto out; 150 } 151 status = arg.status; 152 if (status == NT_STATUS_SUCCESS) { 153 (void) memcpy(&lsa_handle->handle, &arg.domain_handle, 154 sizeof (ndr_hdid_t)); 155 156 if (ndr_is_null_handle(lsa_handle)) 157 status = NT_STATUS_INVALID_PARAMETER; 158 } 159 160 ndr_rpc_release(lsa_handle); 161 162 out: 163 if (status != NT_STATUS_SUCCESS) 164 ndr_rpc_unbind(lsa_handle); 165 return (status); 166 } 167 168 /* 169 * lsar_open_account 170 * 171 * Obtain an LSA account handle. The lsa_handle must be a valid handle 172 * obtained via lsar_open_policy2. The main thing to remember here is 173 * to set up the context in the lsa_account_handle. I'm not sure what 174 * the requirements are for desired access. Some values require admin 175 * access. 176 * 177 * Returns 0 on success. Otherwise non-zero to indicate a failure. 178 */ 179 int 180 lsar_open_account(mlsvc_handle_t *lsa_handle, struct mslsa_sid *sid, 181 mlsvc_handle_t *lsa_account_handle) 182 { 183 struct mslsa_OpenAccount arg; 184 int opnum; 185 int rc; 186 187 if (ndr_is_null_handle(lsa_handle) || sid == NULL) 188 return (-1); 189 190 opnum = LSARPC_OPNUM_OpenAccount; 191 bzero(&arg, sizeof (struct mslsa_OpenAccount)); 192 193 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t)); 194 arg.sid = sid; 195 arg.access_mask = STANDARD_RIGHTS_REQUIRED 196 #if 0 197 | POLICY_VIEW_AUDIT_INFORMATION 198 | POLICY_GET_PRIVATE_INFORMATION 199 | POLICY_TRUST_ADMIN 200 #endif 201 | POLICY_VIEW_LOCAL_INFORMATION; 202 203 if ((rc = ndr_rpc_call(lsa_handle, opnum, &arg)) != 0) 204 return (-1); 205 206 if (arg.status != 0) { 207 rc = -1; 208 } else { 209 ndr_inherit_handle(lsa_account_handle, lsa_handle); 210 211 (void) memcpy(&lsa_account_handle->handle, 212 &arg.account_handle, sizeof (ndr_hdid_t)); 213 214 if (ndr_is_null_handle(lsa_account_handle)) 215 rc = -1; 216 } 217 218 ndr_rpc_release(lsa_handle); 219 return (rc); 220 } 221 222 /* 223 * lsar_close 224 * 225 * Close the LSA connection associated with the handle. The lsa_handle 226 * must be a valid handle obtained via a call to lsar_open_policy2 or 227 * lsar_open_account. On success the handle will be zeroed out to 228 * ensure that it is not used again. If this is the top level handle 229 * (i.e. the one obtained via lsar_open_policy2) the pipe is closed. 230 * 231 * Returns 0 on success. Otherwise non-zero to indicate a failure. 232 */ 233 int 234 lsar_close(mlsvc_handle_t *lsa_handle) 235 { 236 struct mslsa_CloseHandle arg; 237 int opnum; 238 239 if (ndr_is_null_handle(lsa_handle)) 240 return (-1); 241 242 opnum = LSARPC_OPNUM_CloseHandle; 243 bzero(&arg, sizeof (struct mslsa_CloseHandle)); 244 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t)); 245 246 (void) ndr_rpc_call(lsa_handle, opnum, &arg); 247 ndr_rpc_release(lsa_handle); 248 249 if (ndr_is_bind_handle(lsa_handle)) 250 ndr_rpc_unbind(lsa_handle); 251 252 bzero(lsa_handle, sizeof (mlsvc_handle_t)); 253 return (0); 254 } 255 256 /* 257 * lsar_query_security_desc 258 * 259 * Don't use this call yet. It is just a place holder for now. 260 */ 261 int 262 lsar_query_security_desc(mlsvc_handle_t *lsa_handle) 263 { 264 struct mslsa_QuerySecurityObject arg; 265 int rc; 266 int opnum; 267 268 opnum = LSARPC_OPNUM_QuerySecurityObject; 269 270 bzero(&arg, sizeof (struct mslsa_QuerySecurityObject)); 271 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t)); 272 273 rc = ndr_rpc_call(lsa_handle, opnum, &arg); 274 ndr_rpc_release(lsa_handle); 275 return (rc); 276 } 277 278 /* 279 * lsar_query_info_policy 280 * 281 * The general purpose of this function is to allow various pieces of 282 * information to be queried on the domain controller. The only 283 * information queries supported are MSLSA_POLICY_PRIMARY_DOMAIN_INFO 284 * and MSLSA_POLICY_ACCOUNT_DOMAIN_INFO. 285 * 286 * On success, the return code will be 0 and the user_info structure 287 * will be set up. The sid_name_use field will be set to SidTypeDomain 288 * indicating that the domain name and domain sid fields are vaild. If 289 * the infoClass returned from the server is not one of the supported 290 * values, the sid_name_use willbe set to SidTypeUnknown. If the RPC 291 * fails, a negative error code will be returned, in which case the 292 * user_info will not have been updated. 293 */ 294 DWORD 295 lsar_query_info_policy(mlsvc_handle_t *lsa_handle, WORD infoClass, 296 smb_domain_t *info) 297 { 298 struct mslsa_QueryInfoPolicy arg; 299 struct mslsa_PrimaryDomainInfo *pd_info; 300 struct mslsa_AccountDomainInfo *ad_info; 301 struct mslsa_DnsDomainInfo *dns_info; 302 char guid_str[UUID_PRINTABLE_STRING_LENGTH]; 303 char sidstr[SMB_SID_STRSZ]; 304 int opnum; 305 DWORD status; 306 307 if (lsa_handle == NULL || info == NULL) 308 return (NT_STATUS_INVALID_PARAMETER); 309 310 opnum = LSARPC_OPNUM_QueryInfoPolicy; 311 312 bzero(info, sizeof (smb_domain_t)); 313 bzero(&arg, sizeof (struct mslsa_QueryInfoPolicy)); 314 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t)); 315 316 arg.info_class = infoClass; 317 318 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) { 319 status = NT_STATUS_INVALID_PARAMETER; 320 } else if (arg.status != 0) { 321 ndr_rpc_status(lsa_handle, opnum, arg.status); 322 status = NT_SC_VALUE(arg.status); 323 } else { 324 325 switch (infoClass) { 326 case MSLSA_POLICY_PRIMARY_DOMAIN_INFO: 327 pd_info = &arg.ru.pd_info; 328 329 smb_sid_tostr((smb_sid_t *)pd_info->sid, sidstr); 330 info->di_type = SMB_DOMAIN_PRIMARY; 331 smb_domain_set_basic_info(sidstr, 332 (char *)pd_info->name.str, "", info); 333 334 status = NT_STATUS_SUCCESS; 335 break; 336 337 case MSLSA_POLICY_ACCOUNT_DOMAIN_INFO: 338 ad_info = &arg.ru.ad_info; 339 340 smb_sid_tostr((smb_sid_t *)ad_info->sid, sidstr); 341 info->di_type = SMB_DOMAIN_ACCOUNT; 342 smb_domain_set_basic_info(sidstr, 343 (char *)ad_info->name.str, "", info); 344 345 status = NT_STATUS_SUCCESS; 346 break; 347 348 case MSLSA_POLICY_DNS_DOMAIN_INFO: 349 dns_info = &arg.ru.dns_info; 350 ndr_uuid_unparse((ndr_uuid_t *)&dns_info->guid, 351 guid_str); 352 smb_sid_tostr((smb_sid_t *)dns_info->sid, sidstr); 353 354 info->di_type = SMB_DOMAIN_PRIMARY; 355 smb_domain_set_dns_info(sidstr, 356 (char *)dns_info->nb_domain.str, 357 (char *)dns_info->dns_domain.str, 358 (char *)dns_info->forest.str, 359 guid_str, info); 360 status = NT_STATUS_SUCCESS; 361 break; 362 363 default: 364 status = NT_STATUS_INVALID_INFO_CLASS; 365 break; 366 } 367 } 368 369 ndr_rpc_release(lsa_handle); 370 return (status); 371 } 372 373 /* 374 * Lookup a name and obtain the sid/rid. 375 * This is a wrapper for the various lookup sid RPCs. 376 */ 377 uint32_t 378 lsar_lookup_names(mlsvc_handle_t *lsa_handle, char *name, smb_account_t *info) 379 { 380 static lsar_nameop_t ops[] = { 381 lsar_lookup_names3, 382 lsar_lookup_names2, 383 lsar_lookup_names1 384 }; 385 386 const srvsvc_server_info_t *svinfo; 387 lsa_names_t names; 388 char *p; 389 uint32_t length; 390 uint32_t status = NT_STATUS_INVALID_PARAMETER; 391 int n_op = (sizeof (ops) / sizeof (ops[0])); 392 int i; 393 394 if (lsa_handle == NULL || name == NULL || info == NULL) 395 return (NT_STATUS_INVALID_PARAMETER); 396 397 bzero(info, sizeof (smb_account_t)); 398 399 svinfo = ndr_rpc_server_info(lsa_handle); 400 if (svinfo->sv_os == NATIVE_OS_WIN2000 && 401 svinfo->sv_version_major == 5 && svinfo->sv_version_minor == 0) { 402 /* 403 * Windows 2000 doesn't like an LSA lookup for 404 * DOMAIN\Administrator. 405 */ 406 if ((p = strchr(name, '\\')) != 0) { 407 ++p; 408 409 if (strcasecmp(p, "administrator") == 0) 410 name = p; 411 } 412 413 } 414 415 length = smb_wcequiv_strlen(name); 416 names.name[0].length = length; 417 names.name[0].allosize = length; 418 names.name[0].str = (unsigned char *)name; 419 names.n_entry = 1; 420 421 if (ndr_rpc_server_os(lsa_handle) == NATIVE_OS_WIN2000) { 422 for (i = 0; i < n_op; ++i) { 423 ndr_rpc_set_nonull(lsa_handle); 424 status = (*ops[i])(lsa_handle, &names, info); 425 426 if (status != NT_STATUS_INVALID_PARAMETER) 427 break; 428 } 429 } else { 430 ndr_rpc_set_nonull(lsa_handle); 431 status = lsar_lookup_names1(lsa_handle, &names, info); 432 } 433 434 if (status == NT_STATUS_SUCCESS) { 435 info->a_name = lsar_get_username(name); 436 437 if (!smb_account_validate(info)) { 438 smb_account_free(info); 439 status = NT_STATUS_NO_MEMORY; 440 } else { 441 smb_account_trace(info); 442 } 443 } 444 445 return (status); 446 } 447 448 /* 449 * The name may be in one of the following forms: 450 * 451 * domain\username 452 * domain/username 453 * username 454 * username@domain 455 * 456 * Return a strdup'd copy of the username. The caller is responsible 457 * for freeing the allocated memory. 458 */ 459 static char * 460 lsar_get_username(const char *name) 461 { 462 char tmp[MAXNAMELEN]; 463 char *dp = NULL; 464 char *np = NULL; 465 466 (void) strlcpy(tmp, name, MAXNAMELEN); 467 smb_name_parse(tmp, &np, &dp); 468 469 if (dp != NULL && np != NULL) 470 return (strdup(np)); 471 else 472 return (strdup(name)); 473 } 474 475 /* 476 * lsar_lookup_names1 477 * 478 * Lookup a name and obtain the domain and user rid. 479 * 480 * Note: NT returns an error if the mapped_count is non-zero when the RPC 481 * is called. 482 * 483 * If the lookup fails, the status will typically be NT_STATUS_NONE_MAPPED. 484 */ 485 static uint32_t 486 lsar_lookup_names1(mlsvc_handle_t *lsa_handle, lsa_names_t *names, 487 smb_account_t *info) 488 { 489 struct mslsa_LookupNames arg; 490 struct mslsa_rid_entry *rid_entry; 491 struct mslsa_domain_entry *domain_entry; 492 uint32_t status = NT_STATUS_SUCCESS; 493 char *domname; 494 int opnum = LSARPC_OPNUM_LookupNames; 495 496 bzero(&arg, sizeof (struct mslsa_LookupNames)); 497 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t)); 498 arg.lookup_level = LSA_LOOKUP_WKSTA; 499 arg.name_table = (struct mslsa_lup_name_table *)names; 500 501 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) { 502 ndr_rpc_release(lsa_handle); 503 return (NT_STATUS_INVALID_PARAMETER); 504 } 505 506 if (arg.status != NT_STATUS_SUCCESS) { 507 ndr_rpc_status(lsa_handle, opnum, arg.status); 508 ndr_rpc_release(lsa_handle); 509 return (NT_SC_VALUE(arg.status)); 510 } 511 512 if (arg.mapped_count == 0) { 513 ndr_rpc_release(lsa_handle); 514 return (NT_STATUS_NONE_MAPPED); 515 } 516 517 rid_entry = &arg.translated_sids.rids[0]; 518 if (rid_entry->domain_index != 0) { 519 ndr_rpc_release(lsa_handle); 520 return (NT_STATUS_NONE_MAPPED); 521 } 522 523 domain_entry = &arg.domain_table->entries[0]; 524 525 info->a_type = rid_entry->sid_name_use; 526 info->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid); 527 if ((domname = (char *)domain_entry->domain_name.str) != NULL) 528 info->a_domain = strdup(domname); 529 info->a_rid = rid_entry->rid; 530 info->a_sid = smb_sid_splice(info->a_domsid, info->a_rid); 531 532 ndr_rpc_release(lsa_handle); 533 return (status); 534 } 535 536 /* 537 * lsar_lookup_names2 538 */ 539 static uint32_t 540 lsar_lookup_names2(mlsvc_handle_t *lsa_handle, lsa_names_t *names, 541 smb_account_t *info) 542 { 543 struct lsar_LookupNames2 arg; 544 struct lsar_rid_entry2 *rid_entry; 545 struct mslsa_domain_entry *domain_entry; 546 uint32_t status = NT_STATUS_SUCCESS; 547 char *domname; 548 int opnum = LSARPC_OPNUM_LookupNames2; 549 550 bzero(&arg, sizeof (struct lsar_LookupNames2)); 551 (void) memcpy(&arg.policy_handle, lsa_handle, sizeof (mslsa_handle_t)); 552 arg.lookup_level = LSA_LOOKUP_WKSTA; 553 arg.client_revision = LSA_CLIENT_REVISION_AD; 554 arg.name_table = (struct mslsa_lup_name_table *)names; 555 556 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) { 557 ndr_rpc_release(lsa_handle); 558 return (NT_STATUS_INVALID_PARAMETER); 559 } 560 561 if (arg.status != NT_STATUS_SUCCESS) { 562 ndr_rpc_status(lsa_handle, opnum, arg.status); 563 ndr_rpc_release(lsa_handle); 564 return (NT_SC_VALUE(arg.status)); 565 } 566 567 if (arg.mapped_count == 0) { 568 ndr_rpc_release(lsa_handle); 569 return (NT_STATUS_NONE_MAPPED); 570 } 571 572 rid_entry = &arg.translated_sids.rids[0]; 573 if (rid_entry->domain_index != 0) { 574 ndr_rpc_release(lsa_handle); 575 return (NT_STATUS_NONE_MAPPED); 576 } 577 578 domain_entry = &arg.domain_table->entries[0]; 579 580 info->a_type = rid_entry->sid_name_use; 581 info->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid); 582 if ((domname = (char *)domain_entry->domain_name.str) != NULL) 583 info->a_domain = strdup(domname); 584 info->a_rid = rid_entry->rid; 585 info->a_sid = smb_sid_splice(info->a_domsid, info->a_rid); 586 587 ndr_rpc_release(lsa_handle); 588 return (status); 589 } 590 591 /* 592 * lsar_lookup_names3 593 */ 594 static uint32_t 595 lsar_lookup_names3(mlsvc_handle_t *lsa_handle, lsa_names_t *names, 596 smb_account_t *info) 597 { 598 struct lsar_LookupNames3 arg; 599 lsar_translated_sid_ex2_t *sid_entry; 600 struct mslsa_domain_entry *domain_entry; 601 uint32_t status = NT_STATUS_SUCCESS; 602 char *domname; 603 int opnum = LSARPC_OPNUM_LookupNames3; 604 605 bzero(&arg, sizeof (struct lsar_LookupNames3)); 606 (void) memcpy(&arg.policy_handle, lsa_handle, sizeof (mslsa_handle_t)); 607 arg.lookup_level = LSA_LOOKUP_WKSTA; 608 arg.client_revision = LSA_CLIENT_REVISION_AD; 609 arg.name_table = (struct mslsa_lup_name_table *)names; 610 611 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) { 612 ndr_rpc_release(lsa_handle); 613 return (NT_STATUS_INVALID_PARAMETER); 614 } 615 616 if (arg.status != NT_STATUS_SUCCESS) { 617 ndr_rpc_status(lsa_handle, opnum, arg.status); 618 ndr_rpc_release(lsa_handle); 619 return (NT_SC_VALUE(arg.status)); 620 } 621 622 if (arg.mapped_count == 0) { 623 ndr_rpc_release(lsa_handle); 624 return (NT_STATUS_NONE_MAPPED); 625 } 626 627 sid_entry = &arg.translated_sids.sids[0]; 628 if (sid_entry->domain_index != 0) { 629 ndr_rpc_release(lsa_handle); 630 return (NT_STATUS_NONE_MAPPED); 631 } 632 633 domain_entry = &arg.domain_table->entries[0]; 634 635 info->a_type = sid_entry->sid_name_use; 636 info->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid); 637 if ((domname = (char *)domain_entry->domain_name.str) != NULL) 638 info->a_domain = strdup(domname); 639 info->a_sid = smb_sid_dup((smb_sid_t *)sid_entry->sid); 640 (void) smb_sid_getrid(info->a_sid, &info->a_rid); 641 642 ndr_rpc_release(lsa_handle); 643 return (status); 644 } 645 646 /* 647 * lsar_lookup_names4 648 * 649 * This function is only valid if the remote RPC server is a domain 650 * controller and requires the security extensions defined in MS-RPCE. 651 * 652 * Domain controllers will return RPC_NT_PROTSEQ_NOT_SUPPORTED here 653 * because we don't support the RPC_C_AUTHN_NETLOGON security provider. 654 * Non-domain controllers will return NT_STATUS_INVALID_SERVER_STATE. 655 */ 656 static uint32_t /*LINTED E_STATIC_UNUSED*/ 657 lsar_lookup_names4(mlsvc_handle_t *lsa_handle, lsa_names_t *names, 658 smb_account_t *info) 659 { 660 struct lsar_LookupNames4 arg; 661 lsar_translated_sid_ex2_t *sid_entry; 662 struct mslsa_domain_entry *domain_entry; 663 uint32_t status = NT_STATUS_SUCCESS; 664 char *domname; 665 int opnum = LSARPC_OPNUM_LookupNames4; 666 667 bzero(&arg, sizeof (struct lsar_LookupNames4)); 668 arg.lookup_level = LSA_LOOKUP_WKSTA; 669 arg.client_revision = LSA_CLIENT_REVISION_AD; 670 arg.name_table = (struct mslsa_lup_name_table *)names; 671 672 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) { 673 ndr_rpc_release(lsa_handle); 674 return (NT_STATUS_INVALID_PARAMETER); 675 } 676 677 if (arg.status != NT_STATUS_SUCCESS) { 678 ndr_rpc_status(lsa_handle, opnum, arg.status); 679 ndr_rpc_release(lsa_handle); 680 if (arg.status == RPC_NT_PROTSEQ_NOT_SUPPORTED || 681 arg.status == NT_STATUS_INVALID_SERVER_STATE) 682 return (NT_STATUS_INVALID_PARAMETER); 683 return (NT_SC_VALUE(arg.status)); 684 } 685 686 if (arg.mapped_count == 0) { 687 ndr_rpc_release(lsa_handle); 688 return (NT_STATUS_NONE_MAPPED); 689 } 690 691 sid_entry = &arg.translated_sids.sids[0]; 692 if (sid_entry->domain_index != 0) { 693 ndr_rpc_release(lsa_handle); 694 return (NT_STATUS_NONE_MAPPED); 695 } 696 697 domain_entry = &arg.domain_table->entries[0]; 698 699 info->a_type = sid_entry->sid_name_use; 700 info->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid); 701 if ((domname = (char *)domain_entry->domain_name.str) != NULL) 702 info->a_domain = strdup(domname); 703 info->a_sid = smb_sid_dup((smb_sid_t *)sid_entry->sid); 704 (void) smb_sid_getrid(info->a_sid, &info->a_rid); 705 706 ndr_rpc_release(lsa_handle); 707 return (status); 708 } 709 710 /* 711 * Lookup a sid and obtain the domain sid and account name. 712 * This is a wrapper for the various lookup sid RPCs. 713 */ 714 uint32_t 715 lsar_lookup_sids(mlsvc_handle_t *lsa_handle, smb_sid_t *sid, 716 smb_account_t *account) 717 { 718 char sidbuf[SMB_SID_STRSZ]; 719 uint32_t status; 720 721 if (lsa_handle == NULL || sid == NULL || account == NULL) 722 return (NT_STATUS_INVALID_PARAMETER); 723 724 bzero(account, sizeof (smb_account_t)); 725 bzero(sidbuf, SMB_SID_STRSZ); 726 smb_sid_tostr(sid, sidbuf); 727 smb_tracef("%s", sidbuf); 728 729 if (ndr_rpc_server_os(lsa_handle) == NATIVE_OS_WIN2000) 730 status = lsar_lookup_sids2(lsa_handle, (lsa_sid_t *)sid, 731 account); 732 else 733 status = lsar_lookup_sids1(lsa_handle, (lsa_sid_t *)sid, 734 account); 735 736 if (status == NT_STATUS_SUCCESS) { 737 if (!smb_account_validate(account)) { 738 smb_account_free(account); 739 status = NT_STATUS_NO_MEMORY; 740 } else { 741 smb_account_trace(account); 742 } 743 } 744 745 return (status); 746 } 747 748 /* 749 * lsar_lookup_sids1 750 */ 751 static uint32_t 752 lsar_lookup_sids1(mlsvc_handle_t *lsa_handle, lsa_sid_t *sid, 753 smb_account_t *account) 754 { 755 struct mslsa_LookupSids arg; 756 struct mslsa_lup_sid_entry sid_entry; 757 struct mslsa_name_entry *name_entry; 758 struct mslsa_domain_entry *domain_entry; 759 uint32_t status = NT_STATUS_SUCCESS; 760 char *name; 761 int opnum = LSARPC_OPNUM_LookupSids; 762 763 bzero(&arg, sizeof (struct mslsa_LookupSids)); 764 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t)); 765 arg.lookup_level = LSA_LOOKUP_WKSTA; 766 767 sid_entry.psid = sid; 768 arg.lup_sid_table.n_entry = 1; 769 arg.lup_sid_table.entries = &sid_entry; 770 771 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) { 772 ndr_rpc_release(lsa_handle); 773 return (NT_STATUS_INVALID_PARAMETER); 774 } 775 776 if (arg.status != NT_STATUS_SUCCESS) { 777 ndr_rpc_status(lsa_handle, opnum, arg.status); 778 ndr_rpc_release(lsa_handle); 779 return (NT_SC_VALUE(arg.status)); 780 } 781 782 if (arg.mapped_count == 0) { 783 ndr_rpc_release(lsa_handle); 784 return (NT_STATUS_NONE_MAPPED); 785 } 786 787 name_entry = &arg.name_table.entries[0]; 788 if (name_entry->domain_ix != 0) { 789 ndr_rpc_release(lsa_handle); 790 return (NT_STATUS_NONE_MAPPED); 791 } 792 793 name = (char *)name_entry->name.str; 794 account->a_name = (name) ? strdup(name) : strdup(""); 795 account->a_type = name_entry->sid_name_use; 796 account->a_sid = smb_sid_dup((smb_sid_t *)sid); 797 (void) smb_sid_getrid(account->a_sid, &account->a_rid); 798 799 domain_entry = &arg.domain_table->entries[0]; 800 if ((name = (char *)domain_entry->domain_name.str) != NULL) 801 account->a_domain = strdup(name); 802 account->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid); 803 804 ndr_rpc_release(lsa_handle); 805 return (status); 806 } 807 808 /* 809 * lsar_lookup_sids2 810 */ 811 static uint32_t 812 lsar_lookup_sids2(mlsvc_handle_t *lsa_handle, lsa_sid_t *sid, 813 smb_account_t *account) 814 { 815 struct lsar_lookup_sids2 arg; 816 struct lsar_name_entry2 *name_entry; 817 struct mslsa_lup_sid_entry sid_entry; 818 struct mslsa_domain_entry *domain_entry; 819 uint32_t status = NT_STATUS_SUCCESS; 820 char *name; 821 int opnum = LSARPC_OPNUM_LookupSids2; 822 823 bzero(&arg, sizeof (struct lsar_lookup_sids2)); 824 (void) memcpy(&arg.policy_handle, lsa_handle, sizeof (mslsa_handle_t)); 825 826 sid_entry.psid = sid; 827 arg.lup_sid_table.n_entry = 1; 828 arg.lup_sid_table.entries = &sid_entry; 829 arg.lookup_level = LSA_LOOKUP_WKSTA; 830 arg.client_revision = LSA_CLIENT_REVISION_AD; 831 832 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) { 833 ndr_rpc_release(lsa_handle); 834 return (NT_STATUS_INVALID_PARAMETER); 835 } 836 837 if (arg.status != NT_STATUS_SUCCESS) { 838 ndr_rpc_status(lsa_handle, opnum, arg.status); 839 ndr_rpc_release(lsa_handle); 840 return (NT_SC_VALUE(arg.status)); 841 } 842 843 if (arg.mapped_count == 0) { 844 ndr_rpc_release(lsa_handle); 845 return (NT_STATUS_NONE_MAPPED); 846 } 847 848 name_entry = &arg.name_table.entries[0]; 849 if (name_entry->domain_ix != 0) { 850 ndr_rpc_release(lsa_handle); 851 return (NT_STATUS_NONE_MAPPED); 852 } 853 854 name = (char *)name_entry->name.str; 855 account->a_name = (name) ? strdup(name) : strdup(""); 856 account->a_type = name_entry->sid_name_use; 857 account->a_sid = smb_sid_dup((smb_sid_t *)sid); 858 (void) smb_sid_getrid(account->a_sid, &account->a_rid); 859 860 domain_entry = &arg.domain_table->entries[0]; 861 if ((name = (char *)domain_entry->domain_name.str) != NULL) 862 account->a_domain = strdup(name); 863 account->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid); 864 865 ndr_rpc_release(lsa_handle); 866 return (status); 867 } 868 869 /* 870 * lsar_lookup_sids3 871 * 872 * This function is only valid if the remote RPC server is a domain 873 * controller and requires the security extensions defined in MS-RPCE. 874 * 875 * Domain controllers will return RPC_NT_PROTSEQ_NOT_SUPPORTED here 876 * because we don't support the RPC_C_AUTHN_NETLOGON security provider. 877 * Non-domain controllers will return NT_STATUS_INVALID_SERVER_STATE. 878 */ 879 static uint32_t /*LINTED E_STATIC_UNUSED*/ 880 lsar_lookup_sids3(mlsvc_handle_t *lsa_handle, lsa_sid_t *sid, 881 smb_account_t *account) 882 { 883 struct lsar_lookup_sids3 arg; 884 lsar_translated_name_ex_t *name_entry; 885 struct mslsa_lup_sid_entry sid_entry; 886 struct mslsa_domain_entry *domain_entry; 887 uint32_t status = NT_STATUS_SUCCESS; 888 char *name; 889 int opnum = LSARPC_OPNUM_LookupSids3; 890 891 bzero(&arg, sizeof (struct lsar_lookup_sids3)); 892 893 sid_entry.psid = sid; 894 arg.lup_sid_table.n_entry = 1; 895 arg.lup_sid_table.entries = &sid_entry; 896 arg.lookup_level = LSA_LOOKUP_WKSTA; 897 arg.client_revision = LSA_CLIENT_REVISION_AD; 898 899 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) { 900 ndr_rpc_release(lsa_handle); 901 return (NT_STATUS_INVALID_PARAMETER); 902 } 903 904 if (arg.status != NT_STATUS_SUCCESS) { 905 ndr_rpc_status(lsa_handle, opnum, arg.status); 906 ndr_rpc_release(lsa_handle); 907 if (arg.status == RPC_NT_PROTSEQ_NOT_SUPPORTED || 908 arg.status == NT_STATUS_INVALID_SERVER_STATE) 909 return (NT_STATUS_INVALID_PARAMETER); 910 return (NT_SC_VALUE(arg.status)); 911 } 912 913 if (arg.mapped_count == 0) { 914 ndr_rpc_release(lsa_handle); 915 return (NT_STATUS_NONE_MAPPED); 916 } 917 918 name_entry = &arg.name_table.entries[0]; 919 if (name_entry->domain_ix != 0) { 920 ndr_rpc_release(lsa_handle); 921 return (NT_STATUS_NONE_MAPPED); 922 } 923 924 name = (char *)name_entry->name.str; 925 account->a_name = (name) ? strdup(name) : strdup(""); 926 account->a_type = name_entry->sid_name_use; 927 account->a_sid = smb_sid_dup((smb_sid_t *)sid); 928 (void) smb_sid_getrid(account->a_sid, &account->a_rid); 929 930 domain_entry = &arg.domain_table->entries[0]; 931 if ((name = (char *)domain_entry->domain_name.str) != NULL) 932 account->a_domain = strdup(name); 933 account->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid); 934 935 ndr_rpc_release(lsa_handle); 936 return (status); 937 } 938 939 /* 940 * lsar_enum_accounts 941 * 942 * Enumerate the list of accounts (i.e. SIDs). Use the handle returned 943 * from lsa_open_policy2. The enum_context is used to support multiple 944 * calls to this enumeration function. It should be set to 0 on the 945 * first call. It will be updated by the domain controller and should 946 * simply be passed unchanged to subsequent calls until there are no 947 * more accounts. A warning status of 0x1A indicates that no more data 948 * is available. The list of accounts will be returned in accounts. 949 * This list is dynamically allocated using malloc, it should be freed 950 * by the caller when it is no longer required. 951 */ 952 DWORD 953 lsar_enum_accounts(mlsvc_handle_t *lsa_handle, DWORD *enum_context, 954 struct mslsa_EnumAccountBuf *accounts) 955 { 956 struct mslsa_EnumerateAccounts arg; 957 struct mslsa_AccountInfo *info; 958 int opnum; 959 int rc; 960 DWORD status; 961 DWORD n_entries; 962 DWORD i; 963 int nbytes; 964 965 if (lsa_handle == NULL || enum_context == NULL || accounts == NULL) 966 return (NT_STATUS_INTERNAL_ERROR); 967 968 accounts->entries_read = 0; 969 accounts->info = 0; 970 971 opnum = LSARPC_OPNUM_EnumerateAccounts; 972 973 bzero(&arg, sizeof (struct mslsa_EnumerateAccounts)); 974 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t)); 975 arg.enum_context = *enum_context; 976 arg.max_length = MLSVC_MAX_RESPONSE_LEN; 977 978 rc = ndr_rpc_call(lsa_handle, opnum, &arg); 979 if (rc == 0) { 980 status = arg.status; 981 if (arg.status != 0) { 982 if (arg.status == NT_STATUS_NO_MORE_ENTRIES) { 983 *enum_context = arg.enum_context; 984 } else { 985 ndr_rpc_status(lsa_handle, opnum, arg.status); 986 } 987 } else if (arg.enum_buf->entries_read != 0) { 988 n_entries = arg.enum_buf->entries_read; 989 nbytes = n_entries * sizeof (struct mslsa_AccountInfo); 990 991 if ((info = malloc(nbytes)) == NULL) { 992 ndr_rpc_release(lsa_handle); 993 return (NT_STATUS_NO_MEMORY); 994 } 995 996 for (i = 0; i < n_entries; ++i) 997 info[i].sid = (lsa_sid_t *)smb_sid_dup( 998 (smb_sid_t *)arg.enum_buf->info[i].sid); 999 1000 accounts->entries_read = n_entries; 1001 accounts->info = info; 1002 *enum_context = arg.enum_context; 1003 } 1004 } else { 1005 status = NT_STATUS_INVALID_PARAMETER; 1006 } 1007 1008 ndr_rpc_release(lsa_handle); 1009 return (status); 1010 } 1011 1012 /* 1013 * lsar_enum_trusted_domains 1014 * 1015 * Enumerate the list of trusted domains. Use the handle returned from 1016 * lsa_open_policy2. The enum_context is used to support multiple calls 1017 * to this enumeration function. It should be set to 0 on the first 1018 * call. It will be updated by the domain controller and should simply 1019 * be passed unchanged to subsequent calls until there are no more 1020 * domains. 1021 * 1022 * The trusted domains aren't actually returned here. They are added 1023 * to the NT domain database. After all of the trusted domains have 1024 * been discovered, the database can be interrogated to find all of 1025 * the trusted domains. 1026 */ 1027 DWORD 1028 lsar_enum_trusted_domains(mlsvc_handle_t *lsa_handle, DWORD *enum_context, 1029 smb_trusted_domains_t *list) 1030 { 1031 struct mslsa_EnumTrustedDomain arg; 1032 int opnum; 1033 DWORD status; 1034 1035 if (list == NULL) 1036 return (NT_STATUS_INVALID_PARAMETER); 1037 1038 opnum = LSARPC_OPNUM_EnumTrustedDomain; 1039 1040 bzero(list, sizeof (smb_trusted_domains_t)); 1041 bzero(&arg, sizeof (struct mslsa_EnumTrustedDomain)); 1042 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t)); 1043 arg.enum_context = *enum_context; 1044 arg.max_length = MLSVC_MAX_RESPONSE_LEN; 1045 1046 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) { 1047 status = NT_STATUS_INVALID_PARAMETER; 1048 } else if (arg.status != 0) { 1049 *enum_context = arg.enum_context; 1050 status = NT_SC_VALUE(arg.status); 1051 1052 /* 1053 * STATUS_NO_MORE_ENTRIES provides call 1054 * status but does not indicate an error. 1055 */ 1056 if (status != NT_STATUS_NO_MORE_ENTRIES) 1057 ndr_rpc_status(lsa_handle, opnum, arg.status); 1058 } else if (arg.enum_buf->entries_read == 0) { 1059 *enum_context = arg.enum_context; 1060 status = 0; 1061 } else { 1062 lsar_set_trusted_domains(arg.enum_buf, list); 1063 *enum_context = arg.enum_context; 1064 status = 0; 1065 } 1066 1067 ndr_rpc_release(lsa_handle); 1068 return (status); 1069 } 1070 1071 DWORD 1072 lsar_enum_trusted_domains_ex(mlsvc_handle_t *lsa_handle, DWORD *enum_context, 1073 smb_trusted_domains_t *list) 1074 { 1075 struct mslsa_EnumTrustedDomainEx arg; 1076 int opnum; 1077 DWORD status; 1078 1079 if (list == NULL) 1080 return (NT_STATUS_INVALID_PARAMETER); 1081 1082 opnum = LSARPC_OPNUM_EnumTrustedDomainsEx; 1083 1084 bzero(list, sizeof (smb_trusted_domains_t)); 1085 bzero(&arg, sizeof (struct mslsa_EnumTrustedDomainEx)); 1086 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t)); 1087 arg.enum_context = *enum_context; 1088 arg.max_length = MLSVC_MAX_RESPONSE_LEN; 1089 1090 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) { 1091 status = NT_STATUS_INVALID_PARAMETER; 1092 } else if (arg.status != 0) { 1093 *enum_context = arg.enum_context; 1094 status = NT_SC_VALUE(arg.status); 1095 1096 /* 1097 * STATUS_NO_MORE_ENTRIES provides call 1098 * status but does not indicate an error. 1099 */ 1100 if (status != NT_STATUS_NO_MORE_ENTRIES) 1101 ndr_rpc_status(lsa_handle, opnum, arg.status); 1102 } else if (arg.enum_buf->entries_read == 0) { 1103 *enum_context = arg.enum_context; 1104 status = 0; 1105 } else { 1106 lsar_set_trusted_domains_ex(arg.enum_buf, list); 1107 *enum_context = arg.enum_context; 1108 status = 0; 1109 } 1110 1111 ndr_rpc_release(lsa_handle); 1112 return (status); 1113 } 1114 1115 /* 1116 * lsar_enum_privs_account 1117 * 1118 * Privileges enum? Need an account handle. 1119 */ 1120 /*ARGSUSED*/ 1121 int 1122 lsar_enum_privs_account(mlsvc_handle_t *account_handle, smb_account_t *account) 1123 { 1124 struct mslsa_EnumPrivsAccount arg; 1125 int opnum; 1126 int rc; 1127 1128 opnum = LSARPC_OPNUM_EnumPrivsAccount; 1129 1130 bzero(&arg, sizeof (struct mslsa_EnumPrivsAccount)); 1131 (void) memcpy(&arg.account_handle, &account_handle->handle, 1132 sizeof (mslsa_handle_t)); 1133 1134 rc = ndr_rpc_call(account_handle, opnum, &arg); 1135 if ((rc == 0) && (arg.status != 0)) { 1136 ndr_rpc_status(account_handle, opnum, arg.status); 1137 rc = -1; 1138 } 1139 ndr_rpc_release(account_handle); 1140 return (rc); 1141 } 1142 1143 /* 1144 * lsar_lookup_priv_value 1145 * 1146 * Map a privilege name to a local unique id (LUID). Privilege names 1147 * are consistent across the network. LUIDs are machine specific. 1148 * This function provides the means to map a privilege name to the 1149 * LUID used by a remote server to represent it. The handle here is 1150 * a policy handle. 1151 */ 1152 int 1153 lsar_lookup_priv_value(mlsvc_handle_t *lsa_handle, char *name, 1154 struct ms_luid *luid) 1155 { 1156 struct mslsa_LookupPrivValue arg; 1157 int opnum; 1158 int rc; 1159 size_t length; 1160 1161 if (lsa_handle == NULL || name == NULL || luid == NULL) 1162 return (-1); 1163 1164 opnum = LSARPC_OPNUM_LookupPrivValue; 1165 1166 bzero(&arg, sizeof (struct mslsa_LookupPrivValue)); 1167 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t)); 1168 1169 length = smb_wcequiv_strlen(name); 1170 if (ndr_rpc_server_os(lsa_handle) == NATIVE_OS_WIN2000) 1171 length += sizeof (smb_wchar_t); 1172 1173 arg.name.length = length; 1174 arg.name.allosize = length; 1175 arg.name.str = (unsigned char *)name; 1176 1177 rc = ndr_rpc_call(lsa_handle, opnum, &arg); 1178 if (rc == 0) { 1179 if (arg.status != 0) 1180 rc = -1; 1181 else 1182 (void) memcpy(luid, &arg.luid, sizeof (struct ms_luid)); 1183 } 1184 1185 ndr_rpc_release(lsa_handle); 1186 return (rc); 1187 } 1188 1189 /* 1190 * lsar_lookup_priv_name 1191 * 1192 * Map a local unique id (LUID) to a privilege name. Privilege names 1193 * are consistent across the network. LUIDs are machine specific. 1194 * This function the means to map the LUID used by a remote server to 1195 * the appropriate privilege name. The handle here is a policy handle. 1196 */ 1197 int 1198 lsar_lookup_priv_name(mlsvc_handle_t *lsa_handle, struct ms_luid *luid, 1199 char *name, int namelen) 1200 { 1201 struct mslsa_LookupPrivName arg; 1202 int opnum; 1203 int rc; 1204 1205 if (lsa_handle == NULL || luid == NULL || name == NULL) 1206 return (-1); 1207 1208 opnum = LSARPC_OPNUM_LookupPrivName; 1209 1210 bzero(&arg, sizeof (struct mslsa_LookupPrivName)); 1211 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t)); 1212 (void) memcpy(&arg.luid, luid, sizeof (struct ms_luid)); 1213 1214 rc = ndr_rpc_call(lsa_handle, opnum, &arg); 1215 if (rc == 0) { 1216 if (arg.status != 0) 1217 rc = -1; 1218 else 1219 (void) strlcpy(name, (char const *)arg.name->str, 1220 namelen); 1221 } 1222 1223 ndr_rpc_release(lsa_handle); 1224 return (rc); 1225 } 1226 1227 /* 1228 * lsar_lookup_priv_display_name 1229 * 1230 * Map a privilege name to a privilege display name. The input handle 1231 * should be an LSA policy handle and the name would normally be one 1232 * of the privileges defined in smb_privilege.h 1233 * 1234 * There's something peculiar about the return status from NT servers, 1235 * it's not always present. So for now, I'm ignoring the status in the 1236 * RPC response. 1237 * 1238 * Returns NT status codes. 1239 */ 1240 DWORD 1241 lsar_lookup_priv_display_name(mlsvc_handle_t *lsa_handle, char *name, 1242 char *display_name, int display_len) 1243 { 1244 struct mslsa_LookupPrivDisplayName arg; 1245 int opnum; 1246 size_t length; 1247 DWORD status; 1248 1249 if (lsa_handle == NULL || name == NULL || display_name == NULL) 1250 return (NT_STATUS_INVALID_PARAMETER); 1251 1252 opnum = LSARPC_OPNUM_LookupPrivDisplayName; 1253 1254 bzero(&arg, sizeof (struct mslsa_LookupPrivDisplayName)); 1255 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t)); 1256 1257 length = smb_wcequiv_strlen(name); 1258 arg.name.length = length; 1259 arg.name.allosize = length; 1260 arg.name.str = (unsigned char *)name; 1261 1262 arg.client_language = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US); 1263 arg.default_language = MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL); 1264 1265 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) 1266 status = NT_STATUS_INVALID_PARAMETER; 1267 #if 0 1268 else if (arg.status != 0) 1269 status = NT_SC_VALUE(arg.status); 1270 #endif 1271 else { 1272 (void) strlcpy(display_name, 1273 (char const *)arg.display_name->str, display_len); 1274 status = NT_STATUS_SUCCESS; 1275 } 1276 1277 ndr_rpc_release(lsa_handle); 1278 return (status); 1279 } 1280 1281 static void 1282 lsar_set_trusted_domains_ex(struct mslsa_EnumTrustedDomainBufEx *enum_buf, 1283 smb_trusted_domains_t *list) 1284 { 1285 char sidstr[SMB_SID_STRSZ]; 1286 int i; 1287 1288 if (list == NULL || enum_buf == NULL || enum_buf->entries_read == 0) 1289 return; 1290 1291 list->td_num = 0; 1292 list->td_domains = calloc(enum_buf->entries_read, 1293 sizeof (smb_domain_t)); 1294 1295 if (list->td_domains == NULL) 1296 return; 1297 1298 list->td_num = enum_buf->entries_read; 1299 for (i = 0; i < list->td_num; i++) { 1300 smb_sid_tostr((smb_sid_t *)enum_buf->info[i].sid, sidstr); 1301 smb_domain_set_trust_info( 1302 sidstr, 1303 (char *)enum_buf->info[i].nb_name.str, 1304 (char *)enum_buf->info[i].dns_name.str, 1305 enum_buf->info[i].trust_direction, 1306 enum_buf->info[i].trust_type, 1307 enum_buf->info[i].trust_attrs, 1308 &list->td_domains[i]); 1309 } 1310 } 1311 1312 static void 1313 lsar_set_trusted_domains(struct mslsa_EnumTrustedDomainBuf *enum_buf, 1314 smb_trusted_domains_t *list) 1315 { 1316 char sidstr[SMB_SID_STRSZ]; 1317 int i; 1318 1319 if (list == NULL || enum_buf == NULL || enum_buf->entries_read == 0) 1320 return; 1321 1322 list->td_num = 0; 1323 list->td_domains = calloc(enum_buf->entries_read, 1324 sizeof (smb_domain_t)); 1325 1326 if (list->td_domains == NULL) 1327 return; 1328 1329 list->td_num = enum_buf->entries_read; 1330 for (i = 0; i < list->td_num; i++) { 1331 smb_sid_tostr((smb_sid_t *)enum_buf->info[i].sid, sidstr); 1332 smb_domain_set_trust_info( 1333 sidstr, (char *)enum_buf->info[i].name.str, 1334 "", 0, 0, 0, &list->td_domains[i]); 1335 } 1336 } 1337 1338 static void 1339 smb_account_trace(const smb_account_t *info) 1340 { 1341 char sidbuf[SMB_SID_STRSZ]; 1342 1343 bzero(sidbuf, SMB_SID_STRSZ); 1344 smb_sid_tostr(info->a_sid, sidbuf); 1345 1346 smb_tracef("%s %s %s %lu %s", info->a_domain, info->a_name, 1347 sidbuf, info->a_rid, smb_sid_type2str(info->a_type)); 1348 }