Fixed a number of issues applying password policy against LDAP binds. See patch for details.

rob
>From 27b19a5fbf7ea999dd9e69732c61ac58668c29b0 Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcrit...@redhat.com>
Date: Fri, 15 Feb 2013 11:51:59 -0500
Subject: [PATCH] Fix lockout of LDAP bind.

There were several problems:

- A cut-n-paste error where the wrong value was being considered when
  an account was administratively unlocked.
- An off-by-one error where LDAP got one extra bind attempt.
- krbPwdPolicyReference wasn't being retrieved as a virtual attribute so
  only the global_policy was used.
- The lockout duration wasn't examined in the context of too many failed
  logins so was being applied properly.

https://fedorahosted.org/freeipa/ticket/3433
---
 .../ipa-slapi-plugins/ipa-lockout/ipa_lockout.c    | 41 ++++++++++++++++------
 1 file changed, 31 insertions(+), 10 deletions(-)

diff --git a/daemons/ipa-slapi-plugins/ipa-lockout/ipa_lockout.c b/daemons/ipa-slapi-plugins/ipa-lockout/ipa_lockout.c
index fea997d79825e05a6ffe4bf65e22821948794ff3..5aa1f34fa55ee06034fd6f5547d2ea3552842637 100644
--- a/daemons/ipa-slapi-plugins/ipa-lockout/ipa_lockout.c
+++ b/daemons/ipa-slapi-plugins/ipa-lockout/ipa_lockout.c
@@ -588,7 +588,7 @@ done:
 static int ipalockout_preop(Slapi_PBlock *pb)
 {
     char *dn = NULL;
-    char *policy_dn = NULL;
+    const char *policy_dn = NULL;
     Slapi_Entry *target_entry = NULL;
     Slapi_Entry *policy_entry = NULL;
     Slapi_DN *sdn = NULL;
@@ -605,6 +605,10 @@ static int ipalockout_preop(Slapi_PBlock *pb)
     time_t last_failed = 0;
     char *lastfail = NULL;
     char *unlock_time = NULL;
+    int type_name_disposition = 0;
+    char *actual_type_name = NULL;
+    int attr_free_flags = 0;
+    Slapi_ValueSet *values = NULL;
 
     LOG_TRACE("--in-->\n");
 
@@ -656,7 +660,21 @@ static int ipalockout_preop(Slapi_PBlock *pb)
     slapi_value_free(&objectclass);
 
     /* Only continue if there is a password policy */
-    policy_dn = slapi_entry_attr_get_charptr(target_entry, "krbPwdPolicyReference");
+    ldrc = slapi_vattr_values_get(target_entry, "krbPwdPolicyReference",
+                                &values,
+                                &type_name_disposition, &actual_type_name,
+                                SLAPI_VIRTUALATTRS_REQUEST_POINTERS,
+                                &attr_free_flags);
+    if (ldrc == 0) {
+        Slapi_Value *sv = NULL;
+
+        slapi_valueset_first_value(values, &sv);
+
+        if (values != NULL) {
+            policy_dn = slapi_value_get_string(sv);
+        }
+    }
+
     if (policy_dn == NULL) {
         LOG_TRACE("No kerberos password policy\n");
         goto done;
@@ -705,7 +723,7 @@ static int ipalockout_preop(Slapi_PBlock *pb)
             time_t unlock;
 
             memset(&tm, 0, sizeof(struct tm));
-            res = sscanf(lastfail,
+            res = sscanf(unlock_time,
                          "%04u%02u%02u%02u%02u%02u",
                          &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
                          &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
@@ -730,13 +748,14 @@ static int ipalockout_preop(Slapi_PBlock *pb)
     }
 
     lockout_duration = slapi_entry_attr_get_uint(policy_entry, "krbPwdLockoutDuration");
-    if (lockout_duration == 0) {
-        errstr = "Entry permanently locked.\n";
-        ret = LDAP_UNWILLING_TO_PERFORM;
-        goto done;
-    }
 
-    if (failedcount > max_fail) {
+    if (failedcount >= max_fail) {
+        if (lockout_duration == 0) {
+            errstr = "Entry permanently locked.\n";
+            ret = LDAP_UNWILLING_TO_PERFORM;
+            goto done;
+        }
+
         if (time_now < last_failed + lockout_duration) {
             /* Too many failures */
             LOG_TRACE("Too many failed logins. %lu out of %d\n", failedcount, max_fail);
@@ -748,7 +767,9 @@ static int ipalockout_preop(Slapi_PBlock *pb)
 done:
     slapi_entry_free(target_entry);
     slapi_entry_free(policy_entry);
-    if (policy_dn) slapi_ch_free_string(&policy_dn);
+    if (values != NULL) {
+        slapi_vattr_values_free(&values, &actual_type_name, attr_free_flags);
+    }
     if (sdn) slapi_sdn_free(&sdn);
 
     LOG("preop returning %d: %s\n", ret, errstr ? errstr : "success\n");
-- 
1.8.1

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to