From bc770edb788f0b6f719011cda683f045b76b7ba5 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 12 Jan 2004 12:18:11 +0000 Subject: [PATCH] First stab at cracklib support (password quality checking) in Samba 3.0 This adds a configure test, that tries to find out if we have a working cracklib installation, and tries to pick up the debian hints on where the dictionary might be found. Default is per my Fedora Core 1 system - I'm not sure how much it changes. Andrew Bartlett --- source/param/loadparm.c | 4 +++ source/rpc_server/srv_samr_nt.c | 17 +++++++-- source/smbd/chgpasswd.c | 79 +++++++++++++++++++++++++++++------------ source/tests/crack.c | 5 +++ 4 files changed, 79 insertions(+), 26 deletions(-) create mode 100644 source/tests/crack.c diff --git a/source/param/loadparm.c b/source/param/loadparm.c index 81a3a322472..66335e983f8 100644 --- a/source/param/loadparm.c +++ b/source/param/loadparm.c @@ -215,6 +215,7 @@ typedef struct int change_notify_timeout; int map_to_guest; int min_passwd_length; + BOOL use_cracklib; int oplock_break_wait_time; int winbind_cache_time; int iLockSpinCount; @@ -787,6 +788,7 @@ static struct parm_struct parm_table[] = { {"hosts equiv", P_STRING, P_GLOBAL, &Globals.szHostsEquiv, NULL, NULL, FLAG_ADVANCED}, {"min passwd length", P_INTEGER, P_GLOBAL, &Globals.min_passwd_length, NULL, NULL, FLAG_ADVANCED}, {"min password length", P_INTEGER, P_GLOBAL, &Globals.min_passwd_length, NULL, NULL, FLAG_ADVANCED}, + {"use cracklib", P_BOOL, P_GLOBAL, &Globals.use_cracklib, NULL, NULL, FLAG_ADVANCED}, {"map to guest", P_ENUM, P_GLOBAL, &Globals.map_to_guest, NULL, enum_map_to_guest, FLAG_ADVANCED}, {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL, NULL, FLAG_ADVANCED}, {"obey pam restrictions", P_BOOL, P_GLOBAL, &Globals.bObeyPamRestrictions, NULL, NULL, FLAG_ADVANCED}, @@ -1437,6 +1439,7 @@ static void init_globals(void) Globals.map_to_guest = 0; /* By Default, "Never" */ Globals.min_passwd_length = MINPASSWDLENGTH; /* By Default, 5. */ + Globals.use_cracklib = False; Globals.oplock_break_wait_time = 0; /* By Default, 0 msecs. */ Globals.enhanced_browsing = True; Globals.iLockSpinCount = 3; /* Try 3 times. */ @@ -1788,6 +1791,7 @@ FN_GLOBAL_INTEGER(lp_machine_password_timeout, &Globals.machine_password_timeout FN_GLOBAL_INTEGER(lp_change_notify_timeout, &Globals.change_notify_timeout) FN_GLOBAL_INTEGER(lp_map_to_guest, &Globals.map_to_guest) FN_GLOBAL_INTEGER(lp_min_passwd_length, &Globals.min_passwd_length) +FN_GLOBAL_BOOL(lp_use_cracklib, &Globals.use_cracklib) FN_GLOBAL_INTEGER(lp_oplock_break_wait_time, &Globals.oplock_break_wait_time) FN_GLOBAL_INTEGER(lp_lock_spin_count, &Globals.iLockSpinCount) FN_GLOBAL_INTEGER(lp_lock_sleep_time, &Globals.iLockSpinTime) diff --git a/source/rpc_server/srv_samr_nt.c b/source/rpc_server/srv_samr_nt.c index b9974cba8ad..7edd34c8dde 100644 --- a/source/rpc_server/srv_samr_nt.c +++ b/source/rpc_server/srv_samr_nt.c @@ -2834,11 +2834,17 @@ static BOOL set_user_info_23(SAM_USER_INFO_23 *id23, DOM_SID *sid) DEBUG(5, ("Changing trust account or non-unix-user password, not updating /etc/passwd\n")); } else { /* update the UNIX password */ - if (lp_unix_password_sync() ) - if(!chgpasswd(pdb_get_username(pwd), "", plaintext_buf, True)) { + if (lp_unix_password_sync() ) { + struct passwd *passwd = Get_Pwnam(pdb_get_username(pwd)); + if (!passwd) { + DEBUG(1, ("chgpasswd: Username does not exist in system !?!\n")); + } + + if(!chgpasswd(pdb_get_username(pwd), passwd, "", plaintext_buf, True)) { pdb_free_sam(&pwd); return False; } + } } ZERO_STRUCT(plaintext_buf); @@ -2899,7 +2905,12 @@ static BOOL set_user_info_pw(char *pass, DOM_SID *sid) } else { /* update the UNIX password */ if (lp_unix_password_sync()) { - if(!chgpasswd(pdb_get_username(pwd), "", plaintext_buf, True)) { + struct passwd *passwd = Get_Pwnam(pdb_get_username(pwd)); + if (!passwd) { + DEBUG(1, ("chgpasswd: Username does not exist in system !?!\n")); + } + + if(!chgpasswd(pdb_get_username(pwd), passwd, "", plaintext_buf, True)) { pdb_free_sam(&pwd); return False; } diff --git a/source/smbd/chgpasswd.c b/source/smbd/chgpasswd.c index e6117245e7a..07def7549eb 100644 --- a/source/smbd/chgpasswd.c +++ b/source/smbd/chgpasswd.c @@ -49,6 +49,14 @@ #include "includes.h" +#include + +#ifndef HAVE_CRACKLIB_DICTPATH +#ifndef CRACKLIB_DICTPATH +#define CRACKLIB_DICTPATH SAMBA_CRACKLIB_DICTPATH +#endif +#endif + extern struct passdb_ops pdb_ops; static NTSTATUS check_oem_password(const char *user, @@ -441,25 +449,14 @@ while we were waiting\n", WTERMSIG(wstat))); return (chstat); } -BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL as_root) +BOOL chgpasswd(const char *name, const struct passwd *pass, + const char *oldpass, const char *newpass, BOOL as_root) { pstring passwordprogram; pstring chatsequence; size_t i; size_t len; - struct passwd *pass; - - if (!name) { - DEBUG(1, ("chgpasswd: NULL username specfied !\n")); - } - - pass = Get_Pwnam(name); - if (!pass) { - DEBUG(1, ("chgpasswd: Username does not exist in system !\n")); - return False; - } - if (!oldpass) { oldpass = ""; } @@ -471,13 +468,6 @@ BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL #endif /* Take the passed information and test it for minimum criteria */ - /* Minimum password length */ - if (strlen(newpass) < lp_min_passwd_length()) { - /* too short, must be at least MINPASSWDLENGTH */ - DEBUG(0, ("chgpasswd: Password Change: user %s, New password is shorter than minimum password length = %d\n", - name, lp_min_passwd_length())); - return (False); /* inform the user */ - } /* Password is same as old password */ if (strcmp(oldpass, newpass) == 0) { @@ -570,7 +560,8 @@ the string %%u, and the given string %s does not.\n", passwordprogram )); #else /* ALLOW_CHANGE_PASSWORD */ -BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL as_root) +BOOL chgpasswd(const char *name, const struct passwd *pass, + const char *oldpass, const char *newpass, BOOL as_root) { DEBUG(0, ("chgpasswd: Password changing not compiled in (user=%s)\n", name)); return (False); @@ -909,6 +900,8 @@ static NTSTATUS check_oem_password(const char *user, NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passwd, BOOL as_root) { + struct passwd *pass; + BOOL ret; uint32 min_len; @@ -936,7 +929,47 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw /* return NT_STATUS_PWD_TOO_SHORT; */ } - /* TODO: Add cracklib support here */ + pass = Get_Pwnam(pdb_get_username(hnd)); + if (!pass) { + DEBUG(1, ("check_oem_password: Username does not exist in system !?!\n")); + } + +#ifdef HAVE_WORKING_CRACKLIB + if (pass) { + /* if we can, become the user to overcome internal cracklib sillyness */ + if (!push_sec_ctx()) + return NT_STATUS_UNSUCCESSFUL; + + set_sec_ctx(pass->pw_uid, pass->pw_gid, 0, NULL, NULL); + set_re_uid(); + } + + if (lp_use_cracklib()) { + const char *crack_check_reason; + DEBUG(4, ("change_oem_password: Checking password for user [%s]" + " against cracklib. \n", pdb_get_username(hnd))); + DEBUGADD(4, ("If this is your last message, then something is " + "wrong with cracklib, it might be missing it's " + "dictionaries at %s\n", + CRACKLIB_DICTPATH)); + dbgflush(); + + crack_check_reason = FascistCheck(new_passwd, (char *)CRACKLIB_DICTPATH); + if (crack_check_reason) { + DEBUG(1, ("Password Change: user [%s], " + "New password failed cracklib test - %s\n", + pdb_get_username(hnd), crack_check_reason)); + + /* get back to where we should be */ + if (pass) + pop_sec_ctx(); + return NT_STATUS_PASSWORD_RESTRICTION; + } + } + + if (pass) + pop_sec_ctx(); +#endif /* * If unix password sync was requested, attempt to change @@ -951,7 +984,7 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw */ if(lp_unix_password_sync() && - !chgpasswd(pdb_get_username(hnd), old_passwd, new_passwd, as_root)) { + !chgpasswd(pdb_get_username(hnd), pass, old_passwd, new_passwd, as_root)) { return NT_STATUS_ACCESS_DENIED; } diff --git a/source/tests/crack.c b/source/tests/crack.c new file mode 100644 index 00000000000..13428878529 --- /dev/null +++ b/source/tests/crack.c @@ -0,0 +1,5 @@ + +int main(int argc, char **argv) { + FascistCheck("Foo", CRACKLIB_DICTPATH); + return 0; +} -- 2.11.4.GIT