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