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-15052 Need a way to add appliance local user/group ACE from Windows
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-15052 Need a way to add appliance local user/group ACE from Windows
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-3106 ACL editor crash in Windows 2012 R2
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
re #12435 rb3958 r10 is added 2 times to panic info
re #12393 rb3935 Kerberos and smbd disagree about who is our AD server
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/lib/smbsrv/libmlsvc/common/samr_svc.c
          +++ new/usr/src/lib/smbsrv/libmlsvc/common/samr_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
  
    | 
      ↓ open down ↓ | 
    13 lines elided | 
    
      ↑ open up ↑ | 
  
  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      - * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
       24 + * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
  25   25   */
  26   26  
  27   27  /*
  28   28   * Security Accounts Manager RPC (SAMR) server-side interface.
  29   29   *
  30   30   * The SAM is a hierarchical database:
  31   31   * - If you want to talk to the SAM you need a SAM handle.
  32   32   * - If you want to work with a domain, use the SAM handle.
  33   33   *   to obtain a domain handle.
  34   34   * - Use domain handles to obtain user handles etc.
  35   35   */
  36   36  
  37   37  #include <strings.h>
  38   38  #include <unistd.h>
  39   39  #include <netdb.h>
  40   40  #include <assert.h>
  41   41  #include <grp.h>
       42 +#include <libmlrpc/libmlrpc.h>
  42   43  #include <smbsrv/libsmb.h>
  43      -#include <smbsrv/libmlrpc.h>
  44   44  #include <smbsrv/libmlsvc.h>
  45   45  #include <smbsrv/smbinfo.h>
  46   46  #include <smbsrv/nmpipes.h>
  47   47  #include <smbsrv/ndl/samrpc.ndl>
  48   48  #include <samlib.h>
  49   49  
  50   50  /*
  51   51   * The keys associated with the various handles dispensed by the SAMR
  52   52   * server.  These keys can be used to validate client activity.
  53   53   * These values are never passed over the wire so security shouldn't
  54   54   * be an issue.
  55   55   */
  56   56  typedef enum {
  57   57          SAMR_KEY_NULL = 0,
  58   58          SAMR_KEY_CONNECT,
  59   59          SAMR_KEY_DOMAIN,
  60   60          SAMR_KEY_USER,
  61   61          SAMR_KEY_GROUP,
  62   62          SAMR_KEY_ALIAS
  63   63  } samr_key_t;
  64   64  
  65   65  typedef struct samr_keydata {
  66   66          samr_key_t kd_key;
  67   67          smb_domain_type_t kd_type;
  68   68          DWORD kd_rid;
  69   69  } samr_keydata_t;
  70   70  
  71   71  /*
  72   72   * DomainDisplayUser    All user objects (or those derived from user) with
  73   73   *                      userAccountControl containing the UF_NORMAL_ACCOUNT bit.
  74   74   *
  75   75   * DomainDisplayMachine All user objects (or those derived from user) with
  76   76   *                      userAccountControl containing the
  77   77   *                      UF_WORKSTATION_TRUST_ACCOUNT or UF_SERVER_TRUST_ACCOUNT
  78   78   *                      bit.
  79   79   *
  80   80   * DomainDisplayGroup   All group objects (or those derived from group) with
  81   81   *                      groupType equal to GROUP_TYPE_SECURITY_UNIVERSAL or
  82   82   *                      GROUP_TYPE_SECURITY_ACCOUNT.
  83   83   *
  84   84   * DomainDisplayOemUser Same as DomainDisplayUser with OEM strings
  85   85   *
  86   86   * DomainDisplayOemGroup Same as DomainDisplayGroup with OEM strings
  87   87   */
  88   88  typedef enum {
  89   89          DomainDisplayUser = 1,
  90   90          DomainDisplayMachine,
  91   91          DomainDispalyGroup,
  92   92          DomainDisplayOemUser,
  93   93          DomainDisplayOemGroup
  94   94  } samr_displvl_t;
  
    | 
      ↓ open down ↓ | 
    41 lines elided | 
    
      ↑ open up ↑ | 
  
  95   95  
  96   96  #define SAMR_VALID_DISPLEVEL(lvl) \
  97   97          (((lvl) >= DomainDisplayUser) && ((lvl) <= DomainDisplayOemGroup))
  98   98  
  99   99  #define SAMR_SUPPORTED_DISPLEVEL(lvl) (lvl == DomainDisplayUser)
 100  100  
 101  101  static ndr_hdid_t *samr_hdalloc(ndr_xa_t *, samr_key_t, smb_domain_type_t,
 102  102      DWORD);
 103  103  static void samr_hdfree(ndr_xa_t *, ndr_hdid_t *);
 104  104  static ndr_handle_t *samr_hdlookup(ndr_xa_t *, ndr_hdid_t *, samr_key_t);
      105 +static ndr_handle_t *samr_hdlookup_any(ndr_xa_t *, ndr_hdid_t *);
 105  106  static int samr_call_stub(ndr_xa_t *mxa);
 106  107  static DWORD samr_s_enum_local_domains(struct samr_EnumLocalDomain *,
 107  108      ndr_xa_t *);
 108  109  
 109  110  static ndr_stub_table_t samr_stub_table[];
 110  111  
 111  112  static ndr_service_t samr_service = {
 112  113          "SAMR",                         /* name */
 113  114          "Security Accounts Manager",    /* desc */
 114  115          "\\samr",                       /* endpoint */
 115  116          PIPE_LSASS,                     /* sec_addr_port */
 116  117          "12345778-1234-abcd-ef00-0123456789ac", 1,      /* abstract */
 117  118          NDR_TRANSFER_SYNTAX_UUID,               2,      /* transfer */
 118  119          0,                              /* no bind_instance_size */
 119  120          NULL,                           /* no bind_req() */
 120  121          NULL,                           /* no unbind_and_close() */
 121  122          samr_call_stub,                 /* call_stub() */
 122  123          &TYPEINFO(samr_interface),      /* interface ti */
 123  124          samr_stub_table                 /* stub_table */
 124  125  };
 125  126  
 126  127  /*
 127  128   * samr_initialize
 128  129   *
 129  130   * This function registers the SAM RPC interface with the RPC runtime
 130  131   * library. It must be called in order to use either the client side
 131  132   * or the server side functions.
 132  133   */
 133  134  void
 134  135  samr_initialize(void)
 135  136  {
 136  137          (void) ndr_svc_register(&samr_service);
 137  138  }
 138  139  
 139  140  /*
 140  141   * Custom call_stub to set the stream string policy.
 141  142   */
 142  143  static int
 143  144  samr_call_stub(ndr_xa_t *mxa)
 144  145  {
 145  146          NDS_SETF(&mxa->send_nds, NDS_F_NOTERM);
 146  147          NDS_SETF(&mxa->recv_nds, NDS_F_NOTERM);
 147  148  
 148  149          return (ndr_generic_call_stub(mxa));
 149  150  }
 150  151  
 151  152  /*
 152  153   * Handle allocation wrapper to setup the local context.
 153  154   */
 154  155  static ndr_hdid_t *
 155  156  samr_hdalloc(ndr_xa_t *mxa, samr_key_t key, smb_domain_type_t domain_type,
 156  157      DWORD rid)
 157  158  {
 158  159          ndr_handle_t    *hd;
 159  160          ndr_hdid_t      *id;
 160  161          samr_keydata_t  *data;
 161  162  
 162  163          if ((data = malloc(sizeof (samr_keydata_t))) == NULL)
 163  164                  return (NULL);
 164  165  
 165  166          data->kd_key = key;
 166  167          data->kd_type = domain_type;
 167  168          data->kd_rid = rid;
 168  169  
 169  170          if ((id = ndr_hdalloc(mxa, data)) == NULL) {
 170  171                  free(data);
 171  172                  return (NULL);
 172  173          }
 173  174  
 174  175          if ((hd = ndr_hdlookup(mxa, id)) != NULL)
 175  176                  hd->nh_data_free = free;
 176  177  
 177  178          return (id);
 178  179  }
 179  180  
 180  181  /*
 181  182   * Handle deallocation wrapper to free the local context.
 182  183   */
 183  184  static void
 184  185  samr_hdfree(ndr_xa_t *mxa, ndr_hdid_t *id)
 185  186  {
 186  187          ndr_handle_t *hd;
 187  188  
 188  189          if ((hd = ndr_hdlookup(mxa, id)) != NULL) {
 189  190                  free(hd->nh_data);
 190  191                  hd->nh_data = NULL;
 191  192                  ndr_hdfree(mxa, id);
 192  193          }
 193  194  }
 194  195  
 195  196  /*
 196  197   * Handle lookup wrapper to validate the local context.
 197  198   */
 198  199  static ndr_handle_t *
 199  200  samr_hdlookup(ndr_xa_t *mxa, ndr_hdid_t *id, samr_key_t key)
 200  201  {
 201  202          ndr_handle_t *hd;
 202  203          samr_keydata_t *data;
 203  204  
 204  205          if ((hd = ndr_hdlookup(mxa, id)) == NULL)
 205  206                  return (NULL);
 206  207  
  
    | 
      ↓ open down ↓ | 
    92 lines elided | 
    
      ↑ open up ↑ | 
  
 207  208          if ((data = (samr_keydata_t *)hd->nh_data) == NULL)
 208  209                  return (NULL);
 209  210  
 210  211          if (data->kd_key != key)
 211  212                  return (NULL);
 212  213  
 213  214          return (hd);
 214  215  }
 215  216  
 216  217  /*
      218 + * Handle lookup wrapper to validate the local context,
      219 + * but don't limit to one type.
      220 + */
      221 +static ndr_handle_t *
      222 +samr_hdlookup_any(ndr_xa_t *mxa, ndr_hdid_t *id)
      223 +{
      224 +        ndr_handle_t *hd;
      225 +
      226 +        if ((hd = ndr_hdlookup(mxa, id)) == NULL)
      227 +                return (NULL);
      228 +
      229 +        if (hd->nh_data == NULL)
      230 +                return (NULL);
      231 +
      232 +        return (hd);
      233 +}
      234 +
      235 +/*
 217  236   * samr_s_Connect
 218  237   *
 219  238   * This is a request to connect to the local SAM database. We don't
 220  239   * support any form of update request and our database doesn't
 221  240   * contain any private information, so there is little point in
 222  241   * doing any access access checking here.
 223  242   *
 224  243   * Return a handle for use with subsequent SAM requests.
 225  244   */
 226  245  static int
 227  246  samr_s_Connect(void *arg, ndr_xa_t *mxa)
 228  247  {
 229  248          struct samr_Connect *param = arg;
 230  249          ndr_hdid_t *id;
 231  250  
 232  251          id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, SMB_DOMAIN_NULL, 0);
 233  252          if (id) {
 234  253                  bcopy(id, ¶m->handle, sizeof (samr_handle_t));
 235  254                  param->status = 0;
 236  255          } else {
 237  256                  bzero(¶m->handle, sizeof (samr_handle_t));
 238  257                  param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
 239  258          }
 240  259  
 241  260          return (NDR_DRC_OK);
 242  261  }
 243  262  
 244  263  /*
 245  264   * samr_s_CloseHandle
 246  265   *
 247  266   * Close the SAM interface specified by the handle.
 248  267   * Free the handle and zero out the result handle for the client.
 249  268   */
 250  269  static int
 251  270  samr_s_CloseHandle(void *arg, ndr_xa_t *mxa)
 252  271  {
 253  272          struct samr_CloseHandle *param = arg;
  
    | 
      ↓ open down ↓ | 
    27 lines elided | 
    
      ↑ open up ↑ | 
  
 254  273          ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle;
 255  274  
 256  275          samr_hdfree(mxa, id);
 257  276  
 258  277          bzero(¶m->result_handle, sizeof (samr_handle_t));
 259  278          param->status = 0;
 260  279          return (NDR_DRC_OK);
 261  280  }
 262  281  
 263  282  /*
      283 + * samr_s_QuerySecObject
      284 + */
      285 +static int
      286 +samr_s_QuerySecObject(void *arg, ndr_xa_t *mxa)
      287 +{
      288 +        struct samr_QuerySecObject      *param = arg;
      289 +        ndr_hdid_t                      *id;
      290 +        uint32_t                        status;
      291 +        struct samr_sec_desc            *sd;
      292 +
      293 +        id = (ndr_hdid_t *)¶m->obj_handle;
      294 +        if (samr_hdlookup_any(mxa, id) == NULL) {
      295 +                status = NT_STATUS_INVALID_HANDLE;
      296 +                goto QuerySecObjectError;
      297 +        }
      298 +
      299 +        param->sd = NDR_MALLOC(mxa, sizeof (samr_sd_t));
      300 +        if (param->sd == NULL) {
      301 +                status = NT_STATUS_NO_MEMORY;
      302 +                goto QuerySecObjectError;
      303 +        }
      304 +        param->sd->length = sizeof (struct samr_sec_desc);
      305 +
      306 +        sd = NDR_MALLOC(mxa, param->sd->length);
      307 +        if (sd == NULL) {
      308 +                status = NT_STATUS_NO_MEMORY;
      309 +                goto QuerySecObjectError;
      310 +        }
      311 +        bzero(sd, param->sd->length);
      312 +        sd->Revision = 1;
      313 +        sd->Control = SE_SELF_RELATIVE;
      314 +
      315 +        param->sd->data = (void *)sd;
      316 +        param->status = NT_STATUS_SUCCESS;
      317 +        return (NDR_DRC_OK);
      318 +
      319 +QuerySecObjectError:
      320 +        bzero(param, sizeof (struct samr_QuerySecObject));
      321 +        param->status = NT_SC_ERROR(status);
      322 +        return (NDR_DRC_OK);
      323 +}
      324 +
      325 +/*
 264  326   * samr_s_LookupDomain
 265  327   *
 266  328   * This is a request to map a domain name to a domain SID. We can map
 267  329   * the primary domain name, our local domain name (hostname) and the
 268  330   * builtin domain names to the appropriate SID. Anything else will be
 269  331   * rejected.
 270  332   */
 271  333  static int
 272  334  samr_s_LookupDomain(void *arg, ndr_xa_t *mxa)
 273  335  {
 274  336          struct samr_LookupDomain *param = arg;
 275  337          char *domain_name;
 276  338          smb_domain_t di;
 277  339  
 278  340          if ((domain_name = (char *)param->domain_name.str) == NULL) {
 279  341                  bzero(param, sizeof (struct samr_LookupDomain));
 280  342                  param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER);
 281  343                  return (NDR_DRC_OK);
 282  344          }
 283  345  
 284  346          if (!smb_domain_lookup_name(domain_name, &di)) {
 285  347                  bzero(param, sizeof (struct samr_LookupDomain));
 286  348                  param->status = NT_SC_ERROR(NT_STATUS_NO_SUCH_DOMAIN);
 287  349                  return (NDR_DRC_OK);
 288  350          }
 289  351  
 290  352          param->sid = (struct samr_sid *)NDR_SIDDUP(mxa, di.di_binsid);
 291  353          if (param->sid == NULL) {
 292  354                  bzero(param, sizeof (struct samr_LookupDomain));
 293  355                  param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
 294  356                  return (NDR_DRC_OK);
 295  357          }
 296  358  
 297  359          param->status = NT_STATUS_SUCCESS;
 298  360          return (NDR_DRC_OK);
 299  361  }
 300  362  
 301  363  /*
 302  364   * samr_s_EnumLocalDomains
 303  365   *
 304  366   * This is a request for the local domains supported by this server.
 305  367   * All we do here is validate the handle and set the status. The real
 306  368   * work is done in samr_s_enum_local_domains.
 307  369   */
 308  370  static int
 309  371  samr_s_EnumLocalDomains(void *arg, ndr_xa_t *mxa)
 310  372  {
 311  373          struct samr_EnumLocalDomain *param = arg;
 312  374          ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle;
 313  375          DWORD status;
 314  376  
 315  377          if (samr_hdlookup(mxa, id, SAMR_KEY_CONNECT) == NULL)
 316  378                  status = NT_STATUS_ACCESS_DENIED;
 317  379          else
 318  380                  status = samr_s_enum_local_domains(param, mxa);
 319  381  
 320  382          if (status == NT_STATUS_SUCCESS) {
 321  383                  param->enum_context = param->info->entries_read;
 322  384                  param->total_entries = param->info->entries_read;
 323  385                  param->status = NT_STATUS_SUCCESS;
 324  386          } else {
 325  387                  bzero(param, sizeof (struct samr_EnumLocalDomain));
 326  388                  param->status = NT_SC_ERROR(status);
 327  389          }
 328  390  
 329  391          return (NDR_DRC_OK);
 330  392  }
 331  393  
 332  394  
 333  395  /*
 334  396   * samr_s_enum_local_domains
 335  397   *
 336  398   * This function should only be called via samr_s_EnumLocalDomains to
 337  399   * ensure that the appropriate validation is performed. We will answer
 338  400   * queries about two domains: the local domain, synonymous with the
 339  401   * local hostname, and the BUILTIN domain. So we return these two
 340  402   * strings.
 341  403   *
 342  404   * Returns NT status values.
 343  405   */
 344  406  static DWORD
 345  407  samr_s_enum_local_domains(struct samr_EnumLocalDomain *param,
 346  408      ndr_xa_t *mxa)
 347  409  {
 348  410          struct samr_LocalDomainInfo *info;
 349  411          struct samr_LocalDomainEntry *entry;
 350  412          char *hostname;
 351  413  
 352  414          hostname = NDR_MALLOC(mxa, NETBIOS_NAME_SZ);
 353  415          if (hostname == NULL)
 354  416                  return (NT_STATUS_NO_MEMORY);
 355  417  
 356  418          if (smb_getnetbiosname(hostname, NETBIOS_NAME_SZ) != 0)
 357  419                  return (NT_STATUS_NO_MEMORY);
 358  420  
 359  421          entry = NDR_NEWN(mxa, struct samr_LocalDomainEntry, 2);
 360  422          if (entry == NULL)
 361  423                  return (NT_STATUS_NO_MEMORY);
 362  424  
 363  425          bzero(entry, (sizeof (struct samr_LocalDomainEntry) * 2));
 364  426          (void) NDR_MSTRING(mxa, hostname, (ndr_mstring_t *)&entry[0].name);
 365  427          (void) NDR_MSTRING(mxa, "Builtin", (ndr_mstring_t *)&entry[1].name);
 366  428  
 367  429          info = NDR_NEW(mxa, struct samr_LocalDomainInfo);
 368  430          if (info == NULL)
 369  431                  return (NT_STATUS_NO_MEMORY);
 370  432  
 371  433          info->entries_read = 2;
 372  434          info->entry = entry;
 373  435          param->info = info;
 374  436          return (NT_STATUS_SUCCESS);
 375  437  }
 376  438  
 377  439  /*
 378  440   * samr_s_OpenDomain
 379  441   *
 380  442   * This is a request to open a domain within the local SAM database.
 381  443   * The caller must supply a valid connect handle.
 382  444   * We return a handle to be used to access objects within this domain.
 383  445   */
 384  446  static int
 385  447  samr_s_OpenDomain(void *arg, ndr_xa_t *mxa)
 386  448  {
 387  449          struct samr_OpenDomain *param = arg;
 388  450          ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle;
 389  451          smb_domain_t domain;
 390  452  
 391  453          if (samr_hdlookup(mxa, id, SAMR_KEY_CONNECT) == NULL) {
 392  454                  bzero(¶m->domain_handle, sizeof (samr_handle_t));
 393  455                  param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
 394  456                  return (NDR_DRC_OK);
 395  457          }
 396  458  
 397  459          if (!smb_domain_lookup_sid((smb_sid_t *)param->sid, &domain)) {
 398  460                  bzero(¶m->domain_handle, sizeof (samr_handle_t));
 399  461                  param->status = NT_SC_ERROR(NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
 400  462                  return (NDR_DRC_OK);
 401  463          }
 402  464  
 403  465          if ((domain.di_type != SMB_DOMAIN_BUILTIN) &&
 404  466              (domain.di_type != SMB_DOMAIN_LOCAL)) {
 405  467                  bzero(¶m->domain_handle, sizeof (samr_handle_t));
 406  468                  param->status = NT_SC_ERROR(NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
 407  469                  return (NDR_DRC_OK);
 408  470          }
 409  471  
 410  472          id = samr_hdalloc(mxa, SAMR_KEY_DOMAIN, domain.di_type, 0);
 411  473          if (id) {
 412  474                  bcopy(id, ¶m->domain_handle, sizeof (samr_handle_t));
 413  475                  param->status = 0;
 414  476          } else {
 415  477                  bzero(¶m->domain_handle, sizeof (samr_handle_t));
 416  478                  param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
 417  479          }
 418  480  
 419  481          return (NDR_DRC_OK);
 420  482  }
 421  483  
 422  484  /*
 423  485   * samr_s_QueryDomainInfo
 424  486   *
 425  487   * The caller should pass a domain handle.
 426  488   *
 427  489   * Windows 95 Server Manager sends requests for levels 6 and 7 when
 428  490   * the services menu item is selected. Level 2 is basically for getting
 429  491   * number of users, groups, and aliases in a domain.
 430  492   * We have no information on what the various information levels mean.
 431  493   */
 432  494  static int
 433  495  samr_s_QueryDomainInfo(void *arg, ndr_xa_t *mxa)
 434  496  {
 435  497          struct samr_QueryDomainInfo *param = arg;
 436  498          struct samr_QueryDomainInfoRes *info;
 437  499          ndr_hdid_t *id = (ndr_hdid_t *)¶m->domain_handle;
 438  500          ndr_handle_t *hd;
 439  501          samr_keydata_t *data;
 440  502          char *domain;
 441  503          char hostname[NETBIOS_NAME_SZ];
 442  504          int alias_cnt, user_cnt;
 443  505          int rc = 0;
 444  506  
 445  507          if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
 446  508                  bzero(param, sizeof (struct samr_QueryDomainInfo));
 447  509                  param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
 448  510                  return (NDR_DRC_OK);
 449  511          }
 450  512  
 451  513          info = NDR_NEW(mxa, struct samr_QueryDomainInfoRes);
 452  514          if (info == NULL) {
 453  515                  bzero(param, sizeof (struct samr_QueryDomainInfo));
 454  516                  param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
 455  517                  return (NDR_DRC_OK);
 456  518          }
 457  519          info->switch_value = param->info_level;
 458  520          param->info = info;
 459  521  
 460  522          data = (samr_keydata_t *)hd->nh_data;
 461  523  
 462  524          switch (data->kd_type) {
 463  525          case SMB_DOMAIN_BUILTIN:
 464  526                  domain = "BUILTIN";
 465  527                  user_cnt = 0;
 466  528                  alias_cnt = smb_sam_grp_cnt(data->kd_type);
 467  529                  break;
 468  530  
 469  531          case SMB_DOMAIN_LOCAL:
 470  532                  rc = smb_getnetbiosname(hostname, sizeof (hostname));
 471  533                  if (rc == 0) {
 472  534                          domain = hostname;
 473  535                          user_cnt = smb_sam_usr_cnt();
 474  536                          alias_cnt = smb_sam_grp_cnt(data->kd_type);
 475  537                  }
 476  538                  break;
 477  539  
 478  540          default:
 479  541                  bzero(param, sizeof (struct samr_QueryDomainInfo));
 480  542                  param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
 481  543                  return (NDR_DRC_OK);
 482  544          }
 483  545  
 484  546          if (rc != 0) {
 485  547                  bzero(param, sizeof (struct samr_QueryDomainInfo));
 486  548                  param->status = NT_SC_ERROR(NT_STATUS_INTERNAL_ERROR);
 487  549                  return (NDR_DRC_OK);
 488  550          }
 489  551  
 490  552          switch (param->info_level) {
 491  553          case SAMR_QUERY_DOMAIN_INFO_6:
 492  554                  info->ru.info6.unknown1 = 0x00000000;
 493  555                  info->ru.info6.unknown2 = 0x00147FB0;
 494  556                  info->ru.info6.unknown3 = 0x00000000;
 495  557                  info->ru.info6.unknown4 = 0x00000000;
 496  558                  info->ru.info6.unknown5 = 0x00000000;
 497  559                  param->status = NT_STATUS_SUCCESS;
 498  560                  break;
 499  561  
 500  562          case SAMR_QUERY_DOMAIN_INFO_7:
 501  563                  info->ru.info7.unknown1 = 0x00000003;
 502  564                  param->status = NT_STATUS_SUCCESS;
 503  565                  break;
 504  566  
 505  567          case SAMR_QUERY_DOMAIN_INFO_2:
 506  568                  info->ru.info2.unknown1 = 0x00000000;
 507  569                  info->ru.info2.unknown2 = 0x80000000;
 508  570  
 509  571                  (void) NDR_MSTRING(mxa, "",
 510  572                      (ndr_mstring_t *)&(info->ru.info2.s1));
 511  573                  (void) NDR_MSTRING(mxa, domain,
 512  574                      (ndr_mstring_t *)&(info->ru.info2.domain));
 513  575                  (void) NDR_MSTRING(mxa, "",
 514  576                      (ndr_mstring_t *)&(info->ru.info2.s2));
 515  577  
 516  578                  info->ru.info2.sequence_num = 0x0000002B;
 517  579                  info->ru.info2.unknown3 = 0x00000000;
 518  580                  info->ru.info2.unknown4 = 0x00000001;
 519  581                  info->ru.info2.unknown5 = 0x00000003;
 520  582                  info->ru.info2.unknown6 = 0x00000001;
 521  583                  info->ru.info2.num_users = user_cnt;
 522  584                  info->ru.info2.num_groups = 0;
 523  585                  info->ru.info2.num_aliases = alias_cnt;
 524  586                  param->status = NT_STATUS_SUCCESS;
 525  587                  break;
 526  588  
 527  589          default:
 528  590                  bzero(param, sizeof (struct samr_QueryDomainInfo));
 529  591                  return (NDR_DRC_FAULT_REQUEST_OPNUM_INVALID);
 530  592          };
 531  593  
 532  594          return (NDR_DRC_OK);
 533  595  }
 534  596  
 535  597  /*
 536  598   * QueryInfoDomain2: Identical to QueryDomainInfo.
 537  599   */
 538  600  static int
 539  601  samr_s_QueryInfoDomain2(void *arg, ndr_xa_t *mxa)
 540  602  {
 541  603          return (samr_s_QueryDomainInfo(arg, mxa));
 542  604  }
 543  605  
 544  606  /*
 545  607   * Looks up the given name in the specified domain which could
 546  608   * be either the built-in or local domain.
 547  609   *
 548  610   * CAVEAT: this function should be able to handle a list of
 549  611   * names but currently it can only handle one name at a time.
 550  612   */
 551  613  static int
 552  614  samr_s_LookupNames(void *arg, ndr_xa_t *mxa)
 553  615  {
 554  616          struct samr_LookupNames *param = arg;
 555  617          ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle;
 556  618          ndr_handle_t *hd;
 557  619          samr_keydata_t *data;
 558  620          smb_account_t account;
 559  621          smb_wka_t *wka;
 560  622          uint32_t status = NT_STATUS_SUCCESS;
 561  623  
 562  624          if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL)
 563  625                  status = NT_STATUS_INVALID_HANDLE;
 564  626  
 565  627          if (param->n_entry != 1)
 566  628                  status = NT_STATUS_ACCESS_DENIED;
 567  629  
 568  630          if (param->name.str == NULL) {
 569  631                  /*
 570  632                   * Windows NT returns NT_STATUS_NONE_MAPPED.
 571  633                   * Windows 2000 returns STATUS_INVALID_ACCOUNT_NAME.
 572  634                   */
 573  635                  status = NT_STATUS_NONE_MAPPED;
 574  636          }
 575  637  
 576  638          if (status != NT_STATUS_SUCCESS) {
 577  639                  bzero(param, sizeof (struct samr_LookupNames));
 578  640                  param->status = NT_SC_ERROR(status);
 579  641                  return (NDR_DRC_OK);
 580  642          }
 581  643  
 582  644          param->rids.rid = NDR_NEW(mxa, DWORD);
 583  645          param->rid_types.rid_type = NDR_NEW(mxa, DWORD);
 584  646  
 585  647          data = (samr_keydata_t *)hd->nh_data;
 586  648  
 587  649          switch (data->kd_type) {
 588  650          case SMB_DOMAIN_BUILTIN:
 589  651                  wka = smb_wka_lookup_builtin((char *)param->name.str);
 590  652                  if (wka != NULL) {
 591  653                          param->rids.n_entry = 1;
 592  654                          (void) smb_sid_getrid(wka->wka_binsid,
 593  655                              ¶m->rids.rid[0]);
 594  656                          param->rid_types.n_entry = 1;
 595  657                          param->rid_types.rid_type[0] = wka->wka_type;
 596  658                          param->status = NT_STATUS_SUCCESS;
 597  659                          return (NDR_DRC_OK);
 598  660                  }
 599  661                  break;
 600  662  
 601  663          case SMB_DOMAIN_LOCAL:
 602  664                  status = smb_sam_lookup_name(NULL, (char *)param->name.str,
 603  665                      SidTypeUnknown, &account);
 604  666                  if (status == NT_STATUS_SUCCESS) {
 605  667                          param->rids.n_entry = 1;
 606  668                          param->rids.rid[0] = account.a_rid;
 607  669                          param->rid_types.n_entry = 1;
 608  670                          param->rid_types.rid_type[0] = account.a_type;
 609  671                          param->status = NT_STATUS_SUCCESS;
 610  672                          smb_account_free(&account);
 611  673                          return (NDR_DRC_OK);
 612  674                  }
 613  675                  break;
 614  676  
 615  677          default:
 616  678                  bzero(param, sizeof (struct samr_LookupNames));
 617  679                  param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
 618  680                  return (NDR_DRC_OK);
 619  681          }
 620  682  
 621  683          param->rids.n_entry = 0;
 622  684          param->rid_types.n_entry = 0;
 623  685          param->status = NT_SC_ERROR(NT_STATUS_NONE_MAPPED);
 624  686          return (NDR_DRC_OK);
 625  687  }
 626  688  
 627  689  /*
 628  690   * samr_s_OpenUser
 629  691   *
 630  692   * This is a request to open a user within a specified domain in the
 631  693   * local SAM database. The caller must supply a valid domain handle,
 632  694   * obtained via a successful domain open request. The user is
 633  695   * specified by the rid in the request.
 634  696   */
 635  697  static int
 636  698  samr_s_OpenUser(void *arg, ndr_xa_t *mxa)
 637  699  {
 638  700          struct samr_OpenUser *param = arg;
 639  701          ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle;
 640  702          ndr_handle_t *hd;
 641  703          samr_keydata_t *data;
 642  704  
 643  705          if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
 644  706                  bzero(¶m->user_handle, sizeof (samr_handle_t));
 645  707                  param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
 646  708                  return (NDR_DRC_OK);
 647  709          }
 648  710  
 649  711          data = (samr_keydata_t *)hd->nh_data;
 650  712  
 651  713          id = samr_hdalloc(mxa, SAMR_KEY_USER, data->kd_type, param->rid);
 652  714          if (id == NULL) {
 653  715                  bzero(¶m->user_handle, sizeof (samr_handle_t));
 654  716                  param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
 655  717          } else {
 656  718                  bcopy(id, ¶m->user_handle, sizeof (samr_handle_t));
 657  719                  param->status = NT_STATUS_SUCCESS;
 658  720          }
 659  721  
 660  722          return (NDR_DRC_OK);
 661  723  }
 662  724  
 663  725  /*
 664  726   * samr_s_DeleteUser
 665  727   *
 666  728   * Request to delete a user within a specified domain in the local
 667  729   * SAM database.  The caller should supply a valid user handle.
 668  730   */
 669  731  /*ARGSUSED*/
 670  732  static int
 671  733  samr_s_DeleteUser(void *arg, ndr_xa_t *mxa)
 672  734  {
 673  735          struct samr_DeleteUser *param = arg;
 674  736  
 675  737          bzero(param, sizeof (struct samr_DeleteUser));
 676  738          param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
 677  739          return (NDR_DRC_OK);
 678  740  }
 679  741  
 680  742  /*
 681  743   * samr_s_QueryUserInfo
  
    | 
      ↓ open down ↓ | 
    408 lines elided | 
    
      ↑ open up ↑ | 
  
 682  744   *
 683  745   * Returns:
 684  746   * NT_STATUS_SUCCESS
 685  747   * NT_STATUS_ACCESS_DENIED
 686  748   * NT_STATUS_INVALID_INFO_CLASS
 687  749   */
 688  750  /*ARGSUSED*/
 689  751  static int
 690  752  samr_s_QueryUserInfo(void *arg, ndr_xa_t *mxa)
 691  753  {
 692      -        static uint16_t                 owf_buf[8];
 693      -        static uint8_t                  hour_buf[SAMR_SET_USER_HOURS_SZ];
 694  754          struct samr_QueryUserInfo       *param = arg;
 695  755          struct samr_QueryUserInfo21     *all_info;
 696  756          ndr_hdid_t                      *id;
 697  757          ndr_handle_t                    *hd;
 698  758          samr_keydata_t                  *data;
 699  759          smb_domain_t                    di;
 700  760          smb_account_t                   account;
 701  761          smb_sid_t                       *sid;
 702  762          uint32_t                        status;
 703  763  
 704  764          id = (ndr_hdid_t *)¶m->user_handle;
 705  765          if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_USER)) == NULL) {
 706  766                  status = NT_STATUS_INVALID_HANDLE;
 707  767                  goto QueryUserInfoError;
 708  768          }
 709  769  
 710  770          data = (samr_keydata_t *)hd->nh_data;
 711  771  
 712  772          if (param->switch_value != SAMR_QUERY_USER_ALL_INFO) {
 713  773                  status = NT_STATUS_ACCESS_DENIED;
 714  774                  goto QueryUserInfoError;
 715  775          }
 716  776  
 717  777          if (!smb_domain_lookup_type(SMB_DOMAIN_LOCAL, &di)) {
 718  778                  status = NT_STATUS_ACCESS_DENIED;
 719  779                  goto QueryUserInfoError;
 720  780          }
 721  781  
 722  782          if ((sid = smb_sid_splice(di.di_binsid, data->kd_rid)) == NULL) {
 723  783                  status = NT_STATUS_ACCESS_DENIED;
 724  784                  goto QueryUserInfoError;
  
    | 
      ↓ open down ↓ | 
    21 lines elided | 
    
      ↑ open up ↑ | 
  
 725  785          }
 726  786  
 727  787          if (smb_sam_lookup_sid(sid, &account) != NT_STATUS_SUCCESS) {
 728  788                  status = NT_STATUS_ACCESS_DENIED;
 729  789                  goto QueryUserInfoError;
 730  790          }
 731  791  
 732  792          all_info = ¶m->ru.info21;
 733  793          bzero(all_info, sizeof (struct samr_QueryUserInfo21));
 734  794  
 735      -        all_info->WhichFields = SAMR_USER_ALL_USERNAME | SAMR_USER_ALL_USERID;
      795 +        all_info->WhichFields = SAMR_USER_ALL_USERNAME | SAMR_USER_ALL_USERID |
      796 +            SAMR_USER_ALL_FULLNAME | SAMR_USER_ALL_USERACCOUNTCONTROL |
      797 +            SAMR_USER_ALL_ADMINCOMMENT;
 736  798  
 737  799          (void) NDR_MSTRING(mxa, account.a_name,
 738  800              (ndr_mstring_t *)&all_info->UserName);
      801 +        (void) NDR_MSTRING(mxa, account.a_name,
      802 +            (ndr_mstring_t *)&all_info->FullName);
      803 +        (void) NDR_MSTRING(mxa, "",
      804 +            (ndr_mstring_t *)&all_info->AdminComment);
      805 +
 739  806          all_info->UserId = data->kd_rid;
      807 +        all_info->UserAccountControl = SAMR_AF_NORMAL_ACCOUNT |
      808 +            SAMR_AF_DONT_EXPIRE_PASSWD;
      809 +        if ((account.a_flags & SMB_PWF_DISABLE) != 0)
      810 +                all_info->UserAccountControl |= SAMR_AF_ACCOUNTDISABLE;
 740  811  
 741      -        all_info->LmOwfPassword.length = 16;
 742      -        all_info->LmOwfPassword.maxlen = 16;
 743      -        all_info->LmOwfPassword.buf = owf_buf;
 744      -        all_info->NtOwfPassword.length = 16;
 745      -        all_info->NtOwfPassword.maxlen = 16;
 746      -        all_info->NtOwfPassword.buf = owf_buf;
 747      -        all_info->LogonHours.units_per_week = SAMR_HOURS_PER_WEEK;
 748      -        all_info->LogonHours.hours = hour_buf;
 749      -
 750  812          param->address = 1;
 751  813          param->switch_index = SAMR_QUERY_USER_ALL_INFO;
 752  814          param->status = NT_STATUS_SUCCESS;
 753  815          smb_account_free(&account);
 754  816          smb_sid_free(sid);
 755  817          return (NDR_DRC_OK);
 756  818  
 757  819  QueryUserInfoError:
 758  820          smb_sid_free(sid);
 759  821          bzero(param, sizeof (struct samr_QueryUserInfo));
 760  822          param->status = NT_SC_ERROR(status);
 761  823          return (NDR_DRC_OK);
 762  824  }
 763  825  
 764  826  /*
 765  827   * samr_s_QueryUserGroups
 766  828   *
 767  829   * Request the list of groups of which a user is a member.
 768  830   * The user is identified from the handle, which contains an
 769  831   * rid in the discriminator field. Note that this is a local user.
 770  832   */
 771  833  static int
 772  834  samr_s_QueryUserGroups(void *arg, ndr_xa_t *mxa)
 773  835  {
 774  836          struct samr_QueryUserGroups *param = arg;
 775  837          struct samr_UserGroupInfo *info;
 776  838          struct samr_UserGroups *group;
 777  839          ndr_hdid_t *id = (ndr_hdid_t *)¶m->user_handle;
 778  840          ndr_handle_t *hd;
 779  841          samr_keydata_t *data;
 780  842          smb_sid_t *user_sid = NULL;
 781  843          smb_group_t grp;
 782  844          smb_giter_t gi;
 783  845          smb_domain_t di;
 784  846          uint32_t status;
 785  847          int size;
 786  848          int ngrp_max;
 787  849  
 788  850          if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_USER)) == NULL) {
 789  851                  status = NT_STATUS_ACCESS_DENIED;
 790  852                  goto query_error;
 791  853          }
 792  854  
 793  855          data = (samr_keydata_t *)hd->nh_data;
 794  856          switch (data->kd_type) {
 795  857          case SMB_DOMAIN_BUILTIN:
 796  858          case SMB_DOMAIN_LOCAL:
 797  859                  if (!smb_domain_lookup_type(data->kd_type, &di)) {
 798  860                          status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
 799  861                          goto query_error;
 800  862                  }
 801  863                  break;
 802  864          default:
 803  865                  status = NT_STATUS_INVALID_HANDLE;
 804  866                  goto query_error;
 805  867          }
 806  868  
 807  869          user_sid = smb_sid_splice(di.di_binsid, data->kd_rid);
 808  870          if (user_sid == NULL) {
 809  871                  status = NT_STATUS_NO_MEMORY;
 810  872                  goto query_error;
 811  873          }
 812  874  
 813  875          info = NDR_NEW(mxa, struct samr_UserGroupInfo);
 814  876          if (info == NULL) {
 815  877                  status = NT_STATUS_NO_MEMORY;
 816  878                  goto query_error;
 817  879          }
 818  880          bzero(info, sizeof (struct samr_UserGroupInfo));
 819  881  
 820  882          size = 32 * 1024;
 821  883          info->groups = NDR_MALLOC(mxa, size);
 822  884          if (info->groups == NULL) {
 823  885                  status = NT_STATUS_NO_MEMORY;
 824  886                  goto query_error;
 825  887          }
 826  888          ngrp_max = size / sizeof (struct samr_UserGroups);
 827  889  
 828  890          if (smb_lgrp_iteropen(&gi) != SMB_LGRP_SUCCESS) {
 829  891                  status = NT_STATUS_INTERNAL_ERROR;
 830  892                  goto query_error;
 831  893          }
 832  894  
 833  895          info->n_entry = 0;
 834  896          group = info->groups;
 835  897          while ((info->n_entry < ngrp_max) &&
 836  898              (smb_lgrp_iterate(&gi, &grp) == SMB_LGRP_SUCCESS)) {
 837  899                  if (smb_lgrp_is_member(&grp, user_sid)) {
 838  900                          group->rid = grp.sg_rid;
 839  901                          group->attr = grp.sg_attr;
 840  902                          group++;
 841  903                          info->n_entry++;
 842  904                  }
 843  905                  smb_lgrp_free(&grp);
 844  906          }
 845  907          smb_lgrp_iterclose(&gi);
 846  908  
 847  909          free(user_sid);
 848  910          param->info = info;
 849  911          param->status = NT_STATUS_SUCCESS;
 850  912          return (NDR_DRC_OK);
 851  913  
 852  914  query_error:
 853  915          free(user_sid);
 854  916          bzero(param, sizeof (struct samr_QueryUserGroups));
 855  917          param->status = NT_SC_ERROR(status);
 856  918          return (NDR_DRC_OK);
 857  919  }
 858  920  
 859  921  /*
 860  922   * samr_s_OpenGroup
 861  923   *
 862  924   * This is a request to open a group within the specified domain in the
 863  925   * local SAM database. The caller must supply a valid domain handle,
 864  926   * obtained via a successful domain open request. The group is
 865  927   * specified by the rid in the request. If this is a local RID it
 866  928   * should already be encoded with type information.
 867  929   *
 868  930   * We return a handle to be used to access information about this group.
 869  931   */
 870  932  static int
 871  933  samr_s_OpenGroup(void *arg, ndr_xa_t *mxa)
 872  934  {
 873  935          struct samr_OpenGroup *param = arg;
 874  936          ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle;
 875  937          ndr_handle_t *hd;
 876  938          samr_keydata_t *data;
 877  939  
 878  940          if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
 879  941                  bzero(¶m->group_handle, sizeof (samr_handle_t));
 880  942                  param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
 881  943                  return (NDR_DRC_OK);
 882  944          }
 883  945  
 884  946          data = (samr_keydata_t *)hd->nh_data;
 885  947          id = samr_hdalloc(mxa, SAMR_KEY_GROUP, data->kd_type, param->rid);
 886  948  
 887  949          if (id) {
 888  950                  bcopy(id, ¶m->group_handle, sizeof (samr_handle_t));
 889  951                  param->status = 0;
 890  952          } else {
 891  953                  bzero(¶m->group_handle, sizeof (samr_handle_t));
 892  954                  param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
 893  955          }
 894  956  
 895  957          return (NDR_DRC_OK);
 896  958  }
 897  959  
 898  960  /*
 899  961   * samr_s_AddAliasMember
 900  962   *
 901  963   * Add a member to a local SAM group.
 902  964   * The caller must supply a valid group handle.
 903  965   * The member is specified by the sid in the request.
 904  966   */
 905  967  static int
 906  968  samr_s_AddAliasMember(void *arg, ndr_xa_t *mxa)
 907  969  {
 908  970          struct samr_AddAliasMember *param = arg;
 909  971          ndr_hdid_t *id = (ndr_hdid_t *)¶m->alias_handle;
 910  972          ndr_handle_t *hd;
 911  973          samr_keydata_t *data;
 912  974          smb_group_t grp;
 913  975          uint32_t rc;
 914  976          uint32_t status = NT_STATUS_SUCCESS;
 915  977  
 916  978          if (param->sid == NULL) {
 917  979                  bzero(param, sizeof (struct samr_AddAliasMember));
 918  980                  param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER);
 919  981                  return (NDR_DRC_OK);
 920  982          }
 921  983  
 922  984          if (!ndr_is_admin(mxa)) {
 923  985                  bzero(param, sizeof (struct samr_AddAliasMember));
 924  986                  param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
 925  987                  return (NDR_DRC_OK);
 926  988          }
 927  989  
 928  990  
 929  991          if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_ALIAS)) == NULL) {
 930  992                  bzero(param, sizeof (struct samr_AddAliasMember));
 931  993                  param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
 932  994                  return (NDR_DRC_OK);
 933  995          }
 934  996  
 935  997          data = (samr_keydata_t *)hd->nh_data;
 936  998          rc = smb_lgrp_getbyrid(data->kd_rid, data->kd_type, &grp);
 937  999          if (rc != SMB_LGRP_SUCCESS) {
 938 1000                  bzero(param, sizeof (struct samr_AddAliasMember));
 939 1001                  status = smb_lgrp_err_to_ntstatus(rc);
 940 1002                  param->status = NT_SC_ERROR(status);
 941 1003                  return (NDR_DRC_OK);
 942 1004          }
 943 1005  
 944 1006          rc = smb_lgrp_add_member(grp.sg_name,
 945 1007              (smb_sid_t *)param->sid, SidTypeUser);
 946 1008          if (rc != SMB_LGRP_SUCCESS) {
 947 1009                  bzero(param, sizeof (struct samr_AddAliasMember));
 948 1010                  status = smb_lgrp_err_to_ntstatus(rc);
 949 1011                  param->status = NT_SC_ERROR(status);
 950 1012          }
 951 1013          smb_lgrp_free(&grp);
 952 1014  
 953 1015          param->status = status;
 954 1016          return (NDR_DRC_OK);
 955 1017  }
 956 1018  
 957 1019  /*
 958 1020   * samr_s_DeleteAliasMember
 959 1021   *
 960 1022   * Delete a member from a local SAM group.
 961 1023   * The caller must supply a valid group handle.
 962 1024   * The member is specified by the sid in the request.
 963 1025   */
 964 1026  static int
 965 1027  samr_s_DeleteAliasMember(void *arg, ndr_xa_t *mxa)
 966 1028  {
 967 1029          struct samr_DeleteAliasMember *param = arg;
 968 1030          ndr_hdid_t *id = (ndr_hdid_t *)¶m->alias_handle;
 969 1031          ndr_handle_t *hd;
 970 1032          samr_keydata_t *data;
 971 1033          smb_group_t grp;
 972 1034          uint32_t rc;
 973 1035          uint32_t status = NT_STATUS_SUCCESS;
 974 1036  
 975 1037          if (param->sid == NULL) {
 976 1038                  bzero(param, sizeof (struct samr_DeleteAliasMember));
 977 1039                  param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER);
 978 1040                  return (NDR_DRC_OK);
 979 1041          }
 980 1042  
 981 1043          if (!ndr_is_admin(mxa)) {
 982 1044                  bzero(param, sizeof (struct samr_DeleteAliasMember));
 983 1045                  param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
 984 1046                  return (NDR_DRC_OK);
 985 1047          }
 986 1048  
 987 1049          if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_ALIAS)) == NULL) {
 988 1050                  bzero(param, sizeof (struct samr_DeleteAliasMember));
 989 1051                  param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
 990 1052                  return (NDR_DRC_OK);
 991 1053          }
 992 1054  
 993 1055          data = (samr_keydata_t *)hd->nh_data;
 994 1056          rc = smb_lgrp_getbyrid(data->kd_rid, data->kd_type, &grp);
 995 1057          if (rc != SMB_LGRP_SUCCESS) {
 996 1058                  bzero(param, sizeof (struct samr_DeleteAliasMember));
 997 1059                  status = smb_lgrp_err_to_ntstatus(rc);
 998 1060                  param->status = NT_SC_ERROR(status);
 999 1061                  return (NDR_DRC_OK);
1000 1062          }
1001 1063  
1002 1064          rc = smb_lgrp_del_member(grp.sg_name,
1003 1065              (smb_sid_t *)param->sid, SidTypeUser);
1004 1066          if (rc != SMB_LGRP_SUCCESS) {
1005 1067                  bzero(param, sizeof (struct samr_DeleteAliasMember));
1006 1068                  status = smb_lgrp_err_to_ntstatus(rc);
1007 1069                  param->status = NT_SC_ERROR(status);
1008 1070          }
1009 1071          smb_lgrp_free(&grp);
1010 1072  
1011 1073          param->status = status;
1012 1074          return (NDR_DRC_OK);
1013 1075  }
1014 1076  
1015 1077  /*
1016 1078   * samr_s_ListAliasMembers
1017 1079   *
1018 1080   * List members from a local SAM group.
1019 1081   * The caller must supply a valid group handle.
1020 1082   * A list of user SIDs in the specified group is returned to the caller.
1021 1083   */
1022 1084  static int
1023 1085  samr_s_ListAliasMembers(void *arg, ndr_xa_t *mxa)
1024 1086  {
1025 1087          struct samr_ListAliasMembers *param = arg;
1026 1088          ndr_hdid_t *id = (ndr_hdid_t *)¶m->alias_handle;
1027 1089          ndr_handle_t *hd;
1028 1090          samr_keydata_t *data;
1029 1091          smb_group_t grp;
1030 1092          smb_gsid_t *members;
1031 1093          struct samr_SidInfo info;
1032 1094          struct samr_SidList *user;
1033 1095          uint32_t num = 0, size;
1034 1096          int i;
1035 1097          uint32_t rc;
1036 1098          uint32_t status = NT_STATUS_SUCCESS;
1037 1099  
1038 1100          if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_ALIAS)) == NULL) {
1039 1101                  bzero(param, sizeof (struct samr_ListAliasMembers));
1040 1102                  param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
1041 1103                  return (NDR_DRC_OK);
1042 1104          }
1043 1105  
1044 1106          bzero(&info, sizeof (struct samr_SidInfo));
1045 1107          data = (samr_keydata_t *)hd->nh_data;
1046 1108          rc = smb_lgrp_getbyrid(data->kd_rid, data->kd_type, &grp);
1047 1109          if (rc != SMB_LGRP_SUCCESS) {
1048 1110                  bzero(param, sizeof (struct samr_ListAliasMembers));
1049 1111                  status = smb_lgrp_err_to_ntstatus(rc);
1050 1112                  param->status = NT_SC_ERROR(status);
1051 1113                  return (NDR_DRC_OK);
1052 1114          }
1053 1115  
1054 1116          num = grp.sg_nmembers;
1055 1117          members = grp.sg_members;
1056 1118          size = num * sizeof (struct samr_SidList);
1057 1119          info.sidlist = NDR_MALLOC(mxa, size);
1058 1120          if (info.sidlist == NULL) {
1059 1121                  bzero(param, sizeof (struct samr_ListAliasMembers));
1060 1122                  param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1061 1123                  smb_lgrp_free(&grp);
1062 1124                  return (NDR_DRC_OK);
1063 1125          }
1064 1126  
1065 1127          info.n_entry = num;
1066 1128          user = info.sidlist;
1067 1129          for (i = 0; i < num; i++) {
1068 1130                  user->sid = (struct samr_sid *)NDR_SIDDUP(mxa,
1069 1131                      members[i].gs_sid);
1070 1132                  if (user->sid == NULL) {
1071 1133                          bzero(param, sizeof (struct samr_ListAliasMembers));
1072 1134                          param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1073 1135                          smb_lgrp_free(&grp);
1074 1136                          return (NDR_DRC_OK);
1075 1137                  }
1076 1138                  user++;
1077 1139          }
1078 1140          smb_lgrp_free(&grp);
1079 1141  
1080 1142          param->info = info;
1081 1143          param->status = status;
1082 1144          return (NDR_DRC_OK);
1083 1145  }
1084 1146  
1085 1147  /*
1086 1148   * samr_s_Connect2
1087 1149   *
1088 1150   * This is a request to connect to the local SAM database.
1089 1151   * We don't support any form of update request and our database doesn't
1090 1152   * contain any private information, so there is little point in doing
1091 1153   * any access access checking here.
1092 1154   *
1093 1155   * Return a handle for use with subsequent SAM requests.
1094 1156   */
1095 1157  static int
1096 1158  samr_s_Connect2(void *arg, ndr_xa_t *mxa)
1097 1159  {
1098 1160          struct samr_Connect2 *param = arg;
1099 1161          ndr_hdid_t *id;
1100 1162  
1101 1163          id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, SMB_DOMAIN_NULL, 0);
1102 1164          if (id) {
1103 1165                  bcopy(id, ¶m->handle, sizeof (samr_handle_t));
1104 1166                  param->status = 0;
1105 1167          } else {
1106 1168                  bzero(¶m->handle, sizeof (samr_handle_t));
1107 1169                  param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1108 1170          }
1109 1171  
1110 1172          return (NDR_DRC_OK);
1111 1173  }
1112 1174  
1113 1175  /*
1114 1176   * samr_s_GetUserPwInfo
1115 1177   *
1116 1178   * Request for a user's password policy information.
1117 1179   */
1118 1180  /*ARGSUSED*/
1119 1181  static int
1120 1182  samr_s_GetUserPwInfo(void *arg, ndr_xa_t *mxa)
1121 1183  {
1122 1184          static samr_password_info_t     pwinfo;
1123 1185          struct samr_GetUserPwInfo       *param = arg;
1124 1186  
1125 1187          param->pwinfo = &pwinfo;
1126 1188          param->status = NT_STATUS_SUCCESS;
1127 1189          return (NDR_DRC_OK);
1128 1190  }
1129 1191  
1130 1192  /*
1131 1193   * samr_s_CreateUser
1132 1194   */
1133 1195  /*ARGSUSED*/
1134 1196  static int
1135 1197  samr_s_CreateUser(void *arg, ndr_xa_t *mxa)
1136 1198  {
1137 1199          struct samr_CreateUser *param = arg;
1138 1200  
1139 1201          bzero(¶m->user_handle, sizeof (samr_handle_t));
1140 1202          param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
1141 1203          return (NDR_DRC_OK);
1142 1204  }
1143 1205  
1144 1206  /*
1145 1207   * samr_s_ChangePasswordUser2
1146 1208   */
1147 1209  /*ARGSUSED*/
1148 1210  static int
1149 1211  samr_s_ChangePasswordUser2(void *arg, ndr_xa_t *mxa)
1150 1212  {
1151 1213          struct samr_ChangePasswordUser2 *param = arg;
1152 1214  
1153 1215          bzero(param, sizeof (*param));
1154 1216          param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
1155 1217          return (NDR_DRC_OK);
1156 1218  }
1157 1219  
1158 1220  /*
1159 1221   * samr_s_GetDomainPwInfo
1160 1222   *
1161 1223   * Request for the domain password policy information.
1162 1224   */
1163 1225  /*ARGSUSED*/
1164 1226  static int
1165 1227  samr_s_GetDomainPwInfo(void *arg, ndr_xa_t *mxa)
1166 1228  {
1167 1229          static samr_password_info_t     pwinfo;
1168 1230          struct samr_GetDomainPwInfo     *param = arg;
1169 1231  
1170 1232          param->pwinfo = &pwinfo;
1171 1233          param->status = NT_STATUS_SUCCESS;
1172 1234          return (NDR_DRC_OK);
1173 1235  }
1174 1236  
1175 1237  /*
1176 1238   * samr_s_SetUserInfo
1177 1239   */
1178 1240  /*ARGSUSED*/
1179 1241  static int
1180 1242  samr_s_SetUserInfo(void *arg, ndr_xa_t *mxa)
1181 1243  {
1182 1244          struct samr_SetUserInfo *param = arg;
1183 1245  
1184 1246          bzero(param, sizeof (struct samr_SetUserInfo));
1185 1247          param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
1186 1248          return (NDR_DRC_OK);
1187 1249  }
1188 1250  
1189 1251  /*
1190 1252   * samr_s_QueryDispInfo
1191 1253   *
1192 1254   * This function currently return local users' information only.
1193 1255   * This RPC is called repeatedly until all the users info are
1194 1256   * retrieved.
1195 1257   *
1196 1258   * The total count and the returned count are returned as total size
1197 1259   * and returned size.  The client doesn't seem to care.
1198 1260   */
1199 1261  static int
1200 1262  samr_s_QueryDispInfo(void *arg, ndr_xa_t *mxa)
1201 1263  {
1202 1264          struct samr_QueryDispInfo *param = arg;
1203 1265          ndr_hdid_t *id = (ndr_hdid_t *)¶m->domain_handle;
1204 1266          ndr_handle_t *hd;
1205 1267          samr_keydata_t *data;
1206 1268          DWORD status = NT_STATUS_SUCCESS;
1207 1269          struct user_acct_info *user;
1208 1270          smb_pwditer_t pwi;
1209 1271          smb_luser_t *uinfo;
1210 1272          int num_users;
1211 1273          int start_idx;
1212 1274          int max_retcnt, retcnt;
1213 1275          int skip;
1214 1276  
1215 1277          if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
1216 1278                  status = NT_STATUS_INVALID_HANDLE;
1217 1279                  goto error;
1218 1280          }
1219 1281  
1220 1282          if (!SAMR_VALID_DISPLEVEL(param->level)) {
1221 1283                  status = NT_STATUS_INVALID_INFO_CLASS;
1222 1284                  goto error;
1223 1285          }
1224 1286  
1225 1287          if (!SAMR_SUPPORTED_DISPLEVEL(param->level)) {
1226 1288                  status = NT_STATUS_NOT_IMPLEMENTED;
1227 1289                  goto error;
1228 1290          }
1229 1291  
1230 1292          data = (samr_keydata_t *)hd->nh_data;
1231 1293  
1232 1294          switch (data->kd_type) {
1233 1295          case SMB_DOMAIN_BUILTIN:
1234 1296                  goto no_info;
1235 1297  
1236 1298          case SMB_DOMAIN_LOCAL:
1237 1299                  num_users = smb_sam_usr_cnt();
1238 1300                  start_idx = param->start_idx;
1239 1301                  if ((num_users == 0) || (start_idx >= num_users))
1240 1302                          goto no_info;
1241 1303  
1242 1304                  max_retcnt = num_users - start_idx;
1243 1305                  if (max_retcnt > param->max_entries)
1244 1306                          max_retcnt = param->max_entries;
1245 1307                  param->users.acct = NDR_MALLOC(mxa,
1246 1308                      max_retcnt * sizeof (struct user_acct_info));
1247 1309                  user = param->users.acct;
1248 1310                  if (user == NULL) {
1249 1311                          status = NT_STATUS_NO_MEMORY;
1250 1312                          goto error;
1251 1313                  }
1252 1314                  bzero(user, max_retcnt * sizeof (struct user_acct_info));
1253 1315  
1254 1316                  if (smb_pwd_iteropen(&pwi) != SMB_PWE_SUCCESS)
1255 1317                          goto no_info;
1256 1318  
1257 1319                  skip = retcnt = 0;
1258 1320                  while ((uinfo = smb_pwd_iterate(&pwi)) != NULL) {
1259 1321                          if (skip++ < start_idx)
1260 1322                                  continue;
1261 1323  
1262 1324                          if (retcnt++ >= max_retcnt)
1263 1325                                  break;
1264 1326  
1265 1327                          assert(uinfo->su_name != NULL);
1266 1328  
1267 1329                          user->index = start_idx + retcnt;
1268 1330                          user->rid = uinfo->su_rid;
1269 1331                          user->ctrl = ACF_NORMUSER | ACF_PWDNOEXP;
1270 1332                          if (uinfo->su_ctrl & SMB_PWF_DISABLE)
1271 1333                                  user->ctrl |= ACF_DISABLED;
1272 1334                          if (NDR_MSTRING(mxa, uinfo->su_name,
1273 1335                              (ndr_mstring_t *)&user->name) == -1) {
1274 1336                                  smb_pwd_iterclose(&pwi);
1275 1337                                  status = NT_STATUS_NO_MEMORY;
1276 1338                                  goto error;
1277 1339                          }
1278 1340                          (void) NDR_MSTRING(mxa, uinfo->su_fullname,
1279 1341                              (ndr_mstring_t *)&user->fullname);
1280 1342                          (void) NDR_MSTRING(mxa, uinfo->su_desc,
1281 1343                              (ndr_mstring_t *)&user->desc);
1282 1344                          user++;
1283 1345                  }
1284 1346                  smb_pwd_iterclose(&pwi);
1285 1347  
1286 1348                  if (retcnt >= max_retcnt) {
1287 1349                          retcnt = max_retcnt;
1288 1350                          param->status = status;
1289 1351                  } else {
1290 1352                          param->status = NT_STATUS_MORE_ENTRIES;
1291 1353                  }
1292 1354  
1293 1355                  param->users.total_size = num_users;
1294 1356                  param->users.returned_size = retcnt;
1295 1357                  param->users.switch_value = param->level;
1296 1358                  param->users.count = retcnt;
1297 1359  
1298 1360                  break;
1299 1361  
1300 1362          default:
1301 1363                  status = NT_STATUS_INVALID_HANDLE;
1302 1364                  goto error;
1303 1365          }
1304 1366  
1305 1367          return (NDR_DRC_OK);
1306 1368  
1307 1369  no_info:
1308 1370          param->users.total_size = 0;
1309 1371          param->users.returned_size = 0;
1310 1372          param->users.switch_value = param->level;
1311 1373          param->users.count = 0;
1312 1374          param->users.acct = NULL;
1313 1375          param->status = status;
1314 1376          return (NDR_DRC_OK);
1315 1377  
1316 1378  error:
1317 1379          bzero(param, sizeof (struct samr_QueryDispInfo));
1318 1380          param->status = NT_SC_ERROR(status);
1319 1381          return (NDR_DRC_OK);
1320 1382  }
1321 1383  
1322 1384  /*
1323 1385   * samr_s_EnumDomainGroups
1324 1386   *
1325 1387   *
1326 1388   * This function is supposed to return local group information.
1327 1389   * As we don't support local users, this function dosen't send
1328 1390   * back any information.
1329 1391   *
1330 1392   * Added template that returns information for a domain group as None.
1331 1393   * All information is hard-coded from packet captures.
1332 1394   */
1333 1395  static int
1334 1396  samr_s_EnumDomainGroups(void *arg, ndr_xa_t *mxa)
1335 1397  {
1336 1398          struct samr_EnumDomainGroups *param = arg;
1337 1399          ndr_hdid_t *id = (ndr_hdid_t *)¶m->domain_handle;
1338 1400          DWORD status = NT_STATUS_SUCCESS;
1339 1401  
1340 1402          if (samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN) == NULL)
1341 1403                  status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
1342 1404  
1343 1405          param->total_size = 0;
1344 1406          param->returned_size = 0;
1345 1407          param->switch_value = 3;
1346 1408          param->count = 0;
1347 1409          param->groups = 0;
1348 1410          param->status = status;
1349 1411          return (NDR_DRC_OK);
1350 1412  
1351 1413  #ifdef SAMR_SUPPORT_GROUPS
1352 1414          if ((desc->discrim != SAMR_LOCAL_DOMAIN) || (param->start_idx != 0)) {
1353 1415                  param->total_size = 0;
1354 1416                  param->returned_size = 0;
1355 1417                  param->switch_value = 3;
1356 1418                  param->count = 0;
1357 1419                  param->groups = 0;
1358 1420          } else {
1359 1421                  param->total_size = 64;
1360 1422                  param->returned_size = 64;
1361 1423                  param->switch_value = 3;
1362 1424                  param->count = 1;
1363 1425                  param->groups = (struct group_disp_info *)NDR_MALLOC(
1364 1426                      mxa, sizeof (struct group_disp_info));
1365 1427  
1366 1428                  param->groups->count = 1;
1367 1429                  param->groups->acct[0].index = 1;
1368 1430                  param->groups->acct[0].rid = 513;
1369 1431                  param->groups->acct[0].ctrl = 0x7;
1370 1432                  (void) NDR_MSTRING(mxa, "None",
1371 1433                      (ndr_mstring_t *)¶m->groups->acct[0].name);
1372 1434  
1373 1435                  (void) NDR_MSTRING(mxa, "Ordinary users",
1374 1436                      (ndr_mstring_t *)¶m->groups->acct[0].desc);
1375 1437          }
1376 1438  
1377 1439          param->status = NT_STATUS_SUCCESS;
1378 1440          return (NDR_DRC_OK);
1379 1441  #endif
1380 1442  }
1381 1443  
1382 1444  /*
1383 1445   * samr_s_OpenAlias
1384 1446   *
1385 1447   * Lookup for requested alias, if it exists return a handle
1386 1448   * for that alias. The alias domain sid should match with
1387 1449   * the passed domain handle.
1388 1450   */
1389 1451  static int
1390 1452  samr_s_OpenAlias(void *arg, ndr_xa_t *mxa)
1391 1453  {
1392 1454          struct samr_OpenAlias *param = arg;
1393 1455          ndr_hdid_t      *id = (ndr_hdid_t *)¶m->domain_handle;
1394 1456          ndr_handle_t    *hd;
1395 1457          samr_keydata_t  *data;
1396 1458          smb_domain_type_t gd_type;
1397 1459          smb_sid_t       *sid;
1398 1460          smb_wka_t       *wka;
1399 1461          char            sidstr[SMB_SID_STRSZ];
1400 1462          uint32_t        rid;
1401 1463          uint32_t        status;
1402 1464          int             rc;
1403 1465  
1404 1466          if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
1405 1467                  status = NT_STATUS_INVALID_HANDLE;
1406 1468                  goto open_alias_err;
1407 1469          }
1408 1470  
1409 1471          if ((param->access_mask & SAMR_ALIAS_ACCESS_ALL_ACCESS) == 0) {
1410 1472                  status = NT_STATUS_ACCESS_DENIED;
1411 1473                  goto open_alias_err;
1412 1474          }
1413 1475  
1414 1476          data = (samr_keydata_t *)hd->nh_data;
1415 1477          gd_type = (smb_domain_type_t)data->kd_type;
1416 1478          rid = param->rid;
1417 1479  
1418 1480          switch (gd_type) {
1419 1481          case SMB_DOMAIN_BUILTIN:
1420 1482                  (void) snprintf(sidstr, SMB_SID_STRSZ, "%s-%d",
1421 1483                      NT_BUILTIN_DOMAIN_SIDSTR, rid);
1422 1484                  if ((sid = smb_sid_fromstr(sidstr)) == NULL) {
1423 1485                          status = NT_STATUS_NO_SUCH_ALIAS;
1424 1486                          goto open_alias_err;
1425 1487                  }
1426 1488  
1427 1489                  wka = smb_wka_lookup_sid(sid);
1428 1490                  smb_sid_free(sid);
1429 1491  
1430 1492                  if (wka == NULL) {
1431 1493                          status = NT_STATUS_NO_SUCH_ALIAS;
1432 1494                          goto open_alias_err;
1433 1495                  }
1434 1496                  break;
1435 1497  
1436 1498          case SMB_DOMAIN_LOCAL:
1437 1499                  rc = smb_lgrp_getbyrid(rid, gd_type, NULL);
1438 1500                  if (rc != SMB_LGRP_SUCCESS) {
1439 1501                          status = NT_STATUS_NO_SUCH_ALIAS;
1440 1502                          goto open_alias_err;
1441 1503                  }
1442 1504                  break;
1443 1505  
1444 1506          default:
1445 1507                  status = NT_STATUS_NO_SUCH_ALIAS;
1446 1508                  goto open_alias_err;
1447 1509          }
1448 1510  
1449 1511          id = samr_hdalloc(mxa, SAMR_KEY_ALIAS, data->kd_type, param->rid);
1450 1512          if (id) {
1451 1513                  bcopy(id, ¶m->alias_handle, sizeof (samr_handle_t));
1452 1514                  param->status = NT_STATUS_SUCCESS;
1453 1515                  return (NDR_DRC_OK);
1454 1516          }
1455 1517  
1456 1518          status = NT_STATUS_NO_MEMORY;
1457 1519  
1458 1520  open_alias_err:
1459 1521          bzero(¶m->alias_handle, sizeof (samr_handle_t));
1460 1522          param->status = NT_SC_ERROR(status);
1461 1523          return (NDR_DRC_OK);
1462 1524  }
1463 1525  
1464 1526  /*
1465 1527   * samr_s_CreateDomainAlias
1466 1528   *
1467 1529   * Create a local group in the security accounts manager (SAM) database.
1468 1530   * A local SAM group can only be added if a Solaris group already exists
1469 1531   * with the same name.  On success, a valid group handle is returned.
1470 1532   *
1471 1533   * The caller must have administrator rights to execute this function.
1472 1534   */
1473 1535  static int
1474 1536  samr_s_CreateDomainAlias(void *arg, ndr_xa_t *mxa)
1475 1537  {
1476 1538          struct samr_CreateDomainAlias *param = arg;
1477 1539          ndr_hdid_t *id = (ndr_hdid_t *)¶m->alias_handle;
1478 1540          uint32_t status = NT_STATUS_SUCCESS;
1479 1541          smb_group_t grp;
1480 1542          uint32_t rc;
1481 1543          char *gname;
1482 1544  
1483 1545          if (samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN) != NULL) {
1484 1546                  bzero(param, sizeof (struct samr_CreateDomainAlias));
1485 1547                  param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
1486 1548                  return (NDR_DRC_OK);
1487 1549          }
1488 1550  
1489 1551          gname = (char *)param->alias_name.str;
1490 1552          if (gname == NULL) {
1491 1553                  bzero(¶m->alias_handle, sizeof (samr_handle_t));
1492 1554                  param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER);
1493 1555                  return (NDR_DRC_OK);
1494 1556          }
1495 1557  
1496 1558          if ((!ndr_is_admin(mxa)) ||
1497 1559              ((param->access_mask & SAMR_ALIAS_ACCESS_WRITE_ACCOUNT) == 0)) {
1498 1560                  bzero(¶m->alias_handle, sizeof (samr_handle_t));
1499 1561                  param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
1500 1562                  return (NDR_DRC_OK);
1501 1563          }
1502 1564  
1503 1565          rc = smb_lgrp_add(gname, "");
1504 1566          if (rc != SMB_LGRP_SUCCESS) {
1505 1567                  bzero(¶m->alias_handle, sizeof (samr_handle_t));
1506 1568                  status = smb_lgrp_err_to_ntstatus(rc);
1507 1569                  param->status = NT_SC_ERROR(status);
1508 1570                  return (NDR_DRC_OK);
1509 1571          }
1510 1572  
1511 1573          rc = smb_lgrp_getbyname((char *)gname, &grp);
1512 1574          if (rc != SMB_LGRP_SUCCESS) {
1513 1575                  bzero(¶m->alias_handle, sizeof (samr_handle_t));
1514 1576                  status = smb_lgrp_err_to_ntstatus(rc);
1515 1577                  param->status = NT_SC_ERROR(status);
1516 1578                  return (NDR_DRC_OK);
1517 1579          }
1518 1580  
1519 1581          id = samr_hdalloc(mxa, SAMR_KEY_ALIAS, SMB_DOMAIN_LOCAL, grp.sg_rid);
1520 1582          smb_lgrp_free(&grp);
1521 1583          if (id) {
1522 1584                  bcopy(id, ¶m->alias_handle, sizeof (samr_handle_t));
1523 1585                  param->status = status;
1524 1586          } else {
1525 1587                  bzero(¶m->alias_handle, sizeof (samr_handle_t));
1526 1588                  param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1527 1589          }
1528 1590  
1529 1591          return (NDR_DRC_OK);
1530 1592  }
1531 1593  
1532 1594  /*
1533 1595   * samr_s_SetAliasInfo
1534 1596   *
1535 1597   * Similar to NetLocalGroupSetInfo.
1536 1598   */
1537 1599  static int
1538 1600  samr_s_SetAliasInfo(void *arg, ndr_xa_t *mxa)
1539 1601  {
1540 1602          struct samr_SetAliasInfo *param = arg;
1541 1603          ndr_hdid_t *id = (ndr_hdid_t *)¶m->alias_handle;
1542 1604          DWORD status = NT_STATUS_SUCCESS;
1543 1605  
1544 1606          if (samr_hdlookup(mxa, id, SAMR_KEY_ALIAS) == NULL)
1545 1607                  status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
1546 1608  
1547 1609          param->status = status;
1548 1610          return (NDR_DRC_OK);
1549 1611  }
1550 1612  
1551 1613  /*
1552 1614   * samr_s_QueryAliasInfo
1553 1615   *
1554 1616   * Retrieves information about the specified local group account
1555 1617   * by given handle.
1556 1618   */
1557 1619  static int
1558 1620  samr_s_QueryAliasInfo(void *arg, ndr_xa_t *mxa)
1559 1621  {
1560 1622          struct samr_QueryAliasInfo *param = arg;
1561 1623          ndr_hdid_t      *id = (ndr_hdid_t *)¶m->alias_handle;
1562 1624          ndr_handle_t    *hd;
1563 1625          samr_keydata_t  *data;
1564 1626          smb_group_t     grp;
1565 1627          smb_domain_type_t gd_type;
1566 1628          smb_sid_t       *sid;
1567 1629          smb_wka_t       *wka;
1568 1630          char            sidstr[SMB_SID_STRSZ];
1569 1631          char            *name;
1570 1632          char            *desc;
1571 1633          uint32_t        rid;
1572 1634          uint32_t        status;
1573 1635          int             rc;
1574 1636  
1575 1637          if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_ALIAS)) == NULL) {
1576 1638                  status = NT_STATUS_INVALID_HANDLE;
1577 1639                  goto query_alias_err;
1578 1640          }
1579 1641  
1580 1642          data = (samr_keydata_t *)hd->nh_data;
1581 1643          gd_type = (smb_domain_type_t)data->kd_type;
1582 1644          rid = data->kd_rid;
1583 1645  
1584 1646          switch (gd_type) {
1585 1647          case SMB_DOMAIN_BUILTIN:
1586 1648                  (void) snprintf(sidstr, SMB_SID_STRSZ, "%s-%d",
1587 1649                      NT_BUILTIN_DOMAIN_SIDSTR, rid);
1588 1650                  if ((sid = smb_sid_fromstr(sidstr)) == NULL) {
1589 1651                          status = NT_STATUS_NO_SUCH_ALIAS;
1590 1652                          goto query_alias_err;
1591 1653                  }
1592 1654  
1593 1655                  wka = smb_wka_lookup_sid(sid);
1594 1656                  smb_sid_free(sid);
1595 1657  
1596 1658                  if (wka == NULL) {
1597 1659                          status = NT_STATUS_NO_SUCH_ALIAS;
1598 1660                          goto query_alias_err;
1599 1661                  }
1600 1662  
1601 1663                  name = wka->wka_name;
1602 1664                  desc = (wka->wka_desc != NULL) ? wka->wka_desc : "";
1603 1665                  break;
1604 1666  
1605 1667          case SMB_DOMAIN_LOCAL:
1606 1668                  rc = smb_lgrp_getbyrid(rid, gd_type, &grp);
1607 1669                  if (rc != SMB_LGRP_SUCCESS) {
1608 1670                          status = NT_STATUS_NO_SUCH_ALIAS;
1609 1671                          goto query_alias_err;
1610 1672                  }
1611 1673                  name = grp.sg_name;
1612 1674                  desc = grp.sg_cmnt;
1613 1675                  break;
1614 1676  
1615 1677          default:
1616 1678                  status = NT_STATUS_NO_SUCH_ALIAS;
1617 1679                  goto query_alias_err;
1618 1680          }
1619 1681  
1620 1682          switch (param->level) {
1621 1683          case SAMR_QUERY_ALIAS_INFO_GENERAL:
1622 1684                  param->ru.info1.level = param->level;
1623 1685                  (void) NDR_MSTRING(mxa, name,
1624 1686                      (ndr_mstring_t *)¶m->ru.info1.name);
1625 1687                  (void) NDR_MSTRING(mxa, desc,
1626 1688                      (ndr_mstring_t *)¶m->ru.info1.desc);
1627 1689                  param->ru.info1.member_count = 1;
1628 1690                  break;
1629 1691  
1630 1692          case SAMR_QUERY_ALIAS_INFO_NAME:
1631 1693                  param->ru.info2.level = param->level;
1632 1694                  (void) NDR_MSTRING(mxa, name,
1633 1695                      (ndr_mstring_t *)¶m->ru.info2.name);
1634 1696                  break;
1635 1697  
1636 1698          case SAMR_QUERY_ALIAS_INFO_COMMENT:
1637 1699                  param->ru.info3.level = param->level;
1638 1700                  (void) NDR_MSTRING(mxa, desc,
1639 1701                      (ndr_mstring_t *)¶m->ru.info3.desc);
1640 1702                  break;
1641 1703  
1642 1704          default:
1643 1705                  if (gd_type == SMB_DOMAIN_LOCAL)
1644 1706                          smb_lgrp_free(&grp);
1645 1707                  status = NT_STATUS_INVALID_INFO_CLASS;
1646 1708                  goto query_alias_err;
1647 1709          };
1648 1710  
1649 1711          if (gd_type == SMB_DOMAIN_LOCAL)
1650 1712                  smb_lgrp_free(&grp);
1651 1713          param->address = (DWORD)(uintptr_t)¶m->ru;
1652 1714          param->status = 0;
1653 1715          return (NDR_DRC_OK);
1654 1716  
1655 1717  query_alias_err:
1656 1718          param->status = NT_SC_ERROR(status);
1657 1719          return (NDR_DRC_OK);
1658 1720  }
1659 1721  
1660 1722  /*
1661 1723   * samr_s_DeleteDomainAlias
1662 1724   *
1663 1725   * Deletes a local group in the security database, which is the
1664 1726   * security accounts manager (SAM). A valid group handle is returned
1665 1727   * to the caller upon success.
1666 1728   *
1667 1729   * The caller must have administrator rights to execute this function.
1668 1730   */
1669 1731  static int
1670 1732  samr_s_DeleteDomainAlias(void *arg, ndr_xa_t *mxa)
1671 1733  {
1672 1734          struct samr_DeleteDomainAlias *param = arg;
1673 1735          ndr_hdid_t *id = (ndr_hdid_t *)¶m->alias_handle;
1674 1736          ndr_handle_t    *hd;
1675 1737          smb_group_t grp;
1676 1738          samr_keydata_t  *data;
1677 1739          smb_domain_type_t       gd_type;
1678 1740          uint32_t        rid;
1679 1741          uint32_t        rc;
1680 1742          uint32_t        status = NT_STATUS_SUCCESS;
1681 1743  
1682 1744          if (!ndr_is_admin(mxa)) {
1683 1745                  bzero(param, sizeof (struct samr_DeleteDomainAlias));
1684 1746                  param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
1685 1747                  return (NDR_DRC_OK);
1686 1748          }
1687 1749  
1688 1750          if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_ALIAS)) == NULL) {
1689 1751                  bzero(param, sizeof (struct samr_DeleteDomainAlias));
1690 1752                  param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
1691 1753                  return (NDR_DRC_OK);
1692 1754          }
1693 1755  
1694 1756          data = (samr_keydata_t *)hd->nh_data;
1695 1757          gd_type = (smb_domain_type_t)data->kd_type;
1696 1758          rid = data->kd_rid;
1697 1759  
1698 1760          switch (gd_type) {
1699 1761          case SMB_DOMAIN_BUILTIN:
1700 1762                  bzero(param, sizeof (struct samr_DeleteDomainAlias));
1701 1763                  status = NT_SC_ERROR(NT_STATUS_NOT_SUPPORTED);
1702 1764                  break;
1703 1765  
1704 1766          case SMB_DOMAIN_LOCAL:
1705 1767                  rc = smb_lgrp_getbyrid(rid, gd_type, &grp);
1706 1768                  if (rc != SMB_LGRP_SUCCESS) {
1707 1769                          bzero(param, sizeof (struct samr_DeleteDomainAlias));
1708 1770                          status = smb_lgrp_err_to_ntstatus(rc);
1709 1771                          status = NT_SC_ERROR(status);
1710 1772                          break;
1711 1773                  }
1712 1774  
1713 1775                  rc = smb_lgrp_delete(grp.sg_name);
1714 1776                  if (rc != SMB_LGRP_SUCCESS) {
1715 1777                          bzero(param, sizeof (struct samr_DeleteDomainAlias));
1716 1778                          status = smb_lgrp_err_to_ntstatus(rc);
1717 1779                          status = NT_SC_ERROR(status);
1718 1780                  }
1719 1781                  smb_lgrp_free(&grp);
1720 1782                  break;
1721 1783  
1722 1784          default:
1723 1785                  bzero(param, sizeof (struct samr_DeleteDomainAlias));
1724 1786                  status = NT_SC_ERROR(NT_STATUS_NO_SUCH_ALIAS);
1725 1787          }
1726 1788  
1727 1789          param->status = status;
1728 1790          return (NDR_DRC_OK);
1729 1791  }
1730 1792  
1731 1793  /*
1732 1794   * samr_s_EnumDomainAliases
1733 1795   *
1734 1796   * This function sends back a list which contains all local groups' name.
1735 1797   */
1736 1798  static int
1737 1799  samr_s_EnumDomainAliases(void *arg, ndr_xa_t *mxa)
1738 1800  {
1739 1801          struct samr_EnumDomainAliases *param = arg;
1740 1802          ndr_hdid_t *id = (ndr_hdid_t *)¶m->domain_handle;
1741 1803          ndr_handle_t *hd;
1742 1804          samr_keydata_t *data;
1743 1805          smb_group_t grp;
1744 1806          smb_giter_t gi;
1745 1807          int cnt, skip, i;
1746 1808          struct name_rid *info;
1747 1809  
1748 1810          if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
1749 1811                  bzero(param, sizeof (struct samr_EnumDomainAliases));
1750 1812                  param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
1751 1813                  return (NDR_DRC_OK);
1752 1814          }
1753 1815  
1754 1816          data = (samr_keydata_t *)hd->nh_data;
1755 1817  
1756 1818          cnt = smb_sam_grp_cnt(data->kd_type);
1757 1819          if (cnt <= param->resume_handle) {
1758 1820                  param->aliases = (struct aliases_info *)NDR_MALLOC(mxa,
1759 1821                      sizeof (struct aliases_info));
1760 1822  
1761 1823                  if (param->aliases == NULL) {
1762 1824                          bzero(param, sizeof (struct samr_EnumDomainAliases));
1763 1825                          param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1764 1826                          return (NDR_DRC_OK);
1765 1827                  }
1766 1828  
1767 1829                  bzero(param->aliases, sizeof (struct aliases_info));
1768 1830                  param->out_resume = 0;
1769 1831                  param->entries = 0;
1770 1832                  param->status = NT_STATUS_SUCCESS;
1771 1833                  return (NDR_DRC_OK);
1772 1834          }
1773 1835  
1774 1836          cnt -= param->resume_handle;
1775 1837          param->aliases = (struct aliases_info *)NDR_MALLOC(mxa,
1776 1838              sizeof (struct aliases_info) + (cnt-1) * sizeof (struct name_rid));
1777 1839  
1778 1840          if (param->aliases == NULL) {
1779 1841                  bzero(param, sizeof (struct samr_EnumDomainAliases));
1780 1842                  param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1781 1843                  return (NDR_DRC_OK);
1782 1844          }
1783 1845  
1784 1846          if (smb_lgrp_iteropen(&gi) != SMB_LGRP_SUCCESS) {
1785 1847                  bzero(param, sizeof (struct samr_EnumDomainAliases));
1786 1848                  param->status = NT_SC_ERROR(NT_STATUS_INTERNAL_ERROR);
1787 1849                  return (NDR_DRC_OK);
1788 1850          }
1789 1851  
1790 1852          skip = i = 0;
1791 1853          info = param->aliases->info;
1792 1854          while (smb_lgrp_iterate(&gi, &grp) == SMB_LGRP_SUCCESS) {
1793 1855                  if ((skip++ >= param->resume_handle) &&
1794 1856                      (grp.sg_domain == data->kd_type) && (i++ < cnt)) {
1795 1857                          info->rid = grp.sg_rid;
1796 1858                          (void) NDR_MSTRING(mxa, grp.sg_name,
1797 1859                              (ndr_mstring_t *)&info->name);
1798 1860  
1799 1861                          info++;
1800 1862                  }
1801 1863                  smb_lgrp_free(&grp);
1802 1864          }
1803 1865          smb_lgrp_iterclose(&gi);
1804 1866  
1805 1867          param->aliases->count = i;
1806 1868          param->aliases->address = i;
1807 1869  
1808 1870          param->out_resume = i;
1809 1871          param->entries = i;
1810 1872          param->status = 0;
1811 1873          return (NDR_DRC_OK);
1812 1874  }
1813 1875  
1814 1876  /*
1815 1877   * samr_s_Connect4
1816 1878   */
1817 1879  static int
1818 1880  samr_s_Connect4(void *arg, ndr_xa_t *mxa)
1819 1881  {
1820 1882          struct samr_Connect4    *param = arg;
1821 1883          ndr_hdid_t              *id;
1822 1884  
1823 1885          id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, SMB_DOMAIN_NULL, 0);
1824 1886          if (id) {
1825 1887                  bcopy(id, ¶m->handle, sizeof (samr_handle_t));
1826 1888                  param->status = 0;
1827 1889          } else {
1828 1890                  bzero(¶m->handle, sizeof (samr_handle_t));
1829 1891                  param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1830 1892          }
1831 1893  
1832 1894          return (NDR_DRC_OK);
1833 1895  }
1834 1896  
1835 1897  /*
1836 1898   * samr_s_Connect5
1837 1899   *
1838 1900   * This is the connect5 form of the connect request used by Windows XP.
1839 1901   * Returns an RPC fault for now.
1840 1902   */
1841 1903  /*ARGSUSED*/
1842 1904  static int
1843 1905  samr_s_Connect5(void *arg, ndr_xa_t *mxa)
  
    | 
      ↓ open down ↓ | 
    1084 lines elided | 
    
      ↑ open up ↑ | 
  
