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 }