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