Patch for Bad Password Attempt Lockout, samba3.0a22.
David Collier-Brown -- Customer Engineering
David.Collier-Brown at Sun.COM
Thu Mar 27 19:58:24 GMT 2003
Remember, this opens up a new vulnerability, to denial
of service attacks. See, for example
http://www.uksecurityonline.com/threat/password.php
If you're implementing this, implement the approved strategy,
also use by NT, of locking it for a settable period, and
not locking out priveledged accounts.
From
http://calnetad.berkeley.edu/documentation/technical/uc_domain_policy.html
Account lockout duration
Sets the number of minutes an account will be locked out.
Allowable values are 0 (account is lockout out until
administrator unlocks it) or between 1 and 99999 minutes.
WARNING: Setting this value to 0 (until administrator
unlocks) may allow a potential denial of service attack.
It is important to note that the built-in Administrator
account cannot be locked out.
--dave
Jianliang Lu wrote:
> I have implemented the "bad password attempt lockout" policy. If an user
> attempt with the bad password more than the count setted in the policy, then
> his account will be auto-locked, like what did NT. The implementation is only
> for LDAP passdb backend.
> To do this, I have to introduce a new integer attribute in
> samba.schema, "badPwAttempt".
> Folllowing are the patches, any comments?
>
>
>
> Jianliang Lu
> TieSse s.p.a.
> Via Jervis, 60. 10015 Ivrea (To) - Italy
> j.lu at tiesse.com
> luj at libero.it
>
>
> ------------------------------------------------------------------------
>
> --- samba-3.0alpha22-orig/source/auth/auth_sam.c Mon Feb 17 16:31:06 2003
> +++ samba-3.0alpha22-orig/source/auth/auth_sam.c.fix Thu Mar 27 12:40:10 2003
> @@ -326,6 +326,12 @@
> return NT_STATUS_ACCOUNT_DISABLED;
> }
>
> + /* Quit if the account was locked out. */
> + if (acct_ctrl & ACB_AUTOLOCK) {
> + DEBUG(1,("Account for user '%s' was locked out.\n", pdb_get_username(sampass)));
> + return NT_STATUS_ACCOUNT_LOCKED_OUT;
> + }
> +
> /* Test account expire time */
>
> kickoff_time = pdb_get_kickoff_time(sampass);
> @@ -414,6 +420,7 @@
> NTSTATUS nt_status;
> uint8 user_sess_key[16];
> const uint8* lm_hash;
> + uint32 account_policy_lockout, badpwattempt;
>
> if (!user_info || !auth_context) {
> return NT_STATUS_UNSUCCESSFUL;
> @@ -448,10 +455,43 @@
> nt_status = sam_password_ok(auth_context, mem_ctx, sampass, user_info, user_sess_key);
>
> if (!NT_STATUS_IS_OK(nt_status)) {
> + if (NT_STATUS_EQUAL(nt_status,NT_STATUS_WRONG_PASSWORD)) {
> + badpwattempt = (uint32)pdb_get_bad_pw_attempt(sampass) + 1;
> + if (!pdb_set_bad_pw_attempt(sampass, badpwattempt, PDB_CHANGED))
> + DEBUG(1, ("Failed to set 'badPwAttempt' for user % s. \n",
> + user_info->internal_username.str));
> + account_policy_get(AP_BAD_ATTEMPT_LOCKOUT, &account_policy_lockout);
> + if (badpwattempt >= account_policy_lockout)
> + if (!pdb_set_acct_ctrl (sampass,
> + pdb_get_acct_ctrl(sampass) |ACB_AUTOLOCK,
> + PDB_CHANGED)) {
> + DEBUG(1, ("Failed to set 'disabled' flag for user % s. \n",
> + user_info->internal_username.str));
> + }
> +
> + become_root();
> + if (!pdb_update_sam_account(sampass)) {
> + DEBUG(1, ("Failed to modify entry for user % s.\n",
> + user_info->internal_username.str));
> + unbecome_root();
> + }
> + }
> pdb_free_sam(&sampass);
> return nt_status;
> }
>
> + if (!pdb_set_bad_pw_attempt(sampass, 0, PDB_CHANGED))
> + DEBUG(1, ("Failed to set 'badPwAttempt' for user % s. \n",
> + user_info->internal_username.str));
> + if (!pdb_set_logon_time(sampass, time(NULL), PDB_CHANGED))
> + DEBUG(1, ("auth_sam.c : pdb_set_logon_time fialed!\n"));
> +
> + become_root();
> + if(!pdb_update_sam_account(sampass))
> + DEBUG(1, ("Failed to modify entry for user % s.\n",
> + user_info->internal_username.str));
> + unbecome_root();
> +
> if (!NT_STATUS_IS_OK(nt_status = make_server_info_sam(server_info, sampass))) {
> DEBUG(0,("check_sam_security: make_server_info_sam() failed with '%s'\n", nt_errstr(nt_status)));
> return nt_status;
>
>
> ------------------------------------------------------------------------
>
> --- samba-3.0alpha22-orig/source/passdb/passdb.c Mon Feb 24 16:12:31 2003
> +++ samba-3.0alpha22-orig/source/passdb/passdb.c.fix Thu Mar 27 12:40:10 2003
> @@ -60,6 +60,7 @@
> memset(user->private.hours, 0xff, user->private.hours_len); /* available at all hours */
> user->private.unknown_5 = 0x00000000; /* don't know */
> user->private.unknown_6 = 0x000004ec; /* don't know */
> + user->private.bad_pw_attempt = 0; /* bad password attemp count */
>
> /* Some parts of samba strlen their pdb_get...() returns,
> so this keeps the interface unchanged for now. */
>
>
> ------------------------------------------------------------------------
>
> --- samba-3.0alpha22-orig/source/passdb/pdb_get_set.c Thu Jan 9 20:05:59 2003
> +++ samba-3.0alpha22-orig/source/passdb/pdb_get_set.c.fix Thu Mar 27 12:40:10 2003
> @@ -172,6 +172,14 @@
> return (NULL);
> }
>
> +uint32 pdb_get_bad_pw_attempt (const SAM_ACCOUNT *sampass)
> +{
> + if (sampass)
> + return (sampass->private.bad_pw_attempt);
> + else
> + return (-1);
> +}
> +
> /**
> * Get flags showing what is initalised in the SAM_ACCOUNT
> * @param sampass the SAM_ACCOUNT in question
> @@ -1038,6 +1046,16 @@
> return pdb_set_init_flags(sampass, PDB_UNKNOWN6, flag);
> }
>
> +BOOL pdb_set_bad_pw_attempt (SAM_ACCOUNT *sampass, uint32 badpwattempt, enum pdb_value_state flag)
> +{
> + if (!sampass)
> + return False;
> +
> + sampass->private.bad_pw_attempt = badpwattempt;
> +
> + return pdb_set_init_flags(sampass, PDB_BADPWATTEMPT, flag);
> +}
> +
> BOOL pdb_set_hours (SAM_ACCOUNT *sampass, const uint8 *hours, enum pdb_value_state flag)
> {
> if (!sampass)
> @@ -1064,6 +1082,7 @@
> BOOL pdb_set_pass_changed_now (SAM_ACCOUNT *sampass)
> {
> uint32 expire;
> + uint32 min_age;
>
> if (!sampass)
> return False;
> @@ -1082,6 +1101,16 @@
> return False;
> }
>
> + if (!account_policy_get(AP_MIN_PASSWORD_AGE, &min_age)
> + || (min_age==(uint32)-1)) {
> + if (!pdb_set_pass_can_change_time (sampass, 0, PDB_CHANGED))
> + return False;
> + } else {
> + if (!pdb_set_pass_can_change_time (sampass,
> + pdb_get_pass_last_set_time(sampass)
> + + min_age, PDB_CHANGED))
> + return False;
> + }
> return True;
> }
>
>
>
> ------------------------------------------------------------------------
>
> --- samba-3.0alpha22-orig/source/passdb/pdb_ldap.c Thu Mar 13 12:27:01 2003
> +++ samba-3.0alpha22-orig/source/passdb/pdb_ldap.c.fix Thu Mar 27 12:40:10 2003
> @@ -149,7 +149,7 @@
> "logoffTime", "kickoffTime", "cn",
> "pwdCanChange", "pwdMustChange",
> "displayName", "homeDrive",
> - "smbHome", "scriptPath",
> + "smbHome", "scriptPath", "badPwAttempt",
> "profilePath", "description",
> "userWorkstations", "rid",
> "primaryGroupID", "lmPassword",
> @@ -927,7 +927,8 @@
> workstations;
> struct passwd *pw;
> uint32 user_rid,
> - group_rid;
> + group_rid,
> + badpwattempt;
> uint8 smblmpwd[LM_HASH_LEN],
> smbntpwd[NT_HASH_LEN];
> uint16 acct_ctrl = 0,
> @@ -980,6 +981,7 @@
> get_single_attribute(ldap_state->ldap_struct, entry, "rid", temp);
> user_rid = (uint32)atol(temp);
>
> +
> pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
>
> if (!get_single_attribute(ldap_state->ldap_struct, entry, "primaryGroupID", temp)) {
> @@ -1037,6 +1039,12 @@
> pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
> }
>
> + if (!get_single_attribute(ldap_state->ldap_struct, entry, "badPwAttempt", temp)) {
> + /* leave as default */
> + } else {
> + badpwattempt = (uint32)atol(temp);
> + pdb_set_bad_pw_attempt(sampass, badpwattempt, PDB_SET);
> + }
> if (!get_single_attribute(ldap_state->ldap_struct, entry, "logonTime", temp)) {
> /* leave as default */
> } else {
> @@ -1309,6 +1317,11 @@
> make_a_mod(mods, ldap_op, "logonTime", temp);
> }
>
> + if (need_ldap_mod(pdb_add, sampass, PDB_BADPWATTEMPT)) {
> + slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_bad_pw_attempt(sampass));
> + make_a_mod(mods, ldap_op, "badPwAttempt", temp);
> + }
> +
> if (need_ldap_mod(pdb_add, sampass, PDB_LOGOFFTIME)) {
> slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logoff_time(sampass));
> make_a_mod(mods, ldap_op, "logoffTime", temp);
>
>
> ------------------------------------------------------------------------
>
> --- samba-3.0alpha22-orig/source/utils/pdbedit.c Fri Feb 14 23:34:38 2003
> +++ samba-3.0alpha22-orig/source/utils/pdbedit.c.fix Thu Mar 27 12:40:10 2003
> @@ -136,6 +136,7 @@
> tmp = pdb_get_pass_must_change_time(sam_pwent);
> printf ("Password must change: %s\n", tmp ? http_timestring(tmp) : "0");
>
> + printf ("Bad Password Attempt: %d\n", pdb_get_bad_pw_attempt(sam_pwent));
> } else if (smbpwdstyle) {
> if (IS_SAM_UNIX_USER(sam_pwent)) {
> char lm_passwd[33];
>
>
> ------------------------------------------------------------------------
>
> --- ./samba-3.0alpha22-orig/examples/LDAP/samba.schema Mon Jan 6 17:39:40 2003
> +++ ./samba-3.0alpha22-orig/examples/LDAP/samba.schema.fix Thu Mar 27 12:40:10 2003
> @@ -64,6 +64,11 @@
> EQUALITY integerMatch
> SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
>
> +attributetype ( 1.3.6.1.4.1.7165.2.1.19 NAME 'badPwAttempt'
> + DESC 'NT badPwAttempt'
> + EQUALITY integerMatch
> + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
> +
> ##
> ## string settings
> ##
> @@ -134,7 +139,7 @@
> objectclass ( 1.3.6.1.4.1.7165.2.2.3 NAME 'sambaAccount' SUP top AUXILIARY
> DESC 'Samba Auxilary Account'
> MUST ( uid $ rid )
> - MAY ( cn $ lmPassword $ ntPassword $ pwdLastSet $ logonTime $
> + MAY ( cn $ lmPassword $ ntPassword $ pwdLastSet $ logonTime $ badPwAttempt $
> logoffTime $ kickoffTime $ pwdCanChange $ pwdMustChange $ acctFlags $
> displayName $ smbHome $ homeDrive $ scriptPath $ profilePath $
> description $ userWorkstations $ primaryGroupID $ domain ))
>
>
>
> ------------------------------------------------------------------------
>
> --- samba-3.0alpha22-orig/source/include/smb.h Thu Feb 27 22:21:08 2003
> +++ samba-3.0alpha22-orig/source/include/smb.h.fix Thu Mar 27 12:40:10 2003
> @@ -611,6 +611,7 @@
> PDB_UNKNOWN3,
> PDB_UNKNOWN5,
> PDB_UNKNOWN6,
> + PDB_BADPWATTEMPT,
> PDB_LMPASSWD,
> PDB_NTPASSWD,
>
> @@ -684,6 +685,7 @@
>
> uint32 unknown_5; /* 0x0002 0000 */
> uint32 unknown_6; /* 0x0000 04ec */
> + uint32 bad_pw_attempt; /* count of bad password attempt */
> } private;
>
> /* Lets see if the remaining code can get the hint that you
--
David Collier-Brown, | Always do right. This will gratify
Sun Microsystems DCMO | some people and astonish the rest.
Toronto, Ontario |
(905) 415-2849 or x52849 | davecb at canada.sun.com
More information about the samba-technical
mailing list