auth/pass_check.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003    Password checking
00004    Copyright (C) Andrew Tridgell 1992-1998
00005    
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015    
00016    You should have received a copy of the GNU General Public License
00017    along with this program; if not, write to the Free Software
00018    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019 */
00020 
00021 /* this module is for checking a username/password against a system
00022    password database. The SMB encrypted password support is elsewhere */
00023 
00024 #include "includes.h"
00025 
00026 #undef DBGC_CLASS
00027 #define DBGC_CLASS DBGC_AUTH
00028 
00029 /* these are kept here to keep the string_combinations function simple */
00030 static fstring this_user;
00031 #if !defined(WITH_PAM) 
00032 static fstring this_salt;
00033 static fstring this_crypted;
00034 #endif
00035 
00036 #ifdef WITH_AFS
00037 
00038 #include <afs/stds.h>
00039 #include <afs/kautils.h>
00040 
00041 /*******************************************************************
00042 check on AFS authentication
00043 ********************************************************************/
00044 static BOOL afs_auth(char *user, char *password)
00045 {
00046         long password_expires = 0;
00047         char *reason;
00048 
00049         /* For versions of AFS prior to 3.3, this routine has few arguments, */
00050         /* but since I can't find the old documentation... :-)               */
00051         setpag();
00052         if (ka_UserAuthenticateGeneral
00053             (KA_USERAUTH_VERSION + KA_USERAUTH_DOSETPAG, user, (char *)0,       /* instance */
00054              (char *)0,         /* cell */
00055              password, 0,       /* lifetime, default */
00056              &password_expires, /*days 'til it expires */
00057              0,                 /* spare 2 */
00058              &reason) == 0)
00059         {
00060                 return (True);
00061         }
00062         DEBUG(1,
00063               ("AFS authentication for \"%s\" failed (%s)\n", user, reason));
00064         return (False);
00065 }
00066 #endif
00067 
00068 
00069 #ifdef WITH_DFS
00070 
00071 #include <dce/dce_error.h>
00072 #include <dce/sec_login.h>
00073 
00074 /*****************************************************************
00075  This new version of the DFS_AUTH code was donated by Karsten Muuss
00076  <muuss@or.uni-bonn.de>. It fixes the following problems with the
00077  old code :
00078 
00079   - Server credentials may expire
00080   - Client credential cache files have wrong owner
00081   - purge_context() function is called with invalid argument
00082 
00083  This new code was modified to ensure that on exit the uid/gid is
00084  still root, and the original directory is restored. JRA.
00085 ******************************************************************/
00086 
00087 sec_login_handle_t my_dce_sec_context;
00088 int dcelogin_atmost_once = 0;
00089 
00090 /*******************************************************************
00091 check on a DCE/DFS authentication
00092 ********************************************************************/
00093 static BOOL dfs_auth(char *user, char *password)
00094 {
00095         struct tm *t;
00096         error_status_t err;
00097         int err2;
00098         int prterr;
00099         signed32 expire_time, current_time;
00100         boolean32 password_reset;
00101         struct passwd *pw;
00102         sec_passwd_rec_t passwd_rec;
00103         sec_login_auth_src_t auth_src = sec_login_auth_src_network;
00104         unsigned char dce_errstr[dce_c_error_string_len];
00105         gid_t egid;
00106 
00107         if (dcelogin_atmost_once)
00108                 return (False);
00109 
00110 #ifdef HAVE_CRYPT
00111         /*
00112          * We only go for a DCE login context if the given password
00113          * matches that stored in the local password file.. 
00114          * Assumes local passwd file is kept in sync w/ DCE RGY!
00115          */
00116 
00117         if (strcmp((char *)crypt(password, this_salt), this_crypted))
00118         {
00119                 return (False);
00120         }
00121 #endif
00122 
00123         sec_login_get_current_context(&my_dce_sec_context, &err);
00124         if (err != error_status_ok)
00125         {
00126                 dce_error_inq_text(err, dce_errstr, &err2);
00127                 DEBUG(0, ("DCE can't get current context. %s\n", dce_errstr));
00128 
00129                 return (False);
00130         }
00131 
00132         sec_login_certify_identity(my_dce_sec_context, &err);
00133         if (err != error_status_ok)
00134         {
00135                 dce_error_inq_text(err, dce_errstr, &err2);
00136                 DEBUG(0, ("DCE can't get current context. %s\n", dce_errstr));
00137 
00138                 return (False);
00139         }
00140 
00141         sec_login_get_expiration(my_dce_sec_context, &expire_time, &err);
00142         if (err != error_status_ok)
00143         {
00144                 dce_error_inq_text(err, dce_errstr, &err2);
00145                 DEBUG(0, ("DCE can't get expiration. %s\n", dce_errstr));
00146 
00147                 return (False);
00148         }
00149 
00150         time(&current_time);
00151 
00152         if (expire_time < (current_time + 60))
00153         {
00154                 struct passwd *pw;
00155                 sec_passwd_rec_t *key;
00156 
00157                 sec_login_get_pwent(my_dce_sec_context,
00158                                     (sec_login_passwd_t *) & pw, &err);
00159                 if (err != error_status_ok)
00160                 {
00161                         dce_error_inq_text(err, dce_errstr, &err2);
00162                         DEBUG(0, ("DCE can't get pwent. %s\n", dce_errstr));
00163 
00164                         return (False);
00165                 }
00166 
00167                 sec_login_refresh_identity(my_dce_sec_context, &err);
00168                 if (err != error_status_ok)
00169                 {
00170                         dce_error_inq_text(err, dce_errstr, &err2);
00171                         DEBUG(0, ("DCE can't refresh identity. %s\n",
00172                                   dce_errstr));
00173 
00174                         return (False);
00175                 }
00176 
00177                 sec_key_mgmt_get_key(rpc_c_authn_dce_secret, NULL,
00178                                      (unsigned char *)pw->pw_name,
00179                                      sec_c_key_version_none,
00180                                      (void **)&key, &err);
00181                 if (err != error_status_ok)
00182                 {
00183                         dce_error_inq_text(err, dce_errstr, &err2);
00184                         DEBUG(0, ("DCE can't get key for %s. %s\n",
00185                                   pw->pw_name, dce_errstr));
00186 
00187                         return (False);
00188                 }
00189 
00190                 sec_login_valid_and_cert_ident(my_dce_sec_context, key,
00191                                                &password_reset, &auth_src,
00192                                                &err);
00193                 if (err != error_status_ok)
00194                 {
00195                         dce_error_inq_text(err, dce_errstr, &err2);
00196                         DEBUG(0,
00197                               ("DCE can't validate and certify identity for %s. %s\n",
00198                                pw->pw_name, dce_errstr));
00199                 }
00200 
00201                 sec_key_mgmt_free_key(key, &err);
00202                 if (err != error_status_ok)
00203                 {
00204                         dce_error_inq_text(err, dce_errstr, &err2);
00205                         DEBUG(0, ("DCE can't free key.\n", dce_errstr));
00206                 }
00207         }
00208 
00209         if (sec_login_setup_identity((unsigned char *)user,
00210                                      sec_login_no_flags,
00211                                      &my_dce_sec_context, &err) == 0)
00212         {
00213                 dce_error_inq_text(err, dce_errstr, &err2);
00214                 DEBUG(0, ("DCE Setup Identity for %s failed: %s\n",
00215                           user, dce_errstr));
00216                 return (False);
00217         }
00218 
00219         sec_login_get_pwent(my_dce_sec_context,
00220                             (sec_login_passwd_t *) & pw, &err);
00221         if (err != error_status_ok)
00222         {
00223                 dce_error_inq_text(err, dce_errstr, &err2);
00224                 DEBUG(0, ("DCE can't get pwent. %s\n", dce_errstr));
00225 
00226                 return (False);
00227         }
00228 
00229         sec_login_purge_context(&my_dce_sec_context, &err);
00230         if (err != error_status_ok)
00231         {
00232                 dce_error_inq_text(err, dce_errstr, &err2);
00233                 DEBUG(0, ("DCE can't purge context. %s\n", dce_errstr));
00234 
00235                 return (False);
00236         }
00237 
00238         /*
00239          * NB. I'd like to change these to call something like change_to_user()
00240          * instead but currently we don't have a connection
00241          * context to become the correct user. This is already
00242          * fairly platform specific code however, so I think
00243          * this should be ok. I have added code to go
00244          * back to being root on error though. JRA.
00245          */
00246 
00247         egid = getegid();
00248 
00249         set_effective_gid(pw->pw_gid);
00250         set_effective_uid(pw->pw_uid);
00251 
00252         if (sec_login_setup_identity((unsigned char *)user,
00253                                      sec_login_no_flags,
00254                                      &my_dce_sec_context, &err) == 0)
00255         {
00256                 dce_error_inq_text(err, dce_errstr, &err2);
00257                 DEBUG(0, ("DCE Setup Identity for %s failed: %s\n",
00258                           user, dce_errstr));
00259                 goto err;
00260         }
00261 
00262         sec_login_get_pwent(my_dce_sec_context,
00263                             (sec_login_passwd_t *) & pw, &err);
00264         if (err != error_status_ok)
00265         {
00266                 dce_error_inq_text(err, dce_errstr, &err2);
00267                 DEBUG(0, ("DCE can't get pwent. %s\n", dce_errstr));
00268                 goto err;
00269         }
00270 
00271         passwd_rec.version_number = sec_passwd_c_version_none;
00272         passwd_rec.pepper = NULL;
00273         passwd_rec.key.key_type = sec_passwd_plain;
00274         passwd_rec.key.tagged_union.plain = (idl_char *) password;
00275 
00276         sec_login_validate_identity(my_dce_sec_context,
00277                                     &passwd_rec, &password_reset,
00278                                     &auth_src, &err);
00279         if (err != error_status_ok)
00280         {
00281                 dce_error_inq_text(err, dce_errstr, &err2);
00282                 DEBUG(0,
00283                       ("DCE Identity Validation failed for principal %s: %s\n",
00284                        user, dce_errstr));
00285                 goto err;
00286         }
00287 
00288         sec_login_certify_identity(my_dce_sec_context, &err);
00289         if (err != error_status_ok)
00290         {
00291                 dce_error_inq_text(err, dce_errstr, &err2);
00292                 DEBUG(0, ("DCE certify identity failed: %s\n", dce_errstr));
00293                 goto err;
00294         }
00295 
00296         if (auth_src != sec_login_auth_src_network)
00297         {
00298                 DEBUG(0, ("DCE context has no network credentials.\n"));
00299         }
00300 
00301         sec_login_set_context(my_dce_sec_context, &err);
00302         if (err != error_status_ok)
00303         {
00304                 dce_error_inq_text(err, dce_errstr, &err2);
00305                 DEBUG(0,
00306                       ("DCE login failed for principal %s, cant set context: %s\n",
00307                        user, dce_errstr));
00308 
00309                 sec_login_purge_context(&my_dce_sec_context, &err);
00310                 goto err;
00311         }
00312 
00313         sec_login_get_pwent(my_dce_sec_context,
00314                             (sec_login_passwd_t *) & pw, &err);
00315         if (err != error_status_ok)
00316         {
00317                 dce_error_inq_text(err, dce_errstr, &err2);
00318                 DEBUG(0, ("DCE can't get pwent. %s\n", dce_errstr));
00319                 goto err;
00320         }
00321 
00322         DEBUG(0, ("DCE login succeeded for principal %s on pid %d\n",
00323                   user, sys_getpid()));
00324 
00325         DEBUG(3, ("DCE principal: %s\n"
00326                   "          uid: %d\n"
00327                   "          gid: %d\n",
00328                   pw->pw_name, pw->pw_uid, pw->pw_gid));
00329         DEBUG(3, ("         info: %s\n"
00330                   "          dir: %s\n"
00331                   "        shell: %s\n",
00332                   pw->pw_gecos, pw->pw_dir, pw->pw_shell));
00333 
00334         sec_login_get_expiration(my_dce_sec_context, &expire_time, &err);
00335         if (err != error_status_ok)
00336         {
00337                 dce_error_inq_text(err, dce_errstr, &err2);
00338                 DEBUG(0, ("DCE can't get expiration. %s\n", dce_errstr));
00339                 goto err;
00340         }
00341 
00342         set_effective_uid(0);
00343         set_effective_gid(0);
00344 
00345         t = localtime(&expire_time);
00346         if (t) {
00347                 const char *asct = asctime(t);
00348                 if (asct) {
00349                         DEBUG(0,("DCE context expires: %s", asct));
00350                 }
00351         }
00352 
00353         dcelogin_atmost_once = 1;
00354         return (True);
00355 
00356       err:
00357 
00358         /* Go back to root, JRA. */
00359         set_effective_uid(0);
00360         set_effective_gid(egid);
00361         return (False);
00362 }
00363 
00364 void dfs_unlogin(void)
00365 {
00366         error_status_t err;
00367         int err2;
00368         unsigned char dce_errstr[dce_c_error_string_len];
00369 
00370         sec_login_purge_context(&my_dce_sec_context, &err);
00371         if (err != error_status_ok)
00372         {
00373                 dce_error_inq_text(err, dce_errstr, &err2);
00374                 DEBUG(0,
00375                       ("DCE purge login context failed for server instance %d: %s\n",
00376                        sys_getpid(), dce_errstr));
00377         }
00378 }
00379 #endif
00380 
00381 #ifdef LINUX_BIGCRYPT
00382 /****************************************************************************
00383 an enhanced crypt for Linux to handle password longer than 8 characters
00384 ****************************************************************************/
00385 static int linux_bigcrypt(char *password, char *salt1, char *crypted)
00386 {
00387 #define LINUX_PASSWORD_SEG_CHARS 8
00388         char salt[3];
00389         int i;
00390 
00391         StrnCpy(salt, salt1, 2);
00392         crypted += 2;
00393 
00394         for (i = strlen(password); i > 0; i -= LINUX_PASSWORD_SEG_CHARS) {
00395                 char *p = crypt(password, salt) + 2;
00396                 if (strncmp(p, crypted, LINUX_PASSWORD_SEG_CHARS) != 0)
00397                         return (0);
00398                 password += LINUX_PASSWORD_SEG_CHARS;
00399                 crypted += strlen(p);
00400         }
00401 
00402         return (1);
00403 }
00404 #endif
00405 
00406 #ifdef OSF1_ENH_SEC
00407 /****************************************************************************
00408 an enhanced crypt for OSF1
00409 ****************************************************************************/
00410 static char *osf1_bigcrypt(char *password, char *salt1)
00411 {
00412         static char result[AUTH_MAX_PASSWD_LENGTH] = "";
00413         char *p1;
00414         char *p2 = password;
00415         char salt[3];
00416         int i;
00417         int parts = strlen(password) / AUTH_CLEARTEXT_SEG_CHARS;
00418         if (strlen(password) % AUTH_CLEARTEXT_SEG_CHARS)
00419                 parts++;
00420 
00421         StrnCpy(salt, salt1, 2);
00422         StrnCpy(result, salt1, 2);
00423         result[2] = '\0';
00424 
00425         for (i = 0; i < parts; i++) {
00426                 p1 = crypt(p2, salt);
00427                 strncat(result, p1 + 2,
00428                         AUTH_MAX_PASSWD_LENGTH - strlen(p1 + 2) - 1);
00429                 StrnCpy(salt, &result[2 + i * AUTH_CIPHERTEXT_SEG_CHARS], 2);
00430                 p2 += AUTH_CLEARTEXT_SEG_CHARS;
00431         }
00432 
00433         return (result);
00434 }
00435 #endif
00436 
00437 
00438 /****************************************************************************
00439 apply a function to upper/lower case combinations
00440 of a string and return true if one of them returns true.
00441 try all combinations with N uppercase letters.
00442 offset is the first char to try and change (start with 0)
00443 it assumes the string starts lowercased
00444 ****************************************************************************/
00445 static NTSTATUS string_combinations2(char *s, int offset, NTSTATUS (*fn) (const char *),
00446                                  int N)
00447 {
00448         int len = strlen(s);
00449         int i;
00450         NTSTATUS nt_status;
00451 
00452 #ifdef PASSWORD_LENGTH
00453         len = MIN(len, PASSWORD_LENGTH);
00454 #endif
00455 
00456         if (N <= 0 || offset >= len)
00457                 return (fn(s));
00458 
00459         for (i = offset; i < (len - (N - 1)); i++) {
00460                 char c = s[i];
00461                 if (!islower_ascii(c))
00462                         continue;
00463                 s[i] = toupper_ascii(c);
00464                 if (!NT_STATUS_EQUAL(nt_status = string_combinations2(s, i + 1, fn, N - 1),NT_STATUS_WRONG_PASSWORD)) {
00465                         return (nt_status);
00466                 }
00467                 s[i] = c;
00468         }
00469         return (NT_STATUS_WRONG_PASSWORD);
00470 }
00471 
00472 /****************************************************************************
00473 apply a function to upper/lower case combinations
00474 of a string and return true if one of them returns true.
00475 try all combinations with up to N uppercase letters.
00476 offset is the first char to try and change (start with 0)
00477 it assumes the string starts lowercased
00478 ****************************************************************************/
00479 static NTSTATUS string_combinations(char *s, NTSTATUS (*fn) (const char *), int N)
00480 {
00481         int n;
00482         NTSTATUS nt_status;
00483         for (n = 1; n <= N; n++)
00484                 if (!NT_STATUS_EQUAL(nt_status = string_combinations2(s, 0, fn, n), NT_STATUS_WRONG_PASSWORD))
00485                         return nt_status;
00486         return NT_STATUS_WRONG_PASSWORD;
00487 }
00488 
00489 
00490 /****************************************************************************
00491 core of password checking routine
00492 ****************************************************************************/
00493 static NTSTATUS password_check(const char *password)
00494 {
00495 #ifdef WITH_PAM
00496         return smb_pam_passcheck(this_user, password);
00497 #else
00498 
00499         BOOL ret;
00500 
00501 #ifdef WITH_AFS
00502         if (afs_auth(this_user, password))
00503                 return NT_STATUS_OK;
00504 #endif /* WITH_AFS */
00505 
00506 #ifdef WITH_DFS
00507         if (dfs_auth(this_user, password))
00508                 return NT_STATUS_OK;
00509 #endif /* WITH_DFS */
00510 
00511 #ifdef OSF1_ENH_SEC
00512         
00513         ret = (strcmp(osf1_bigcrypt(password, this_salt),
00514                       this_crypted) == 0);
00515         if (!ret) {
00516                 DEBUG(2,
00517                       ("OSF1_ENH_SEC failed. Trying normal crypt.\n"));
00518                 ret = (strcmp((char *)crypt(password, this_salt), this_crypted) == 0);
00519         }
00520         if (ret) {
00521                 return NT_STATUS_OK;
00522         } else {
00523                 return NT_STATUS_WRONG_PASSWORD;
00524         }
00525         
00526 #endif /* OSF1_ENH_SEC */
00527         
00528 #ifdef ULTRIX_AUTH
00529         ret = (strcmp((char *)crypt16(password, this_salt), this_crypted) == 0);
00530         if (ret) {
00531                 return NT_STATUS_OK;
00532         } else {
00533                 return NT_STATUS_WRONG_PASSWORD;
00534         }
00535         
00536 #endif /* ULTRIX_AUTH */
00537         
00538 #ifdef LINUX_BIGCRYPT
00539         ret = (linux_bigcrypt(password, this_salt, this_crypted));
00540         if (ret) {
00541                 return NT_STATUS_OK;
00542         } else {
00543                 return NT_STATUS_WRONG_PASSWORD;
00544         }
00545 #endif /* LINUX_BIGCRYPT */
00546         
00547 #if defined(HAVE_BIGCRYPT) && defined(HAVE_CRYPT) && defined(USE_BOTH_CRYPT_CALLS)
00548         
00549         /*
00550          * Some systems have bigcrypt in the C library but might not
00551          * actually use it for the password hashes (HPUX 10.20) is
00552          * a noteable example. So we try bigcrypt first, followed
00553          * by crypt.
00554          */
00555 
00556         if (strcmp(bigcrypt(password, this_salt), this_crypted) == 0)
00557                 return NT_STATUS_OK;
00558         else
00559                 ret = (strcmp((char *)crypt(password, this_salt), this_crypted) == 0);
00560         if (ret) {
00561                 return NT_STATUS_OK;
00562         } else {
00563                 return NT_STATUS_WRONG_PASSWORD;
00564         }
00565 #else /* HAVE_BIGCRYPT && HAVE_CRYPT && USE_BOTH_CRYPT_CALLS */
00566         
00567 #ifdef HAVE_BIGCRYPT
00568         ret = (strcmp(bigcrypt(password, this_salt), this_crypted) == 0);
00569         if (ret) {
00570                 return NT_STATUS_OK;
00571         } else {
00572                 return NT_STATUS_WRONG_PASSWORD;
00573         }
00574 #endif /* HAVE_BIGCRYPT */
00575         
00576 #ifndef HAVE_CRYPT
00577         DEBUG(1, ("Warning - no crypt available\n"));
00578         return NT_STATUS_LOGON_FAILURE;
00579 #else /* HAVE_CRYPT */
00580         ret = (strcmp((char *)crypt(password, this_salt), this_crypted) == 0);
00581         if (ret) {
00582                 return NT_STATUS_OK;
00583         } else {
00584                 return NT_STATUS_WRONG_PASSWORD;
00585         }
00586 #endif /* HAVE_CRYPT */
00587 #endif /* HAVE_BIGCRYPT && HAVE_CRYPT && USE_BOTH_CRYPT_CALLS */
00588 #endif /* WITH_PAM */
00589 }
00590 
00591 
00592 
00593 /****************************************************************************
00594 CHECK if a username/password is OK
00595 the function pointer fn() points to a function to call when a successful
00596 match is found and is used to update the encrypted password file 
00597 return NT_STATUS_OK on correct match, appropriate error otherwise
00598 ****************************************************************************/
00599 
00600 NTSTATUS pass_check(const struct passwd *pass, const char *user, const char *password, 
00601                     int pwlen, BOOL (*fn) (const char *, const char *), BOOL run_cracker)
00602 {
00603         pstring pass2;
00604         int level = lp_passwordlevel();
00605 
00606         NTSTATUS nt_status;
00607 
00608 #ifdef DEBUG_PASSWORD
00609         DEBUG(100, ("checking user=[%s] pass=[%s]\n", user, password));
00610 #endif
00611 
00612         if (!password)
00613                 return NT_STATUS_LOGON_FAILURE;
00614 
00615         if (((!*password) || (!pwlen)) && !lp_null_passwords())
00616                 return NT_STATUS_LOGON_FAILURE;
00617 
00618 #if defined(WITH_PAM) 
00619 
00620         /*
00621          * If we're using PAM we want to short-circuit all the 
00622          * checks below and dive straight into the PAM code.
00623          */
00624 
00625         fstrcpy(this_user, user);
00626 
00627         DEBUG(4, ("pass_check: Checking (PAM) password for user %s (l=%d)\n", user, pwlen));
00628 
00629 #else /* Not using PAM */
00630 
00631         DEBUG(4, ("pass_check: Checking password for user %s (l=%d)\n", user, pwlen));
00632 
00633         if (!pass) {
00634                 DEBUG(3, ("Couldn't find user %s\n", user));
00635                 return NT_STATUS_NO_SUCH_USER;
00636         }
00637 
00638 
00639         /* Copy into global for the convenience of looping code */
00640         /* Also the place to keep the 'password' no matter what
00641            crazy struct it started in... */
00642         fstrcpy(this_crypted, pass->pw_passwd);
00643         fstrcpy(this_salt, pass->pw_passwd);
00644 
00645 #ifdef HAVE_GETSPNAM
00646         {
00647                 struct spwd *spass;
00648 
00649                 /* many shadow systems require you to be root to get
00650                    the password, in most cases this should already be
00651                    the case when this function is called, except
00652                    perhaps for IPC password changing requests */
00653 
00654                 spass = getspnam(pass->pw_name);
00655                 if (spass && spass->sp_pwdp) {
00656                         fstrcpy(this_crypted, spass->sp_pwdp);
00657                         fstrcpy(this_salt, spass->sp_pwdp);
00658                 }
00659         }
00660 #elif defined(IA_UINFO)
00661         {
00662                 /* Need to get password with SVR4.2's ia_ functions
00663                    instead of get{sp,pw}ent functions. Required by
00664                    UnixWare 2.x, tested on version
00665                    2.1. (tangent@cyberport.com) */
00666                 uinfo_t uinfo;
00667                 if (ia_openinfo(pass->pw_name, &uinfo) != -1)
00668                         ia_get_logpwd(uinfo, &(pass->pw_passwd));
00669         }
00670 #endif
00671 
00672 #ifdef HAVE_GETPRPWNAM
00673         {
00674                 struct pr_passwd *pr_pw = getprpwnam(pass->pw_name);
00675                 if (pr_pw && pr_pw->ufld.fd_encrypt)
00676                         fstrcpy(this_crypted, pr_pw->ufld.fd_encrypt);
00677         }
00678 #endif
00679 
00680 #ifdef HAVE_GETPWANAM
00681         {
00682                 struct passwd_adjunct *pwret;
00683                 pwret = getpwanam(s);
00684                 if (pwret && pwret->pwa_passwd)
00685                         fstrcpy(this_crypted, pwret->pwa_passwd);
00686         }
00687 #endif
00688 
00689 #ifdef OSF1_ENH_SEC
00690         {
00691                 struct pr_passwd *mypasswd;
00692                 DEBUG(5, ("Checking password for user %s in OSF1_ENH_SEC\n",
00693                           user));
00694                 mypasswd = getprpwnam(user);
00695                 if (mypasswd) {
00696                         fstrcpy(this_user, mypasswd->ufld.fd_name);
00697                         fstrcpy(this_crypted, mypasswd->ufld.fd_encrypt);
00698                 } else {
00699                         DEBUG(5,
00700                               ("OSF1_ENH_SEC: No entry for user %s in protected database !\n",
00701                                user));
00702                 }
00703         }
00704 #endif
00705 
00706 #ifdef ULTRIX_AUTH
00707         {
00708                 AUTHORIZATION *ap = getauthuid(pass->pw_uid);
00709                 if (ap) {
00710                         fstrcpy(this_crypted, ap->a_password);
00711                         endauthent();
00712                 }
00713         }
00714 #endif
00715 
00716 #if defined(HAVE_TRUNCATED_SALT)
00717         /* crypt on some platforms (HPUX in particular)
00718            won't work with more than 2 salt characters. */
00719         this_salt[2] = 0;
00720 #endif
00721 
00722         if (!*this_crypted) {
00723                 if (!lp_null_passwords()) {
00724                         DEBUG(2, ("Disallowing %s with null password\n",
00725                                   this_user));
00726                         return NT_STATUS_LOGON_FAILURE;
00727                 }
00728                 if (!*password) {
00729                         DEBUG(3,
00730                               ("Allowing access to %s with null password\n",
00731                                this_user));
00732                         return NT_STATUS_OK;
00733                 }
00734         }
00735 
00736 #endif /* defined(WITH_PAM) */
00737 
00738         /* try it as it came to us */
00739         nt_status = password_check(password);
00740         if NT_STATUS_IS_OK(nt_status) {
00741                 if (fn) {
00742                         fn(user, password);
00743                 }
00744                 return (nt_status);
00745         } else if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD)) {
00746                 /* No point continuing if its not the password thats to blame (ie PAM disabled). */
00747                 return (nt_status);
00748         }
00749 
00750         if (!run_cracker) {
00751                 return (nt_status);
00752         }
00753 
00754         /* if the password was given to us with mixed case then we don't
00755          * need to proceed as we know it hasn't been case modified by the
00756          * client */
00757         if (strhasupper(password) && strhaslower(password)) {
00758                 return nt_status;
00759         }
00760 
00761         /* make a copy of it */
00762         pstrcpy(pass2, password);
00763 
00764         /* try all lowercase if it's currently all uppercase */
00765         if (strhasupper(pass2)) {
00766                 strlower_m(pass2);
00767                 if NT_STATUS_IS_OK(nt_status = password_check(pass2)) {
00768                         if (fn)
00769                                 fn(user, pass2);
00770                         return (nt_status);
00771                 }
00772         }
00773 
00774         /* give up? */
00775         if (level < 1) {
00776                 return NT_STATUS_WRONG_PASSWORD;
00777         }
00778 
00779         /* last chance - all combinations of up to level chars upper! */
00780         strlower_m(pass2);
00781  
00782         if (NT_STATUS_IS_OK(nt_status = string_combinations(pass2, password_check, level))) {
00783                 if (fn)
00784                         fn(user, pass2);
00785                 return nt_status;
00786         }
00787         
00788         return NT_STATUS_WRONG_PASSWORD;
00789 }

Sambaに対してSat Aug 29 21:22:52 2009に生成されました。  doxygen 1.4.7