Print this page
    
NEX-17589 Get "too high" smbd error when copy big file to cifs share
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-17795 SMB logon should tolerate idmap problems
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-15558 SMB logon fails during 1st second after service start
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-15558 SMB logon fails during 1st second after service start
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-9497 SMB should bypass ACL traverse checking
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-3080 SMB1 signing problem with Kerberos auth.
Reviewed by: Bayard Bell <bayard.bell@nexenta.com>
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
NEX-2461 smb_split_sid uses wrong allocation size
NEX-1810 extended security Kerberos (inbound)
SMB-126 Unable to map share from win2003/win2003R2 client ...
SMB-107 Unable to map network drive in workgroup mode using Windows XP...
SMB-68 NTLM(v1) inbound with Extended Session Security
SMB-56 extended security NTLMSSP, inbound
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/lib/smbsrv/libmlsvc/common/smb_logon.c
          +++ new/usr/src/lib/smbsrv/libmlsvc/common/smb_logon.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   *
  
    | 
      ↓ open down ↓ | 
    12 lines elided | 
    
      ↑ open up ↑ | 
  
  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   * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  23      - * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
  24   23   * Copyright (c) 2016 by Delphix. All rights reserved.
       24 + * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  25   25   */
  26   26  
  27   27  #include <unistd.h>
  28   28  #include <strings.h>
  29   29  #include <pwd.h>
  30   30  #include <grp.h>
  31   31  #include <time.h>
  32   32  #include <syslog.h>
  33   33  #include <assert.h>
  34   34  #include <synch.h>
  35   35  
  36   36  #include <smbsrv/libsmb.h>
  37   37  #include <smbsrv/libmlsvc.h>
  38   38  
  39   39  #include <smbsrv/smbinfo.h>
  40   40  #include <smbsrv/smb_token.h>
  41   41  #include <lsalib.h>
  42   42  
  43   43  static smb_account_t smb_guest;
  44   44  static smb_account_t smb_domusers;
  45   45  static rwlock_t smb_logoninit_rwl;
  46   46  
  47   47  typedef void (*smb_logonop_t)(smb_logon_t *, smb_token_t *);
  48   48  
  49   49  static void smb_logon_local(smb_logon_t *, smb_token_t *);
  50   50  static void smb_logon_guest(smb_logon_t *, smb_token_t *);
  51   51  static void smb_logon_anon(smb_logon_t *, smb_token_t *);
  52   52  
  53   53  static uint32_t smb_token_auth_local(smb_logon_t *, smb_token_t *,
  54   54      smb_passwd_t *);
  55   55  
  56   56  static uint32_t smb_token_setup_local(smb_passwd_t *, smb_token_t *);
  57   57  static uint32_t smb_token_setup_guest(smb_logon_t *, smb_token_t *);
  58   58  static uint32_t smb_token_setup_anon(smb_token_t *token);
  59   59  
  60   60  static boolean_t smb_token_is_member(smb_token_t *, smb_sid_t *);
  61   61  static uint32_t smb_token_setup_wingrps(smb_token_t *);
  62   62  static smb_posix_grps_t *smb_token_create_pxgrps(uid_t);
  63   63  
  64   64  static void smb_guest_account(char *, size_t);
  65   65  
  66   66  /* Consolidation private function from Network Repository */
  67   67  extern int _getgroupsbymember(const char *, gid_t[], int, int);
  68   68  
  69   69  static idmap_stat
  70   70  smb_token_idmap(smb_token_t *token, smb_idmap_batch_t *sib)
  71   71  {
  72   72          idmap_stat stat;
  73   73          smb_idmap_t *sim;
  74   74          smb_id_t *id;
  75   75          int i;
  76   76  
  77   77          if (!token || !sib)
  78   78                  return (IDMAP_ERR_ARG);
  79   79  
  80   80          sim = sib->sib_maps;
  81   81  
  82   82          if (token->tkn_flags & SMB_ATF_ANON) {
  83   83                  token->tkn_user.i_id = UID_NOBODY;
  84   84                  token->tkn_owner.i_id = UID_NOBODY;
  85   85          } else {
  86   86                  /* User SID */
  87   87                  id = &token->tkn_user;
  88   88                  sim->sim_id = &id->i_id;
  89   89                  stat = smb_idmap_batch_getid(sib->sib_idmaph, sim++,
  90   90                      id->i_sid, SMB_IDMAP_USER);
  91   91  
  92   92                  if (stat != IDMAP_SUCCESS)
  93   93                          return (stat);
  94   94  
  95   95                  /* Owner SID */
  96   96                  id = &token->tkn_owner;
  97   97                  sim->sim_id = &id->i_id;
  98   98                  stat = smb_idmap_batch_getid(sib->sib_idmaph, sim++,
  99   99                      id->i_sid, SMB_IDMAP_USER);
 100  100  
 101  101                  if (stat != IDMAP_SUCCESS)
 102  102                          return (stat);
 103  103          }
 104  104  
 105  105          /* Primary Group SID */
 106  106          id = &token->tkn_primary_grp;
 107  107          sim->sim_id = &id->i_id;
 108  108          stat = smb_idmap_batch_getid(sib->sib_idmaph, sim++, id->i_sid,
 109  109              SMB_IDMAP_GROUP);
 110  110  
 111  111          if (stat != IDMAP_SUCCESS)
 112  112                  return (stat);
 113  113  
 114  114          /* Other Windows Group SIDs */
 115  115          for (i = 0; i < token->tkn_win_grps.i_cnt; i++, sim++) {
 116  116                  id = &token->tkn_win_grps.i_ids[i];
 117  117                  sim->sim_id = &id->i_id;
 118  118                  stat = smb_idmap_batch_getid(sib->sib_idmaph, sim,
 119  119                      id->i_sid, SMB_IDMAP_GROUP);
 120  120  
 121  121                  if (stat != IDMAP_SUCCESS)
  
    | 
      ↓ open down ↓ | 
    87 lines elided | 
    
      ↑ open up ↑ | 
  
 122  122                          break;
 123  123          }
 124  124  
 125  125          return (stat);
 126  126  }
 127  127  
 128  128  /*
 129  129   * smb_token_sids2ids
 130  130   *
 131  131   * This will map all the SIDs of the access token to UIDs/GIDs.
      132 + * However, if there are some SIDs we can't map to UIDs/GIDs,
      133 + * we don't want to fail the logon, and instead just log the
      134 + * SIDs we could not map and continue as best we can.
      135 + * The flag SMB_IDMAP_SKIP_ERRS below does that.
 132  136   *
 133  137   * Returns 0 upon success.  Otherwise, returns -1.
 134  138   */
 135  139  static int
 136  140  smb_token_sids2ids(smb_token_t *token)
 137  141  {
 138  142          idmap_stat stat;
 139  143          int nmaps;
 140  144          smb_idmap_batch_t sib;
 141  145  
 142  146          /*
 143  147           * Number of idmap lookups: user SID, owner SID, primary group SID,
 144  148           * and all Windows group SIDs. Skip user/owner SID for Anonymous.
 145  149           */
 146  150          if (token->tkn_flags & SMB_ATF_ANON)
 147  151                  nmaps = token->tkn_win_grps.i_cnt + 1;
 148  152          else
 149  153                  nmaps = token->tkn_win_grps.i_cnt + 3;
 150  154  
 151      -        stat = smb_idmap_batch_create(&sib, nmaps, SMB_IDMAP_SID2ID);
      155 +        stat = smb_idmap_batch_create(&sib, nmaps,
      156 +            SMB_IDMAP_SID2ID | SMB_IDMAP_SKIP_ERRS);
 152  157          if (stat != IDMAP_SUCCESS)
 153  158                  return (-1);
 154  159  
 155  160          stat = smb_token_idmap(token, &sib);
 156  161          if (stat != IDMAP_SUCCESS) {
 157  162                  smb_idmap_batch_destroy(&sib);
 158  163                  return (-1);
 159  164          }
 160  165  
 161  166          stat = smb_idmap_batch_getmappings(&sib);
 162  167          smb_idmap_check("smb_idmap_batch_getmappings", stat);
 163  168          smb_idmap_batch_destroy(&sib);
 164  169  
 165  170          return (stat == IDMAP_SUCCESS ? 0 : -1);
 166  171  }
 167  172  
 168  173  /*
 169  174   * smb_token_create_pxgrps
 170  175   *
 171  176   * Setup the POSIX group membership of the access token if the given UID is
 172  177   * a POSIX UID (non-ephemeral). Both the user's primary group and
 173  178   * supplementary groups will be added to the POSIX group array of the access
 174  179   * token.
 175  180   */
 176  181  static smb_posix_grps_t *
 177  182  smb_token_create_pxgrps(uid_t uid)
 178  183  {
 179  184          struct passwd *pwd;
 180  185          smb_posix_grps_t *pgrps;
 181  186          int ngroups_max, num;
 182  187          gid_t *gids;
 183  188  
 184  189          if ((ngroups_max = sysconf(_SC_NGROUPS_MAX)) < 0) {
 185  190                  syslog(LOG_ERR, "smb_logon: failed to get _SC_NGROUPS_MAX");
 186  191                  return (NULL);
 187  192          }
 188  193  
 189  194          pwd = getpwuid(uid);
 190  195          if (pwd == NULL) {
 191  196                  pgrps = malloc(sizeof (smb_posix_grps_t));
 192  197                  if (pgrps == NULL)
 193  198                          return (NULL);
 194  199  
 195  200                  pgrps->pg_ngrps = 0;
 196  201                  return (pgrps);
 197  202          }
 198  203  
 199  204          if (pwd->pw_name == NULL) {
 200  205                  pgrps = malloc(sizeof (smb_posix_grps_t));
 201  206                  if (pgrps == NULL)
 202  207                          return (NULL);
 203  208  
 204  209                  pgrps->pg_ngrps = 1;
 205  210                  pgrps->pg_grps[0] = pwd->pw_gid;
 206  211                  return (pgrps);
 207  212          }
 208  213  
 209  214          gids = (gid_t *)malloc(ngroups_max * sizeof (gid_t));
 210  215          if (gids == NULL) {
 211  216                  return (NULL);
 212  217          }
 213  218          bzero(gids, ngroups_max * sizeof (gid_t));
 214  219  
 215  220          gids[0] = pwd->pw_gid;
 216  221  
 217  222          /*
 218  223           * Setup the groups starting at index 1 (the last arg)
 219  224           * of gids array.
 220  225           */
 221  226          num = _getgroupsbymember(pwd->pw_name, gids, ngroups_max, 1);
 222  227  
 223  228          if (num == -1) {
 224  229                  syslog(LOG_ERR, "smb_logon: unable "
 225  230                      "to get user's supplementary groups");
 226  231                  num = 1;
 227  232          }
 228  233  
 229  234          pgrps = (smb_posix_grps_t *)malloc(SMB_POSIX_GRPS_SIZE(num));
 230  235          if (pgrps) {
 231  236                  pgrps->pg_ngrps = num;
 232  237                  bcopy(gids, pgrps->pg_grps, num * sizeof (gid_t));
 233  238          }
 234  239  
 235  240          free(gids);
 236  241          return (pgrps);
 237  242  }
 238  243  
 239  244  /*
 240  245   * smb_token_destroy
 241  246   *
 242  247   * Release all of the memory associated with a token structure. Ensure
 243  248   * that the token has been unlinked before calling.
 244  249   */
 245  250  void
 246  251  smb_token_destroy(smb_token_t *token)
 247  252  {
 248  253          if (token != NULL) {
 249  254                  smb_sid_free(token->tkn_user.i_sid);
 250  255                  smb_sid_free(token->tkn_owner.i_sid);
 251  256                  smb_sid_free(token->tkn_primary_grp.i_sid);
 252  257                  smb_ids_free(&token->tkn_win_grps);
 253  258                  smb_privset_free(token->tkn_privileges);
 254  259                  free(token->tkn_posix_grps);
 255  260                  free(token->tkn_account_name);
 256  261                  free(token->tkn_domain_name);
 257  262                  free(token->tkn_ssnkey.val);
 258  263                  bzero(token, sizeof (smb_token_t));
 259  264                  free(token);
 260  265          }
 261  266  }
 262  267  
 263  268  /*
 264  269   * Token owner should be set to local Administrators group
 265  270   * in two cases:
 266  271   *   1. The logged on user is a member of Domain Admins group
 267  272   *   2. They are a member of local Administrators group
 268  273   */
 269  274  static void
 270  275  smb_token_set_owner(smb_token_t *token)
 271  276  {
 272  277  #ifdef SMB_SUPPORT_GROUP_OWNER
 273  278          smb_sid_t *owner_sid;
 274  279  
 275  280          if (token->tkn_flags & SMB_ATF_ADMIN) {
 276  281                  owner_sid = smb_wka_get_sid("Administrators");
 277  282                  assert(owner_sid);
 278  283          } else {
 279  284                  owner_sid = token->tkn_user->i_sid;
 280  285          }
 281  286  
 282  287          token->tkn_owner.i_sid = smb_sid_dup(owner_sid);
 283  288  #endif
 284  289          token->tkn_owner.i_sid = smb_sid_dup(token->tkn_user.i_sid);
 285  290  }
 286  291  
 287  292  static smb_privset_t *
 288  293  smb_token_create_privs(smb_token_t *token)
 289  294  {
 290  295          smb_privset_t *privs;
 291  296          smb_giter_t gi;
 292  297          smb_group_t grp;
 293  298          int rc;
 294  299  
 295  300          privs = smb_privset_new();
 296  301          if (privs == NULL)
 297  302                  return (NULL);
 298  303  
 299  304          if (smb_lgrp_iteropen(&gi) != SMB_LGRP_SUCCESS) {
 300  305                  smb_privset_free(privs);
 301  306                  return (NULL);
 302  307          }
 303  308  
 304  309          while (smb_lgrp_iterate(&gi, &grp) == SMB_LGRP_SUCCESS) {
 305  310                  if (smb_lgrp_is_member(&grp, token->tkn_user.i_sid))
 306  311                          smb_privset_merge(privs, grp.sg_privs);
 307  312                  smb_lgrp_free(&grp);
 308  313          }
 309  314          smb_lgrp_iterclose(&gi);
 310  315  
 311  316          if (token->tkn_flags & SMB_ATF_ADMIN) {
 312  317                  char admgrp[] = "Administrators";
 313  318  
 314  319                  rc = smb_lgrp_getbyname(admgrp, &grp);
 315  320                  if (rc == SMB_LGRP_SUCCESS) {
  
    | 
      ↓ open down ↓ | 
    154 lines elided | 
    
      ↑ open up ↑ | 
  
 316  321                          smb_privset_merge(privs, grp.sg_privs);
 317  322                          smb_lgrp_free(&grp);
 318  323                  }
 319  324  
 320  325                  /*
 321  326                   * This privilege is required to view/edit SACL
 322  327                   */
 323  328                  smb_privset_enable(privs, SE_SECURITY_LUID);
 324  329          }
 325  330  
      331 +        /*
      332 +         * Members of "Authenticated Users" (!anon) should normally get
      333 +         * "Bypass traverse checking" privilege, though we allow this
      334 +         * to be disabled (see smb.4).  For historical reasons, the
      335 +         * internal privilege name is "SeChangeNotifyPrivilege".
      336 +         */
      337 +        if ((token->tkn_flags & SMB_ATF_ANON) == 0 &&
      338 +            smb_config_getbool(SMB_CI_BYPASS_TRAVERSE_CHECKING))
      339 +                smb_privset_enable(privs, SE_CHANGE_NOTIFY_LUID);
      340 +
 326  341          return (privs);
 327  342  }
 328  343  
 329  344  static void
 330  345  smb_token_set_flags(smb_token_t *token)
 331  346  {
 332  347          if (smb_token_is_member(token, smb_wka_get_sid("Administrators")))
 333  348                  token->tkn_flags |= SMB_ATF_ADMIN;
 334  349  
 335  350          if (smb_token_is_member(token, smb_wka_get_sid("Power Users")))
 336  351                  token->tkn_flags |= SMB_ATF_POWERUSER;
 337  352  
 338  353          if (smb_token_is_member(token, smb_wka_get_sid("Backup Operators")))
 339  354                  token->tkn_flags |= SMB_ATF_BACKUPOP;
 340  355  }
 341  356  
 342  357  /*
 343  358   * Common token setup for both local and domain users.
 344  359   * This function must be called after the initial setup
 345  360   * has been done.
 346  361   *
 347  362   * Note that the order of calls in this function are important.
 348  363   *
 349  364   * Returns B_TRUE for success.
 350  365   */
 351  366  boolean_t
 352  367  smb_token_setup_common(smb_token_t *token)
 353  368  {
 354  369          smb_token_set_flags(token);
 355  370  
 356  371          smb_token_set_owner(token);
 357  372          if (token->tkn_owner.i_sid == NULL)
 358  373                  return (B_FALSE);
 359  374  
 360  375          /* Privileges */
 361  376          token->tkn_privileges = smb_token_create_privs(token);
 362  377          if (token->tkn_privileges == NULL)
 363  378                  return (B_FALSE);
 364  379  
 365  380          if (smb_token_sids2ids(token) != 0) {
 366  381                  syslog(LOG_ERR, "%s\\%s: idmap failed",
 367  382                      token->tkn_domain_name, token->tkn_account_name);
 368  383                  return (B_FALSE);
 369  384          }
 370  385  
 371  386          /* Solaris Groups */
 372  387          token->tkn_posix_grps = smb_token_create_pxgrps(token->tkn_user.i_id);
 373  388  
 374  389          return (smb_token_valid(token));
 375  390  }
 376  391  
 377  392  uint32_t
 378  393  smb_logon_init(void)
 379  394  {
 380  395          uint32_t status;
 381  396  
 382  397          (void) rw_wrlock(&smb_logoninit_rwl);
 383  398          status = smb_sam_lookup_name(NULL, "guest", SidTypeUser, &smb_guest);
 384  399          if (status != NT_STATUS_SUCCESS) {
 385  400                  (void) rw_unlock(&smb_logoninit_rwl);
 386  401                  return (status);
 387  402          }
 388  403  
 389  404          status = smb_sam_lookup_name(NULL, "domain users", SidTypeGroup,
 390  405              &smb_domusers);
 391  406          if (status != NT_STATUS_SUCCESS) {
 392  407                  smb_account_free(&smb_guest);
 393  408                  bzero(&smb_guest, sizeof (smb_account_t));
 394  409                  (void) rw_unlock(&smb_logoninit_rwl);
 395  410                  return (status);
 396  411          }
 397  412  
 398  413          (void) rw_unlock(&smb_logoninit_rwl);
 399  414          return (status);
 400  415  }
 401  416  
 402  417  void
 403  418  smb_logon_fini(void)
 404  419  {
 405  420          (void) rw_wrlock(&smb_logoninit_rwl);
 406  421          smb_account_free(&smb_guest);
 407  422          smb_account_free(&smb_domusers);
 408  423          bzero(&smb_guest, sizeof (smb_account_t));
 409  424          bzero(&smb_domusers, sizeof (smb_account_t));
  
    | 
      ↓ open down ↓ | 
    74 lines elided | 
    
      ↑ open up ↑ | 
  
 410  425          (void) rw_unlock(&smb_logoninit_rwl);
 411  426  }
 412  427  
 413  428  /*
 414  429   * Perform user authentication.
 415  430   *
 416  431   * The dispatched functions must only update the user_info status if they
 417  432   * attempt to authenticate the user.
 418  433   *
 419  434   * On success, a pointer to a new access token is returned.
      435 + * On failure, NULL return and status in user_info->lg_status
 420  436   */
 421  437  smb_token_t *
 422  438  smb_logon(smb_logon_t *user_info)
 423  439  {
 424  440          static smb_logonop_t    ops[] = {
 425  441                  smb_logon_anon,
 426  442                  smb_logon_local,
 427  443                  smb_logon_domain,
 428  444                  smb_logon_guest
 429  445          };
 430  446          smb_token_t             *token = NULL;
 431  447          smb_domain_t            domain;
 432  448          int                     n_op = (sizeof (ops) / sizeof (ops[0]));
 433  449          int                     i;
 434  450  
 435  451          user_info->lg_secmode = smb_config_get_secmode();
 436      -        user_info->lg_status = NT_STATUS_NO_SUCH_USER;
 437  452  
 438  453          if (smb_domain_lookup_name(user_info->lg_e_domain, &domain))
 439  454                  user_info->lg_domain_type = domain.di_type;
 440  455          else
 441  456                  user_info->lg_domain_type = SMB_DOMAIN_NULL;
 442  457  
 443  458          if ((token = calloc(1, sizeof (smb_token_t))) == NULL) {
 444  459                  syslog(LOG_ERR, "logon[%s\\%s]: %m",
 445  460                      user_info->lg_e_domain, user_info->lg_e_username);
 446  461                  return (NULL);
 447  462          }
 448  463  
      464 +        /*
      465 +         * If any logonop function takes significant action
      466 +         * (logon or authoratative failure) it will change
      467 +         * this status field to something else.
      468 +         */
      469 +        user_info->lg_status = NT_STATUS_NO_SUCH_USER;
 449  470          for (i = 0; i < n_op; ++i) {
 450  471                  (*ops[i])(user_info, token);
 451  472  
 452  473                  if (user_info->lg_status == NT_STATUS_SUCCESS)
 453  474                          break;
 454  475          }
 455  476  
 456  477          if (user_info->lg_status == NT_STATUS_SUCCESS) {
 457  478                  if (smb_token_setup_common(token))
 458      -                        return (token);
      479 +                        return (token); /* success */
      480 +                /*
      481 +                 * (else) smb_token_setup_common failed, which usually
      482 +                 * means smb_token_sids2ids() failed to map some SIDs to
      483 +                 * Unix IDs.  This indicates an idmap config problem.
      484 +                 */
      485 +                user_info->lg_status = NT_STATUS_INTERNAL_ERROR;
 459  486          }
 460  487  
 461  488          smb_token_destroy(token);
      489 +
      490 +        /*
      491 +         * Any unknown user or bad password should result in
      492 +         * NT_STATUS_LOGON_FAILURE (so we don't give hints).
      493 +         */
      494 +        if (user_info->lg_status == NT_STATUS_NO_SUCH_USER ||
      495 +            user_info->lg_status == NT_STATUS_WRONG_PASSWORD)
      496 +                user_info->lg_status = NT_STATUS_LOGON_FAILURE;
      497 +
 462  498          return (NULL);
 463  499  }
 464  500  
 465  501  /*
 466  502   * If the user has an entry in the local database, attempt local authentication.
 467  503   *
 468  504   * In domain mode, we try to exclude domain accounts, which we do by only
 469  505   * accepting local or null (blank) domain names here.  Some clients (Mac OS)
 470  506   * don't always send the domain name.
 471  507   *
 472  508   * If we are not going to attempt authentication, this function must return
 473  509   * without updating the status.
 474  510   */
 475  511  static void
 476  512  smb_logon_local(smb_logon_t *user_info, smb_token_t *token)
 477  513  {
 478  514          char guest[SMB_USERNAME_MAXLEN];
 479  515          smb_passwd_t smbpw;
 480  516          uint32_t status;
 481  517  
 482  518          if (user_info->lg_secmode == SMB_SECMODE_DOMAIN) {
 483  519                  if ((user_info->lg_domain_type != SMB_DOMAIN_LOCAL) &&
 484  520                      (user_info->lg_domain_type != SMB_DOMAIN_NULL))
 485  521                          return;
 486  522          }
 487  523  
 488  524          /*
 489  525           * If the requested account name is "guest" (or whatever
 490  526           * our guest account is named) then don't handle it here.
 491  527           * Let this request fall through to smb_logon_guest().
 492  528           */
 493  529          smb_guest_account(guest, SMB_USERNAME_MAXLEN);
 494  530          if (smb_strcasecmp(guest, user_info->lg_e_username, 0) == 0)
 495  531                  return;
 496  532  
 497  533          status = smb_token_auth_local(user_info, token, &smbpw);
 498  534          if (status == NT_STATUS_SUCCESS)
 499  535                  status = smb_token_setup_local(&smbpw, token);
 500  536  
 501  537          user_info->lg_status = status;
 502  538  }
 503  539  
 504  540  /*
 505  541   * Guest authentication.  This may be a local guest account or the guest
 506  542   * account may be mapped to a local account.  These accounts are regular
 507  543   * accounts with normal password protection.
 508  544   *
 509  545   * Only proceed with a guest logon if previous logon options have resulted
 510  546   * in NO_SUCH_USER.
 511  547   *
 512  548   * If we are not going to attempt authentication, this function must return
 513  549   * without updating the status.
 514  550   */
 515  551  static void
 516  552  smb_logon_guest(smb_logon_t *user_info, smb_token_t *token)
 517  553  {
 518  554          char guest[SMB_USERNAME_MAXLEN];
 519  555          smb_passwd_t smbpw;
 520  556          char *temp;
 521  557  
 522  558          if (user_info->lg_status != NT_STATUS_NO_SUCH_USER)
 523  559                  return;
 524  560  
 525  561          /* Get the name of the guest account. */
 526  562          smb_guest_account(guest, SMB_USERNAME_MAXLEN);
 527  563  
 528  564          /* Does the guest account exist? */
 529  565          if (smb_pwd_getpwnam(guest, &smbpw) == NULL)
 530  566                  return;
 531  567  
 532  568          /* Is it enabled? (empty p/w is OK) */
 533  569          if (smbpw.pw_flags & SMB_PWF_DISABLE)
 534  570                  return;
 535  571  
 536  572          /*
 537  573           * OK, give the client a guest logon.  Note that on entry,
 538  574           * lg_e_username is typically something other than "guest"
 539  575           * so we need to set the effective username when createing
 540  576           * the guest token.
 541  577           */
 542  578          temp = user_info->lg_e_username;
 543  579          user_info->lg_e_username = guest;
 544  580          user_info->lg_status = smb_token_setup_guest(user_info, token);
 545  581          user_info->lg_e_username = temp;
 546  582  }
 547  583  
 548  584  /*
 549  585   * If user_info represents an anonymous user then setup the token.
 550  586   * Otherwise return without updating the status.
 551  587   */
 552  588  static void
 553  589  smb_logon_anon(smb_logon_t *user_info, smb_token_t *token)
 554  590  {
 555  591          if (user_info->lg_flags & SMB_ATF_ANON)
 556  592                  user_info->lg_status = smb_token_setup_anon(token);
 557  593  }
 558  594  
 559  595  /*
 560  596   * Try both LM hash and NT hashes with user's password(s) to authenticate
 561  597   * the user.
 562  598   */
 563  599  static uint32_t
 564  600  smb_token_auth_local(smb_logon_t *user_info, smb_token_t *token,
 565  601      smb_passwd_t *smbpw)
 566  602  {
 567  603          boolean_t ok;
 568  604          uint32_t status = NT_STATUS_SUCCESS;
 569  605  
 570  606          if (smb_pwd_getpwnam(user_info->lg_e_username, smbpw) == NULL)
 571  607                  return (NT_STATUS_NO_SUCH_USER);
 572  608  
 573  609          if (smbpw->pw_flags & SMB_PWF_DISABLE)
 574  610                  return (NT_STATUS_ACCOUNT_DISABLED);
 575  611  
 576  612          if ((smbpw->pw_flags & (SMB_PWF_LM | SMB_PWF_NT)) == 0) {
 577  613                  /*
 578  614                   * The SMB passwords have not been set.
 579  615                   * Return an error that suggests the
 580  616                   * password needs to be set.
 581  617                   */
 582  618                  return (NT_STATUS_PASSWORD_EXPIRED);
 583  619          }
 584  620  
 585  621          token->tkn_ssnkey.val = malloc(SMBAUTH_SESSION_KEY_SZ);
 586  622          if (token->tkn_ssnkey.val == NULL)
 587  623                  return (NT_STATUS_NO_MEMORY);
 588  624          token->tkn_ssnkey.len = SMBAUTH_SESSION_KEY_SZ;
 589  625  
 590  626          ok = smb_auth_validate(
 591  627              smbpw,
 592  628              user_info->lg_domain,
 593  629              user_info->lg_username,
 594  630              user_info->lg_challenge_key.val,
 595  631              user_info->lg_challenge_key.len,
 596  632              user_info->lg_nt_password.val,
 597  633              user_info->lg_nt_password.len,
 598  634              user_info->lg_lm_password.val,
 599  635              user_info->lg_lm_password.len,
 600  636              token->tkn_ssnkey.val);
 601  637          if (ok)
 602  638                  return (NT_STATUS_SUCCESS);
 603  639  
 604  640          free(token->tkn_ssnkey.val);
 605  641          token->tkn_ssnkey.val = NULL;
 606  642          token->tkn_ssnkey.len = 0;
 607  643  
 608  644          status = NT_STATUS_WRONG_PASSWORD;
 609  645          syslog(LOG_NOTICE, "logon[%s\\%s]: %s",
 610  646              user_info->lg_e_domain, user_info->lg_e_username,
 611  647              xlate_nt_status(status));
 612  648  
 613  649          return (status);
 614  650  }
 615  651  
 616  652  /*
 617  653   * Setup an access token for the specified local user.
 618  654   */
 619  655  static uint32_t
 620  656  smb_token_setup_local(smb_passwd_t *smbpw, smb_token_t *token)
 621  657  {
 622  658          idmap_stat stat;
 623  659          smb_idmap_batch_t sib;
 624  660          smb_idmap_t *umap, *gmap;
 625  661          struct passwd pw;
 626  662          char pwbuf[1024];
 627  663          char nbname[NETBIOS_NAME_SZ];
 628  664  
 629  665          (void) smb_getnetbiosname(nbname, sizeof (nbname));
 630  666          token->tkn_account_name = strdup(smbpw->pw_name);
 631  667          token->tkn_domain_name = strdup(nbname);
 632  668  
 633  669          if (token->tkn_account_name == NULL ||
 634  670              token->tkn_domain_name == NULL)
 635  671                  return (NT_STATUS_NO_MEMORY);
 636  672  
 637  673          if (getpwuid_r(smbpw->pw_uid, &pw, pwbuf, sizeof (pwbuf)) == NULL)
 638  674                  return (NT_STATUS_NO_SUCH_USER);
 639  675  
 640  676          /* Get the SID for user's uid & gid */
 641  677          stat = smb_idmap_batch_create(&sib, 2, SMB_IDMAP_ID2SID);
 642  678          if (stat != IDMAP_SUCCESS)
 643  679                  return (NT_STATUS_INTERNAL_ERROR);
 644  680  
 645  681          umap = &sib.sib_maps[0];
 646  682          stat = smb_idmap_batch_getsid(sib.sib_idmaph, umap, pw.pw_uid,
 647  683              SMB_IDMAP_USER);
 648  684  
 649  685          if (stat != IDMAP_SUCCESS) {
 650  686                  smb_idmap_batch_destroy(&sib);
 651  687                  return (NT_STATUS_INTERNAL_ERROR);
 652  688          }
 653  689  
 654  690          gmap = &sib.sib_maps[1];
 655  691          stat = smb_idmap_batch_getsid(sib.sib_idmaph, gmap, pw.pw_gid,
 656  692              SMB_IDMAP_GROUP);
 657  693  
 658  694          if (stat != IDMAP_SUCCESS) {
 659  695                  smb_idmap_batch_destroy(&sib);
 660  696                  return (NT_STATUS_INTERNAL_ERROR);
 661  697          }
 662  698  
 663  699          if (smb_idmap_batch_getmappings(&sib) != IDMAP_SUCCESS)
 664  700                  return (NT_STATUS_INTERNAL_ERROR);
 665  701  
 666  702          token->tkn_user.i_sid = smb_sid_dup(umap->sim_sid);
 667  703          token->tkn_primary_grp.i_sid = smb_sid_dup(gmap->sim_sid);
 668  704  
 669  705          smb_idmap_batch_destroy(&sib);
 670  706  
 671  707          if (token->tkn_user.i_sid == NULL ||
 672  708              token->tkn_primary_grp.i_sid == NULL)
 673  709                  return (NT_STATUS_NO_MEMORY);
 674  710  
 675  711          return (smb_token_setup_wingrps(token));
 676  712  }
 677  713  
 678  714  /*
 679  715   * Setup access token for guest connections
 680  716   */
 681  717  static uint32_t
 682  718  smb_token_setup_guest(smb_logon_t *user_info, smb_token_t *token)
 683  719  {
 684  720          token->tkn_account_name = strdup(user_info->lg_e_username);
 685  721  
 686  722          (void) rw_rdlock(&smb_logoninit_rwl);
 687  723          token->tkn_domain_name = strdup(smb_guest.a_domain);
 688  724          token->tkn_user.i_sid = smb_sid_dup(smb_guest.a_sid);
 689  725          token->tkn_primary_grp.i_sid = smb_sid_dup(smb_domusers.a_sid);
 690  726          (void) rw_unlock(&smb_logoninit_rwl);
 691  727          token->tkn_flags = SMB_ATF_GUEST;
 692  728  
 693  729          if (token->tkn_account_name == NULL ||
 694  730              token->tkn_domain_name == NULL ||
 695  731              token->tkn_user.i_sid == NULL ||
 696  732              token->tkn_primary_grp.i_sid == NULL)
 697  733                  return (NT_STATUS_NO_MEMORY);
 698  734  
 699  735          return (smb_token_setup_wingrps(token));
 700  736  }
 701  737  
 702  738  /*
 703  739   * Setup access token for anonymous connections
 704  740   */
 705  741  static uint32_t
 706  742  smb_token_setup_anon(smb_token_t *token)
 707  743  {
 708  744          smb_sid_t *user_sid;
 709  745  
 710  746          token->tkn_account_name = strdup("Anonymous");
 711  747          token->tkn_domain_name = strdup("NT Authority");
 712  748          user_sid = smb_wka_get_sid("Anonymous");
 713  749          token->tkn_user.i_sid = smb_sid_dup(user_sid);
 714  750          token->tkn_primary_grp.i_sid = smb_sid_dup(user_sid);
 715  751          token->tkn_flags = SMB_ATF_ANON;
 716  752  
 717  753          if (token->tkn_account_name == NULL ||
 718  754              token->tkn_domain_name == NULL ||
 719  755              token->tkn_user.i_sid == NULL ||
 720  756              token->tkn_primary_grp.i_sid == NULL)
 721  757                  return (NT_STATUS_NO_MEMORY);
 722  758  
 723  759          return (smb_token_setup_wingrps(token));
 724  760  }
 725  761  
 726  762  /*
 727  763   * smb_token_user_sid
 728  764   *
 729  765   * Return a pointer to the user SID in the specified token. A null
 730  766   * pointer indicates an error.
 731  767   */
 732  768  static smb_sid_t *
 733  769  smb_token_user_sid(smb_token_t *token)
 734  770  {
 735  771          return ((token) ? token->tkn_user.i_sid : NULL);
 736  772  }
 737  773  
 738  774  /*
 739  775   * smb_token_group_sid
 740  776   *
 741  777   * Return a pointer to the group SID as indicated by the iterator.
 742  778   * Setting the iterator to 0 before calling this function will return
 743  779   * the first group, which will always be the primary group. The
 744  780   * iterator will be incremented before returning the SID so that this
 745  781   * function can be used to cycle through the groups. The caller can
 746  782   * adjust the iterator as required between calls to obtain any specific
 747  783   * group.
 748  784   *
 749  785   * On success a pointer to the appropriate group SID will be returned.
 750  786   * Otherwise a null pointer will be returned.
 751  787   */
 752  788  static smb_sid_t *
 753  789  smb_token_group_sid(smb_token_t *token, int *iterator)
 754  790  {
 755  791          int index;
 756  792  
 757  793          if (token == NULL || iterator == NULL)
 758  794                  return (NULL);
 759  795  
 760  796          if (token->tkn_win_grps.i_ids == NULL)
 761  797                  return (NULL);
 762  798  
 763  799          index = *iterator;
 764  800  
 765  801          if (index < 0 || index >= token->tkn_win_grps.i_cnt)
 766  802                  return (NULL);
 767  803  
 768  804          ++(*iterator);
 769  805          return (token->tkn_win_grps.i_ids[index].i_sid);
 770  806  }
 771  807  
 772  808  /*
 773  809   * smb_token_is_member
 774  810   *
 775  811   * This function will determine whether or not the specified SID is a
 776  812   * member of a token. The user SID and all group SIDs are tested.
 777  813   * Returns 1 if the SID is a member of the token. Otherwise returns 0.
 778  814   */
 779  815  static boolean_t
 780  816  smb_token_is_member(smb_token_t *token, smb_sid_t *sid)
 781  817  {
 782  818          smb_sid_t *tsid;
 783  819          int iterator = 0;
 784  820  
 785  821          if (token == NULL || sid == NULL)
 786  822                  return (B_FALSE);
 787  823  
 788  824          tsid = smb_token_user_sid(token);
 789  825          while (tsid) {
 790  826                  if (smb_sid_cmp(tsid, sid))
 791  827                          return (B_TRUE);
 792  828  
 793  829                  tsid = smb_token_group_sid(token, &iterator);
 794  830          }
 795  831  
 796  832          return (B_FALSE);
 797  833  }
 798  834  
 799  835  /*
 800  836   * smb_token_log
 801  837   *
 802  838   * Diagnostic routine to write the contents of a token to the log.
 803  839   */
 804  840  void
 805  841  smb_token_log(smb_token_t *token)
 806  842  {
 807  843          smb_ids_t *w_grps;
 808  844          smb_id_t *grp;
 809  845          smb_posix_grps_t *x_grps;
 810  846          char sidstr[SMB_SID_STRSZ];
 811  847          int i;
 812  848  
 813  849          if (token == NULL)
 814  850                  return;
 815  851  
 816  852          syslog(LOG_DEBUG, "Token for %s\\%s",
 817  853              (token->tkn_domain_name) ? token->tkn_domain_name : "-NULL-",
 818  854              (token->tkn_account_name) ? token->tkn_account_name : "-NULL-");
 819  855  
 820  856          syslog(LOG_DEBUG, "   User->Attr: %d", token->tkn_user.i_attrs);
 821  857          smb_sid_tostr((smb_sid_t *)token->tkn_user.i_sid, sidstr);
 822  858          syslog(LOG_DEBUG, "   User->Sid: %s (id=%u)", sidstr,
 823  859              token->tkn_user.i_id);
 824  860  
 825  861          smb_sid_tostr((smb_sid_t *)token->tkn_owner.i_sid, sidstr);
 826  862          syslog(LOG_DEBUG, "   Ownr->Sid: %s (id=%u)",
 827  863              sidstr, token->tkn_owner.i_id);
 828  864  
 829  865          smb_sid_tostr((smb_sid_t *)token->tkn_primary_grp.i_sid, sidstr);
 830  866          syslog(LOG_DEBUG, "   PGrp->Sid: %s (id=%u)",
 831  867              sidstr, token->tkn_primary_grp.i_id);
 832  868  
 833  869          w_grps = &token->tkn_win_grps;
 834  870          if (w_grps->i_ids) {
 835  871                  syslog(LOG_DEBUG, "   Windows groups: %d", w_grps->i_cnt);
 836  872                  grp = w_grps->i_ids;
 837  873                  for (i = 0; i < w_grps->i_cnt; ++i, grp++) {
 838  874                          syslog(LOG_DEBUG,
 839  875                              "    Grp[%d].Attr:%d", i, grp->i_attrs);
 840  876                          if (grp->i_sid != NULL) {
 841  877                                  smb_sid_tostr((smb_sid_t *)grp->i_sid, sidstr);
 842  878                                  syslog(LOG_DEBUG,
 843  879                                      "    Grp[%d].Sid: %s (id=%u)", i, sidstr,
 844  880                                      grp->i_id);
 845  881                          }
 846  882                  }
 847  883          } else {
 848  884                  syslog(LOG_DEBUG, "   No Windows groups");
 849  885          }
 850  886  
 851  887          x_grps = token->tkn_posix_grps;
 852  888          if (x_grps) {
 853  889                  syslog(LOG_DEBUG, "   Solaris groups: %d", x_grps->pg_ngrps);
 854  890                  for (i = 0; i < x_grps->pg_ngrps; i++)
 855  891                          syslog(LOG_DEBUG, "    %u", x_grps->pg_grps[i]);
 856  892          } else {
 857  893                  syslog(LOG_DEBUG, "   No Solaris groups");
 858  894          }
 859  895  
 860  896          if (token->tkn_privileges)
 861  897                  smb_privset_log(token->tkn_privileges);
 862  898          else
 863  899                  syslog(LOG_DEBUG, "   No privileges");
 864  900  }
 865  901  
 866  902  /*
 867  903   * Sets up local and well-known group membership for the given
 868  904   * token. Two assumptions have been made here:
 869  905   *
 870  906   *   a) token already contains a valid user SID so that group
 871  907   *      memberships can be established
 872  908   *
 873  909   *   b) token belongs to a local or anonymous user
 874  910   */
 875  911  static uint32_t
 876  912  smb_token_setup_wingrps(smb_token_t *token)
 877  913  {
 878  914          smb_ids_t tkn_grps;
 879  915          uint32_t status;
 880  916  
 881  917  
 882  918          /*
 883  919           * We always want the user's primary group in the list
 884  920           * of groups.
 885  921           */
 886  922          tkn_grps.i_cnt = 1;
 887  923          if ((tkn_grps.i_ids = malloc(sizeof (smb_id_t))) == NULL)
 888  924                  return (NT_STATUS_NO_MEMORY);
 889  925  
 890  926          tkn_grps.i_ids->i_sid = smb_sid_dup(token->tkn_primary_grp.i_sid);
 891  927          tkn_grps.i_ids->i_attrs = token->tkn_primary_grp.i_attrs;
 892  928          if (tkn_grps.i_ids->i_sid == NULL) {
 893  929                  smb_ids_free(&tkn_grps);
 894  930                  return (NT_STATUS_NO_MEMORY);
 895  931          }
 896  932  
 897  933          status = smb_sam_usr_groups(token->tkn_user.i_sid, &tkn_grps);
 898  934          if (status != NT_STATUS_SUCCESS) {
 899  935                  smb_ids_free(&tkn_grps);
 900  936                  return (status);
 901  937          }
 902  938  
 903  939          status = smb_wka_token_groups(token->tkn_flags, &tkn_grps);
 904  940          if (status != NT_STATUS_SUCCESS) {
 905  941                  smb_ids_free(&tkn_grps);
 906  942                  return (status);
 907  943          }
 908  944  
 909  945          token->tkn_win_grps = tkn_grps;
 910  946          return (status);
 911  947  }
 912  948  
 913  949  /*
 914  950   * Returns the guest account name in the provided buffer.
 915  951   *
 916  952   * By default the name would be "guest" unless there's
 917  953   * a idmap name-based rule which maps the guest to a local
 918  954   * Solaris user in which case the name of that user is
 919  955   * returned.
 920  956   */
 921  957  static void
 922  958  smb_guest_account(char *guest, size_t buflen)
 923  959  {
 924  960          idmap_stat stat;
 925  961          uid_t guest_uid;
 926  962          struct passwd pw;
 927  963          char pwbuf[1024];
 928  964          int idtype;
 929  965  
 930  966          /* default Guest account name */
 931  967          (void) rw_rdlock(&smb_logoninit_rwl);
 932  968          (void) strlcpy(guest, smb_guest.a_name, buflen);
 933  969  
 934  970          idtype = SMB_IDMAP_USER;
 935  971          stat = smb_idmap_getid(smb_guest.a_sid, &guest_uid, &idtype);
 936  972          (void) rw_unlock(&smb_logoninit_rwl);
 937  973  
 938  974          if (stat != IDMAP_SUCCESS)
 939  975                  return;
 940  976  
 941  977          /* If Ephemeral ID return the default name */
 942  978          if (IDMAP_ID_IS_EPHEMERAL(guest_uid))
 943  979                  return;
 944  980  
 945  981          if (getpwuid_r(guest_uid, &pw, pwbuf, sizeof (pwbuf)) == NULL)
 946  982                  return;
 947  983  
 948  984          (void) strlcpy(guest, pw.pw_name, buflen);
 949  985  }
  
    | 
      ↓ open down ↓ | 
    478 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX