root/source3/smbd/password.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_valid_user_struct_internal
  2. get_valid_user_struct
  3. is_partial_auth_vuid
  4. get_partial_auth_user_struct
  5. invalidate_vuid
  6. invalidate_all_vuids
  7. increment_next_vuid
  8. register_initial_vuid
  9. register_homes_share
  10. register_existing_vuid
  11. add_session_user
  12. add_session_workgroup
  13. get_session_workgroup
  14. user_in_netgroup
  15. user_in_list
  16. user_ok
  17. validate_group
  18. authorise_login

   1 /*
   2    Unix SMB/CIFS implementation.
   3    Password and authentication handling
   4    Copyright (C) Andrew Tridgell 1992-1998
   5    Copyright (C) Jeremy Allison 2007.
   6 
   7    This program is free software; you can redistribute it and/or modify
   8    it under the terms of the GNU General Public License as published by
   9    the Free Software Foundation; either version 3 of the License, or
  10    (at your option) any later version.
  11 
  12    This program is distributed in the hope that it will be useful,
  13    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15    GNU General Public License for more details.
  16 
  17    You should have received a copy of the GNU General Public License
  18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  19 */
  20 
  21 #include "includes.h"
  22 #include "smbd/globals.h"
  23 
  24 enum server_allocated_state { SERVER_ALLOCATED_REQUIRED_YES,
  25                                 SERVER_ALLOCATED_REQUIRED_NO,
  26                                 SERVER_ALLOCATED_REQUIRED_ANY};
  27 
  28 static user_struct *get_valid_user_struct_internal(uint16 vuid,
     /* [<][>][^][v][top][bottom][index][help] */
  29                         enum server_allocated_state server_allocated)
  30 {
  31         user_struct *usp;
  32         int count=0;
  33 
  34         if (vuid == UID_FIELD_INVALID)
  35                 return NULL;
  36 
  37         for (usp=validated_users;usp;usp=usp->next,count++) {
  38                 if (vuid == usp->vuid) {
  39                         switch (server_allocated) {
  40                                 case SERVER_ALLOCATED_REQUIRED_YES:
  41                                         if (usp->server_info == NULL) {
  42                                                 continue;
  43                                         }
  44                                         break;
  45                                 case SERVER_ALLOCATED_REQUIRED_NO:
  46                                         if (usp->server_info != NULL) {
  47                                                 continue;
  48                                         }
  49                                 case SERVER_ALLOCATED_REQUIRED_ANY:
  50                                         break;
  51                         }
  52                         if (count > 10) {
  53                                 DLIST_PROMOTE(validated_users, usp);
  54                         }
  55                         return usp;
  56                 }
  57         }
  58 
  59         return NULL;
  60 }
  61 
  62 /****************************************************************************
  63  Check if a uid has been validated, and return an pointer to the user_struct
  64  if it has. NULL if not. vuid is biased by an offset. This allows us to
  65  tell random client vuid's (normally zero) from valid vuids.
  66 ****************************************************************************/
  67 
  68 user_struct *get_valid_user_struct(uint16 vuid)
     /* [<][>][^][v][top][bottom][index][help] */
  69 {
  70         return get_valid_user_struct_internal(vuid,
  71                         SERVER_ALLOCATED_REQUIRED_YES);
  72 }
  73 
  74 bool is_partial_auth_vuid(uint16 vuid)
     /* [<][>][^][v][top][bottom][index][help] */
  75 {
  76         return (get_partial_auth_user_struct(vuid) != NULL);
  77 }
  78 
  79 /****************************************************************************
  80  Get the user struct of a partial NTLMSSP login
  81 ****************************************************************************/
  82 
  83 user_struct *get_partial_auth_user_struct(uint16 vuid)
     /* [<][>][^][v][top][bottom][index][help] */
  84 {
  85         return get_valid_user_struct_internal(vuid,
  86                         SERVER_ALLOCATED_REQUIRED_NO);
  87 }
  88 
  89 /****************************************************************************
  90  Invalidate a uid.
  91 ****************************************************************************/
  92 
  93 void invalidate_vuid(uint16 vuid)
     /* [<][>][^][v][top][bottom][index][help] */
  94 {
  95         user_struct *vuser = NULL;
  96 
  97         vuser = get_valid_user_struct_internal(vuid,
  98                         SERVER_ALLOCATED_REQUIRED_ANY);
  99         if (vuser == NULL) {
 100                 return;
 101         }
 102 
 103         session_yield(vuser);
 104 
 105         if (vuser->auth_ntlmssp_state) {
 106                 auth_ntlmssp_end(&vuser->auth_ntlmssp_state);
 107         }
 108 
 109         DLIST_REMOVE(validated_users, vuser);
 110 
 111         /* clear the vuid from the 'cache' on each connection, and
 112            from the vuid 'owner' of connections */
 113         conn_clear_vuid_caches(vuid);
 114 
 115         TALLOC_FREE(vuser);
 116         num_validated_vuids--;
 117 }
 118 
 119 /****************************************************************************
 120  Invalidate all vuid entries for this process.
 121 ****************************************************************************/
 122 
 123 void invalidate_all_vuids(void)
     /* [<][>][^][v][top][bottom][index][help] */
 124 {
 125         while (validated_users != NULL) {
 126                 invalidate_vuid(validated_users->vuid);
 127         }
 128 }
 129 
 130 static void increment_next_vuid(uint16_t *vuid)
     /* [<][>][^][v][top][bottom][index][help] */
 131 {
 132         *vuid += 1;
 133 
 134         /* Check for vuid wrap. */
 135         if (*vuid == UID_FIELD_INVALID) {
 136                 *vuid = VUID_OFFSET;
 137         }
 138 }
 139 
 140 /****************************************************
 141  Create a new partial auth user struct.
 142 *****************************************************/
 143 
 144 int register_initial_vuid(void)
     /* [<][>][^][v][top][bottom][index][help] */
 145 {
 146         user_struct *vuser;
 147 
 148         /* Paranoia check. */
 149         if(lp_security() == SEC_SHARE) {
 150                 smb_panic("register_initial_vuid: "
 151                         "Tried to register uid in security=share");
 152         }
 153 
 154         /* Limit allowed vuids to 16bits - VUID_OFFSET. */
 155         if (num_validated_vuids >= 0xFFFF-VUID_OFFSET) {
 156                 return UID_FIELD_INVALID;
 157         }
 158 
 159         if((vuser = talloc_zero(NULL, user_struct)) == NULL) {
 160                 DEBUG(0,("register_initial_vuid: "
 161                                 "Failed to talloc users struct!\n"));
 162                 return UID_FIELD_INVALID;
 163         }
 164 
 165         /* Allocate a free vuid. Yes this is a linear search... */
 166         while( get_valid_user_struct_internal(next_vuid,
 167                         SERVER_ALLOCATED_REQUIRED_ANY) != NULL ) {
 168                 increment_next_vuid(&next_vuid);
 169         }
 170 
 171         DEBUG(10,("register_initial_vuid: allocated vuid = %u\n",
 172                 (unsigned int)next_vuid ));
 173 
 174         vuser->vuid = next_vuid;
 175 
 176         /*
 177          * This happens in an unfinished NTLMSSP session setup. We
 178          * need to allocate a vuid between the first and second calls
 179          * to NTLMSSP.
 180          */
 181         increment_next_vuid(&next_vuid);
 182         num_validated_vuids++;
 183 
 184         DLIST_ADD(validated_users, vuser);
 185         return vuser->vuid;
 186 }
 187 
 188 static int register_homes_share(const char *username)
     /* [<][>][^][v][top][bottom][index][help] */
 189 {
 190         int result;
 191         struct passwd *pwd;
 192 
 193         result = lp_servicenumber(username);
 194         if (result != -1) {
 195                 DEBUG(3, ("Using static (or previously created) service for "
 196                           "user '%s'; path = '%s'\n", username,
 197                           lp_pathname(result)));
 198                 return result;
 199         }
 200 
 201         pwd = getpwnam_alloc(talloc_tos(), username);
 202 
 203         if ((pwd == NULL) || (pwd->pw_dir[0] == '\0')) {
 204                 DEBUG(3, ("No home directory defined for user '%s'\n",
 205                           username));
 206                 TALLOC_FREE(pwd);
 207                 return -1;
 208         }
 209 
 210         DEBUG(3, ("Adding homes service for user '%s' using home directory: "
 211                   "'%s'\n", username, pwd->pw_dir));
 212 
 213         result = add_home_service(username, username, pwd->pw_dir);
 214 
 215         TALLOC_FREE(pwd);
 216         return result;
 217 }
 218 
 219 /**
 220  *  register that a valid login has been performed, establish 'session'.
 221  *  @param server_info The token returned from the authentication process.
 222  *   (now 'owned' by register_existing_vuid)
 223  *
 224  *  @param session_key The User session key for the login session (now also
 225  *  'owned' by register_existing_vuid)
 226  *
 227  *  @param respose_blob The NT challenge-response, if available.  (May be
 228  *  freed after this call)
 229  *
 230  *  @param smb_name The untranslated name of the user
 231  *
 232  *  @return Newly allocated vuid, biased by an offset. (This allows us to
 233  *   tell random client vuid's (normally zero) from valid vuids.)
 234  *
 235  */
 236 
 237 int register_existing_vuid(uint16 vuid,
     /* [<][>][^][v][top][bottom][index][help] */
 238                         auth_serversupplied_info *server_info,
 239                         DATA_BLOB response_blob,
 240                         const char *smb_name)
 241 {
 242         fstring tmp;
 243         user_struct *vuser;
 244 
 245         vuser = get_partial_auth_user_struct(vuid);
 246         if (!vuser) {
 247                 goto fail;
 248         }
 249 
 250         /* Use this to keep tabs on all our info from the authentication */
 251         vuser->server_info = talloc_move(vuser, &server_info);
 252 
 253         /* This is a potentially untrusted username */
 254         alpha_strcpy(tmp, smb_name, ". _-$", sizeof(tmp));
 255 
 256         vuser->server_info->sanitized_username = talloc_strdup(
 257                 vuser->server_info, tmp);
 258 
 259         DEBUG(10,("register_existing_vuid: (%u,%u) %s %s %s guest=%d\n",
 260                   (unsigned int)vuser->server_info->utok.uid,
 261                   (unsigned int)vuser->server_info->utok.gid,
 262                   vuser->server_info->unix_name,
 263                   vuser->server_info->sanitized_username,
 264                   pdb_get_domain(vuser->server_info->sam_account),
 265                   vuser->server_info->guest ));
 266 
 267         DEBUG(3, ("register_existing_vuid: User name: %s\t"
 268                   "Real name: %s\n", vuser->server_info->unix_name,
 269                   pdb_get_fullname(vuser->server_info->sam_account)));
 270 
 271         if (!vuser->server_info->ptok) {
 272                 DEBUG(1, ("register_existing_vuid: server_info does not "
 273                         "contain a user_token - cannot continue\n"));
 274                 goto fail;
 275         }
 276 
 277         DEBUG(3,("register_existing_vuid: UNIX uid %d is UNIX user %s, "
 278                 "and will be vuid %u\n", (int)vuser->server_info->utok.uid,
 279                  vuser->server_info->unix_name, vuser->vuid));
 280 
 281         if (!session_claim(vuser)) {
 282                 DEBUG(1, ("register_existing_vuid: Failed to claim session "
 283                         "for vuid=%d\n",
 284                         vuser->vuid));
 285                 goto fail;
 286         }
 287 
 288         /* Register a home dir service for this user if
 289         (a) This is not a guest connection,
 290         (b) we have a home directory defined
 291         (c) there s not an existing static share by that name
 292         If a share exists by this name (autoloaded or not) reuse it . */
 293 
 294         vuser->homes_snum = -1;
 295 
 296         if (!vuser->server_info->guest) {
 297                 vuser->homes_snum = register_homes_share(
 298                         vuser->server_info->unix_name);
 299         }
 300 
 301         if (srv_is_signing_negotiated() && !vuser->server_info->guest &&
 302                         !srv_signing_started()) {
 303                 /* Try and turn on server signing on the first non-guest
 304                  * sessionsetup. */
 305                 srv_set_signing(vuser->server_info->user_session_key, response_blob);
 306         }
 307 
 308         /* fill in the current_user_info struct */
 309         set_current_user_info(
 310                 vuser->server_info->sanitized_username,
 311                 vuser->server_info->unix_name,
 312                 pdb_get_domain(vuser->server_info->sam_account));
 313 
 314         return vuser->vuid;
 315 
 316   fail:
 317 
 318         if (vuser) {
 319                 invalidate_vuid(vuid);
 320         }
 321         return UID_FIELD_INVALID;
 322 }
 323 
 324 /****************************************************************************
 325  Add a name to the session users list.
 326 ****************************************************************************/
 327 
 328 void add_session_user(const char *user)
     /* [<][>][^][v][top][bottom][index][help] */
 329 {
 330         struct passwd *pw;
 331         char *tmp;
 332 
 333         pw = Get_Pwnam_alloc(talloc_tos(), user);
 334 
 335         if (pw == NULL) {
 336                 return;
 337         }
 338 
 339         if (session_userlist == NULL) {
 340                 session_userlist = SMB_STRDUP(pw->pw_name);
 341                 goto done;
 342         }
 343 
 344         if (in_list(pw->pw_name,session_userlist,False) ) {
 345                 goto done;
 346         }
 347 
 348         if (strlen(session_userlist) > 128 * 1024) {
 349                 DEBUG(3,("add_session_user: session userlist already "
 350                          "too large.\n"));
 351                 goto done;
 352         }
 353 
 354         if (asprintf(&tmp, "%s %s", session_userlist, pw->pw_name) == -1) {
 355                 DEBUG(3, ("asprintf failed\n"));
 356                 goto done;
 357         }
 358 
 359         SAFE_FREE(session_userlist);
 360         session_userlist = tmp;
 361  done:
 362         TALLOC_FREE(pw);
 363 }
 364 
 365 /****************************************************************************
 366  In security=share mode we need to store the client workgroup, as that's
 367   what Vista uses for the NTLMv2 calculation.
 368 ****************************************************************************/
 369 
 370 void add_session_workgroup(const char *workgroup)
     /* [<][>][^][v][top][bottom][index][help] */
 371 {
 372         if (session_workgroup) {
 373                 SAFE_FREE(session_workgroup);
 374         }
 375         session_workgroup = smb_xstrdup(workgroup);
 376 }
 377 
 378 /****************************************************************************
 379  In security=share mode we need to return the client workgroup, as that's
 380   what Vista uses for the NTLMv2 calculation.
 381 ****************************************************************************/
 382 
 383 const char *get_session_workgroup(void)
     /* [<][>][^][v][top][bottom][index][help] */
 384 {
 385         return session_workgroup;
 386 }
 387 
 388 /****************************************************************************
 389  Check if a user is in a netgroup user list. If at first we don't succeed,
 390  try lower case.
 391 ****************************************************************************/
 392 
 393 bool user_in_netgroup(const char *user, const char *ngname)
     /* [<][>][^][v][top][bottom][index][help] */
 394 {
 395 #ifdef HAVE_NETGROUP
 396         fstring lowercase_user;
 397 
 398         if (my_yp_domain == NULL)
 399                 yp_get_default_domain(&my_yp_domain);
 400 
 401         if(my_yp_domain == NULL) {
 402                 DEBUG(5,("Unable to get default yp domain, "
 403                         "let's try without specifying it\n"));
 404         }
 405 
 406         DEBUG(5,("looking for user %s of domain %s in netgroup %s\n",
 407                 user, my_yp_domain?my_yp_domain:"(ANY)", ngname));
 408 
 409         if (innetgr(ngname, NULL, user, my_yp_domain)) {
 410                 DEBUG(5,("user_in_netgroup: Found\n"));
 411                 return (True);
 412         } else {
 413 
 414                 /*
 415                  * Ok, innetgr is case sensitive. Try once more with lowercase
 416                  * just in case. Attempt to fix #703. JRA.
 417                  */
 418 
 419                 fstrcpy(lowercase_user, user);
 420                 strlower_m(lowercase_user);
 421 
 422                 DEBUG(5,("looking for user %s of domain %s in netgroup %s\n",
 423                         lowercase_user, my_yp_domain?my_yp_domain:"(ANY)", ngname));
 424 
 425                 if (innetgr(ngname, NULL, lowercase_user, my_yp_domain)) {
 426                         DEBUG(5,("user_in_netgroup: Found\n"));
 427                         return (True);
 428                 }
 429         }
 430 #endif /* HAVE_NETGROUP */
 431         return False;
 432 }
 433 
 434 /****************************************************************************
 435  Check if a user is in a user list - can check combinations of UNIX
 436  and netgroup lists.
 437 ****************************************************************************/
 438 
 439 bool user_in_list(const char *user,const char **list)
     /* [<][>][^][v][top][bottom][index][help] */
 440 {
 441         if (!list || !*list)
 442                 return False;
 443 
 444         DEBUG(10,("user_in_list: checking user %s in list\n", user));
 445 
 446         while (*list) {
 447 
 448                 DEBUG(10,("user_in_list: checking user |%s| against |%s|\n",
 449                           user, *list));
 450 
 451                 /*
 452                  * Check raw username.
 453                  */
 454                 if (strequal(user, *list))
 455                         return(True);
 456 
 457                 /*
 458                  * Now check to see if any combination
 459                  * of UNIX and netgroups has been specified.
 460                  */
 461 
 462                 if(**list == '@') {
 463                         /*
 464                          * Old behaviour. Check netgroup list
 465                          * followed by UNIX list.
 466                          */
 467                         if(user_in_netgroup(user, *list +1))
 468                                 return True;
 469                         if(user_in_group(user, *list +1))
 470                                 return True;
 471                 } else if (**list == '+') {
 472 
 473                         if((*(*list +1)) == '&') {
 474                                 /*
 475                                  * Search UNIX list followed by netgroup.
 476                                  */
 477                                 if(user_in_group(user, *list +2))
 478                                         return True;
 479                                 if(user_in_netgroup(user, *list +2))
 480                                         return True;
 481 
 482                         } else {
 483 
 484                                 /*
 485                                  * Just search UNIX list.
 486                                  */
 487 
 488                                 if(user_in_group(user, *list +1))
 489                                         return True;
 490                         }
 491 
 492                 } else if (**list == '&') {
 493 
 494                         if(*(*list +1) == '+') {
 495                                 /*
 496                                  * Search netgroup list followed by UNIX list.
 497                                  */
 498                                 if(user_in_netgroup(user, *list +2))
 499                                         return True;
 500                                 if(user_in_group(user, *list +2))
 501                                         return True;
 502                         } else {
 503                                 /*
 504                                  * Just search netgroup list.
 505                                  */
 506                                 if(user_in_netgroup(user, *list +1))
 507                                         return True;
 508                         }
 509                 }
 510 
 511                 list++;
 512         }
 513         return(False);
 514 }
 515 
 516 /****************************************************************************
 517  Check if a username is valid.
 518 ****************************************************************************/
 519 
 520 static bool user_ok(const char *user, int snum)
     /* [<][>][^][v][top][bottom][index][help] */
 521 {
 522         char **valid, **invalid;
 523         bool ret;
 524 
 525         valid = invalid = NULL;
 526         ret = True;
 527 
 528         if (lp_invalid_users(snum)) {
 529                 invalid = str_list_copy(talloc_tos(), lp_invalid_users(snum));
 530                 if (invalid &&
 531                     str_list_substitute(invalid, "%S", lp_servicename(snum))) {
 532 
 533                         /* This is used in sec=share only, so no current user
 534                          * around to pass to str_list_sub_basic() */
 535 
 536                         if ( invalid && str_list_sub_basic(invalid, "", "") ) {
 537                                 ret = !user_in_list(user,
 538                                                     (const char **)invalid);
 539                         }
 540                 }
 541         }
 542         TALLOC_FREE(invalid);
 543 
 544         if (ret && lp_valid_users(snum)) {
 545                 valid = str_list_copy(talloc_tos(), lp_valid_users(snum));
 546                 if ( valid &&
 547                      str_list_substitute(valid, "%S", lp_servicename(snum)) ) {
 548 
 549                         /* This is used in sec=share only, so no current user
 550                          * around to pass to str_list_sub_basic() */
 551 
 552                         if ( valid && str_list_sub_basic(valid, "", "") ) {
 553                                 ret = user_in_list(user, (const char **)valid);
 554                         }
 555                 }
 556         }
 557         TALLOC_FREE(valid);
 558 
 559         if (ret && lp_onlyuser(snum)) {
 560                 char **user_list = str_list_make_v3(
 561                         talloc_tos(), lp_username(snum), NULL);
 562                 if (user_list &&
 563                     str_list_substitute(user_list, "%S",
 564                                         lp_servicename(snum))) {
 565                         ret = user_in_list(user, (const char **)user_list);
 566                 }
 567                 TALLOC_FREE(user_list);
 568         }
 569 
 570         return(ret);
 571 }
 572 
 573 /****************************************************************************
 574  Validate a group username entry. Return the username or NULL.
 575 ****************************************************************************/
 576 
 577 static char *validate_group(char *group, DATA_BLOB password,int snum)
     /* [<][>][^][v][top][bottom][index][help] */
 578 {
 579 #ifdef HAVE_NETGROUP
 580         {
 581                 char *host, *user, *domain;
 582                 setnetgrent(group);
 583                 while (getnetgrent(&host, &user, &domain)) {
 584                         if (user) {
 585                                 if (user_ok(user, snum) && 
 586                                     password_ok(user,password)) {
 587                                         endnetgrent();
 588                                         return(user);
 589                                 }
 590                         }
 591                 }
 592                 endnetgrent();
 593         }
 594 #endif
 595 
 596 #ifdef HAVE_GETGRENT
 597         {
 598                 struct group *gptr;
 599                 setgrent();
 600                 while ((gptr = (struct group *)getgrent())) {
 601                         if (strequal(gptr->gr_name,group))
 602                                 break;
 603                 }
 604 
 605                 /*
 606                  * As user_ok can recurse doing a getgrent(), we must
 607                  * copy the member list onto the heap before
 608                  * use. Bug pointed out by leon@eatworms.swmed.edu.
 609                  */
 610 
 611                 if (gptr) {
 612                         char *member_list = NULL;
 613                         size_t list_len = 0;
 614                         char *member;
 615                         int i;
 616 
 617                         for(i = 0; gptr->gr_mem && gptr->gr_mem[i]; i++) {
 618                                 list_len += strlen(gptr->gr_mem[i])+1;
 619                         }
 620                         list_len++;
 621 
 622                         member_list = (char *)SMB_MALLOC(list_len);
 623                         if (!member_list) {
 624                                 endgrent();
 625                                 return NULL;
 626                         }
 627 
 628                         *member_list = '\0';
 629                         member = member_list;
 630 
 631                         for(i = 0; gptr->gr_mem && gptr->gr_mem[i]; i++) {
 632                                 size_t member_len = strlen(gptr->gr_mem[i])+1;
 633 
 634                                 DEBUG(10,("validate_group: = gr_mem = "
 635                                           "%s\n", gptr->gr_mem[i]));
 636 
 637                                 safe_strcpy(member, gptr->gr_mem[i],
 638                                         list_len - (member-member_list));
 639                                 member += member_len;
 640                         }
 641 
 642                         endgrent();
 643 
 644                         member = member_list;
 645                         while (*member) {
 646                                 if (user_ok(member,snum) &&
 647                                     password_ok(member,password)) {
 648                                         char *name = talloc_strdup(talloc_tos(),
 649                                                                 member);
 650                                         SAFE_FREE(member_list);
 651                                         return name;
 652                                 }
 653 
 654                                 DEBUG(10,("validate_group = member = %s\n",
 655                                           member));
 656 
 657                                 member += strlen(member) + 1;
 658                         }
 659 
 660                         SAFE_FREE(member_list);
 661                 } else {
 662                         endgrent();
 663                         return NULL;
 664                 }
 665         }
 666 #endif
 667         return(NULL);
 668 }
 669 
 670 /****************************************************************************
 671  Check for authority to login to a service with a given username/password.
 672  Note this is *NOT* used when logging on using sessionsetup_and_X.
 673 ****************************************************************************/
 674 
 675 bool authorise_login(int snum, fstring user, DATA_BLOB password,
     /* [<][>][^][v][top][bottom][index][help] */
 676                      bool *guest)
 677 {
 678         bool ok = False;
 679 
 680 #ifdef DEBUG_PASSWORD
 681         DEBUG(100,("authorise_login: checking authorisation on "
 682                    "user=%s pass=%s\n", user,password.data));
 683 #endif
 684 
 685         *guest = False;
 686 
 687         /* there are several possibilities:
 688                 1) login as the given user with given password
 689                 2) login as a previously registered username with the given
 690                    password
 691                 3) login as a session list username with the given password
 692                 4) login as a previously validated user/password pair
 693                 5) login as the "user =" user with given password
 694                 6) login as the "user =" user with no password
 695                    (guest connection)
 696                 7) login as guest user with no password
 697 
 698                 if the service is guest_only then steps 1 to 5 are skipped
 699         */
 700 
 701         /* now check the list of session users */
 702         if (!ok) {
 703                 char *auser;
 704                 char *user_list = NULL;
 705                 char *saveptr;
 706 
 707                 if ( session_userlist )
 708                         user_list = SMB_STRDUP(session_userlist);
 709                 else
 710                         user_list = SMB_STRDUP("");
 711 
 712                 if (!user_list)
 713                         return(False);
 714 
 715                 for (auser = strtok_r(user_list, LIST_SEP, &saveptr);
 716                      !ok && auser;
 717                      auser = strtok_r(NULL, LIST_SEP, &saveptr)) {
 718                         fstring user2;
 719                         fstrcpy(user2,auser);
 720                         if (!user_ok(user2,snum))
 721                                 continue;
 722 
 723                         if (password_ok(user2,password)) {
 724                                 ok = True;
 725                                 fstrcpy(user,user2);
 726                                 DEBUG(3,("authorise_login: ACCEPTED: session "
 727                                          "list username (%s) and given "
 728                                          "password ok\n", user));
 729                         }
 730                 }
 731 
 732                 SAFE_FREE(user_list);
 733         }
 734 
 735         /* check the user= fields and the given password */
 736         if (!ok && lp_username(snum)) {
 737                 TALLOC_CTX *ctx = talloc_tos();
 738                 char *auser;
 739                 char *user_list = talloc_strdup(ctx, lp_username(snum));
 740                 char *saveptr;
 741 
 742                 if (!user_list) {
 743                         goto check_guest;
 744                 }
 745 
 746                 user_list = talloc_string_sub(ctx,
 747                                 user_list,
 748                                 "%S",
 749                                 lp_servicename(snum));
 750 
 751                 if (!user_list) {
 752                         goto check_guest;
 753                 }
 754 
 755                 for (auser = strtok_r(user_list, LIST_SEP, &saveptr);
 756                      auser && !ok;
 757                      auser = strtok_r(NULL, LIST_SEP, &saveptr)) {
 758                         if (*auser == '@') {
 759                                 auser = validate_group(auser+1,password,snum);
 760                                 if (auser) {
 761                                         ok = True;
 762                                         fstrcpy(user,auser);
 763                                         DEBUG(3,("authorise_login: ACCEPTED: "
 764                                                  "group username and given "
 765                                                  "password ok (%s)\n", user));
 766                                 }
 767                         } else {
 768                                 fstring user2;
 769                                 fstrcpy(user2,auser);
 770                                 if (user_ok(user2,snum) &&
 771                                     password_ok(user2,password)) {
 772                                         ok = True;
 773                                         fstrcpy(user,user2);
 774                                         DEBUG(3,("authorise_login: ACCEPTED: "
 775                                                  "user list username and "
 776                                                  "given password ok (%s)\n",
 777                                                  user));
 778                                 }
 779                         }
 780                 }
 781         }
 782 
 783   check_guest:
 784 
 785         /* check for a normal guest connection */
 786         if (!ok && GUEST_OK(snum)) {
 787                 struct passwd *guest_pw;
 788                 fstring guestname;
 789                 fstrcpy(guestname,lp_guestaccount());
 790                 guest_pw = Get_Pwnam_alloc(talloc_tos(), guestname);
 791                 if (guest_pw != NULL) {
 792                         fstrcpy(user,guestname);
 793                         ok = True;
 794                         DEBUG(3,("authorise_login: ACCEPTED: guest account "
 795                                  "and guest ok (%s)\n", user));
 796                 } else {
 797                         DEBUG(0,("authorise_login: Invalid guest account "
 798                                  "%s??\n",guestname));
 799                 }
 800                 TALLOC_FREE(guest_pw);
 801                 *guest = True;
 802         }
 803 
 804         if (ok && !user_ok(user, snum)) {
 805                 DEBUG(0,("authorise_login: rejected invalid user %s\n",user));
 806                 ok = False;
 807         }
 808 
 809         return(ok);
 810 }

/* [<][>][^][v][top][bottom][index][help] */