LCOV - code coverage report
Current view: top level - source3/auth - pass_check.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 0 31 0.0 %
Date: 2024-04-21 15:09:00 Functions: 0 2 0.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Password checking
       4             :    Copyright (C) Andrew Tridgell 1992-1998
       5             : 
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : /* this module is for checking a username/password against a system
      21             :    password database. The SMB encrypted password support is elsewhere */
      22             : 
      23             : #include "includes.h"
      24             : #include "system/passwd.h"
      25             : #include "auth.h"
      26             : 
      27             : #undef DBGC_CLASS
      28             : #define DBGC_CLASS DBGC_AUTH
      29             : 
      30             : #if !defined(WITH_PAM)
      31             : static char *ths_salt;
      32             : /* This must be writable. */
      33             : static char *get_this_salt(void)
      34             : {
      35             :         return ths_salt;
      36             : }
      37             : 
      38             : /* We may be setting a modified version of the same
      39             :  * string, so don't free before use. */
      40             : 
      41             : static const char *set_this_salt(const char *newsalt)
      42             : {
      43             :         char *orig_salt = ths_salt;
      44             :         ths_salt = SMB_STRDUP(newsalt);
      45             :         SAFE_FREE(orig_salt);
      46             :         return ths_salt;
      47             : }
      48             : 
      49             : static char *ths_crypted;
      50             : static const char *get_this_crypted(void)
      51             : {
      52             :         if (!ths_crypted) {
      53             :                 return "";
      54             :         }
      55             :         return ths_crypted;
      56             : }
      57             : 
      58             : static const char *set_this_crypted(const char *newcrypted)
      59             : {
      60             :         char *orig_crypted = ths_crypted;
      61             :         ths_crypted = SMB_STRDUP(newcrypted);
      62             :         SAFE_FREE(orig_crypted);
      63             :         return ths_crypted;
      64             : }
      65             : #endif
      66             : 
      67             : 
      68             : 
      69             : 
      70             : 
      71             : 
      72             : 
      73             : /****************************************************************************
      74             : core of password checking routine
      75             : ****************************************************************************/
      76           0 : static NTSTATUS password_check(const char *user, const char *password, const void *private_data)
      77             : {
      78             : #ifdef WITH_PAM
      79           0 :         const char *rhost = (const char *)private_data;
      80           0 :         return smb_pam_passcheck(user, rhost, password);
      81             : #else
      82             : 
      83             :         bool ret;
      84             : 
      85             : 
      86             : 
      87             : 
      88             : #ifdef ULTRIX_AUTH
      89             :         ret = (strcmp((char *)crypt16(password, get_this_salt()), get_this_crypted()) == 0);
      90             :         if (ret) {
      91             :                 return NT_STATUS_OK;
      92             :         } else {
      93             :                 return NT_STATUS_WRONG_PASSWORD;
      94             :         }
      95             : 
      96             : #endif /* ULTRIX_AUTH */
      97             : 
      98             : 
      99             : 
     100             : #ifdef HAVE_BIGCRYPT
     101             :         ret = (strcmp(bigcrypt(password, get_this_salt()), get_this_crypted()) == 0);
     102             :         if (ret) {
     103             :                 return NT_STATUS_OK;
     104             :         } else {
     105             :                 return NT_STATUS_WRONG_PASSWORD;
     106             :         }
     107             : #endif /* HAVE_BIGCRYPT */
     108             : 
     109             : #ifndef HAVE_CRYPT
     110             :         DEBUG(1, ("Warning - no crypt available\n"));
     111             :         return NT_STATUS_LOGON_FAILURE;
     112             : #else /* HAVE_CRYPT */
     113             :         ret = (strcmp((char *)crypt(password, get_this_salt()), get_this_crypted()) == 0);
     114             :         if (ret) {
     115             :                 return NT_STATUS_OK;
     116             :         } else {
     117             :                 return NT_STATUS_WRONG_PASSWORD;
     118             :         }
     119             : #endif /* HAVE_CRYPT */
     120             : #endif /* WITH_PAM */
     121             : }
     122             : 
     123             : 
     124             : 
     125             : /****************************************************************************
     126             : CHECK if a username/password is OK
     127             : the function pointer fn() points to a function to call when a successful
     128             : match is found and is used to update the encrypted password file 
     129             : return NT_STATUS_OK on correct match, appropriate error otherwise
     130             : ****************************************************************************/
     131             : 
     132           0 : NTSTATUS pass_check(const struct passwd *pass,
     133             :                     const char *user,
     134             :                     const char *rhost,
     135             :                     const char *password,
     136             :                     bool run_cracker)
     137             : {
     138           0 :         char *pass2 = NULL;
     139             : 
     140           0 :         NTSTATUS nt_status;
     141             : 
     142             : #ifdef DEBUG_PASSWORD
     143           0 :         DEBUG(100, ("checking user=[%s] pass=[%s]\n", user, password));
     144             : #endif
     145             : 
     146           0 :         if (!password)
     147           0 :                 return NT_STATUS_LOGON_FAILURE;
     148             : 
     149           0 :         if ((!*password) && !lp_null_passwords())
     150           0 :                 return NT_STATUS_LOGON_FAILURE;
     151             : 
     152             : #if defined(WITH_PAM) 
     153             : 
     154             :         /*
     155             :          * If we're using PAM we want to short-circuit all the 
     156             :          * checks below and dive straight into the PAM code.
     157             :          */
     158             : 
     159           0 :         DEBUG(4, ("pass_check: Checking (PAM) password for user %s\n", user));
     160             : 
     161             : #else /* Not using PAM */
     162             : 
     163             :         DEBUG(4, ("pass_check: Checking password for user %s\n", user));
     164             : 
     165             :         if (!pass) {
     166             :                 DEBUG(3, ("Couldn't find user %s\n", user));
     167             :                 return NT_STATUS_NO_SUCH_USER;
     168             :         }
     169             : 
     170             : 
     171             :         /* Copy into global for the convenience of looping code */
     172             :         /* Also the place to keep the 'password' no matter what
     173             :            crazy struct it started in... */
     174             :         if (set_this_crypted(pass->pw_passwd) == NULL) {
     175             :                 return NT_STATUS_NO_MEMORY;
     176             :         }
     177             :         if (set_this_salt(pass->pw_passwd) == NULL) {
     178             :                 return NT_STATUS_NO_MEMORY;
     179             :         }
     180             : 
     181             : #ifdef HAVE_GETSPNAM
     182             :         {
     183             :                 struct spwd *spass;
     184             : 
     185             :                 /* many shadow systems require you to be root to get
     186             :                    the password, in most cases this should already be
     187             :                    the case when this function is called, except
     188             :                    perhaps for IPC password changing requests */
     189             : 
     190             :                 spass = getspnam(pass->pw_name);
     191             :                 if (spass && spass->sp_pwdp) {
     192             :                         if (set_this_crypted(spass->sp_pwdp) == NULL) {
     193             :                                 return NT_STATUS_NO_MEMORY;
     194             :                         }
     195             :                         if (set_this_salt(spass->sp_pwdp) == NULL) {
     196             :                                 return NT_STATUS_NO_MEMORY;
     197             :                         }
     198             :                 }
     199             :         }
     200             : #elif defined(IA_UINFO)
     201             :         {
     202             :                 /* Need to get password with SVR4.2's ia_ functions
     203             :                    instead of get{sp,pw}ent functions. Required by
     204             :                    UnixWare 2.x, tested on version
     205             :                    2.1. (tangent@cyberport.com) */
     206             :                 uinfo_t uinfo;
     207             :                 if (ia_openinfo(pass->pw_name, &uinfo) != -1)
     208             :                         ia_get_logpwd(uinfo, &(pass->pw_passwd));
     209             :         }
     210             : #endif
     211             : 
     212             : 
     213             : #ifdef HAVE_GETPWANAM
     214             :         {
     215             :                 struct passwd_adjunct *pwret;
     216             :                 pwret = getpwanam(s);
     217             :                 if (pwret && pwret->pwa_passwd) {
     218             :                         if (set_this_crypted(pwret->pwa_passwd) == NULL) {
     219             :                                 return NT_STATUS_NO_MEMORY;
     220             :                         }
     221             :                 }
     222             :         }
     223             : #endif
     224             : 
     225             : 
     226             : #ifdef ULTRIX_AUTH
     227             :         {
     228             :                 AUTHORIZATION *ap = getauthuid(pass->pw_uid);
     229             :                 if (ap) {
     230             :                         if (set_this_crypted(ap->a_password) == NULL) {
     231             :                                 endauthent();
     232             :                                 return NT_STATUS_NO_MEMORY;
     233             :                         }
     234             :                         endauthent();
     235             :                 }
     236             :         }
     237             : #endif
     238             : 
     239             : 
     240             :         if (!get_this_crypted() || !*get_this_crypted()) {
     241             :                 if (!lp_null_passwords()) {
     242             :                         DEBUG(2, ("Disallowing %s with null password\n",
     243             :                                   user));
     244             :                         return NT_STATUS_LOGON_FAILURE;
     245             :                 }
     246             :                 if (!*password) {
     247             :                         DEBUG(3,
     248             :                               ("Allowing access to %s with null password\n",
     249             :                                user));
     250             :                         return NT_STATUS_OK;
     251             :                 }
     252             :         }
     253             : 
     254             : #endif /* defined(WITH_PAM) */
     255             : 
     256             :         /* try it as it came to us */
     257           0 :         nt_status = password_check(user, password, (const void *)rhost);
     258           0 :         if NT_STATUS_IS_OK(nt_status) {
     259           0 :                 return (nt_status);
     260           0 :         } else if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD)) {
     261             :                 /* No point continuing if its not the password that's to blame (ie PAM disabled). */
     262           0 :                 return (nt_status);
     263             :         }
     264             : 
     265           0 :         if (!run_cracker) {
     266           0 :                 return (nt_status);
     267             :         }
     268             : 
     269             :         /* if the password was given to us with mixed case then we don't
     270             :          * need to proceed as we know it hasn't been case modified by the
     271             :          * client */
     272           0 :         if (strhasupper(password) && strhaslower(password)) {
     273           0 :                 return nt_status;
     274             :         }
     275             : 
     276             :         /* make a copy of it */
     277           0 :         pass2 = talloc_strdup(talloc_tos(), password);
     278           0 :         if (!pass2) {
     279           0 :                 return NT_STATUS_NO_MEMORY;
     280             :         }
     281             : 
     282             :         /* try all lowercase if it's currently all uppercase */
     283           0 :         if (strhasupper(pass2)) {
     284           0 :                 if (!strlower_m(pass2)) {
     285           0 :                         return NT_STATUS_INVALID_PARAMETER;
     286             :                 }
     287           0 :                 nt_status = password_check(user, pass2, (const void *)rhost);
     288           0 :                 if (NT_STATUS_IS_OK(nt_status)) {
     289           0 :                         return (nt_status);
     290             :                 }
     291             :         }
     292             : 
     293           0 :         return NT_STATUS_WRONG_PASSWORD;
     294             : }

Generated by: LCOV version 1.14