summaryrefslogtreecommitdiffstats
path: root/source/auth/pass_check.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/auth/pass_check.c')
-rw-r--r--source/auth/pass_check.c371
1 files changed, 226 insertions, 145 deletions
diff --git a/source/auth/pass_check.c b/source/auth/pass_check.c
index e1783bfd1e2..68f0566aee7 100644
--- a/source/auth/pass_check.c
+++ b/source/auth/pass_check.c
@@ -1,5 +1,6 @@
/*
- Unix SMB/CIFS implementation.
+ Unix SMB/Netbios implementation.
+ Version 1.9.
Password checking
Copyright (C) Andrew Tridgell 1992-1998
@@ -23,15 +24,10 @@
#include "includes.h"
-#undef DBGC_CLASS
-#define DBGC_CLASS DBGC_AUTH
-
/* these are kept here to keep the string_combinations function simple */
static fstring this_user;
-#if !defined(WITH_PAM)
static fstring this_salt;
static fstring this_crypted;
-#endif
#ifdef WITH_AFS
@@ -372,6 +368,122 @@ void dfs_unlogin(void)
}
#endif
+#ifdef KRB5_AUTH
+
+#include <krb5.h>
+
+/*******************************************************************
+check on Kerberos authentication
+********************************************************************/
+static BOOL krb5_auth(char *user, char *password)
+{
+ krb5_data tgtname = {
+ 0,
+ KRB5_TGS_NAME_SIZE,
+ KRB5_TGS_NAME
+ };
+ krb5_context kcontext;
+ krb5_principal kprinc;
+ krb5_principal server;
+ krb5_creds kcreds;
+ int options = 0;
+ krb5_address **addrs = (krb5_address **) 0;
+ krb5_preauthtype *preauth = NULL;
+ krb5_keytab keytab = NULL;
+ krb5_timestamp now;
+ krb5_ccache ccache = NULL;
+ int retval;
+ char *name;
+
+ if (retval = krb5_init_context(&kcontext))
+ {
+ return (False);
+ }
+
+ if (retval = krb5_timeofday(kcontext, &now))
+ {
+ return (False);
+ }
+
+ if (retval = krb5_cc_default(kcontext, &ccache))
+ {
+ return (False);
+ }
+
+ if (retval = krb5_parse_name(kcontext, user, &kprinc))
+ {
+ return (False);
+ }
+
+ ZERO_STRUCT(kcreds);
+
+ kcreds.client = kprinc;
+
+ if ((retval = krb5_build_principal_ext(kcontext, &server,
+ krb5_princ_realm(kcontext,
+ kprinc)->
+ length,
+ krb5_princ_realm(kcontext,
+ kprinc)->data,
+ tgtname.length, tgtname.data,
+ krb5_princ_realm(kcontext,
+ kprinc)->
+ length,
+ krb5_princ_realm(kcontext,
+ kprinc)->data,
+ 0)))
+ {
+ return (False);
+ }
+
+ kcreds.server = server;
+
+ retval = krb5_get_in_tkt_with_password(kcontext,
+ options,
+ addrs,
+ NULL,
+ preauth,
+ password, 0, &kcreds, 0);
+
+ if (retval)
+ {
+ return (False);
+ }
+
+ return (True);
+}
+#endif /* KRB5_AUTH */
+
+#ifdef KRB4_AUTH
+#include <krb.h>
+
+/*******************************************************************
+check on Kerberos authentication
+********************************************************************/
+static BOOL krb4_auth(char *user, char *password)
+{
+ char realm[REALM_SZ];
+ char tkfile[MAXPATHLEN];
+
+ if (krb_get_lrealm(realm, 1) != KSUCCESS)
+ {
+ (void)safe_strcpy(realm, KRB_REALM, sizeof(realm) - 1);
+ }
+
+ (void)slprintf(tkfile, sizeof(tkfile) - 1, "/tmp/samba_tkt_%d",
+ (int)sys_getpid());
+
+ krb_set_tkt_string(tkfile);
+ if (krb_verify_user(user, "", realm, password, 0, "rmcd") == KSUCCESS)
+ {
+ unlink(tkfile);
+ return 1;
+ }
+ unlink(tkfile);
+ return 0;
+}
+#endif /* KRB4_AUTH */
+
#ifdef LINUX_BIGCRYPT
/****************************************************************************
an enhanced crypt for Linux to handle password longer than 8 characters
@@ -436,12 +548,11 @@ try all combinations with N uppercase letters.
offset is the first char to try and change (start with 0)
it assumes the string starts lowercased
****************************************************************************/
-static NTSTATUS string_combinations2(char *s, int offset, NTSTATUS (*fn) (const char *),
+static BOOL string_combinations2(char *s, int offset, BOOL (*fn) (char *),
int N)
{
int len = strlen(s);
int i;
- NTSTATUS nt_status;
#ifdef PASSWORD_LENGTH
len = MIN(len, PASSWORD_LENGTH);
@@ -455,12 +566,11 @@ static NTSTATUS string_combinations2(char *s, int offset, NTSTATUS (*fn) (const
if (!islower(c))
continue;
s[i] = toupper(c);
- if (!NT_STATUS_EQUAL(nt_status = string_combinations2(s, i + 1, fn, N - 1),NT_STATUS_WRONG_PASSWORD)) {
- return (nt_status);
- }
+ if (string_combinations2(s, i + 1, fn, N - 1))
+ return (True);
s[i] = c;
}
- return (NT_STATUS_WRONG_PASSWORD);
+ return (False);
}
/****************************************************************************
@@ -470,76 +580,71 @@ try all combinations with up to N uppercase letters.
offset is the first char to try and change (start with 0)
it assumes the string starts lowercased
****************************************************************************/
-static NTSTATUS string_combinations(char *s, NTSTATUS (*fn) (const char *), int N)
+static BOOL string_combinations(char *s, BOOL (*fn) (char *), int N)
{
int n;
- NTSTATUS nt_status;
for (n = 1; n <= N; n++)
- if (!NT_STATUS_EQUAL(nt_status = string_combinations2(s, 0, fn, n), NT_STATUS_WRONG_PASSWORD))
- return nt_status;
- return NT_STATUS_WRONG_PASSWORD;
+ if (string_combinations2(s, 0, fn, n))
+ return (True);
+ return (False);
}
/****************************************************************************
core of password checking routine
****************************************************************************/
-static NTSTATUS password_check(const char *password)
+static BOOL password_check(char *password)
{
-#ifdef WITH_PAM
- return smb_pam_passcheck(this_user, password);
-#else
- BOOL ret;
+#ifdef WITH_PAM
+ return (NT_STATUS_IS_OK(smb_pam_passcheck(this_user, password)));
+#endif /* WITH_PAM */
#ifdef WITH_AFS
if (afs_auth(this_user, password))
- return NT_STATUS_OK;
+ return (True);
#endif /* WITH_AFS */
#ifdef WITH_DFS
if (dfs_auth(this_user, password))
- return NT_STATUS_OK;
+ return (True);
#endif /* WITH_DFS */
+#ifdef KRB5_AUTH
+ if (krb5_auth(this_user, password))
+ return (True);
+#endif /* KRB5_AUTH */
+
+#ifdef KRB4_AUTH
+ if (krb4_auth(this_user, password))
+ return (True);
+#endif /* KRB4_AUTH */
+
#ifdef OSF1_ENH_SEC
-
- ret = (strcmp(osf1_bigcrypt(password, this_salt),
- this_crypted) == 0);
- if (!ret) {
- DEBUG(2,
- ("OSF1_ENH_SEC failed. Trying normal crypt.\n"));
- ret = (strcmp((char *)crypt(password, this_salt), this_crypted) == 0);
- }
- if (ret) {
- return NT_STATUS_OK;
- } else {
- return NT_STATUS_WRONG_PASSWORD;
+ {
+ BOOL ret =
+ (strcmp
+ (osf1_bigcrypt(password, this_salt),
+ this_crypted) == 0);
+ if (!ret) {
+ DEBUG(2,
+ ("OSF1_ENH_SEC failed. Trying normal crypt.\n"));
+ ret = (strcmp((char *)crypt(password, this_salt), this_crypted) == 0);
+ }
+ return ret;
}
-
#endif /* OSF1_ENH_SEC */
-
+
#ifdef ULTRIX_AUTH
- ret = (strcmp((char *)crypt16(password, this_salt), this_crypted) == 0);
- if (ret) {
- return NT_STATUS_OK;
- } else {
- return NT_STATUS_WRONG_PASSWORD;
- }
-
+ return (strcmp((char *)crypt16(password, this_salt), this_crypted) == 0);
#endif /* ULTRIX_AUTH */
-
+
#ifdef LINUX_BIGCRYPT
- ret = (linux_bigcrypt(password, this_salt, this_crypted));
- if (ret) {
- return NT_STATUS_OK;
- } else {
- return NT_STATUS_WRONG_PASSWORD;
- }
+ return (linux_bigcrypt(password, this_salt, this_crypted));
#endif /* LINUX_BIGCRYPT */
-
+
#if defined(HAVE_BIGCRYPT) && defined(HAVE_CRYPT) && defined(USE_BOTH_CRYPT_CALLS)
-
+
/*
* Some systems have bigcrypt in the C library but might not
* actually use it for the password hashes (HPUX 10.20) is
@@ -548,68 +653,61 @@ static NTSTATUS password_check(const char *password)
*/
if (strcmp(bigcrypt(password, this_salt), this_crypted) == 0)
- return NT_STATUS_OK;
+ return True;
else
- ret = (strcmp((char *)crypt(password, this_salt), this_crypted) == 0);
- if (ret) {
- return NT_STATUS_OK;
- } else {
- return NT_STATUS_WRONG_PASSWORD;
- }
+ return (strcmp((char *)crypt(password, this_salt), this_crypted) == 0);
#else /* HAVE_BIGCRYPT && HAVE_CRYPT && USE_BOTH_CRYPT_CALLS */
-
+
#ifdef HAVE_BIGCRYPT
- ret = (strcmp(bigcrypt(password, this_salt), this_crypted) == 0);
- if (ret) {
- return NT_STATUS_OK;
- } else {
- return NT_STATUS_WRONG_PASSWORD;
- }
+ return (strcmp(bigcrypt(password, this_salt), this_crypted) == 0);
#endif /* HAVE_BIGCRYPT */
-
+
#ifndef HAVE_CRYPT
DEBUG(1, ("Warning - no crypt available\n"));
- return NT_STATUS_LOGON_FAILURE;
+ return (False);
#else /* HAVE_CRYPT */
- ret = (strcmp((char *)crypt(password, this_salt), this_crypted) == 0);
- if (ret) {
- return NT_STATUS_OK;
- } else {
- return NT_STATUS_WRONG_PASSWORD;
- }
+ return (strcmp((char *)crypt(password, this_salt), this_crypted) == 0);
#endif /* HAVE_CRYPT */
#endif /* HAVE_BIGCRYPT && HAVE_CRYPT && USE_BOTH_CRYPT_CALLS */
-#endif /* WITH_PAM || KRB4_AUTH || KRB5_AUTH */
}
/****************************************************************************
-CHECK if a username/password is OK
+check if a username/password is OK
the function pointer fn() points to a function to call when a successful
match is found and is used to update the encrypted password file
-return NT_STATUS_OK on correct match, appropriate error otherwise
+return True on correct match, False otherwise
****************************************************************************/
-NTSTATUS pass_check(const struct passwd *pass, const char *user, const char *password,
- int pwlen, BOOL (*fn) (const char *, const char *), BOOL run_cracker)
+BOOL pass_check(char *user, char *password, int pwlen, struct passwd *pwd,
+ BOOL (*fn) (char *, char *))
{
pstring pass2;
int level = lp_passwordlevel();
+ struct passwd *pass = NULL;
- NTSTATUS nt_status;
+ if (password)
+ password[pwlen] = 0;
#if DEBUG_PASSWORD
DEBUG(100, ("checking user=[%s] pass=[%s]\n", user, password));
#endif
if (!password)
- return NT_STATUS_LOGON_FAILURE;
+ return (False);
if (((!*password) || (!pwlen)) && !lp_null_passwords())
- return NT_STATUS_LOGON_FAILURE;
+ return (False);
-#if defined(WITH_PAM)
+ if (pwd && !user) {
+ pass = (struct passwd *)pwd;
+ user = pass->pw_name;
+ } else {
+ pass = Get_Pwnam(user, True);
+ }
+
+#ifdef WITH_PAM
/*
* If we're using PAM we want to short-circuit all the
@@ -626,16 +724,9 @@ NTSTATUS pass_check(const struct passwd *pass, const char *user, const char *pas
if (!pass) {
DEBUG(3, ("Couldn't find user %s\n", user));
- return NT_STATUS_NO_SUCH_USER;
+ return (False);
}
-
- /* Copy into global for the convenience of looping code */
- /* Also the place to keep the 'password' no matter what
- crazy struct it started in... */
- fstrcpy(this_crypted, pass->pw_passwd);
- fstrcpy(this_salt, pass->pw_passwd);
-
#ifdef HAVE_GETSPNAM
{
struct spwd *spass;
@@ -646,10 +737,8 @@ NTSTATUS pass_check(const struct passwd *pass, const char *user, const char *pas
perhaps for IPC password changing requests */
spass = getspnam(pass->pw_name);
- if (spass && spass->sp_pwdp) {
- fstrcpy(this_crypted, spass->sp_pwdp);
- fstrcpy(this_salt, spass->sp_pwdp);
- }
+ if (spass && spass->sp_pwdp)
+ pstrcpy(pass->pw_passwd, spass->sp_pwdp);
}
#elif defined(IA_UINFO)
{
@@ -667,16 +756,7 @@ NTSTATUS pass_check(const struct passwd *pass, const char *user, const char *pas
{
struct pr_passwd *pr_pw = getprpwnam(pass->pw_name);
if (pr_pw && pr_pw->ufld.fd_encrypt)
- fstrcpy(this_crypted, pr_pw->ufld.fd_encrypt);
- }
-#endif
-
-#ifdef HAVE_GETPWANAM
- {
- struct passwd_adjunct *pwret;
- pwret = getpwanam(s);
- if (pwret && pwret->pwa_passwd)
- fstrcpy(this_crypted, pwret->pwa_passwd);
+ pstrcpy(pass->pw_passwd, pr_pw->ufld.fd_encrypt);
}
#endif
@@ -687,8 +767,8 @@ NTSTATUS pass_check(const struct passwd *pass, const char *user, const char *pas
user));
mypasswd = getprpwnam(user);
if (mypasswd) {
- fstrcpy(this_user, mypasswd->ufld.fd_name);
- fstrcpy(this_crypted, mypasswd->ufld.fd_encrypt);
+ fstrcpy(pass->pw_name, mypasswd->ufld.fd_name);
+ fstrcpy(pass->pw_passwd, mypasswd->ufld.fd_encrypt);
} else {
DEBUG(5,
("OSF1_ENH_SEC: No entry for user %s in protected database !\n",
@@ -701,84 +781,85 @@ NTSTATUS pass_check(const struct passwd *pass, const char *user, const char *pas
{
AUTHORIZATION *ap = getauthuid(pass->pw_uid);
if (ap) {
- fstrcpy(this_crypted, ap->a_password);
+ fstrcpy(pass->pw_passwd, ap->a_password);
endauthent();
}
}
#endif
+ /* extract relevant info */
+ fstrcpy(this_user, pass->pw_name);
+ fstrcpy(this_salt, pass->pw_passwd);
+
#if defined(HAVE_TRUNCATED_SALT)
/* crypt on some platforms (HPUX in particular)
won't work with more than 2 salt characters. */
this_salt[2] = 0;
#endif
+ fstrcpy(this_crypted, pass->pw_passwd);
+
if (!*this_crypted) {
if (!lp_null_passwords()) {
DEBUG(2, ("Disallowing %s with null password\n",
this_user));
- return NT_STATUS_LOGON_FAILURE;
+ return (False);
}
if (!*password) {
DEBUG(3,
("Allowing access to %s with null password\n",
this_user));
- return NT_STATUS_OK;
+ return (True);
}
}
-#endif /* defined(WITH_PAM) */
+#endif /* WITH_PAM */
/* try it as it came to us */
- nt_status = password_check(password);
- if NT_STATUS_IS_OK(nt_status) {
- if (fn) {
- fn(user, password);
- }
- return (nt_status);
- } else if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD)) {
- /* No point continuing if its not the password thats to blame (ie PAM disabled). */
- return (nt_status);
- }
-
- if (!run_cracker) {
- return (nt_status);
+ if (password_check(password)) {
+ if (fn)
+ fn(user, password);
+ return (True);
}
/* if the password was given to us with mixed case then we don't
- * need to proceed as we know it hasn't been case modified by the
- * client */
+ need to proceed as we know it hasn't been case modified by the
+ client */
if (strhasupper(password) && strhaslower(password)) {
- return nt_status;
+ return (False);
}
/* make a copy of it */
- pstrcpy(pass2, password);
+ StrnCpy(pass2, password, sizeof(pass2) - 1);
/* try all lowercase if it's currently all uppercase */
- if (strhasupper(pass2)) {
- strlower(pass2);
- if NT_STATUS_IS_OK(nt_status = password_check(pass2)) {
- if (fn)
- fn(user, pass2);
- return (nt_status);
+ if (strhasupper(password)) {
+ strlower(password);
+ if (password_check(password)) {
+ if (fn)
+ fn(user, password);
+ return (True);
}
}
/* give up? */
if (level < 1) {
- return NT_STATUS_WRONG_PASSWORD;
+ /* restore it */
+ fstrcpy(password, pass2);
+ return (False);
}
/* last chance - all combinations of up to level chars upper! */
- strlower(pass2);
+ strlower(password);
-
- if (NT_STATUS_IS_OK(nt_status = string_combinations(pass2, password_check, level))) {
- if (fn)
- fn(user, pass2);
- return nt_status;
+ if (string_combinations(password, password_check, level)) {
+ if (fn)
+ fn(user, password);
+ return (True);
}
-
- return NT_STATUS_WRONG_PASSWORD;
+
+ /* restore it */
+ fstrcpy(password, pass2);
+
+ return (False);
}