1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * 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;
  45 static rwlock_t smb_logoninit_rwl;
  46 
  47 typedef void (*smb_logonop_t)(smb_logon_t *, smb_token_t *);
  48 
  49 static void smb_logon_local(smb_logon_t *, smb_token_t *);
  50 static void smb_logon_guest(smb_logon_t *, smb_token_t *);
  51 static void smb_logon_anon(smb_logon_t *, smb_token_t *);
  52 
  53 static uint32_t smb_token_auth_local(smb_logon_t *, smb_token_t *,
  54     smb_passwd_t *);
  55 
  56 static uint32_t smb_token_setup_local(smb_passwd_t *, smb_token_t *);
  57 static uint32_t smb_token_setup_guest(smb_logon_t *, smb_token_t *);
  58 static uint32_t smb_token_setup_anon(smb_token_t *token);
  59 
  60 static boolean_t smb_token_is_member(smb_token_t *, smb_sid_t *);
  61 static uint32_t smb_token_setup_wingrps(smb_token_t *);
  62 static smb_posix_grps_t *smb_token_create_pxgrps(uid_t);
  63 
  64 static void smb_guest_account(char *, size_t);
  65 
  66 /* Consolidation private function from Network Repository */
  67 extern int _getgroupsbymember(const char *, gid_t[], int, int);
  68 
  69 static idmap_stat
  70 smb_token_idmap(smb_token_t *token, smb_idmap_batch_t *sib)
  71 {
  72         idmap_stat stat;
  73         smb_idmap_t *sim;
  74         smb_id_t *id;
  75         int i;
  76 
  77         if (!token || !sib)
  78                 return (IDMAP_ERR_ARG);
  79 
  80         sim = sib->sib_maps;
  81 
  82         if (token->tkn_flags & SMB_ATF_ANON) {
  83                 token->tkn_user.i_id = UID_NOBODY;
  84                 token->tkn_owner.i_id = UID_NOBODY;
  85         } else {
  86                 /* User SID */
  87                 id = &token->tkn_user;
  88                 sim->sim_id = &id->i_id;
  89                 stat = smb_idmap_batch_getid(sib->sib_idmaph, sim++,
  90                     id->i_sid, SMB_IDMAP_USER);
  91 
  92                 if (stat != IDMAP_SUCCESS)
  93                         return (stat);
  94 
  95                 /* Owner SID */
  96                 id = &token->tkn_owner;
  97                 sim->sim_id = &id->i_id;
  98                 stat = smb_idmap_batch_getid(sib->sib_idmaph, sim++,
  99                     id->i_sid, SMB_IDMAP_USER);
 100 
 101                 if (stat != IDMAP_SUCCESS)
 102                         return (stat);
 103         }
 104 
 105         /* Primary Group SID */
 106         id = &token->tkn_primary_grp;
 107         sim->sim_id = &id->i_id;
 108         stat = smb_idmap_batch_getid(sib->sib_idmaph, sim++, id->i_sid,
 109             SMB_IDMAP_GROUP);
 110 
 111         if (stat != IDMAP_SUCCESS)
 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
 177  * a POSIX UID (non-ephemeral). Both the user's primary group and
 178  * supplementary groups will be added to the POSIX group array of the access
 179  * token.
 180  */
 181 static smb_posix_grps_t *
 182 smb_token_create_pxgrps(uid_t uid)
 183 {
 184         struct passwd *pwd;
 185         smb_posix_grps_t *pgrps;
 186         int ngroups_max, num;
 187         gid_t *gids;
 188 
 189         if ((ngroups_max = sysconf(_SC_NGROUPS_MAX)) < 0) {
 190                 syslog(LOG_ERR, "smb_logon: failed to get _SC_NGROUPS_MAX");
 191                 return (NULL);
 192         }
 193 
 194         pwd = getpwuid(uid);
 195         if (pwd == NULL) {
 196                 pgrps = malloc(sizeof (smb_posix_grps_t));
 197                 if (pgrps == NULL)
 198                         return (NULL);
 199 
 200                 pgrps->pg_ngrps = 0;
 201                 return (pgrps);
 202         }
 203 
 204         if (pwd->pw_name == NULL) {
 205                 pgrps = malloc(sizeof (smb_posix_grps_t));
 206                 if (pgrps == NULL)
 207                         return (NULL);
 208 
 209                 pgrps->pg_ngrps = 1;
 210                 pgrps->pg_grps[0] = pwd->pw_gid;
 211                 return (pgrps);
 212         }
 213 
 214         gids = (gid_t *)malloc(ngroups_max * sizeof (gid_t));
 215         if (gids == NULL) {
 216                 return (NULL);
 217         }
 218         bzero(gids, ngroups_max * sizeof (gid_t));
 219 
 220         gids[0] = pwd->pw_gid;
 221 
 222         /*
 223          * Setup the groups starting at index 1 (the last arg)
 224          * of gids array.
 225          */
 226         num = _getgroupsbymember(pwd->pw_name, gids, ngroups_max, 1);
 227 
 228         if (num == -1) {
 229                 syslog(LOG_ERR, "smb_logon: unable "
 230                     "to get user's supplementary groups");
 231                 num = 1;
 232         }
 233 
 234         pgrps = (smb_posix_grps_t *)malloc(SMB_POSIX_GRPS_SIZE(num));
 235         if (pgrps) {
 236                 pgrps->pg_ngrps = num;
 237                 bcopy(gids, pgrps->pg_grps, num * sizeof (gid_t));
 238         }
 239 
 240         free(gids);
 241         return (pgrps);
 242 }
 243 
 244 /*
 245  * smb_token_destroy
 246  *
 247  * Release all of the memory associated with a token structure. Ensure
 248  * that the token has been unlinked before calling.
 249  */
 250 void
 251 smb_token_destroy(smb_token_t *token)
 252 {
 253         if (token != NULL) {
 254                 smb_sid_free(token->tkn_user.i_sid);
 255                 smb_sid_free(token->tkn_owner.i_sid);
 256                 smb_sid_free(token->tkn_primary_grp.i_sid);
 257                 smb_ids_free(&token->tkn_win_grps);
 258                 smb_privset_free(token->tkn_privileges);
 259                 free(token->tkn_posix_grps);
 260                 free(token->tkn_account_name);
 261                 free(token->tkn_domain_name);
 262                 free(token->tkn_ssnkey.val);
 263                 bzero(token, sizeof (smb_token_t));
 264                 free(token);
 265         }
 266 }
 267 
 268 /*
 269  * Token owner should be set to local Administrators group
 270  * in two cases:
 271  *   1. The logged on user is a member of Domain Admins group
 272  *   2. They are a member of local Administrators group
 273  */
 274 static void
 275 smb_token_set_owner(smb_token_t *token)
 276 {
 277 #ifdef SMB_SUPPORT_GROUP_OWNER
 278         smb_sid_t *owner_sid;
 279 
 280         if (token->tkn_flags & SMB_ATF_ADMIN) {
 281                 owner_sid = smb_wka_get_sid("Administrators");
 282                 assert(owner_sid);
 283         } else {
 284                 owner_sid = token->tkn_user->i_sid;
 285         }
 286 
 287         token->tkn_owner.i_sid = smb_sid_dup(owner_sid);
 288 #endif
 289         token->tkn_owner.i_sid = smb_sid_dup(token->tkn_user.i_sid);
 290 }
 291 
 292 static smb_privset_t *
 293 smb_token_create_privs(smb_token_t *token)
 294 {
 295         smb_privset_t *privs;
 296         smb_giter_t gi;
 297         smb_group_t grp;
 298         int rc;
 299 
 300         privs = smb_privset_new();
 301         if (privs == NULL)
 302                 return (NULL);
 303 
 304         if (smb_lgrp_iteropen(&gi) != SMB_LGRP_SUCCESS) {
 305                 smb_privset_free(privs);
 306                 return (NULL);
 307         }
 308 
 309         while (smb_lgrp_iterate(&gi, &grp) == SMB_LGRP_SUCCESS) {
 310                 if (smb_lgrp_is_member(&grp, token->tkn_user.i_sid))
 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.
 361  *
 362  * Note that the order of calls in this function are important.
 363  *
 364  * Returns B_TRUE for success.
 365  */
 366 boolean_t
 367 smb_token_setup_common(smb_token_t *token)
 368 {
 369         smb_token_set_flags(token);
 370 
 371         smb_token_set_owner(token);
 372         if (token->tkn_owner.i_sid == NULL)
 373                 return (B_FALSE);
 374 
 375         /* Privileges */
 376         token->tkn_privileges = smb_token_create_privs(token);
 377         if (token->tkn_privileges == NULL)
 378                 return (B_FALSE);
 379 
 380         if (smb_token_sids2ids(token) != 0) {
 381                 syslog(LOG_ERR, "%s\\%s: idmap failed",
 382                     token->tkn_domain_name, token->tkn_account_name);
 383                 return (B_FALSE);
 384         }
 385 
 386         /* Solaris Groups */
 387         token->tkn_posix_grps = smb_token_create_pxgrps(token->tkn_user.i_id);
 388 
 389         return (smb_token_valid(token));
 390 }
 391 
 392 uint32_t
 393 smb_logon_init(void)
 394 {
 395         uint32_t status;
 396 
 397         (void) rw_wrlock(&smb_logoninit_rwl);
 398         status = smb_sam_lookup_name(NULL, "guest", SidTypeUser, &smb_guest);
 399         if (status != NT_STATUS_SUCCESS) {
 400                 (void) rw_unlock(&smb_logoninit_rwl);
 401                 return (status);
 402         }
 403 
 404         status = smb_sam_lookup_name(NULL, "domain users", SidTypeGroup,
 405             &smb_domusers);
 406         if (status != NT_STATUS_SUCCESS) {
 407                 smb_account_free(&smb_guest);
 408                 bzero(&smb_guest, sizeof (smb_account_t));
 409                 (void) rw_unlock(&smb_logoninit_rwl);
 410                 return (status);
 411         }
 412 
 413         (void) rw_unlock(&smb_logoninit_rwl);
 414         return (status);
 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 
 518         if (user_info->lg_secmode == SMB_SECMODE_DOMAIN) {
 519                 if ((user_info->lg_domain_type != SMB_DOMAIN_LOCAL) &&
 520                     (user_info->lg_domain_type != SMB_DOMAIN_NULL))
 521                         return;
 522         }
 523 
 524         /*
 525          * If the requested account name is "guest" (or whatever
 526          * our guest account is named) then don't handle it here.
 527          * Let this request fall through to smb_logon_guest().
 528          */
 529         smb_guest_account(guest, SMB_USERNAME_MAXLEN);
 530         if (smb_strcasecmp(guest, user_info->lg_e_username, 0) == 0)
 531                 return;
 532 
 533         status = smb_token_auth_local(user_info, token, &smbpw);
 534         if (status == NT_STATUS_SUCCESS)
 535                 status = smb_token_setup_local(&smbpw, token);
 536 
 537         user_info->lg_status = status;
 538 }
 539 
 540 /*
 541  * Guest authentication.  This may be a local guest account or the guest
 542  * account may be mapped to a local account.  These accounts are regular
 543  * accounts with normal password protection.
 544  *
 545  * Only proceed with a guest logon if previous logon options have resulted
 546  * in NO_SUCH_USER.
 547  *
 548  * If we are not going to attempt authentication, this function must return
 549  * without updating the status.
 550  */
 551 static void
 552 smb_logon_guest(smb_logon_t *user_info, smb_token_t *token)
 553 {
 554         char guest[SMB_USERNAME_MAXLEN];
 555         smb_passwd_t smbpw;
 556         char *temp;
 557 
 558         if (user_info->lg_status != NT_STATUS_NO_SUCH_USER)
 559                 return;
 560 
 561         /* Get the name of the guest account. */
 562         smb_guest_account(guest, SMB_USERNAME_MAXLEN);
 563 
 564         /* Does the guest account exist? */
 565         if (smb_pwd_getpwnam(guest, &smbpw) == NULL)
 566                 return;
 567 
 568         /* Is it enabled? (empty p/w is OK) */
 569         if (smbpw.pw_flags & SMB_PWF_DISABLE)
 570                 return;
 571 
 572         /*
 573          * OK, give the client a guest logon.  Note that on entry,
 574          * lg_e_username is typically something other than "guest"
 575          * so we need to set the effective username when createing
 576          * the guest token.
 577          */
 578         temp = user_info->lg_e_username;
 579         user_info->lg_e_username = guest;
 580         user_info->lg_status = smb_token_setup_guest(user_info, token);
 581         user_info->lg_e_username = temp;
 582 }
 583 
 584 /*
 585  * If user_info represents an anonymous user then setup the token.
 586  * Otherwise return without updating the status.
 587  */
 588 static void
 589 smb_logon_anon(smb_logon_t *user_info, smb_token_t *token)
 590 {
 591         if (user_info->lg_flags & SMB_ATF_ANON)
 592                 user_info->lg_status = smb_token_setup_anon(token);
 593 }
 594 
 595 /*
 596  * Try both LM hash and NT hashes with user's password(s) to authenticate
 597  * the user.
 598  */
 599 static uint32_t
 600 smb_token_auth_local(smb_logon_t *user_info, smb_token_t *token,
 601     smb_passwd_t *smbpw)
 602 {
 603         boolean_t ok;
 604         uint32_t status = NT_STATUS_SUCCESS;
 605 
 606         if (smb_pwd_getpwnam(user_info->lg_e_username, smbpw) == NULL)
 607                 return (NT_STATUS_NO_SUCH_USER);
 608 
 609         if (smbpw->pw_flags & SMB_PWF_DISABLE)
 610                 return (NT_STATUS_ACCOUNT_DISABLED);
 611 
 612         if ((smbpw->pw_flags & (SMB_PWF_LM | SMB_PWF_NT)) == 0) {
 613                 /*
 614                  * The SMB passwords have not been set.
 615                  * Return an error that suggests the
 616                  * password needs to be set.
 617                  */
 618                 return (NT_STATUS_PASSWORD_EXPIRED);
 619         }
 620 
 621         token->tkn_ssnkey.val = malloc(SMBAUTH_SESSION_KEY_SZ);
 622         if (token->tkn_ssnkey.val == NULL)
 623                 return (NT_STATUS_NO_MEMORY);
 624         token->tkn_ssnkey.len = SMBAUTH_SESSION_KEY_SZ;
 625 
 626         ok = smb_auth_validate(
 627             smbpw,
 628             user_info->lg_domain,
 629             user_info->lg_username,
 630             user_info->lg_challenge_key.val,
 631             user_info->lg_challenge_key.len,
 632             user_info->lg_nt_password.val,
 633             user_info->lg_nt_password.len,
 634             user_info->lg_lm_password.val,
 635             user_info->lg_lm_password.len,
 636             token->tkn_ssnkey.val);
 637         if (ok)
 638                 return (NT_STATUS_SUCCESS);
 639 
 640         free(token->tkn_ssnkey.val);
 641         token->tkn_ssnkey.val = NULL;
 642         token->tkn_ssnkey.len = 0;
 643 
 644         status = NT_STATUS_WRONG_PASSWORD;
 645         syslog(LOG_NOTICE, "logon[%s\\%s]: %s",
 646             user_info->lg_e_domain, user_info->lg_e_username,
 647             xlate_nt_status(status));
 648 
 649         return (status);
 650 }
 651 
 652 /*
 653  * Setup an access token for the specified local user.
 654  */
 655 static uint32_t
 656 smb_token_setup_local(smb_passwd_t *smbpw, smb_token_t *token)
 657 {
 658         idmap_stat stat;
 659         smb_idmap_batch_t sib;
 660         smb_idmap_t *umap, *gmap;
 661         struct passwd pw;
 662         char pwbuf[1024];
 663         char nbname[NETBIOS_NAME_SZ];
 664 
 665         (void) smb_getnetbiosname(nbname, sizeof (nbname));
 666         token->tkn_account_name = strdup(smbpw->pw_name);
 667         token->tkn_domain_name = strdup(nbname);
 668 
 669         if (token->tkn_account_name == NULL ||
 670             token->tkn_domain_name == NULL)
 671                 return (NT_STATUS_NO_MEMORY);
 672 
 673         if (getpwuid_r(smbpw->pw_uid, &pw, pwbuf, sizeof (pwbuf)) == NULL)
 674                 return (NT_STATUS_NO_SUCH_USER);
 675 
 676         /* Get the SID for user's uid & gid */
 677         stat = smb_idmap_batch_create(&sib, 2, SMB_IDMAP_ID2SID);
 678         if (stat != IDMAP_SUCCESS)
 679                 return (NT_STATUS_INTERNAL_ERROR);
 680 
 681         umap = &sib.sib_maps[0];
 682         stat = smb_idmap_batch_getsid(sib.sib_idmaph, umap, pw.pw_uid,
 683             SMB_IDMAP_USER);
 684 
 685         if (stat != IDMAP_SUCCESS) {
 686                 smb_idmap_batch_destroy(&sib);
 687                 return (NT_STATUS_INTERNAL_ERROR);
 688         }
 689 
 690         gmap = &sib.sib_maps[1];
 691         stat = smb_idmap_batch_getsid(sib.sib_idmaph, gmap, pw.pw_gid,
 692             SMB_IDMAP_GROUP);
 693 
 694         if (stat != IDMAP_SUCCESS) {
 695                 smb_idmap_batch_destroy(&sib);
 696                 return (NT_STATUS_INTERNAL_ERROR);
 697         }
 698 
 699         if (smb_idmap_batch_getmappings(&sib) != IDMAP_SUCCESS)
 700                 return (NT_STATUS_INTERNAL_ERROR);
 701 
 702         token->tkn_user.i_sid = smb_sid_dup(umap->sim_sid);
 703         token->tkn_primary_grp.i_sid = smb_sid_dup(gmap->sim_sid);
 704 
 705         smb_idmap_batch_destroy(&sib);
 706 
 707         if (token->tkn_user.i_sid == NULL ||
 708             token->tkn_primary_grp.i_sid == NULL)
 709                 return (NT_STATUS_NO_MEMORY);
 710 
 711         return (smb_token_setup_wingrps(token));
 712 }
 713 
 714 /*
 715  * Setup access token for guest connections
 716  */
 717 static uint32_t
 718 smb_token_setup_guest(smb_logon_t *user_info, smb_token_t *token)
 719 {
 720         token->tkn_account_name = strdup(user_info->lg_e_username);
 721 
 722         (void) rw_rdlock(&smb_logoninit_rwl);
 723         token->tkn_domain_name = strdup(smb_guest.a_domain);
 724         token->tkn_user.i_sid = smb_sid_dup(smb_guest.a_sid);
 725         token->tkn_primary_grp.i_sid = smb_sid_dup(smb_domusers.a_sid);
 726         (void) rw_unlock(&smb_logoninit_rwl);
 727         token->tkn_flags = SMB_ATF_GUEST;
 728 
 729         if (token->tkn_account_name == NULL ||
 730             token->tkn_domain_name == NULL ||
 731             token->tkn_user.i_sid == NULL ||
 732             token->tkn_primary_grp.i_sid == NULL)
 733                 return (NT_STATUS_NO_MEMORY);
 734 
 735         return (smb_token_setup_wingrps(token));
 736 }
 737 
 738 /*
 739  * Setup access token for anonymous connections
 740  */
 741 static uint32_t
 742 smb_token_setup_anon(smb_token_t *token)
 743 {
 744         smb_sid_t *user_sid;
 745 
 746         token->tkn_account_name = strdup("Anonymous");
 747         token->tkn_domain_name = strdup("NT Authority");
 748         user_sid = smb_wka_get_sid("Anonymous");
 749         token->tkn_user.i_sid = smb_sid_dup(user_sid);
 750         token->tkn_primary_grp.i_sid = smb_sid_dup(user_sid);
 751         token->tkn_flags = SMB_ATF_ANON;
 752 
 753         if (token->tkn_account_name == NULL ||
 754             token->tkn_domain_name == NULL ||
 755             token->tkn_user.i_sid == NULL ||
 756             token->tkn_primary_grp.i_sid == NULL)
 757                 return (NT_STATUS_NO_MEMORY);
 758 
 759         return (smb_token_setup_wingrps(token));
 760 }
 761 
 762 /*
 763  * smb_token_user_sid
 764  *
 765  * Return a pointer to the user SID in the specified token. A null
 766  * pointer indicates an error.
 767  */
 768 static smb_sid_t *
 769 smb_token_user_sid(smb_token_t *token)
 770 {
 771         return ((token) ? token->tkn_user.i_sid : NULL);
 772 }
 773 
 774 /*
 775  * smb_token_group_sid
 776  *
 777  * Return a pointer to the group SID as indicated by the iterator.
 778  * Setting the iterator to 0 before calling this function will return
 779  * the first group, which will always be the primary group. The
 780  * iterator will be incremented before returning the SID so that this
 781  * function can be used to cycle through the groups. The caller can
 782  * adjust the iterator as required between calls to obtain any specific
 783  * group.
 784  *
 785  * On success a pointer to the appropriate group SID will be returned.
 786  * Otherwise a null pointer will be returned.
 787  */
 788 static smb_sid_t *
 789 smb_token_group_sid(smb_token_t *token, int *iterator)
 790 {
 791         int index;
 792 
 793         if (token == NULL || iterator == NULL)
 794                 return (NULL);
 795 
 796         if (token->tkn_win_grps.i_ids == NULL)
 797                 return (NULL);
 798 
 799         index = *iterator;
 800 
 801         if (index < 0 || index >= token->tkn_win_grps.i_cnt)
 802                 return (NULL);
 803 
 804         ++(*iterator);
 805         return (token->tkn_win_grps.i_ids[index].i_sid);
 806 }
 807 
 808 /*
 809  * smb_token_is_member
 810  *
 811  * This function will determine whether or not the specified SID is a
 812  * member of a token. The user SID and all group SIDs are tested.
 813  * Returns 1 if the SID is a member of the token. Otherwise returns 0.
 814  */
 815 static boolean_t
 816 smb_token_is_member(smb_token_t *token, smb_sid_t *sid)
 817 {
 818         smb_sid_t *tsid;
 819         int iterator = 0;
 820 
 821         if (token == NULL || sid == NULL)
 822                 return (B_FALSE);
 823 
 824         tsid = smb_token_user_sid(token);
 825         while (tsid) {
 826                 if (smb_sid_cmp(tsid, sid))
 827                         return (B_TRUE);
 828 
 829                 tsid = smb_token_group_sid(token, &iterator);
 830         }
 831 
 832         return (B_FALSE);
 833 }
 834 
 835 /*
 836  * smb_token_log
 837  *
 838  * Diagnostic routine to write the contents of a token to the log.
 839  */
 840 void
 841 smb_token_log(smb_token_t *token)
 842 {
 843         smb_ids_t *w_grps;
 844         smb_id_t *grp;
 845         smb_posix_grps_t *x_grps;
 846         char sidstr[SMB_SID_STRSZ];
 847         int i;
 848 
 849         if (token == NULL)
 850                 return;
 851 
 852         syslog(LOG_DEBUG, "Token for %s\\%s",
 853             (token->tkn_domain_name) ? token->tkn_domain_name : "-NULL-",
 854             (token->tkn_account_name) ? token->tkn_account_name : "-NULL-");
 855 
 856         syslog(LOG_DEBUG, "   User->Attr: %d", token->tkn_user.i_attrs);
 857         smb_sid_tostr((smb_sid_t *)token->tkn_user.i_sid, sidstr);
 858         syslog(LOG_DEBUG, "   User->Sid: %s (id=%u)", sidstr,
 859             token->tkn_user.i_id);
 860 
 861         smb_sid_tostr((smb_sid_t *)token->tkn_owner.i_sid, sidstr);
 862         syslog(LOG_DEBUG, "   Ownr->Sid: %s (id=%u)",
 863             sidstr, token->tkn_owner.i_id);
 864 
 865         smb_sid_tostr((smb_sid_t *)token->tkn_primary_grp.i_sid, sidstr);
 866         syslog(LOG_DEBUG, "   PGrp->Sid: %s (id=%u)",
 867             sidstr, token->tkn_primary_grp.i_id);
 868 
 869         w_grps = &token->tkn_win_grps;
 870         if (w_grps->i_ids) {
 871                 syslog(LOG_DEBUG, "   Windows groups: %d", w_grps->i_cnt);
 872                 grp = w_grps->i_ids;
 873                 for (i = 0; i < w_grps->i_cnt; ++i, grp++) {
 874                         syslog(LOG_DEBUG,
 875                             "    Grp[%d].Attr:%d", i, grp->i_attrs);
 876                         if (grp->i_sid != NULL) {
 877                                 smb_sid_tostr((smb_sid_t *)grp->i_sid, sidstr);
 878                                 syslog(LOG_DEBUG,
 879                                     "    Grp[%d].Sid: %s (id=%u)", i, sidstr,
 880                                     grp->i_id);
 881                         }
 882                 }
 883         } else {
 884                 syslog(LOG_DEBUG, "   No Windows groups");
 885         }
 886 
 887         x_grps = token->tkn_posix_grps;
 888         if (x_grps) {
 889                 syslog(LOG_DEBUG, "   Solaris groups: %d", x_grps->pg_ngrps);
 890                 for (i = 0; i < x_grps->pg_ngrps; i++)
 891                         syslog(LOG_DEBUG, "    %u", x_grps->pg_grps[i]);
 892         } else {
 893                 syslog(LOG_DEBUG, "   No Solaris groups");
 894         }
 895 
 896         if (token->tkn_privileges)
 897                 smb_privset_log(token->tkn_privileges);
 898         else
 899                 syslog(LOG_DEBUG, "   No privileges");
 900 }
 901 
 902 /*
 903  * Sets up local and well-known group membership for the given
 904  * token. Two assumptions have been made here:
 905  *
 906  *   a) token already contains a valid user SID so that group
 907  *      memberships can be established
 908  *
 909  *   b) token belongs to a local or anonymous user
 910  */
 911 static uint32_t
 912 smb_token_setup_wingrps(smb_token_t *token)
 913 {
 914         smb_ids_t tkn_grps;
 915         uint32_t status;
 916 
 917 
 918         /*
 919          * We always want the user's primary group in the list
 920          * of groups.
 921          */
 922         tkn_grps.i_cnt = 1;
 923         if ((tkn_grps.i_ids = malloc(sizeof (smb_id_t))) == NULL)
 924                 return (NT_STATUS_NO_MEMORY);
 925 
 926         tkn_grps.i_ids->i_sid = smb_sid_dup(token->tkn_primary_grp.i_sid);
 927         tkn_grps.i_ids->i_attrs = token->tkn_primary_grp.i_attrs;
 928         if (tkn_grps.i_ids->i_sid == NULL) {
 929                 smb_ids_free(&tkn_grps);
 930                 return (NT_STATUS_NO_MEMORY);
 931         }
 932 
 933         status = smb_sam_usr_groups(token->tkn_user.i_sid, &tkn_grps);
 934         if (status != NT_STATUS_SUCCESS) {
 935                 smb_ids_free(&tkn_grps);
 936                 return (status);
 937         }
 938 
 939         status = smb_wka_token_groups(token->tkn_flags, &tkn_grps);
 940         if (status != NT_STATUS_SUCCESS) {
 941                 smb_ids_free(&tkn_grps);
 942                 return (status);
 943         }
 944 
 945         token->tkn_win_grps = tkn_grps;
 946         return (status);
 947 }
 948 
 949 /*
 950  * Returns the guest account name in the provided buffer.
 951  *
 952  * By default the name would be "guest" unless there's
 953  * a idmap name-based rule which maps the guest to a local
 954  * Solaris user in which case the name of that user is
 955  * returned.
 956  */
 957 static void
 958 smb_guest_account(char *guest, size_t buflen)
 959 {
 960         idmap_stat stat;
 961         uid_t guest_uid;
 962         struct passwd pw;
 963         char pwbuf[1024];
 964         int idtype;
 965 
 966         /* default Guest account name */
 967         (void) rw_rdlock(&smb_logoninit_rwl);
 968         (void) strlcpy(guest, smb_guest.a_name, buflen);
 969 
 970         idtype = SMB_IDMAP_USER;
 971         stat = smb_idmap_getid(smb_guest.a_sid, &guest_uid, &idtype);
 972         (void) rw_unlock(&smb_logoninit_rwl);
 973 
 974         if (stat != IDMAP_SUCCESS)
 975                 return;
 976 
 977         /* If Ephemeral ID return the default name */
 978         if (IDMAP_ID_IS_EPHEMERAL(guest_uid))
 979                 return;
 980 
 981         if (getpwuid_r(guest_uid, &pw, pwbuf, sizeof (pwbuf)) == NULL)
 982                 return;
 983 
 984         (void) strlcpy(guest, pw.pw_name, buflen);
 985 }