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 lsa_names_t names; 387 char *p; 388 uint32_t length; 389 uint32_t status = NT_STATUS_INVALID_PARAMETER; 390 int n_op = (sizeof (ops) / sizeof (ops[0])); 391 int i; 392 393 if (lsa_handle == NULL || name == NULL || info == NULL) 394 return (NT_STATUS_INVALID_PARAMETER); 395 396 bzero(info, sizeof (smb_account_t)); 397 398 /* 399 * Windows 2000 (or later) doesn't like an LSA lookup for 400 * DOMAIN\Administrator. 401 */ 402 if ((p = strchr(name, '\\')) != 0) { 403 ++p; 404 405 if (strcasecmp(p, "administrator") == 0) 406 name = p; 407 } 408 409 length = smb_wcequiv_strlen(name); 410 names.name[0].length = length; 411 names.name[0].allosize = length; 412 names.name[0].str = (unsigned char *)name; 413 names.n_entry = 1; 414 415 for (i = 0; i < n_op; ++i) { 416 ndr_rpc_set_nonull(lsa_handle); 417 status = (*ops[i])(lsa_handle, &names, info); 418 419 if (status != NT_STATUS_INVALID_PARAMETER) 420 break; 421 } 422 423 if (status == NT_STATUS_SUCCESS) { 424 info->a_name = lsar_get_username(name); 425 426 if (!smb_account_validate(info)) { 427 smb_account_free(info); 428 status = NT_STATUS_NO_MEMORY; 429 } else { 430 smb_account_trace(info); 431 } 432 } 433 434 return (status); 435 } 436 437 /* 438 * The name may be in one of the following forms: 439 * 440 * domain\username 441 * domain/username 442 * username 443 * username@domain 444 * 445 * Return a strdup'd copy of the username. The caller is responsible 446 * for freeing the allocated memory. 447 */ 448 static char * 449 lsar_get_username(const char *name) 450 { 451 char tmp[MAXNAMELEN]; 452 char *dp = NULL; 453 char *np = NULL; 454 455 (void) strlcpy(tmp, name, MAXNAMELEN); 456 smb_name_parse(tmp, &np, &dp); 457 458 if (dp != NULL && np != NULL) 459 return (strdup(np)); 460 else 461 return (strdup(name)); 462 } 463 464 /* 465 * lsar_lookup_names1 466 * 467 * Lookup a name and obtain the domain and user rid. 468 * 469 * Note: NT returns an error if the mapped_count is non-zero when the RPC 470 * is called. 471 * 472 * If the lookup fails, the status will typically be NT_STATUS_NONE_MAPPED. 473 */ 474 static uint32_t 475 lsar_lookup_names1(mlsvc_handle_t *lsa_handle, lsa_names_t *names, 476 smb_account_t *info) 477 { 478 struct mslsa_LookupNames arg; 479 struct mslsa_rid_entry *rid_entry; 480 struct mslsa_domain_entry *domain_entry; 481 uint32_t status = NT_STATUS_SUCCESS; 482 char *domname; 483 int opnum = LSARPC_OPNUM_LookupNames; 484 485 bzero(&arg, sizeof (struct mslsa_LookupNames)); 486 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t)); 487 arg.lookup_level = LSA_LOOKUP_WKSTA; 488 arg.name_table = (struct mslsa_lup_name_table *)names; 489 490 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) { 491 ndr_rpc_release(lsa_handle); 492 return (NT_STATUS_INVALID_PARAMETER); 493 } 494 495 if (arg.status != NT_STATUS_SUCCESS) { 496 ndr_rpc_status(lsa_handle, opnum, arg.status); 497 ndr_rpc_release(lsa_handle); 498 return (NT_SC_VALUE(arg.status)); 499 } 500 501 if (arg.mapped_count == 0) { 502 ndr_rpc_release(lsa_handle); 503 return (NT_STATUS_NONE_MAPPED); 504 } 505 506 rid_entry = &arg.translated_sids.rids[0]; 507 if (rid_entry->domain_index != 0) { 508 ndr_rpc_release(lsa_handle); 509 return (NT_STATUS_NONE_MAPPED); 510 } 511 512 domain_entry = &arg.domain_table->entries[0]; 513 514 info->a_type = rid_entry->sid_name_use; 515 info->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid); 516 if ((domname = (char *)domain_entry->domain_name.str) != NULL) 517 info->a_domain = strdup(domname); 518 info->a_rid = rid_entry->rid; 519 info->a_sid = smb_sid_splice(info->a_domsid, info->a_rid); 520 521 ndr_rpc_release(lsa_handle); 522 return (status); 523 } 524 525 /* 526 * lsar_lookup_names2 527 */ 528 static uint32_t 529 lsar_lookup_names2(mlsvc_handle_t *lsa_handle, lsa_names_t *names, 530 smb_account_t *info) 531 { 532 struct lsar_LookupNames2 arg; 533 struct lsar_rid_entry2 *rid_entry; 534 struct mslsa_domain_entry *domain_entry; 535 uint32_t status = NT_STATUS_SUCCESS; 536 char *domname; 537 int opnum = LSARPC_OPNUM_LookupNames2; 538 539 bzero(&arg, sizeof (struct lsar_LookupNames2)); 540 (void) memcpy(&arg.policy_handle, lsa_handle, sizeof (mslsa_handle_t)); 541 arg.lookup_level = LSA_LOOKUP_WKSTA; 542 arg.client_revision = LSA_CLIENT_REVISION_AD; 543 arg.name_table = (struct mslsa_lup_name_table *)names; 544 545 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) { 546 ndr_rpc_release(lsa_handle); 547 return (NT_STATUS_INVALID_PARAMETER); 548 } 549 550 if (arg.status != NT_STATUS_SUCCESS) { 551 ndr_rpc_status(lsa_handle, opnum, arg.status); 552 ndr_rpc_release(lsa_handle); 553 return (NT_SC_VALUE(arg.status)); 554 } 555 556 if (arg.mapped_count == 0) { 557 ndr_rpc_release(lsa_handle); 558 return (NT_STATUS_NONE_MAPPED); 559 } 560 561 rid_entry = &arg.translated_sids.rids[0]; 562 if (rid_entry->domain_index != 0) { 563 ndr_rpc_release(lsa_handle); 564 return (NT_STATUS_NONE_MAPPED); 565 } 566 567 domain_entry = &arg.domain_table->entries[0]; 568 569 info->a_type = rid_entry->sid_name_use; 570 info->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid); 571 if ((domname = (char *)domain_entry->domain_name.str) != NULL) 572 info->a_domain = strdup(domname); 573 info->a_rid = rid_entry->rid; 574 info->a_sid = smb_sid_splice(info->a_domsid, info->a_rid); 575 576 ndr_rpc_release(lsa_handle); 577 return (status); 578 } 579 580 /* 581 * lsar_lookup_names3 582 */ 583 static uint32_t 584 lsar_lookup_names3(mlsvc_handle_t *lsa_handle, lsa_names_t *names, 585 smb_account_t *info) 586 { 587 struct lsar_LookupNames3 arg; 588 lsar_translated_sid_ex2_t *sid_entry; 589 struct mslsa_domain_entry *domain_entry; 590 uint32_t status = NT_STATUS_SUCCESS; 591 char *domname; 592 int opnum = LSARPC_OPNUM_LookupNames3; 593 594 bzero(&arg, sizeof (struct lsar_LookupNames3)); 595 (void) memcpy(&arg.policy_handle, lsa_handle, sizeof (mslsa_handle_t)); 596 arg.lookup_level = LSA_LOOKUP_WKSTA; 597 arg.client_revision = LSA_CLIENT_REVISION_AD; 598 arg.name_table = (struct mslsa_lup_name_table *)names; 599 600 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) { 601 ndr_rpc_release(lsa_handle); 602 return (NT_STATUS_INVALID_PARAMETER); 603 } 604 605 if (arg.status != NT_STATUS_SUCCESS) { 606 ndr_rpc_status(lsa_handle, opnum, arg.status); 607 ndr_rpc_release(lsa_handle); 608 return (NT_SC_VALUE(arg.status)); 609 } 610 611 if (arg.mapped_count == 0) { 612 ndr_rpc_release(lsa_handle); 613 return (NT_STATUS_NONE_MAPPED); 614 } 615 616 sid_entry = &arg.translated_sids.sids[0]; 617 if (sid_entry->domain_index != 0) { 618 ndr_rpc_release(lsa_handle); 619 return (NT_STATUS_NONE_MAPPED); 620 } 621 622 domain_entry = &arg.domain_table->entries[0]; 623 624 info->a_type = sid_entry->sid_name_use; 625 info->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid); 626 if ((domname = (char *)domain_entry->domain_name.str) != NULL) 627 info->a_domain = strdup(domname); 628 info->a_sid = smb_sid_dup((smb_sid_t *)sid_entry->sid); 629 (void) smb_sid_getrid(info->a_sid, &info->a_rid); 630 631 ndr_rpc_release(lsa_handle); 632 return (status); 633 } 634 635 /* 636 * lsar_lookup_names4 637 * 638 * This function is only valid if the remote RPC server is a domain 639 * controller and requires the security extensions defined in MS-RPCE. 640 * 641 * Domain controllers will return RPC_NT_PROTSEQ_NOT_SUPPORTED here 642 * because we don't support the RPC_C_AUTHN_NETLOGON security provider. 643 * Non-domain controllers will return NT_STATUS_INVALID_SERVER_STATE. 644 */ 645 static uint32_t /*LINTED E_STATIC_UNUSED*/ 646 lsar_lookup_names4(mlsvc_handle_t *lsa_handle, lsa_names_t *names, 647 smb_account_t *info) 648 { 649 struct lsar_LookupNames4 arg; 650 lsar_translated_sid_ex2_t *sid_entry; 651 struct mslsa_domain_entry *domain_entry; 652 uint32_t status = NT_STATUS_SUCCESS; 653 char *domname; 654 int opnum = LSARPC_OPNUM_LookupNames4; 655 656 bzero(&arg, sizeof (struct lsar_LookupNames4)); 657 arg.lookup_level = LSA_LOOKUP_WKSTA; 658 arg.client_revision = LSA_CLIENT_REVISION_AD; 659 arg.name_table = (struct mslsa_lup_name_table *)names; 660 661 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) { 662 ndr_rpc_release(lsa_handle); 663 return (NT_STATUS_INVALID_PARAMETER); 664 } 665 666 if (arg.status != NT_STATUS_SUCCESS) { 667 ndr_rpc_status(lsa_handle, opnum, arg.status); 668 ndr_rpc_release(lsa_handle); 669 if (arg.status == RPC_NT_PROTSEQ_NOT_SUPPORTED || 670 arg.status == NT_STATUS_INVALID_SERVER_STATE) 671 return (NT_STATUS_INVALID_PARAMETER); 672 return (NT_SC_VALUE(arg.status)); 673 } 674 675 if (arg.mapped_count == 0) { 676 ndr_rpc_release(lsa_handle); 677 return (NT_STATUS_NONE_MAPPED); 678 } 679 680 sid_entry = &arg.translated_sids.sids[0]; 681 if (sid_entry->domain_index != 0) { 682 ndr_rpc_release(lsa_handle); 683 return (NT_STATUS_NONE_MAPPED); 684 } 685 686 domain_entry = &arg.domain_table->entries[0]; 687 688 info->a_type = sid_entry->sid_name_use; 689 info->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid); 690 if ((domname = (char *)domain_entry->domain_name.str) != NULL) 691 info->a_domain = strdup(domname); 692 info->a_sid = smb_sid_dup((smb_sid_t *)sid_entry->sid); 693 (void) smb_sid_getrid(info->a_sid, &info->a_rid); 694 695 ndr_rpc_release(lsa_handle); 696 return (status); 697 } 698 699 /* 700 * Lookup a sid and obtain the domain sid and account name. 701 * This is a wrapper for the various lookup sid RPCs. 702 */ 703 uint32_t 704 lsar_lookup_sids(mlsvc_handle_t *lsa_handle, smb_sid_t *sid, 705 smb_account_t *account) 706 { 707 char sidbuf[SMB_SID_STRSZ]; 708 uint32_t status; 709 710 if (lsa_handle == NULL || sid == NULL || account == NULL) 711 return (NT_STATUS_INVALID_PARAMETER); 712 713 bzero(account, sizeof (smb_account_t)); 714 bzero(sidbuf, SMB_SID_STRSZ); 715 smb_sid_tostr(sid, sidbuf); 716 smb_tracef("%s", sidbuf); 717 718 status = lsar_lookup_sids2(lsa_handle, (lsa_sid_t *)sid, account); 719 if (status == RPC_NT_PROCNUM_OUT_OF_RANGE) 720 status = lsar_lookup_sids1(lsa_handle, (lsa_sid_t *)sid, 721 account); 722 723 if (status == NT_STATUS_SUCCESS) { 724 if (!smb_account_validate(account)) { 725 smb_account_free(account); 726 status = NT_STATUS_NO_MEMORY; 727 } else { 728 smb_account_trace(account); 729 } 730 } 731 732 return (status); 733 } 734 735 /* 736 * lsar_lookup_sids1 737 */ 738 static uint32_t 739 lsar_lookup_sids1(mlsvc_handle_t *lsa_handle, lsa_sid_t *sid, 740 smb_account_t *account) 741 { 742 struct mslsa_LookupSids arg; 743 struct mslsa_lup_sid_entry sid_entry; 744 struct mslsa_name_entry *name_entry; 745 struct mslsa_domain_entry *domain_entry; 746 uint32_t status = NT_STATUS_SUCCESS; 747 char *name; 748 int opnum = LSARPC_OPNUM_LookupSids; 749 750 bzero(&arg, sizeof (struct mslsa_LookupSids)); 751 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t)); 752 arg.lookup_level = LSA_LOOKUP_WKSTA; 753 754 sid_entry.psid = sid; 755 arg.lup_sid_table.n_entry = 1; 756 arg.lup_sid_table.entries = &sid_entry; 757 758 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) { 759 ndr_rpc_release(lsa_handle); 760 return (NT_STATUS_INVALID_PARAMETER); 761 } 762 763 if (arg.status != NT_STATUS_SUCCESS) { 764 ndr_rpc_status(lsa_handle, opnum, arg.status); 765 ndr_rpc_release(lsa_handle); 766 return (NT_SC_VALUE(arg.status)); 767 } 768 769 if (arg.mapped_count == 0) { 770 ndr_rpc_release(lsa_handle); 771 return (NT_STATUS_NONE_MAPPED); 772 } 773 774 name_entry = &arg.name_table.entries[0]; 775 if (name_entry->domain_ix != 0) { 776 ndr_rpc_release(lsa_handle); 777 return (NT_STATUS_NONE_MAPPED); 778 } 779 780 name = (char *)name_entry->name.str; 781 account->a_name = (name) ? strdup(name) : strdup(""); 782 account->a_type = name_entry->sid_name_use; 783 account->a_sid = smb_sid_dup((smb_sid_t *)sid); 784 (void) smb_sid_getrid(account->a_sid, &account->a_rid); 785 786 domain_entry = &arg.domain_table->entries[0]; 787 if ((name = (char *)domain_entry->domain_name.str) != NULL) 788 account->a_domain = strdup(name); 789 account->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid); 790 791 ndr_rpc_release(lsa_handle); 792 return (status); 793 } 794 795 /* 796 * lsar_lookup_sids2 797 */ 798 static uint32_t 799 lsar_lookup_sids2(mlsvc_handle_t *lsa_handle, lsa_sid_t *sid, 800 smb_account_t *account) 801 { 802 struct lsar_lookup_sids2 arg; 803 struct lsar_name_entry2 *name_entry; 804 struct mslsa_lup_sid_entry sid_entry; 805 struct mslsa_domain_entry *domain_entry; 806 uint32_t status = NT_STATUS_SUCCESS; 807 char *name; 808 int opnum = LSARPC_OPNUM_LookupSids2; 809 810 bzero(&arg, sizeof (struct lsar_lookup_sids2)); 811 (void) memcpy(&arg.policy_handle, lsa_handle, sizeof (mslsa_handle_t)); 812 813 sid_entry.psid = sid; 814 arg.lup_sid_table.n_entry = 1; 815 arg.lup_sid_table.entries = &sid_entry; 816 arg.lookup_level = LSA_LOOKUP_WKSTA; 817 arg.client_revision = LSA_CLIENT_REVISION_AD; 818 819 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) { 820 ndr_rpc_release(lsa_handle); 821 return (NT_STATUS_INVALID_PARAMETER); 822 } 823 824 if (arg.status != NT_STATUS_SUCCESS) { 825 ndr_rpc_status(lsa_handle, opnum, arg.status); 826 ndr_rpc_release(lsa_handle); 827 return (NT_SC_VALUE(arg.status)); 828 } 829 830 if (arg.mapped_count == 0) { 831 ndr_rpc_release(lsa_handle); 832 return (NT_STATUS_NONE_MAPPED); 833 } 834 835 name_entry = &arg.name_table.entries[0]; 836 if (name_entry->domain_ix != 0) { 837 ndr_rpc_release(lsa_handle); 838 return (NT_STATUS_NONE_MAPPED); 839 } 840 841 name = (char *)name_entry->name.str; 842 account->a_name = (name) ? strdup(name) : strdup(""); 843 account->a_type = name_entry->sid_name_use; 844 account->a_sid = smb_sid_dup((smb_sid_t *)sid); 845 (void) smb_sid_getrid(account->a_sid, &account->a_rid); 846 847 domain_entry = &arg.domain_table->entries[0]; 848 if ((name = (char *)domain_entry->domain_name.str) != NULL) 849 account->a_domain = strdup(name); 850 account->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid); 851 852 ndr_rpc_release(lsa_handle); 853 return (status); 854 } 855 856 /* 857 * lsar_lookup_sids3 858 * 859 * This function is only valid if the remote RPC server is a domain 860 * controller and requires the security extensions defined in MS-RPCE. 861 * 862 * Domain controllers will return RPC_NT_PROTSEQ_NOT_SUPPORTED here 863 * because we don't support the RPC_C_AUTHN_NETLOGON security provider. 864 * Non-domain controllers will return NT_STATUS_INVALID_SERVER_STATE. 865 */ 866 static uint32_t /*LINTED E_STATIC_UNUSED*/ 867 lsar_lookup_sids3(mlsvc_handle_t *lsa_handle, lsa_sid_t *sid, 868 smb_account_t *account) 869 { 870 struct lsar_lookup_sids3 arg; 871 lsar_translated_name_ex_t *name_entry; 872 struct mslsa_lup_sid_entry sid_entry; 873 struct mslsa_domain_entry *domain_entry; 874 uint32_t status = NT_STATUS_SUCCESS; 875 char *name; 876 int opnum = LSARPC_OPNUM_LookupSids3; 877 878 bzero(&arg, sizeof (struct lsar_lookup_sids3)); 879 880 sid_entry.psid = sid; 881 arg.lup_sid_table.n_entry = 1; 882 arg.lup_sid_table.entries = &sid_entry; 883 arg.lookup_level = LSA_LOOKUP_WKSTA; 884 arg.client_revision = LSA_CLIENT_REVISION_AD; 885 886 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) { 887 ndr_rpc_release(lsa_handle); 888 return (NT_STATUS_INVALID_PARAMETER); 889 } 890 891 if (arg.status != NT_STATUS_SUCCESS) { 892 ndr_rpc_status(lsa_handle, opnum, arg.status); 893 ndr_rpc_release(lsa_handle); 894 if (arg.status == RPC_NT_PROTSEQ_NOT_SUPPORTED || 895 arg.status == NT_STATUS_INVALID_SERVER_STATE) 896 return (NT_STATUS_INVALID_PARAMETER); 897 return (NT_SC_VALUE(arg.status)); 898 } 899 900 if (arg.mapped_count == 0) { 901 ndr_rpc_release(lsa_handle); 902 return (NT_STATUS_NONE_MAPPED); 903 } 904 905 name_entry = &arg.name_table.entries[0]; 906 if (name_entry->domain_ix != 0) { 907 ndr_rpc_release(lsa_handle); 908 return (NT_STATUS_NONE_MAPPED); 909 } 910 911 name = (char *)name_entry->name.str; 912 account->a_name = (name) ? strdup(name) : strdup(""); 913 account->a_type = name_entry->sid_name_use; 914 account->a_sid = smb_sid_dup((smb_sid_t *)sid); 915 (void) smb_sid_getrid(account->a_sid, &account->a_rid); 916 917 domain_entry = &arg.domain_table->entries[0]; 918 if ((name = (char *)domain_entry->domain_name.str) != NULL) 919 account->a_domain = strdup(name); 920 account->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid); 921 922 ndr_rpc_release(lsa_handle); 923 return (status); 924 } 925 926 /* 927 * lsar_enum_accounts 928 * 929 * Enumerate the list of accounts (i.e. SIDs). Use the handle returned 930 * from lsa_open_policy2. The enum_context is used to support multiple 931 * calls to this enumeration function. It should be set to 0 on the 932 * first call. It will be updated by the domain controller and should 933 * simply be passed unchanged to subsequent calls until there are no 934 * more accounts. A warning status of 0x1A indicates that no more data 935 * is available. The list of accounts will be returned in accounts. 936 * This list is dynamically allocated using malloc, it should be freed 937 * by the caller when it is no longer required. 938 */ 939 DWORD 940 lsar_enum_accounts(mlsvc_handle_t *lsa_handle, DWORD *enum_context, 941 struct mslsa_EnumAccountBuf *accounts) 942 { 943 struct mslsa_EnumerateAccounts arg; 944 struct mslsa_AccountInfo *info; 945 int opnum; 946 int rc; 947 DWORD status; 948 DWORD n_entries; 949 DWORD i; 950 int nbytes; 951 952 if (lsa_handle == NULL || enum_context == NULL || accounts == NULL) 953 return (NT_STATUS_INTERNAL_ERROR); 954 955 accounts->entries_read = 0; 956 accounts->info = 0; 957 958 opnum = LSARPC_OPNUM_EnumerateAccounts; 959 960 bzero(&arg, sizeof (struct mslsa_EnumerateAccounts)); 961 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t)); 962 arg.enum_context = *enum_context; 963 arg.max_length = MLSVC_MAX_RESPONSE_LEN; 964 965 rc = ndr_rpc_call(lsa_handle, opnum, &arg); 966 if (rc == 0) { 967 status = arg.status; 968 if (arg.status != 0) { 969 if (arg.status == NT_STATUS_NO_MORE_ENTRIES) { 970 *enum_context = arg.enum_context; 971 } else { 972 ndr_rpc_status(lsa_handle, opnum, arg.status); 973 } 974 } else if (arg.enum_buf->entries_read != 0) { 975 n_entries = arg.enum_buf->entries_read; 976 nbytes = n_entries * sizeof (struct mslsa_AccountInfo); 977 978 if ((info = malloc(nbytes)) == NULL) { 979 ndr_rpc_release(lsa_handle); 980 return (NT_STATUS_NO_MEMORY); 981 } 982 983 for (i = 0; i < n_entries; ++i) 984 info[i].sid = (lsa_sid_t *)smb_sid_dup( 985 (smb_sid_t *)arg.enum_buf->info[i].sid); 986 987 accounts->entries_read = n_entries; 988 accounts->info = info; 989 *enum_context = arg.enum_context; 990 } 991 } else { 992 status = NT_STATUS_INVALID_PARAMETER; 993 } 994 995 ndr_rpc_release(lsa_handle); 996 return (status); 997 } 998 999 /* 1000 * lsar_enum_trusted_domains 1001 * 1002 * Enumerate the list of trusted domains. Use the handle returned from 1003 * lsa_open_policy2. The enum_context is used to support multiple calls 1004 * to this enumeration function. It should be set to 0 on the first 1005 * call. It will be updated by the domain controller and should simply 1006 * be passed unchanged to subsequent calls until there are no more 1007 * domains. 1008 * 1009 * The trusted domains aren't actually returned here. They are added 1010 * to the NT domain database. After all of the trusted domains have 1011 * been discovered, the database can be interrogated to find all of 1012 * the trusted domains. 1013 */ 1014 DWORD 1015 lsar_enum_trusted_domains(mlsvc_handle_t *lsa_handle, DWORD *enum_context, 1016 smb_trusted_domains_t *list) 1017 { 1018 struct mslsa_EnumTrustedDomain arg; 1019 int opnum; 1020 DWORD status; 1021 1022 if (list == NULL) 1023 return (NT_STATUS_INVALID_PARAMETER); 1024 1025 opnum = LSARPC_OPNUM_EnumTrustedDomain; 1026 1027 bzero(list, sizeof (smb_trusted_domains_t)); 1028 bzero(&arg, sizeof (struct mslsa_EnumTrustedDomain)); 1029 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t)); 1030 arg.enum_context = *enum_context; 1031 arg.max_length = MLSVC_MAX_RESPONSE_LEN; 1032 1033 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) { 1034 status = NT_STATUS_INVALID_PARAMETER; 1035 } else if (arg.status != 0) { 1036 *enum_context = arg.enum_context; 1037 status = NT_SC_VALUE(arg.status); 1038 1039 /* 1040 * STATUS_NO_MORE_ENTRIES provides call 1041 * status but does not indicate an error. 1042 */ 1043 if (status != NT_STATUS_NO_MORE_ENTRIES) 1044 ndr_rpc_status(lsa_handle, opnum, arg.status); 1045 } else if (arg.enum_buf->entries_read == 0) { 1046 *enum_context = arg.enum_context; 1047 status = 0; 1048 } else { 1049 lsar_set_trusted_domains(arg.enum_buf, list); 1050 *enum_context = arg.enum_context; 1051 status = 0; 1052 } 1053 1054 ndr_rpc_release(lsa_handle); 1055 return (status); 1056 } 1057 1058 DWORD 1059 lsar_enum_trusted_domains_ex(mlsvc_handle_t *lsa_handle, DWORD *enum_context, 1060 smb_trusted_domains_t *list) 1061 { 1062 struct mslsa_EnumTrustedDomainEx arg; 1063 int opnum; 1064 DWORD status; 1065 1066 if (list == NULL) 1067 return (NT_STATUS_INVALID_PARAMETER); 1068 1069 opnum = LSARPC_OPNUM_EnumTrustedDomainsEx; 1070 1071 bzero(list, sizeof (smb_trusted_domains_t)); 1072 bzero(&arg, sizeof (struct mslsa_EnumTrustedDomainEx)); 1073 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t)); 1074 arg.enum_context = *enum_context; 1075 arg.max_length = MLSVC_MAX_RESPONSE_LEN; 1076 1077 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) { 1078 status = NT_STATUS_INVALID_PARAMETER; 1079 } else if (arg.status != 0) { 1080 *enum_context = arg.enum_context; 1081 status = NT_SC_VALUE(arg.status); 1082 1083 /* 1084 * STATUS_NO_MORE_ENTRIES provides call 1085 * status but does not indicate an error. 1086 */ 1087 if (status != NT_STATUS_NO_MORE_ENTRIES) 1088 ndr_rpc_status(lsa_handle, opnum, arg.status); 1089 } else if (arg.enum_buf->entries_read == 0) { 1090 *enum_context = arg.enum_context; 1091 status = 0; 1092 } else { 1093 lsar_set_trusted_domains_ex(arg.enum_buf, list); 1094 *enum_context = arg.enum_context; 1095 status = 0; 1096 } 1097 1098 ndr_rpc_release(lsa_handle); 1099 return (status); 1100 } 1101 1102 /* 1103 * lsar_enum_privs_account 1104 * 1105 * Privileges enum? Need an account handle. 1106 */ 1107 /*ARGSUSED*/ 1108 int 1109 lsar_enum_privs_account(mlsvc_handle_t *account_handle, smb_account_t *account) 1110 { 1111 struct mslsa_EnumPrivsAccount arg; 1112 int opnum; 1113 int rc; 1114 1115 opnum = LSARPC_OPNUM_EnumPrivsAccount; 1116 1117 bzero(&arg, sizeof (struct mslsa_EnumPrivsAccount)); 1118 (void) memcpy(&arg.account_handle, &account_handle->handle, 1119 sizeof (mslsa_handle_t)); 1120 1121 rc = ndr_rpc_call(account_handle, opnum, &arg); 1122 if ((rc == 0) && (arg.status != 0)) { 1123 ndr_rpc_status(account_handle, opnum, arg.status); 1124 rc = -1; 1125 } 1126 ndr_rpc_release(account_handle); 1127 return (rc); 1128 } 1129 1130 /* 1131 * lsar_lookup_priv_value 1132 * 1133 * Map a privilege name to a local unique id (LUID). Privilege names 1134 * are consistent across the network. LUIDs are machine specific. 1135 * This function provides the means to map a privilege name to the 1136 * LUID used by a remote server to represent it. The handle here is 1137 * a policy handle. 1138 */ 1139 int 1140 lsar_lookup_priv_value(mlsvc_handle_t *lsa_handle, char *name, 1141 struct ms_luid *luid) 1142 { 1143 struct mslsa_LookupPrivValue arg; 1144 int opnum; 1145 int rc; 1146 size_t length; 1147 1148 if (lsa_handle == NULL || name == NULL || luid == NULL) 1149 return (-1); 1150 1151 opnum = LSARPC_OPNUM_LookupPrivValue; 1152 1153 bzero(&arg, sizeof (struct mslsa_LookupPrivValue)); 1154 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t)); 1155 1156 length = smb_wcequiv_strlen(name); 1157 length += sizeof (smb_wchar_t); 1158 1159 arg.name.length = length; 1160 arg.name.allosize = length; 1161 arg.name.str = (unsigned char *)name; 1162 1163 rc = ndr_rpc_call(lsa_handle, opnum, &arg); 1164 if (rc == 0) { 1165 if (arg.status != 0) 1166 rc = -1; 1167 else 1168 (void) memcpy(luid, &arg.luid, sizeof (struct ms_luid)); 1169 } 1170 1171 ndr_rpc_release(lsa_handle); 1172 return (rc); 1173 } 1174 1175 /* 1176 * lsar_lookup_priv_name 1177 * 1178 * Map a local unique id (LUID) to a privilege name. Privilege names 1179 * are consistent across the network. LUIDs are machine specific. 1180 * This function the means to map the LUID used by a remote server to 1181 * the appropriate privilege name. The handle here is a policy handle. 1182 */ 1183 int 1184 lsar_lookup_priv_name(mlsvc_handle_t *lsa_handle, struct ms_luid *luid, 1185 char *name, int namelen) 1186 { 1187 struct mslsa_LookupPrivName arg; 1188 int opnum; 1189 int rc; 1190 1191 if (lsa_handle == NULL || luid == NULL || name == NULL) 1192 return (-1); 1193 1194 opnum = LSARPC_OPNUM_LookupPrivName; 1195 1196 bzero(&arg, sizeof (struct mslsa_LookupPrivName)); 1197 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t)); 1198 (void) memcpy(&arg.luid, luid, sizeof (struct ms_luid)); 1199 1200 rc = ndr_rpc_call(lsa_handle, opnum, &arg); 1201 if (rc == 0) { 1202 if (arg.status != 0) 1203 rc = -1; 1204 else 1205 (void) strlcpy(name, (char const *)arg.name->str, 1206 namelen); 1207 } 1208 1209 ndr_rpc_release(lsa_handle); 1210 return (rc); 1211 } 1212 1213 /* 1214 * lsar_lookup_priv_display_name 1215 * 1216 * Map a privilege name to a privilege display name. The input handle 1217 * should be an LSA policy handle and the name would normally be one 1218 * of the privileges defined in smb_privilege.h 1219 * 1220 * There's something peculiar about the return status from NT servers, 1221 * it's not always present. So for now, I'm ignoring the status in the 1222 * RPC response. 1223 * 1224 * Returns NT status codes. 1225 */ 1226 DWORD 1227 lsar_lookup_priv_display_name(mlsvc_handle_t *lsa_handle, char *name, 1228 char *display_name, int display_len) 1229 { 1230 struct mslsa_LookupPrivDisplayName arg; 1231 int opnum; 1232 size_t length; 1233 DWORD status; 1234 1235 if (lsa_handle == NULL || name == NULL || display_name == NULL) 1236 return (NT_STATUS_INVALID_PARAMETER); 1237 1238 opnum = LSARPC_OPNUM_LookupPrivDisplayName; 1239 1240 bzero(&arg, sizeof (struct mslsa_LookupPrivDisplayName)); 1241 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t)); 1242 1243 length = smb_wcequiv_strlen(name); 1244 arg.name.length = length; 1245 arg.name.allosize = length; 1246 arg.name.str = (unsigned char *)name; 1247 1248 arg.client_language = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US); 1249 arg.default_language = MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL); 1250 1251 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) 1252 status = NT_STATUS_INVALID_PARAMETER; 1253 #if 0 1254 else if (arg.status != 0) 1255 status = NT_SC_VALUE(arg.status); 1256 #endif 1257 else { 1258 (void) strlcpy(display_name, 1259 (char const *)arg.display_name->str, display_len); 1260 status = NT_STATUS_SUCCESS; 1261 } 1262 1263 ndr_rpc_release(lsa_handle); 1264 return (status); 1265 } 1266 1267 static void 1268 lsar_set_trusted_domains_ex(struct mslsa_EnumTrustedDomainBufEx *enum_buf, 1269 smb_trusted_domains_t *list) 1270 { 1271 char sidstr[SMB_SID_STRSZ]; 1272 int i; 1273 1274 if (list == NULL || enum_buf == NULL || enum_buf->entries_read == 0) 1275 return; 1276 1277 list->td_num = 0; 1278 list->td_domains = calloc(enum_buf->entries_read, 1279 sizeof (smb_domain_t)); 1280 1281 if (list->td_domains == NULL) 1282 return; 1283 1284 list->td_num = enum_buf->entries_read; 1285 for (i = 0; i < list->td_num; i++) { 1286 smb_sid_tostr((smb_sid_t *)enum_buf->info[i].sid, sidstr); 1287 smb_domain_set_trust_info( 1288 sidstr, 1289 (char *)enum_buf->info[i].nb_name.str, 1290 (char *)enum_buf->info[i].dns_name.str, 1291 enum_buf->info[i].trust_direction, 1292 enum_buf->info[i].trust_type, 1293 enum_buf->info[i].trust_attrs, 1294 &list->td_domains[i]); 1295 } 1296 } 1297 1298 static void 1299 lsar_set_trusted_domains(struct mslsa_EnumTrustedDomainBuf *enum_buf, 1300 smb_trusted_domains_t *list) 1301 { 1302 char sidstr[SMB_SID_STRSZ]; 1303 int i; 1304 1305 if (list == NULL || enum_buf == NULL || enum_buf->entries_read == 0) 1306 return; 1307 1308 list->td_num = 0; 1309 list->td_domains = calloc(enum_buf->entries_read, 1310 sizeof (smb_domain_t)); 1311 1312 if (list->td_domains == NULL) 1313 return; 1314 1315 list->td_num = enum_buf->entries_read; 1316 for (i = 0; i < list->td_num; i++) { 1317 smb_sid_tostr((smb_sid_t *)enum_buf->info[i].sid, sidstr); 1318 smb_domain_set_trust_info( 1319 sidstr, (char *)enum_buf->info[i].name.str, 1320 "", 0, 0, 0, &list->td_domains[i]); 1321 } 1322 } 1323 1324 static void 1325 smb_account_trace(const smb_account_t *info) 1326 { 1327 char sidbuf[SMB_SID_STRSZ]; 1328 1329 bzero(sidbuf, SMB_SID_STRSZ); 1330 smb_sid_tostr(info->a_sid, sidbuf); 1331 1332 smb_tracef("%s %s %s %lu %s", info->a_domain, info->a_name, 1333 sidbuf, info->a_rid, smb_sid_type2str(info->a_type)); 1334 } 1335