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 2013 Nexenta Systems, Inc.  All rights reserved.
  25  */
  26 
  27 /*
  28  * Local Security Authority RPC (LSAR) server-side interface.
  29  */
  30 
  31 #include <unistd.h>
  32 #include <strings.h>
  33 #include <pwd.h>
  34 #include <grp.h>
  35 
  36 #include <libmlrpc/libmlrpc.h>
  37 #include <smbsrv/libsmb.h>
  38 #include <smbsrv/libmlsvc.h>
  39 #include <smbsrv/ndl/lsarpc.ndl>
  40 #include <lsalib.h>
  41 #include <smbsrv/smbinfo.h>
  42 #include <smbsrv/nmpipes.h>
  43 #include <smbsrv/ntlocale.h>
  44 
  45 struct local_group_table {
  46         WORD sid_name_use;
  47         WORD domain_ix;
  48         char *sid;
  49         char *name;
  50 };
  51 
  52 static int lsarpc_key_domain;
  53 static int lsarpc_key_account;
  54 
  55 static int lsarpc_call_stub(ndr_xa_t *mxa);
  56 
  57 static int lsarpc_s_CloseHandle(void *, ndr_xa_t *);
  58 static int lsarpc_s_QuerySecurityObject(void *, ndr_xa_t *);
  59 static int lsarpc_s_EnumAccounts(void *, ndr_xa_t *);
  60 static int lsarpc_s_EnumTrustedDomain(void *, ndr_xa_t *);
  61 static int lsarpc_s_EnumTrustedDomainsEx(void *, ndr_xa_t *);
  62 static int lsarpc_s_OpenAccount(void *, ndr_xa_t *);
  63 static int lsarpc_s_EnumPrivsAccount(void *, ndr_xa_t *);
  64 static int lsarpc_s_LookupPrivValue(void *, ndr_xa_t *);
  65 static int lsarpc_s_LookupPrivName(void *, ndr_xa_t *);
  66 static int lsarpc_s_LookupPrivDisplayName(void *, ndr_xa_t *);
  67 static int lsarpc_s_CreateSecret(void *, ndr_xa_t *);
  68 static int lsarpc_s_OpenSecret(void *, ndr_xa_t *);
  69 static int lsarpc_s_QueryInfoPolicy(void *, ndr_xa_t *);
  70 static int lsarpc_s_OpenDomainHandle(void *, ndr_xa_t *);
  71 static int lsarpc_s_OpenDomainHandle(void *, ndr_xa_t *);
  72 static int lsarpc_s_LookupSids(void *, ndr_xa_t *);
  73 static int lsarpc_s_LookupNames(void *, ndr_xa_t *);
  74 static int lsarpc_s_GetConnectedUser(void *, ndr_xa_t *);
  75 static int lsarpc_s_LookupSids2(void *, ndr_xa_t *);
  76 static int lsarpc_s_LookupSids3(void *, ndr_xa_t *);
  77 static int lsarpc_s_LookupNames2(void *, ndr_xa_t *);
  78 static int lsarpc_s_LookupNames3(void *, ndr_xa_t *);
  79 static int lsarpc_s_LookupNames4(void *, ndr_xa_t *);
  80 
  81 static DWORD lsarpc_s_PrimaryDomainInfo(struct mslsa_PrimaryDomainInfo *,
  82     ndr_xa_t *);
  83 static DWORD lsarpc_s_AccountDomainInfo(struct mslsa_AccountDomainInfo *,
  84     ndr_xa_t *);
  85 static int lsarpc_s_UpdateDomainTable(ndr_xa_t *,
  86     smb_account_t *, struct mslsa_domain_table *, DWORD *);
  87 
  88 static ndr_stub_table_t lsarpc_stub_table[] = {
  89         { lsarpc_s_CloseHandle,           LSARPC_OPNUM_CloseHandle },
  90         { lsarpc_s_QuerySecurityObject,   LSARPC_OPNUM_QuerySecurityObject },
  91         { lsarpc_s_EnumAccounts,          LSARPC_OPNUM_EnumerateAccounts },
  92         { lsarpc_s_EnumTrustedDomain,     LSARPC_OPNUM_EnumTrustedDomain },
  93         { lsarpc_s_EnumTrustedDomainsEx,  LSARPC_OPNUM_EnumTrustedDomainsEx },
  94         { lsarpc_s_OpenAccount,           LSARPC_OPNUM_OpenAccount },
  95         { lsarpc_s_EnumPrivsAccount,      LSARPC_OPNUM_EnumPrivsAccount },
  96         { lsarpc_s_LookupPrivValue,       LSARPC_OPNUM_LookupPrivValue },
  97         { lsarpc_s_LookupPrivName,        LSARPC_OPNUM_LookupPrivName },
  98         { lsarpc_s_LookupPrivDisplayName, LSARPC_OPNUM_LookupPrivDisplayName },
  99         { lsarpc_s_CreateSecret,          LSARPC_OPNUM_CreateSecret },
 100         { lsarpc_s_OpenSecret,            LSARPC_OPNUM_OpenSecret },
 101         { lsarpc_s_QueryInfoPolicy,       LSARPC_OPNUM_QueryInfoPolicy },
 102         { lsarpc_s_OpenDomainHandle,      LSARPC_OPNUM_OpenPolicy },
 103         { lsarpc_s_OpenDomainHandle,      LSARPC_OPNUM_OpenPolicy2 },
 104         { lsarpc_s_LookupSids,            LSARPC_OPNUM_LookupSids },
 105         { lsarpc_s_LookupNames,           LSARPC_OPNUM_LookupNames },
 106         { lsarpc_s_GetConnectedUser,      LSARPC_OPNUM_GetConnectedUser },
 107         { lsarpc_s_LookupSids2,           LSARPC_OPNUM_LookupSids2 },
 108         { lsarpc_s_LookupSids3,           LSARPC_OPNUM_LookupSids3 },
 109         { lsarpc_s_LookupNames2,          LSARPC_OPNUM_LookupNames2 },
 110         { lsarpc_s_LookupNames3,          LSARPC_OPNUM_LookupNames3 },
 111         { lsarpc_s_LookupNames4,          LSARPC_OPNUM_LookupNames4 },
 112         {0}
 113 };
 114 
 115 static ndr_service_t lsarpc_service = {
 116         "LSARPC",                       /* name */
 117         "Local Security Authority",     /* desc */
 118         "\\lsarpc",                     /* endpoint */
 119         PIPE_LSASS,                     /* sec_addr_port */
 120         "12345778-1234-abcd-ef00-0123456789ab", 0,      /* abstract */
 121         NDR_TRANSFER_SYNTAX_UUID,               2,      /* transfer */
 122         0,                              /* no bind_instance_size */
 123         NULL,                           /* no bind_req() */
 124         NULL,                           /* no unbind_and_close() */
 125         lsarpc_call_stub,               /* call_stub() */
 126         &TYPEINFO(lsarpc_interface),        /* interface ti */
 127         lsarpc_stub_table               /* stub_table */
 128 };
 129 
 130 /*
 131  * lsarpc_initialize
 132  *
 133  * This function registers the LSA RPC interface with the RPC runtime
 134  * library. It must be called in order to use either the client side
 135  * or the server side functions.
 136  */
 137 void
 138 lsarpc_initialize(void)
 139 {
 140         (void) ndr_svc_register(&lsarpc_service);
 141 }
 142 
 143 /*
 144  * Custom call_stub to set the stream string policy.
 145  */
 146 static int
 147 lsarpc_call_stub(ndr_xa_t *mxa)
 148 {
 149         NDS_SETF(&mxa->send_nds, NDS_F_NOTERM);
 150         NDS_SETF(&mxa->recv_nds, NDS_F_NOTERM);
 151 
 152         return (ndr_generic_call_stub(mxa));
 153 }
 154 
 155 /*
 156  * lsarpc_s_OpenDomainHandle opnum=0x06
 157  *
 158  * This is a request to open the LSA (OpenPolicy and OpenPolicy2).
 159  * The client is looking for an LSA domain handle.
 160  */
 161 static int
 162 lsarpc_s_OpenDomainHandle(void *arg, ndr_xa_t *mxa)
 163 {
 164         struct mslsa_OpenPolicy2 *param = arg;
 165         ndr_hdid_t *id;
 166 
 167         if ((id = ndr_hdalloc(mxa, &lsarpc_key_domain)) != NULL) {
 168                 bcopy(id, &param->domain_handle, sizeof (mslsa_handle_t));
 169                 param->status = NT_STATUS_SUCCESS;
 170         } else {
 171                 bzero(&param->domain_handle, sizeof (mslsa_handle_t));
 172                 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
 173         }
 174 
 175         return (NDR_DRC_OK);
 176 }
 177 
 178 /*
 179  * lsarpc_s_CloseHandle opnum=0x00
 180  *
 181  * This is a request to close the LSA interface specified by the handle.
 182  * We don't track handles (yet), so just zero out the handle and return
 183  * NDR_DRC_OK. Setting the handle to zero appears to be standard
 184  * behaviour and someone may rely on it, i.e. we do on the client side.
 185  */
 186 static int
 187 lsarpc_s_CloseHandle(void *arg, ndr_xa_t *mxa)
 188 {
 189         struct mslsa_CloseHandle *param = arg;
 190         ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
 191 
 192         ndr_hdfree(mxa, id);
 193 
 194         bzero(&param->result_handle, sizeof (param->result_handle));
 195         param->status = NT_STATUS_SUCCESS;
 196         return (NDR_DRC_OK);
 197 }
 198 
 199 /*
 200  * lsarpc_s_QuerySecurityObject
 201  */
 202 /*ARGSUSED*/
 203 static int
 204 lsarpc_s_QuerySecurityObject(void *arg, ndr_xa_t *mxa)
 205 {
 206         struct mslsa_QuerySecurityObject *param = arg;
 207 
 208         bzero(param, sizeof (struct mslsa_QuerySecurityObject));
 209         param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
 210 
 211         return (NDR_DRC_OK);
 212 }
 213 
 214 /*
 215  * lsarpc_s_EnumAccounts
 216  *
 217  * Enumerate the list of local accounts SIDs. The client should supply
 218  * a valid OpenPolicy2 handle. The enum_context is used to support
 219  * multiple enumeration calls to obtain the complete list of SIDs.
 220  * It should be set to 0 on the first call and passed unchanged on
 221  * subsequent calls until there are no more accounts - the server will
 222  * return STATUS_NO_MORE_ENTRIES.
 223  *
 224  * For now just set the status to access-denied. Note that we still have
 225  * to provide a valid address for enum_buf because it's a reference and
 226  * the marshalling rules require that references must not be null.
 227  * The enum_context is used to support multiple
 228  */
 229 static int
 230 lsarpc_s_EnumAccounts(void *arg, ndr_xa_t *mxa)
 231 {
 232         struct mslsa_EnumerateAccounts *param = arg;
 233         struct mslsa_EnumAccountBuf *enum_buf;
 234 
 235         bzero(param, sizeof (struct mslsa_EnumerateAccounts));
 236 
 237         enum_buf = NDR_NEW(mxa, struct mslsa_EnumAccountBuf);
 238         if (enum_buf == NULL) {
 239                 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
 240                 return (NDR_DRC_OK);
 241         }
 242 
 243         bzero(enum_buf, sizeof (struct mslsa_EnumAccountBuf));
 244         param->enum_buf = enum_buf;
 245         param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
 246         return (NDR_DRC_OK);
 247 }
 248 
 249 
 250 /*
 251  * lsarpc_s_EnumTrustedDomain
 252  *
 253  * This is the server side function for handling requests to enumerate
 254  * the list of trusted domains: currently held in the NT domain database.
 255  * This call requires an OpenPolicy2 handle. The enum_context is used to
 256  * support multiple enumeration calls to obtain the complete list.
 257  * It should be set to 0 on the first call and passed unchanged on
 258  * subsequent calls until there are no more accounts - the server will
 259  * return STATUS_NO_MORE_ENTRIES.
 260  *
 261  * For now just set the status to access-denied. Note that we still have
 262  * to provide a valid address for enum_buf because it's a reference and
 263  * the marshalling rules require that references must not be null.
 264  */
 265 static int
 266 lsarpc_s_EnumTrustedDomain(void *arg, ndr_xa_t *mxa)
 267 {
 268         struct mslsa_EnumTrustedDomain *param = arg;
 269         struct mslsa_EnumTrustedDomainBuf *enum_buf;
 270 
 271         bzero(param, sizeof (struct mslsa_EnumTrustedDomain));
 272 
 273         enum_buf = NDR_NEW(mxa, struct mslsa_EnumTrustedDomainBuf);
 274         if (enum_buf == NULL) {
 275                 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
 276                 return (NDR_DRC_OK);
 277         }
 278 
 279         bzero(enum_buf, sizeof (struct mslsa_EnumTrustedDomainBuf));
 280         param->enum_buf = enum_buf;
 281         param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
 282         return (NDR_DRC_OK);
 283 }
 284 
 285 /*
 286  * lsarpc_s_EnumTrustedDomainsEx
 287  *
 288  * This is the server side function for handling requests to enumerate
 289  * the list of trusted domains: currently held in the NT domain database.
 290  * This call requires an OpenPolicy2 handle. The enum_context is used to
 291  * support multiple enumeration calls to obtain the complete list.
 292  * It should be set to 0 on the first call and passed unchanged on
 293  * subsequent calls until there are no more accounts - the server will
 294  * return STATUS_NO_MORE_ENTRIES.
 295  *
 296  * For now just set the status to access-denied. Note that we still have
 297  * to provide a valid address for enum_buf because it's a reference and
 298  * the marshalling rules require that references must not be null.
 299  */
 300 static int
 301 lsarpc_s_EnumTrustedDomainsEx(void *arg, ndr_xa_t *mxa)
 302 {
 303         struct mslsa_EnumTrustedDomainEx *param = arg;
 304         struct mslsa_EnumTrustedDomainBufEx *enum_buf;
 305 
 306         bzero(param, sizeof (struct mslsa_EnumTrustedDomainEx));
 307 
 308         enum_buf = NDR_NEW(mxa, struct mslsa_EnumTrustedDomainBufEx);
 309         if (enum_buf == NULL) {
 310                 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
 311                 return (NDR_DRC_OK);
 312         }
 313 
 314         bzero(enum_buf, sizeof (struct mslsa_EnumTrustedDomainBufEx));
 315         param->enum_buf = enum_buf;
 316         param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
 317         return (NDR_DRC_OK);
 318 }
 319 
 320 /*
 321  * lsarpc_s_OpenAccount
 322  *
 323  * This is a request to open an account handle.
 324  */
 325 static int
 326 lsarpc_s_OpenAccount(void *arg, ndr_xa_t *mxa)
 327 {
 328         struct mslsa_OpenAccount *param = arg;
 329         ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
 330         ndr_handle_t *hd;
 331 
 332         hd = ndr_hdlookup(mxa, id);
 333         if ((hd == NULL) || (hd->nh_data != &lsarpc_key_domain)) {
 334                 bzero(param, sizeof (struct mslsa_OpenAccount));
 335                 param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
 336                 return (NDR_DRC_OK);
 337         }
 338 
 339         if ((id = ndr_hdalloc(mxa, &lsarpc_key_account)) != NULL) {
 340                 bcopy(id, &param->account_handle, sizeof (mslsa_handle_t));
 341                 param->status = NT_STATUS_SUCCESS;
 342         } else {
 343                 bzero(&param->account_handle, sizeof (mslsa_handle_t));
 344                 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
 345         }
 346 
 347         return (NDR_DRC_OK);
 348 }
 349 
 350 
 351 /*
 352  * lsarpc_s_EnumPrivsAccount
 353  *
 354  * This is the server side function for handling requests for account
 355  * privileges. For now just set the status to not-supported status and
 356  * return NDR_DRC_OK. Note that we still have to provide a valid
 357  * address for enum_buf because it's a reference and the marshalling
 358  * rules require that references must not be null.
 359  */
 360 /*ARGSUSED*/
 361 static int
 362 lsarpc_s_EnumPrivsAccount(void *arg, ndr_xa_t *mxa)
 363 {
 364         struct mslsa_EnumPrivsAccount *param = arg;
 365 
 366         bzero(param, sizeof (struct mslsa_EnumPrivsAccount));
 367         param->status = NT_SC_ERROR(NT_STATUS_NOT_SUPPORTED);
 368         return (NDR_DRC_OK);
 369 }
 370 
 371 /*
 372  * lsarpc_s_LookupPrivValue
 373  *
 374  * Server side function used to map a privilege name to a locally unique
 375  * identifier (LUID).
 376  */
 377 /*ARGSUSED*/
 378 static int
 379 lsarpc_s_LookupPrivValue(void *arg, ndr_xa_t *mxa)
 380 {
 381         struct mslsa_LookupPrivValue *param = arg;
 382         smb_privinfo_t *pi;
 383 
 384         if ((pi = smb_priv_getbyname((char *)param->name.str)) == NULL) {
 385                 bzero(param, sizeof (struct mslsa_LookupPrivValue));
 386                 param->status = NT_SC_ERROR(NT_STATUS_NO_SUCH_PRIVILEGE);
 387                 return (NDR_DRC_OK);
 388         }
 389 
 390         param->luid.low_part = pi->id;
 391         param->luid.high_part = 0;
 392         param->status = NT_STATUS_SUCCESS;
 393         return (NDR_DRC_OK);
 394 }
 395 
 396 /*
 397  * lsarpc_s_LookupPrivName
 398  *
 399  * Server side function used to map a locally unique identifier (LUID)
 400  * to the appropriate privilege name string.
 401  */
 402 static int
 403 lsarpc_s_LookupPrivName(void *arg, ndr_xa_t *mxa)
 404 {
 405         struct mslsa_LookupPrivName *param = arg;
 406         smb_privinfo_t *pi;
 407         int rc;
 408 
 409         if ((pi = smb_priv_getbyvalue(param->luid.low_part)) == NULL) {
 410                 bzero(param, sizeof (struct mslsa_LookupPrivName));
 411                 param->status = NT_SC_ERROR(NT_STATUS_NO_SUCH_PRIVILEGE);
 412                 return (NDR_DRC_OK);
 413         }
 414 
 415         param->name = NDR_NEW(mxa, mslsa_string_t);
 416         if (param->name == NULL) {
 417                 bzero(param, sizeof (struct mslsa_LookupPrivName));
 418                 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
 419                 return (NDR_DRC_OK);
 420         }
 421 
 422         rc = NDR_MSTRING(mxa, pi->name, (ndr_mstring_t *)param->name);
 423         if (rc == -1) {
 424                 bzero(param, sizeof (struct mslsa_LookupPrivName));
 425                 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
 426                 return (NDR_DRC_OK);
 427         }
 428 
 429         param->status = NT_STATUS_SUCCESS;
 430         return (NDR_DRC_OK);
 431 }
 432 
 433 /*
 434  * lsarpc_s_LookupPrivDisplayName
 435  *
 436  * This is the server side function for handling requests for account
 437  * privileges. For now just set the status to not-supported status and
 438  * return NDR_DRC_OK.
 439  */
 440 static int
 441 lsarpc_s_LookupPrivDisplayName(void *arg, ndr_xa_t *mxa)
 442 {
 443         struct mslsa_LookupPrivDisplayName *param = arg;
 444         smb_privinfo_t *pi;
 445         int rc;
 446 
 447         if ((pi = smb_priv_getbyname((char *)param->name.str)) == NULL) {
 448                 bzero(param, sizeof (struct mslsa_LookupPrivDisplayName));
 449                 param->status = NT_SC_ERROR(NT_STATUS_NO_SUCH_PRIVILEGE);
 450                 return (NDR_DRC_OK);
 451         }
 452 
 453         param->display_name = NDR_NEW(mxa, mslsa_string_t);
 454         if (param->display_name == NULL) {
 455                 bzero(param, sizeof (struct mslsa_LookupPrivDisplayName));
 456                 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
 457                 return (NDR_DRC_OK);
 458         }
 459 
 460         rc = NDR_MSTRING(mxa, pi->display_name,
 461             (ndr_mstring_t *)param->display_name);
 462         if (rc == -1) {
 463                 bzero(param, sizeof (struct mslsa_LookupPrivDisplayName));
 464                 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
 465                 return (NDR_DRC_OK);
 466         }
 467 
 468         param->language_ret = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
 469         param->status = NT_STATUS_SUCCESS;
 470         return (NDR_DRC_OK);
 471 }
 472 
 473 static int
 474 lsarpc_s_CreateSecret(void *arg, ndr_xa_t *mxa)
 475 {
 476         struct mslsa_CreateSecret *param = arg;
 477         ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
 478         ndr_handle_t *hd;
 479 
 480         hd = ndr_hdlookup(mxa, id);
 481         if ((hd == NULL) || (hd->nh_data != &lsarpc_key_domain)) {
 482                 bzero(param, sizeof (struct mslsa_OpenAccount));
 483                 param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
 484                 return (NDR_DRC_OK);
 485         }
 486 
 487         bzero(&param->secret_handle, sizeof (mslsa_handle_t));
 488         param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
 489         return (NDR_DRC_OK);
 490 }
 491 
 492 static int
 493 lsarpc_s_OpenSecret(void *arg, ndr_xa_t *mxa)
 494 {
 495         struct mslsa_OpenSecret *param = arg;
 496         ndr_hdid_t *id = (ndr_hdid_t *)&param->handle;
 497         ndr_handle_t *hd;
 498 
 499         hd = ndr_hdlookup(mxa, id);
 500         if ((hd == NULL) || (hd->nh_data != &lsarpc_key_domain)) {
 501                 bzero(param, sizeof (struct mslsa_OpenAccount));
 502                 param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
 503                 return (NDR_DRC_OK);
 504         }
 505 
 506         bzero(&param->secret_handle, sizeof (mslsa_handle_t));
 507         param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
 508         return (NDR_DRC_OK);
 509 }
 510 
 511 /*
 512  * lsarpc_s_GetConnectedUser
 513  *
 514  * Return the account name and NetBIOS domain name for the user making
 515  * the request.  The hostname field should be ignored by the server.
 516  *
 517  * Note: MacOS uses this, whether we're a domain member or not.
 518  */
 519 static int
 520 lsarpc_s_GetConnectedUser(void *arg, ndr_xa_t *mxa)
 521 {
 522         struct mslsa_GetConnectedUser *param = arg;
 523         smb_netuserinfo_t *user = mxa->pipe->np_user;
 524         DWORD status = NT_STATUS_SUCCESS;
 525         int rc1;
 526         int rc2;
 527 
 528         param->owner = NDR_NEW(mxa, struct mslsa_string_desc);
 529         param->domain = NDR_NEW(mxa, struct mslsa_DomainName);
 530         if (param->owner == NULL || param->domain == NULL) {
 531                 status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
 532                 param->status = status;
 533                 return (NDR_DRC_OK);
 534         }
 535 
 536         param->domain->name = NDR_NEW(mxa, struct mslsa_string_desc);
 537         if (param->domain->name == NULL) {
 538                 status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
 539                 param->status = status;
 540                 return (NDR_DRC_OK);
 541         }
 542 
 543         rc1 = NDR_MSTRING(mxa, user->ui_account,
 544             (ndr_mstring_t *)param->owner);
 545         rc2 = NDR_MSTRING(mxa, user->ui_domain,
 546             (ndr_mstring_t *)param->domain->name);
 547 
 548         if (rc1 == -1 || rc2 == -1)
 549                 status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
 550 
 551         param->status = status;
 552         return (NDR_DRC_OK);
 553 }
 554 
 555 
 556 /*
 557  * lsarpc_s_QueryInfoPolicy
 558  *
 559  * This is the server side function for handling LSA information policy
 560  * queries. Currently, we only support primary domain and account
 561  * domain queries. This is just a front end to switch on the request
 562  * and hand it off to the appropriate function to actually deal with
 563  * obtaining and building the response.
 564  */
 565 static int
 566 lsarpc_s_QueryInfoPolicy(void *arg, ndr_xa_t *mxa)
 567 {
 568         struct mslsa_QueryInfoPolicy *param = arg;
 569         union mslsa_PolicyInfoResUnion *ru = &param->ru;
 570         int security_mode;
 571         DWORD status;
 572 
 573         param->switch_value = param->info_class;
 574 
 575         switch (param->info_class) {
 576         case MSLSA_POLICY_AUDIT_EVENTS_INFO:
 577                 ru->audit_events.enabled = 0;
 578                 ru->audit_events.count = 1;
 579                 ru->audit_events.settings
 580                     = NDR_MALLOC(mxa, sizeof (DWORD));
 581                 bzero(ru->audit_events.settings, sizeof (DWORD));
 582                 status = NT_STATUS_SUCCESS;
 583                 break;
 584 
 585         case MSLSA_POLICY_PRIMARY_DOMAIN_INFO:
 586                 status = lsarpc_s_PrimaryDomainInfo(&ru->pd_info, mxa);
 587                 break;
 588 
 589         case MSLSA_POLICY_ACCOUNT_DOMAIN_INFO:
 590                 status = lsarpc_s_AccountDomainInfo(&ru->ad_info, mxa);
 591                 break;
 592 
 593         case MSLSA_POLICY_SERVER_ROLE_INFO:
 594                 security_mode = smb_config_get_secmode();
 595 
 596                 if (security_mode == SMB_SECMODE_DOMAIN)
 597                         ru->server_role.role = LSA_ROLE_MEMBER_SERVER;
 598                 else
 599                         ru->server_role.role = LSA_ROLE_STANDALONE_SERVER;
 600 
 601                 ru->server_role.pad = 0;
 602                 status = NT_STATUS_SUCCESS;
 603                 break;
 604 
 605         default:
 606                 bzero(param, sizeof (struct mslsa_QueryInfoPolicy));
 607                 param->status = NT_SC_ERROR(NT_STATUS_INVALID_INFO_CLASS);
 608                 return (NDR_DRC_OK);
 609         }
 610 
 611         if (status != NT_STATUS_SUCCESS)
 612                 param->status = NT_SC_ERROR(status);
 613         else
 614                 param->status = NT_STATUS_SUCCESS;
 615         param->address = (DWORD)(uintptr_t)ru;
 616 
 617         return (NDR_DRC_OK);
 618 }
 619 
 620 
 621 /*
 622  * lsarpc_s_PrimaryDomainInfo
 623  *
 624  * Service primary domain policy queries.  In domain mode, return the
 625  * primary domain name and SID.   In workgroup mode, return the local
 626  * hostname and local domain SID.
 627  *
 628  * Note: info is zeroed on entry to ensure the SID and name do not
 629  * contain spurious values if an error is returned.
 630  */
 631 static DWORD
 632 lsarpc_s_PrimaryDomainInfo(struct mslsa_PrimaryDomainInfo *info,
 633     ndr_xa_t *mxa)
 634 {
 635         smb_domain_t di;
 636         boolean_t found;
 637         int rc;
 638 
 639         bzero(info, sizeof (struct mslsa_PrimaryDomainInfo));
 640 
 641         if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN)
 642                 found = smb_domain_lookup_type(SMB_DOMAIN_LOCAL, &di);
 643         else
 644                 found = smb_domain_lookup_type(SMB_DOMAIN_PRIMARY, &di);
 645 
 646         if (!found)
 647                 return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
 648 
 649         rc = NDR_MSTRING(mxa, di.di_nbname, (ndr_mstring_t *)&info->name);
 650         info->sid = (struct mslsa_sid *)NDR_SIDDUP(mxa, di.di_binsid);
 651 
 652         if ((rc == -1) || (info->sid == NULL))
 653                 return (NT_STATUS_NO_MEMORY);
 654 
 655         return (NT_STATUS_SUCCESS);
 656 }
 657 
 658 
 659 /*
 660  * lsarpc_s_AccountDomainInfo
 661  *
 662  * Service account domain policy queries.  We return our local domain
 663  * information so that the client knows who to query for information
 664  * on local names and SIDs.  The domain name is the local hostname.
 665  *
 666  * Note: info is zeroed on entry to ensure the SID and name do not
 667  * contain spurious values if an error is returned.
 668  */
 669 static DWORD
 670 lsarpc_s_AccountDomainInfo(struct mslsa_AccountDomainInfo *info,
 671     ndr_xa_t *mxa)
 672 {
 673         smb_domain_t di;
 674         int rc;
 675 
 676         bzero(info, sizeof (struct mslsa_AccountDomainInfo));
 677 
 678         if (!smb_domain_lookup_type(SMB_DOMAIN_LOCAL, &di))
 679                 return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
 680 
 681         rc = NDR_MSTRING(mxa, di.di_nbname, (ndr_mstring_t *)&info->name);
 682         info->sid = (struct mslsa_sid *)NDR_SIDDUP(mxa, di.di_binsid);
 683 
 684         if ((rc == -1) || (info->sid == NULL))
 685                 return (NT_STATUS_NO_MEMORY);
 686 
 687         return (NT_STATUS_SUCCESS);
 688 }
 689 
 690 /*
 691  * lsarpc_s_LookupNames
 692  *
 693  * This is the service side function for handling name lookup requests.
 694  * Currently, we only support lookups of a single name. This is also a
 695  * pass through interface so all we do is act as a proxy between the
 696  * client and the DC.
 697  */
 698 static int
 699 lsarpc_s_LookupNames(void *arg, ndr_xa_t *mxa)
 700 {
 701         struct mslsa_LookupNames *param = arg;
 702         struct mslsa_rid_entry *rids;
 703         struct mslsa_domain_table *domain_table;
 704         struct mslsa_domain_entry *domain_entry;
 705         smb_account_t account;
 706         uint32_t status;
 707         char *accname;
 708         int rc = 0;
 709 
 710         if (param->name_table->n_entry != 1)
 711                 return (NDR_DRC_FAULT_PARAM_0_UNIMPLEMENTED);
 712 
 713         rids = NDR_NEW(mxa, struct mslsa_rid_entry);
 714         domain_table = NDR_NEW(mxa, struct mslsa_domain_table);
 715         domain_entry = NDR_NEW(mxa, struct mslsa_domain_entry);
 716 
 717         if (rids == NULL || domain_table == NULL || domain_entry == NULL) {
 718                 bzero(param, sizeof (struct mslsa_LookupNames));
 719                 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
 720                 return (NDR_DRC_OK);
 721         }
 722 
 723         accname = (char *)param->name_table->names->str;
 724         status = lsa_lookup_name(accname, SidTypeUnknown, &account);
 725         if (status != NT_STATUS_SUCCESS) {
 726                 bzero(param, sizeof (struct mslsa_LookupNames));
 727                 param->status = NT_SC_ERROR(status);
 728                 return (NDR_DRC_OK);
 729         }
 730 
 731         /*
 732          * Set up the rid table.
 733          */
 734         rids[0].sid_name_use = account.a_type;
 735         rids[0].rid = account.a_rid;
 736         rids[0].domain_index = 0;
 737         param->translated_sids.n_entry = 1;
 738         param->translated_sids.rids = rids;
 739 
 740         /*
 741          * Set up the domain table.
 742          */
 743         domain_table->entries = domain_entry;
 744         domain_table->n_entry = 1;
 745         domain_table->max_n_entry = MLSVC_DOMAIN_MAX;
 746 
 747         rc = NDR_MSTRING(mxa, account.a_domain,
 748             (ndr_mstring_t *)&domain_entry->domain_name);
 749         domain_entry->domain_sid =
 750             (struct mslsa_sid *)NDR_SIDDUP(mxa, account.a_domsid);
 751 
 752         if (rc == -1 || domain_entry->domain_sid == NULL) {
 753                 smb_account_free(&account);
 754                 bzero(param, sizeof (struct mslsa_LookupNames));
 755                 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
 756                 return (NDR_DRC_OK);
 757         }
 758 
 759         param->domain_table = domain_table;
 760         param->mapped_count = 1;
 761         param->status = NT_STATUS_SUCCESS;
 762 
 763         smb_account_free(&account);
 764         return (NDR_DRC_OK);
 765 }
 766 
 767 /*
 768  * lsarpc_s_LookupSids
 769  *
 770  * This is the service side function for handling sid lookup requests.
 771  * We have to set up both the name table and the domain table in the
 772  * response. For each SID, we check for UNIX domain (local lookup) or
 773  * NT domain (DC lookup) and call the appropriate lookup function. This
 774  * should resolve the SID to a name. Then we need to update the domain
 775  * table and make the name entry point at the appropriate domain table
 776  * entry.
 777  *
 778  *
 779  * This RPC should behave as if LookupOptions is LSA_LOOKUP_OPT_ALL and
 780  * ClientRevision is LSA_CLIENT_REVISION_NT.
 781  *
 782  * On success return 0. Otherwise return an RPC specific error code.
 783  */
 784 
 785 static int
 786 lsarpc_s_LookupSids(void *arg, ndr_xa_t *mxa)
 787 {
 788         struct mslsa_LookupSids *param = arg;
 789         struct mslsa_domain_table *domain_table;
 790         struct mslsa_domain_entry *domain_entry;
 791         struct mslsa_name_entry *names;
 792         struct mslsa_name_entry *name;
 793         smb_account_t account;
 794         smb_sid_t *sid;
 795         DWORD n_entry;
 796         DWORD n_mapped;
 797         char sidstr[SMB_SID_STRSZ];
 798         int result;
 799         int i;
 800 
 801         bzero(&account, sizeof (smb_account_t));
 802         n_mapped = 0;
 803         n_entry = param->lup_sid_table.n_entry;
 804 
 805         names = NDR_NEWN(mxa, struct mslsa_name_entry, n_entry);
 806         domain_table = NDR_NEW(mxa, struct mslsa_domain_table);
 807         domain_entry = NDR_NEWN(mxa, struct mslsa_domain_entry,
 808             MLSVC_DOMAIN_MAX);
 809 
 810         if (names == NULL || domain_table == NULL || domain_entry == NULL)
 811                 goto lookup_sid_failed;
 812 
 813         domain_table->entries = domain_entry;
 814         domain_table->n_entry = 0;
 815         domain_table->max_n_entry = MLSVC_DOMAIN_MAX;
 816 
 817         name = names;
 818         for (i = 0; i < n_entry; ++i, name++) {
 819                 bzero(name, sizeof (struct mslsa_name_entry));
 820                 sid = (smb_sid_t *)param->lup_sid_table.entries[i].psid;
 821 
 822                 result = lsa_lookup_sid(sid, &account);
 823                 if ((result != NT_STATUS_SUCCESS) ||
 824                     (account.a_name == NULL) || (*account.a_name == '\0')) {
 825                         account.a_type = SidTypeUnknown;
 826                         smb_sid_tostr(sid, sidstr);
 827 
 828                         if (NDR_MSTRING(mxa, sidstr,
 829                             (ndr_mstring_t *)&name->name) == -1)
 830                                 goto lookup_sid_failed;
 831 
 832                 } else {
 833                         if (NDR_MSTRING(mxa, account.a_name,
 834                             (ndr_mstring_t *)&name->name) == -1)
 835                                 goto lookup_sid_failed;
 836 
 837                         ++n_mapped;
 838                 }
 839 
 840                 name->sid_name_use = account.a_type;
 841 
 842                 result = lsarpc_s_UpdateDomainTable(mxa, &account,
 843                     domain_table, &name->domain_ix);
 844                 if (result == -1)
 845                         goto lookup_sid_failed;
 846 
 847                 smb_account_free(&account);
 848         }
 849 
 850         param->domain_table = domain_table;
 851         param->name_table.n_entry = n_entry;
 852         param->name_table.entries = names;
 853         param->mapped_count = n_mapped;
 854 
 855         if (n_mapped == n_entry)
 856                 param->status = NT_STATUS_SUCCESS;
 857         else if (n_mapped == 0)
 858                 param->status = NT_STATUS_NONE_MAPPED;
 859         else
 860                 param->status = NT_STATUS_SOME_NOT_MAPPED;
 861 
 862         return (NDR_DRC_OK);
 863 
 864 lookup_sid_failed:
 865         smb_account_free(&account);
 866         bzero(param, sizeof (struct mslsa_LookupSids));
 867         return (NDR_DRC_FAULT_OUT_OF_MEMORY);
 868 }
 869 
 870 /*
 871  * lsarpc_s_UpdateDomainTable
 872  *
 873  * This routine is responsible for maintaining the domain table which
 874  * will be returned from a SID lookup. Whenever a name is added to the
 875  * name table, this function should be called with the corresponding
 876  * domain name. If the domain information is not already in the table,
 877  * it is added. On success return 0; Otherwise -1 is returned.
 878  */
 879 static int
 880 lsarpc_s_UpdateDomainTable(ndr_xa_t *mxa,
 881     smb_account_t *account, struct mslsa_domain_table *domain_table,
 882     DWORD *domain_idx)
 883 {
 884         struct mslsa_domain_entry *dentry;
 885         DWORD n_entry;
 886         DWORD i;
 887         int rc;
 888 
 889         if (account->a_type == SidTypeUnknown ||
 890             account->a_type == SidTypeInvalid) {
 891                 /*
 892                  * These types don't need to reference an entry in the
 893                  * domain table. So return -1.
 894                  */
 895                 *domain_idx = (DWORD)-1;
 896                 return (0);
 897         }
 898 
 899         if ((dentry = domain_table->entries) == NULL)
 900                 return (-1);
 901 
 902         if ((n_entry = domain_table->n_entry) >= MLSVC_DOMAIN_MAX)
 903                 return (-1);
 904 
 905         for (i = 0; i < n_entry; ++i) {
 906                 if (smb_sid_cmp((smb_sid_t *)dentry[i].domain_sid,
 907                     account->a_domsid)) {
 908                         *domain_idx = i;
 909                         return (0);
 910                 }
 911         }
 912 
 913         if (i == MLSVC_DOMAIN_MAX)
 914                 return (-1);
 915 
 916         rc = NDR_MSTRING(mxa, account->a_domain,
 917             (ndr_mstring_t *)&dentry[i].domain_name);
 918         dentry[i].domain_sid =
 919             (struct mslsa_sid *)NDR_SIDDUP(mxa, account->a_domsid);
 920 
 921         if (rc == -1 || dentry[i].domain_sid == NULL)
 922                 return (-1);
 923 
 924         ++domain_table->n_entry;
 925         *domain_idx = i;
 926         return (0);
 927 }
 928 
 929 /*
 930  * lsarpc_s_LookupSids2
 931  *
 932  * Other than the use of lsar_lookup_sids2 and lsar_name_entry2, this
 933  * is identical to lsarpc_s_LookupSids.
 934  *
 935  * Ignore lookup_level, it is reserved and should be zero.
 936  */
 937 static int
 938 lsarpc_s_LookupSids2(void *arg, ndr_xa_t *mxa)
 939 {
 940         struct lsar_lookup_sids2 *param = arg;
 941         struct lsar_name_entry2 *names;
 942         struct lsar_name_entry2 *name;
 943         struct mslsa_domain_table *domain_table;
 944         struct mslsa_domain_entry *domain_entry;
 945         smb_account_t account;
 946         smb_sid_t *sid;
 947         DWORD n_entry;
 948         DWORD n_mapped;
 949         char sidstr[SMB_SID_STRSZ];
 950         int result;
 951         int i;
 952 
 953         bzero(&account, sizeof (smb_account_t));
 954         n_mapped = 0;
 955         n_entry = param->lup_sid_table.n_entry;
 956 
 957         names = NDR_NEWN(mxa, struct lsar_name_entry2, n_entry);
 958         domain_table = NDR_NEW(mxa, struct mslsa_domain_table);
 959         domain_entry = NDR_NEWN(mxa, struct mslsa_domain_entry,
 960             MLSVC_DOMAIN_MAX);
 961 
 962         if (names == NULL || domain_table == NULL || domain_entry == NULL)
 963                 goto lookup_sid_failed;
 964 
 965         domain_table->entries = domain_entry;
 966         domain_table->n_entry = 0;
 967         domain_table->max_n_entry = MLSVC_DOMAIN_MAX;
 968 
 969         name = names;
 970         for (i = 0; i < n_entry; ++i, name++) {
 971                 bzero(name, sizeof (struct lsar_name_entry2));
 972                 sid = (smb_sid_t *)param->lup_sid_table.entries[i].psid;
 973 
 974                 result = lsa_lookup_sid(sid, &account);
 975                 if ((result != NT_STATUS_SUCCESS) ||
 976                     (account.a_name == NULL) || (*account.a_name == '\0')) {
 977                         account.a_type = SidTypeUnknown;
 978                         smb_sid_tostr(sid, sidstr);
 979 
 980                         if (NDR_MSTRING(mxa, sidstr,
 981                             (ndr_mstring_t *)&name->name) == -1)
 982                                 goto lookup_sid_failed;
 983 
 984                 } else {
 985                         if (NDR_MSTRING(mxa, account.a_name,
 986                             (ndr_mstring_t *)&name->name) == -1)
 987                                 goto lookup_sid_failed;
 988 
 989                         ++n_mapped;
 990                 }
 991 
 992                 name->sid_name_use = account.a_type;
 993 
 994                 result = lsarpc_s_UpdateDomainTable(mxa, &account,
 995                     domain_table, &name->domain_ix);
 996                 if (result == -1)
 997                         goto lookup_sid_failed;
 998 
 999                 smb_account_free(&account);
1000         }
1001 
1002         param->domain_table = domain_table;
1003         param->name_table.n_entry = n_entry;
1004         param->name_table.entries = names;
1005         param->mapped_count = n_mapped;
1006 
1007         if (n_mapped == n_entry)
1008                 param->status = NT_STATUS_SUCCESS;
1009         else if (n_mapped == 0)
1010                 param->status = NT_STATUS_NONE_MAPPED;
1011         else
1012                 param->status = NT_STATUS_SOME_NOT_MAPPED;
1013 
1014         return (NDR_DRC_OK);
1015 
1016 lookup_sid_failed:
1017         smb_account_free(&account);
1018         bzero(param, sizeof (struct lsar_lookup_sids2));
1019         return (NDR_DRC_FAULT_OUT_OF_MEMORY);
1020 }
1021 
1022 /*
1023  * LookupSids3 is only valid on domain controllers.
1024  * Other servers must return NT_STATUS_INVALID_SERVER_STATE.
1025  */
1026 /*ARGSUSED*/
1027 static int
1028 lsarpc_s_LookupSids3(void *arg, ndr_xa_t *mxa)
1029 {
1030         struct lsar_lookup_sids3 *param = arg;
1031 
1032         bzero(param, sizeof (struct lsar_lookup_sids3));
1033         param->status = NT_SC_ERROR(NT_STATUS_INVALID_SERVER_STATE);
1034         return (NDR_DRC_OK);
1035 }
1036 
1037 /*
1038  * lsarpc_s_LookupNames2
1039  *
1040  * Other than the use of lsar_LookupNames2 and lsar_rid_entry2, this
1041  * is identical to lsarpc_s_LookupNames.
1042  *
1043  * If LookupOptions contains LSA_LOOKUP_OPT_LOCAL and LookupLevel is not
1044  * LSA_LOOKUP_WKSTA, return STATUS_INVALID_PARAMETER.
1045  */
1046 static int
1047 lsarpc_s_LookupNames2(void *arg, ndr_xa_t *mxa)
1048 {
1049         struct lsar_LookupNames2 *param = arg;
1050         struct lsar_rid_entry2 *rids;
1051         struct mslsa_domain_table *domain_table;
1052         struct mslsa_domain_entry *domain_entry;
1053         smb_account_t account;
1054         uint32_t status;
1055         char *accname;
1056         int rc = 0;
1057 
1058         if (param->name_table->n_entry != 1)
1059                 return (NDR_DRC_FAULT_PARAM_0_UNIMPLEMENTED);
1060 
1061         if ((param->lookup_options & LSA_LOOKUP_OPT_LOCAL) &&
1062             param->lookup_level != LSA_LOOKUP_WKSTA) {
1063                 bzero(param, sizeof (struct lsar_LookupNames2));
1064                 param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER);
1065                 return (NDR_DRC_OK);
1066         }
1067 
1068         rids = NDR_NEW(mxa, struct lsar_rid_entry2);
1069         domain_table = NDR_NEW(mxa, struct mslsa_domain_table);
1070         domain_entry = NDR_NEW(mxa, struct mslsa_domain_entry);
1071 
1072         if (rids == NULL || domain_table == NULL || domain_entry == NULL) {
1073                 bzero(param, sizeof (struct lsar_LookupNames2));
1074                 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1075                 return (NDR_DRC_OK);
1076         }
1077 
1078         accname = (char *)param->name_table->names->str;
1079         status = lsa_lookup_name(accname, SidTypeUnknown, &account);
1080         if (status != NT_STATUS_SUCCESS) {
1081                 bzero(param, sizeof (struct lsar_LookupNames2));
1082                 param->status = NT_SC_ERROR(status);
1083                 return (NDR_DRC_OK);
1084         }
1085 
1086         /*
1087          * Set up the rid table.
1088          */
1089         bzero(rids, sizeof (struct lsar_rid_entry2));
1090         rids[0].sid_name_use = account.a_type;
1091         rids[0].rid = account.a_rid;
1092         rids[0].domain_index = 0;
1093         param->translated_sids.n_entry = 1;
1094         param->translated_sids.rids = rids;
1095 
1096         /*
1097          * Set up the domain table.
1098          */
1099         domain_table->entries = domain_entry;
1100         domain_table->n_entry = 1;
1101         domain_table->max_n_entry = MLSVC_DOMAIN_MAX;
1102 
1103         rc = NDR_MSTRING(mxa, account.a_domain,
1104             (ndr_mstring_t *)&domain_entry->domain_name);
1105 
1106         domain_entry->domain_sid =
1107             (struct mslsa_sid *)NDR_SIDDUP(mxa, account.a_domsid);
1108 
1109         if (rc == -1 || domain_entry->domain_sid == NULL) {
1110                 smb_account_free(&account);
1111                 bzero(param, sizeof (struct lsar_LookupNames2));
1112                 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1113                 return (NDR_DRC_OK);
1114         }
1115 
1116         param->domain_table = domain_table;
1117         param->mapped_count = 1;
1118         param->status = NT_STATUS_SUCCESS;
1119 
1120         smb_account_free(&account);
1121         return (NDR_DRC_OK);
1122 }
1123 
1124 /*
1125  * Other than the use of lsar_LookupNames2 and lsar_rid_entry2, this
1126  * is identical to lsarpc_s_LookupNames.
1127  *
1128  * If LookupOptions contains LSA_LOOKUP_OPT_LOCAL and LookupLevel is not
1129  * LSA_LOOKUP_WKSTA, return STATUS_INVALID_PARAMETER.
1130  */
1131 static int
1132 lsarpc_s_LookupNames3(void *arg, ndr_xa_t *mxa)
1133 {
1134         struct lsar_LookupNames3        *param = arg;
1135         struct lsar_translated_sid_ex2  *sids;
1136         struct mslsa_domain_table       *domain_table;
1137         struct mslsa_domain_entry       *domain_entry;
1138         smb_account_t                   account;
1139         uint32_t                        status;
1140         char                            *accname;
1141         int                             rc = 0;
1142 
1143         if (param->name_table->n_entry != 1)
1144                 return (NDR_DRC_FAULT_PARAM_0_UNIMPLEMENTED);
1145 
1146         if ((param->lookup_options & LSA_LOOKUP_OPT_LOCAL) &&
1147             param->lookup_level != LSA_LOOKUP_WKSTA) {
1148                 bzero(param, sizeof (struct lsar_LookupNames3));
1149                 param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER);
1150                 return (NDR_DRC_OK);
1151         }
1152 
1153         sids = NDR_NEW(mxa, struct lsar_translated_sid_ex2);
1154         domain_table = NDR_NEW(mxa, struct mslsa_domain_table);
1155         domain_entry = NDR_NEW(mxa, struct mslsa_domain_entry);
1156 
1157         if (sids == NULL || domain_table == NULL || domain_entry == NULL) {
1158                 bzero(param, sizeof (struct lsar_LookupNames3));
1159                 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1160                 return (NDR_DRC_OK);
1161         }
1162 
1163         accname = (char *)param->name_table->names->str;
1164         status = lsa_lookup_name(accname, SidTypeUnknown, &account);
1165         if (status != NT_STATUS_SUCCESS) {
1166                 bzero(param, sizeof (struct lsar_LookupNames3));
1167                 param->status = NT_SC_ERROR(status);
1168                 return (NDR_DRC_OK);
1169         }
1170 
1171         /*
1172          * Set up the SID table.
1173          */
1174         bzero(sids, sizeof (struct lsar_translated_sid_ex2));
1175         sids[0].sid_name_use = account.a_type;
1176         sids[0].sid = (struct mslsa_sid *)NDR_SIDDUP(mxa, account.a_sid);
1177         sids[0].domain_index = 0;
1178         param->translated_sids.n_entry = 1;
1179         param->translated_sids.sids = sids;
1180 
1181         /*
1182          * Set up the domain table.
1183          */
1184         domain_table->entries = domain_entry;
1185         domain_table->n_entry = 1;
1186         domain_table->max_n_entry = MLSVC_DOMAIN_MAX;
1187 
1188         rc = NDR_MSTRING(mxa, account.a_domain,
1189             (ndr_mstring_t *)&domain_entry->domain_name);
1190 
1191         domain_entry->domain_sid =
1192             (struct mslsa_sid *)NDR_SIDDUP(mxa, account.a_domsid);
1193 
1194         if (rc == -1 || domain_entry->domain_sid == NULL) {
1195                 smb_account_free(&account);
1196                 bzero(param, sizeof (struct lsar_LookupNames3));
1197                 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1198                 return (NDR_DRC_OK);
1199         }
1200 
1201         param->domain_table = domain_table;
1202         param->mapped_count = 1;
1203         param->status = NT_STATUS_SUCCESS;
1204 
1205         smb_account_free(&account);
1206         return (NDR_DRC_OK);
1207 }
1208 
1209 /*
1210  * LookupNames4 is only valid on domain controllers.
1211  * Other servers must return NT_STATUS_INVALID_SERVER_STATE.
1212  */
1213 /*ARGSUSED*/
1214 static int
1215 lsarpc_s_LookupNames4(void *arg, ndr_xa_t *mxa)
1216 {
1217         struct lsar_LookupNames4 *param = arg;
1218 
1219         bzero(param, sizeof (struct lsar_LookupNames4));
1220         param->status = NT_SC_ERROR(NT_STATUS_INVALID_SERVER_STATE);
1221         return (NDR_DRC_OK);
1222 }
1223 
1224 /*
1225  * There is a bug in the way that ndrgen and the marshalling code handles
1226  * unions so we need to fix some of the data offsets at runtime. The
1227  * following macros and the fixup functions handle the corrections.
1228  */
1229 
1230 DECL_FIXUP_STRUCT(mslsa_PolicyInfoResUnion);
1231 DECL_FIXUP_STRUCT(mslsa_PolicyInfoRes);
1232 DECL_FIXUP_STRUCT(mslsa_QueryInfoPolicy);
1233 void
1234 fixup_mslsa_QueryInfoPolicy(struct mslsa_QueryInfoPolicy *val)
1235 {
1236         unsigned short size1 = 0;
1237         unsigned short size2 = 0;
1238         unsigned short size3 = 0;
1239 
1240         switch (val->info_class) {
1241                 case MSLSA_POLICY_AUDIT_EVENTS_INFO:
1242                         size1 = sizeof (struct mslsa_AuditEventsInfo);
1243                         break;
1244 
1245                 case MSLSA_POLICY_PRIMARY_DOMAIN_INFO:
1246                         size1 = sizeof (struct mslsa_PrimaryDomainInfo);
1247                         break;
1248 
1249                 case MSLSA_POLICY_ACCOUNT_DOMAIN_INFO:
1250                         size1 = sizeof (struct mslsa_AccountDomainInfo);
1251                         break;
1252 
1253                 case MSLSA_POLICY_SERVER_ROLE_INFO:
1254                         size1 = sizeof (struct mslsa_ServerRoleInfo);
1255                         break;
1256 
1257                 case MSLSA_POLICY_DNS_DOMAIN_INFO:
1258                         size1 = sizeof (struct mslsa_DnsDomainInfo);
1259                         break;
1260 
1261                 default:
1262                         return;
1263         };
1264 
1265         size2 = size1 + (2 * sizeof (DWORD));
1266         size3 = size2 + sizeof (ndr_request_hdr_t) + sizeof (DWORD);
1267 
1268         FIXUP_PDU_SIZE(mslsa_PolicyInfoResUnion, size1);
1269         FIXUP_PDU_SIZE(mslsa_PolicyInfoRes, size2);
1270         FIXUP_PDU_SIZE(mslsa_QueryInfoPolicy, size3);
1271 }