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


   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
  24  * Copyright (c) 2016 by Delphix. All rights reserved.

  25  */
  26 
  27 #include <unistd.h>
  28 #include <strings.h>
  29 #include <pwd.h>
  30 #include <grp.h>
  31 #include <time.h>
  32 #include <syslog.h>
  33 #include <assert.h>
  34 #include <synch.h>
  35 
  36 #include <smbsrv/libsmb.h>
  37 #include <smbsrv/libmlsvc.h>
  38 
  39 #include <smbsrv/smbinfo.h>
  40 #include <smbsrv/smb_token.h>
  41 #include <lsalib.h>
  42 
  43 static smb_account_t smb_guest;
  44 static smb_account_t smb_domusers;


 112                 return (stat);
 113 
 114         /* Other Windows Group SIDs */
 115         for (i = 0; i < token->tkn_win_grps.i_cnt; i++, sim++) {
 116                 id = &token->tkn_win_grps.i_ids[i];
 117                 sim->sim_id = &id->i_id;
 118                 stat = smb_idmap_batch_getid(sib->sib_idmaph, sim,
 119                     id->i_sid, SMB_IDMAP_GROUP);
 120 
 121                 if (stat != IDMAP_SUCCESS)
 122                         break;
 123         }
 124 
 125         return (stat);
 126 }
 127 
 128 /*
 129  * smb_token_sids2ids
 130  *
 131  * This will map all the SIDs of the access token to UIDs/GIDs.




 132  *
 133  * Returns 0 upon success.  Otherwise, returns -1.
 134  */
 135 static int
 136 smb_token_sids2ids(smb_token_t *token)
 137 {
 138         idmap_stat stat;
 139         int nmaps;
 140         smb_idmap_batch_t sib;
 141 
 142         /*
 143          * Number of idmap lookups: user SID, owner SID, primary group SID,
 144          * and all Windows group SIDs. Skip user/owner SID for Anonymous.
 145          */
 146         if (token->tkn_flags & SMB_ATF_ANON)
 147                 nmaps = token->tkn_win_grps.i_cnt + 1;
 148         else
 149                 nmaps = token->tkn_win_grps.i_cnt + 3;
 150 
 151         stat = smb_idmap_batch_create(&sib, nmaps, SMB_IDMAP_SID2ID);

 152         if (stat != IDMAP_SUCCESS)
 153                 return (-1);
 154 
 155         stat = smb_token_idmap(token, &sib);
 156         if (stat != IDMAP_SUCCESS) {
 157                 smb_idmap_batch_destroy(&sib);
 158                 return (-1);
 159         }
 160 
 161         stat = smb_idmap_batch_getmappings(&sib);
 162         smb_idmap_check("smb_idmap_batch_getmappings", stat);
 163         smb_idmap_batch_destroy(&sib);
 164 
 165         return (stat == IDMAP_SUCCESS ? 0 : -1);
 166 }
 167 
 168 /*
 169  * smb_token_create_pxgrps
 170  *
 171  * Setup the POSIX group membership of the access token if the given UID is


 306                         smb_privset_merge(privs, grp.sg_privs);
 307                 smb_lgrp_free(&grp);
 308         }
 309         smb_lgrp_iterclose(&gi);
 310 
 311         if (token->tkn_flags & SMB_ATF_ADMIN) {
 312                 char admgrp[] = "Administrators";
 313 
 314                 rc = smb_lgrp_getbyname(admgrp, &grp);
 315                 if (rc == SMB_LGRP_SUCCESS) {
 316                         smb_privset_merge(privs, grp.sg_privs);
 317                         smb_lgrp_free(&grp);
 318                 }
 319 
 320                 /*
 321                  * This privilege is required to view/edit SACL
 322                  */
 323                 smb_privset_enable(privs, SE_SECURITY_LUID);
 324         }
 325 










 326         return (privs);
 327 }
 328 
 329 static void
 330 smb_token_set_flags(smb_token_t *token)
 331 {
 332         if (smb_token_is_member(token, smb_wka_get_sid("Administrators")))
 333                 token->tkn_flags |= SMB_ATF_ADMIN;
 334 
 335         if (smb_token_is_member(token, smb_wka_get_sid("Power Users")))
 336                 token->tkn_flags |= SMB_ATF_POWERUSER;
 337 
 338         if (smb_token_is_member(token, smb_wka_get_sid("Backup Operators")))
 339                 token->tkn_flags |= SMB_ATF_BACKUPOP;
 340 }
 341 
 342 /*
 343  * Common token setup for both local and domain users.
 344  * This function must be called after the initial setup
 345  * has been done.


 400 }
 401 
 402 void
 403 smb_logon_fini(void)
 404 {
 405         (void) rw_wrlock(&smb_logoninit_rwl);
 406         smb_account_free(&smb_guest);
 407         smb_account_free(&smb_domusers);
 408         bzero(&smb_guest, sizeof (smb_account_t));
 409         bzero(&smb_domusers, sizeof (smb_account_t));
 410         (void) rw_unlock(&smb_logoninit_rwl);
 411 }
 412 
 413 /*
 414  * Perform user authentication.
 415  *
 416  * The dispatched functions must only update the user_info status if they
 417  * attempt to authenticate the user.
 418  *
 419  * On success, a pointer to a new access token is returned.

 420  */
 421 smb_token_t *
 422 smb_logon(smb_logon_t *user_info)
 423 {
 424         static smb_logonop_t    ops[] = {
 425                 smb_logon_anon,
 426                 smb_logon_local,
 427                 smb_logon_domain,
 428                 smb_logon_guest
 429         };
 430         smb_token_t             *token = NULL;
 431         smb_domain_t            domain;
 432         int                     n_op = (sizeof (ops) / sizeof (ops[0]));
 433         int                     i;
 434 
 435         user_info->lg_secmode = smb_config_get_secmode();
 436         user_info->lg_status = NT_STATUS_NO_SUCH_USER;
 437 
 438         if (smb_domain_lookup_name(user_info->lg_e_domain, &domain))
 439                 user_info->lg_domain_type = domain.di_type;
 440         else
 441                 user_info->lg_domain_type = SMB_DOMAIN_NULL;
 442 
 443         if ((token = calloc(1, sizeof (smb_token_t))) == NULL) {
 444                 syslog(LOG_ERR, "logon[%s\\%s]: %m",
 445                     user_info->lg_e_domain, user_info->lg_e_username);
 446                 return (NULL);
 447         }
 448 






 449         for (i = 0; i < n_op; ++i) {
 450                 (*ops[i])(user_info, token);
 451 
 452                 if (user_info->lg_status == NT_STATUS_SUCCESS)
 453                         break;
 454         }
 455 
 456         if (user_info->lg_status == NT_STATUS_SUCCESS) {
 457                 if (smb_token_setup_common(token))
 458                         return (token);






 459         }
 460 
 461         smb_token_destroy(token);









 462         return (NULL);
 463 }
 464 
 465 /*
 466  * If the user has an entry in the local database, attempt local authentication.
 467  *
 468  * In domain mode, we try to exclude domain accounts, which we do by only
 469  * accepting local or null (blank) domain names here.  Some clients (Mac OS)
 470  * don't always send the domain name.
 471  *
 472  * If we are not going to attempt authentication, this function must return
 473  * without updating the status.
 474  */
 475 static void
 476 smb_logon_local(smb_logon_t *user_info, smb_token_t *token)
 477 {
 478         char guest[SMB_USERNAME_MAXLEN];
 479         smb_passwd_t smbpw;
 480         uint32_t status;
 481 




   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.

  23  * Copyright (c) 2016 by Delphix. All rights reserved.
  24  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  25  */
  26 
  27 #include <unistd.h>
  28 #include <strings.h>
  29 #include <pwd.h>
  30 #include <grp.h>
  31 #include <time.h>
  32 #include <syslog.h>
  33 #include <assert.h>
  34 #include <synch.h>
  35 
  36 #include <smbsrv/libsmb.h>
  37 #include <smbsrv/libmlsvc.h>
  38 
  39 #include <smbsrv/smbinfo.h>
  40 #include <smbsrv/smb_token.h>
  41 #include <lsalib.h>
  42 
  43 static smb_account_t smb_guest;
  44 static smb_account_t smb_domusers;


 112                 return (stat);
 113 
 114         /* Other Windows Group SIDs */
 115         for (i = 0; i < token->tkn_win_grps.i_cnt; i++, sim++) {
 116                 id = &token->tkn_win_grps.i_ids[i];
 117                 sim->sim_id = &id->i_id;
 118                 stat = smb_idmap_batch_getid(sib->sib_idmaph, sim,
 119                     id->i_sid, SMB_IDMAP_GROUP);
 120 
 121                 if (stat != IDMAP_SUCCESS)
 122                         break;
 123         }
 124 
 125         return (stat);
 126 }
 127 
 128 /*
 129  * smb_token_sids2ids
 130  *
 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.
 136  *
 137  * Returns 0 upon success.  Otherwise, returns -1.
 138  */
 139 static int
 140 smb_token_sids2ids(smb_token_t *token)
 141 {
 142         idmap_stat stat;
 143         int nmaps;
 144         smb_idmap_batch_t sib;
 145 
 146         /*
 147          * Number of idmap lookups: user SID, owner SID, primary group SID,
 148          * and all Windows group SIDs. Skip user/owner SID for Anonymous.
 149          */
 150         if (token->tkn_flags & SMB_ATF_ANON)
 151                 nmaps = token->tkn_win_grps.i_cnt + 1;
 152         else
 153                 nmaps = token->tkn_win_grps.i_cnt + 3;
 154 
 155         stat = smb_idmap_batch_create(&sib, nmaps,
 156             SMB_IDMAP_SID2ID | SMB_IDMAP_SKIP_ERRS);
 157         if (stat != IDMAP_SUCCESS)
 158                 return (-1);
 159 
 160         stat = smb_token_idmap(token, &sib);
 161         if (stat != IDMAP_SUCCESS) {
 162                 smb_idmap_batch_destroy(&sib);
 163                 return (-1);
 164         }
 165 
 166         stat = smb_idmap_batch_getmappings(&sib);
 167         smb_idmap_check("smb_idmap_batch_getmappings", stat);
 168         smb_idmap_batch_destroy(&sib);
 169 
 170         return (stat == IDMAP_SUCCESS ? 0 : -1);
 171 }
 172 
 173 /*
 174  * smb_token_create_pxgrps
 175  *
 176  * Setup the POSIX group membership of the access token if the given UID is


 311                         smb_privset_merge(privs, grp.sg_privs);
 312                 smb_lgrp_free(&grp);
 313         }
 314         smb_lgrp_iterclose(&gi);
 315 
 316         if (token->tkn_flags & SMB_ATF_ADMIN) {
 317                 char admgrp[] = "Administrators";
 318 
 319                 rc = smb_lgrp_getbyname(admgrp, &grp);
 320                 if (rc == SMB_LGRP_SUCCESS) {
 321                         smb_privset_merge(privs, grp.sg_privs);
 322                         smb_lgrp_free(&grp);
 323                 }
 324 
 325                 /*
 326                  * This privilege is required to view/edit SACL
 327                  */
 328                 smb_privset_enable(privs, SE_SECURITY_LUID);
 329         }
 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 
 341         return (privs);
 342 }
 343 
 344 static void
 345 smb_token_set_flags(smb_token_t *token)
 346 {
 347         if (smb_token_is_member(token, smb_wka_get_sid("Administrators")))
 348                 token->tkn_flags |= SMB_ATF_ADMIN;
 349 
 350         if (smb_token_is_member(token, smb_wka_get_sid("Power Users")))
 351                 token->tkn_flags |= SMB_ATF_POWERUSER;
 352 
 353         if (smb_token_is_member(token, smb_wka_get_sid("Backup Operators")))
 354                 token->tkn_flags |= SMB_ATF_BACKUPOP;
 355 }
 356 
 357 /*
 358  * Common token setup for both local and domain users.
 359  * This function must be called after the initial setup
 360  * has been done.


 415 }
 416 
 417 void
 418 smb_logon_fini(void)
 419 {
 420         (void) rw_wrlock(&smb_logoninit_rwl);
 421         smb_account_free(&smb_guest);
 422         smb_account_free(&smb_domusers);
 423         bzero(&smb_guest, sizeof (smb_account_t));
 424         bzero(&smb_domusers, sizeof (smb_account_t));
 425         (void) rw_unlock(&smb_logoninit_rwl);
 426 }
 427 
 428 /*
 429  * Perform user authentication.
 430  *
 431  * The dispatched functions must only update the user_info status if they
 432  * attempt to authenticate the user.
 433  *
 434  * On success, a pointer to a new access token is returned.
 435  * On failure, NULL return and status in user_info->lg_status
 436  */
 437 smb_token_t *
 438 smb_logon(smb_logon_t *user_info)
 439 {
 440         static smb_logonop_t    ops[] = {
 441                 smb_logon_anon,
 442                 smb_logon_local,
 443                 smb_logon_domain,
 444                 smb_logon_guest
 445         };
 446         smb_token_t             *token = NULL;
 447         smb_domain_t            domain;
 448         int                     n_op = (sizeof (ops) / sizeof (ops[0]));
 449         int                     i;
 450 
 451         user_info->lg_secmode = smb_config_get_secmode();

 452 
 453         if (smb_domain_lookup_name(user_info->lg_e_domain, &domain))
 454                 user_info->lg_domain_type = domain.di_type;
 455         else
 456                 user_info->lg_domain_type = SMB_DOMAIN_NULL;
 457 
 458         if ((token = calloc(1, sizeof (smb_token_t))) == NULL) {
 459                 syslog(LOG_ERR, "logon[%s\\%s]: %m",
 460                     user_info->lg_e_domain, user_info->lg_e_username);
 461                 return (NULL);
 462         }
 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;
 470         for (i = 0; i < n_op; ++i) {
 471                 (*ops[i])(user_info, token);
 472 
 473                 if (user_info->lg_status == NT_STATUS_SUCCESS)
 474                         break;
 475         }
 476 
 477         if (user_info->lg_status == NT_STATUS_SUCCESS) {
 478                 if (smb_token_setup_common(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;
 486         }
 487 
 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 
 498         return (NULL);
 499 }
 500 
 501 /*
 502  * If the user has an entry in the local database, attempt local authentication.
 503  *
 504  * In domain mode, we try to exclude domain accounts, which we do by only
 505  * accepting local or null (blank) domain names here.  Some clients (Mac OS)
 506  * don't always send the domain name.
 507  *
 508  * If we are not going to attempt authentication, this function must return
 509  * without updating the status.
 510  */
 511 static void
 512 smb_logon_local(smb_logon_t *user_info, smb_token_t *token)
 513 {
 514         char guest[SMB_USERNAME_MAXLEN];
 515         smb_passwd_t smbpw;
 516         uint32_t status;
 517