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