1844 1906  {
1845 1907          struct samr_Connect5 *param = arg;
1846 1908  
1847 1909          bzero(param, sizeof (struct samr_Connect5));
1848 1910          return (NDR_DRC_FAULT_REQUEST_OPNUM_INVALID);
1849 1911  }
1850 1912  
1851 1913  static ndr_stub_table_t samr_stub_table[] = {
1852 1914          { samr_s_Connect,               SAMR_OPNUM_Connect },
1853 1915          { samr_s_CloseHandle,           SAMR_OPNUM_CloseHandle },
     1916 +        { samr_s_QuerySecObject,        SAMR_OPNUM_QuerySecObject },
1854 1917          { samr_s_LookupDomain,          SAMR_OPNUM_LookupDomain },
1855 1918          { samr_s_EnumLocalDomains,      SAMR_OPNUM_EnumLocalDomains },
1856 1919          { samr_s_OpenDomain,            SAMR_OPNUM_OpenDomain },
1857 1920          { samr_s_QueryDomainInfo,       SAMR_OPNUM_QueryDomainInfo },
1858 1921          { samr_s_QueryInfoDomain2,      SAMR_OPNUM_QueryInfoDomain2 },
1859 1922          { samr_s_LookupNames,           SAMR_OPNUM_LookupNames },
1860 1923          { samr_s_OpenUser,              SAMR_OPNUM_OpenUser },
1861 1924          { samr_s_DeleteUser,            SAMR_OPNUM_DeleteUser },
1862 1925          { samr_s_QueryUserInfo,         SAMR_OPNUM_QueryUserInfo },
1863 1926          { samr_s_QueryUserGroups,       SAMR_OPNUM_QueryUserGroups },
1864 1927          { samr_s_OpenGroup,             SAMR_OPNUM_OpenGroup },
1865 1928          { samr_s_Connect2,              SAMR_OPNUM_Connect2 },
1866 1929          { samr_s_GetUserPwInfo,         SAMR_OPNUM_GetUserPwInfo },
1867 1930          { samr_s_CreateUser,            SAMR_OPNUM_CreateUser },
1868 1931          { samr_s_ChangePasswordUser2,   SAMR_OPNUM_ChangePasswordUser2 },
1869 1932          { samr_s_GetDomainPwInfo,       SAMR_OPNUM_GetDomainPwInfo },
1870 1933          { samr_s_SetUserInfo,           SAMR_OPNUM_SetUserInfo },
1871 1934          { samr_s_Connect4,              SAMR_OPNUM_Connect4 },
1872 1935          { samr_s_Connect5,              SAMR_OPNUM_Connect5 },
1873 1936          { samr_s_QueryDispInfo,         SAMR_OPNUM_QueryDispInfo },
1874 1937          { samr_s_OpenAlias,             SAMR_OPNUM_OpenAlias },
1875 1938          { samr_s_CreateDomainAlias,     SAMR_OPNUM_CreateDomainAlias },
1876 1939          { samr_s_SetAliasInfo,          SAMR_OPNUM_SetAliasInfo },
1877 1940          { samr_s_QueryAliasInfo,        SAMR_OPNUM_QueryAliasInfo },
1878 1941          { samr_s_DeleteDomainAlias,     SAMR_OPNUM_DeleteDomainAlias },
1879 1942          { samr_s_EnumDomainAliases,     SAMR_OPNUM_EnumDomainAliases },
1880 1943          { samr_s_EnumDomainGroups,      SAMR_OPNUM_EnumDomainGroups },
1881 1944          { samr_s_AddAliasMember,        SAMR_OPNUM_AddAliasMember },
1882 1945          { samr_s_DeleteAliasMember,     SAMR_OPNUM_DeleteAliasMember },
1883 1946          { samr_s_ListAliasMembers,      SAMR_OPNUM_ListAliasMembers },
1884 1947          {0}
1885 1948  };
1886 1949  
1887 1950  /*
1888 1951   * There is a bug in the way that midl and the marshalling code handles
1889 1952   * unions so we need to fix some of the data offsets at runtime. The
1890 1953   * following macros and the fixup functions handle the corrections.
1891 1954   */
1892 1955  
1893 1956  DECL_FIXUP_STRUCT(samr_QueryAliasInfo_ru);
1894 1957  DECL_FIXUP_STRUCT(samr_QueryAliasInfoRes);
1895 1958  DECL_FIXUP_STRUCT(samr_QueryAliasInfo);
1896 1959  
1897 1960  DECL_FIXUP_STRUCT(QueryUserInfo_result_u);
1898 1961  DECL_FIXUP_STRUCT(QueryUserInfo_result);
1899 1962  DECL_FIXUP_STRUCT(samr_QueryUserInfo);
1900 1963  
1901 1964  void
1902 1965  fixup_samr_QueryAliasInfo(struct samr_QueryAliasInfo *val)
1903 1966  {
1904 1967          unsigned short size1 = 0;
1905 1968          unsigned short size2 = 0;
1906 1969          unsigned short size3 = 0;
1907 1970  
1908 1971          switch (val->level) {
1909 1972          case SAMR_QUERY_ALIAS_INFO_GENERAL:
1910 1973                  size1 = sizeof (struct samr_QueryAliasInfoGeneral);
1911 1974                  break;
1912 1975          case SAMR_QUERY_ALIAS_INFO_NAME:
1913 1976                  size1 = sizeof (struct samr_QueryAliasInfoName);
1914 1977                  break;
1915 1978          case SAMR_QUERY_ALIAS_INFO_COMMENT:
1916 1979                  size1 = sizeof (struct samr_QueryAliasInfoComment);
1917 1980                  break;
1918 1981  
1919 1982          default:
1920 1983                  return;
1921 1984          };
1922 1985  
1923 1986          size2 = size1 + (2 * sizeof (DWORD));
1924 1987          size3 = size2 + sizeof (ndr_request_hdr_t) + sizeof (DWORD);
1925 1988  
1926 1989          FIXUP_PDU_SIZE(samr_QueryAliasInfo_ru, size1);
1927 1990          FIXUP_PDU_SIZE(samr_QueryAliasInfoRes, size2);
1928 1991          FIXUP_PDU_SIZE(samr_QueryAliasInfo, size3);
1929 1992  }
1930 1993  
1931 1994  void
1932 1995  fixup_samr_QueryUserInfo(struct samr_QueryUserInfo *val)
1933 1996  {
1934 1997          unsigned short size1 = 0;
1935 1998          unsigned short size2 = 0;
1936 1999          unsigned short size3 = 0;
1937 2000  
1938 2001          switch (val->switch_index) {
1939 2002                  CASE_INFO_ENT(samr_QueryUserInfo, 1);
1940 2003                  CASE_INFO_ENT(samr_QueryUserInfo, 6);
1941 2004                  CASE_INFO_ENT(samr_QueryUserInfo, 7);
1942 2005                  CASE_INFO_ENT(samr_QueryUserInfo, 8);
1943 2006                  CASE_INFO_ENT(samr_QueryUserInfo, 9);
1944 2007                  CASE_INFO_ENT(samr_QueryUserInfo, 16);
1945 2008                  CASE_INFO_ENT(samr_QueryUserInfo, 21);
1946 2009  
1947 2010                  default:
1948 2011                          return;
1949 2012          };
1950 2013  
1951 2014          size2 = size1 + (2 * sizeof (DWORD));
1952 2015          size3 = size2 + sizeof (ndr_request_hdr_t) + sizeof (DWORD);
1953 2016  
1954 2017          FIXUP_PDU_SIZE(QueryUserInfo_result_u, size1);
1955 2018          FIXUP_PDU_SIZE(QueryUserInfo_result, size2);
1956 2019          FIXUP_PDU_SIZE(samr_QueryUserInfo, size3);
1957 2020  }
1958 2021  
1959 2022  /*
1960 2023   * As long as there is only one entry in the union, there is no need
1961 2024   * to patch anything.
1962 2025   */
1963 2026  /*ARGSUSED*/
1964 2027  void
1965 2028  fixup_samr_QueryGroupInfo(struct samr_QueryGroupInfo *val)
1966 2029  {
1967 2030  }
  
    | 
      ↓ open down ↓ | 
    104 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX