[SSSD] [PATCHES] SDAP: Lock out ssh keys when account naturally expires

Jakub Hrozek jhrozek at redhat.com
Tue Mar 3 14:28:28 UTC 2015


On Mon, Mar 02, 2015 at 11:42:06PM +0100, Lukas Slebodnik wrote:
> On (22/01/15 17:06), Pavel Reichl wrote:
> >Second patch now contains unit test.
> 
> >From f8686fbb988d29309a41064a678c0daf4aa40b6b Mon Sep 17 00:00:00 2001
> >From: Pavel Reichl <preichl at redhat.com>
> >Date: Mon, 19 Jan 2015 03:24:09 -0500
> >Subject: [PATCH 1/3] SDAP: new option - pwdlocking natural/only by admin
> >
> >This is a follow up to #2364.
> >To distinguish user locked out from accessing machine via SSH if an
> >account was administratively locked (pwdAccountLockedTime set to
> >000001010000Z) in the OpenLDAP Password Policy overlay or if user
> >password is locked out from natural reasons (too many attempts, expired
> >password).
> >
> >Part of solution for:
> >https://fedorahosted.org/sssd/ticket/2534
> You wrote in description of this ticket that it it is a follow up to #2364.
> from my point of view it is an extension.
> 
> Do we really need an option to enable this feature?
> 
> The current implementation locks account with pwdAccountLockedTime set to
> 000001010000Z. The other values(dates) are ignored.

I would prefer if we didn't add a new option as well, but since we released
a version that only supported the lockout and not any other semantics,
I don't think we can get away with just changing the functionality. A
minor version can break functionality. But a major version can :-)

So I propose the following:
1) Add a new value for ldap_access_order called "ppolicy" that would
evaluate the pwdAccountLockedTime fully, including the new
functionality in this patchset
2) In 1.12, deprecate the "lockout" option and log a warning that it
will be removed in future relase and users should migrate to "ppolicy"
option
3) In master (1.13), remove the "lockout" ldap_access_order value

That way, we won't add a new option and I think the "ppolicy" option is
better anyway.

> >From 942f9ab711ac787f10bcc18bd8b638e6f8a540b9 Mon Sep 17 00:00:00 2001
> >From: Pavel Reichl <preichl at redhat.com>
> >Date: Tue, 20 Jan 2015 16:27:41 -0500
> >Subject: [PATCH 2/3] UTIL: convert GeneralizedTime to unix time
> >
> >New utility function *convert_time* to convert GeneralizedTime to
> >unix time.

According to the slapo-ppolicy man page, the pwdAccountLockedTime is
just generalizedTime and according to RFC 4517, it's possible to use any
timezone, but the UTC zone is preferred:
~~~~~~~~~~~~~~~~~~~~~
The time value represents coordinated universal time (equivalent to Greenwich
Mean Time) if the "Z" form of <g-time-zone> is used; otherwise, the value
represents a local time in the time zone indicated by <g-differential>.
In the latter case, coordinated universal time can be calculated by
subtracting the differential from the local time.  The "Z" form of
<g-time-zone> SHOULD be used in preference to <g-differential>.
~~~~~~~~~~~~~~~~~~~~~

I would suggest that the utility function would only support the "Z"
form and return a special error code if another timezone is specified.
In that case, the sssd access code would return ACCESS_DENIED and log a
failure saying that the timezone specifier in ppolicy is not supported.

The reason is that when it comes to access control, I strongly prefer
using non-ambiguous formats. We'll see if there are any users out there
who actually use a non-Zulu time in ppolicy and can improve the support
later.

Of course, the name of the function must make it clear that only time
specification with a trailing "Z" is supported, also the man page should
make it clear in description of "ppolicy" ldap_access_order that only "Z"
is supported.

> >---
> > Makefile.am            |  3 ++-
> > src/tests/util-tests.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
> > src/util/util.c        | 39 +++++++++++++++++++++++++++++++++++++++
> > src/util/util.h        |  3 +++
> > 4 files changed, 91 insertions(+), 1 deletion(-)
> >
> >diff --git a/Makefile.am b/Makefile.am
> >index ca8921bb132db6b7a57d9436a3219057d08b64c6..2da86572752d0702b8983f4cc647188c8cc81382 100644
> >--- a/Makefile.am
> >+++ b/Makefile.am
> >@@ -1535,7 +1535,8 @@ simple_access_tests_LDADD = \
> >     libsss_test_common.la
> > 
> > util_tests_SOURCES = \
> >-    src/tests/util-tests.c
> >+    src/tests/util-tests.c \
> >+    src/util/util.c
> It's better to link test with internal library (libsss_util.so) rather
> then add source file to the test. It's not necessary to change it now.
> Please try to ammend cmocka test in future. (test_utils)
> 
> It's not necessary to change it now. It's just info for the future.
> 
> BTW. You didn't add $(NULL) to the end of aotomake variable.
> 
> > util_tests_CFLAGS = \
> >     $(AM_CFLAGS) \
> >     $(CHECK_CFLAGS)
> >diff --git a/src/tests/util-tests.c b/src/tests/util-tests.c
> >index 94015d8e1e0efb143a4fea998f1b16db1e63365e..ebfae703ff7962c12b9eddf83d2c2e61db29b6eb 100644
> >--- a/src/tests/util-tests.c
> >+++ b/src/tests/util-tests.c
> >@@ -28,6 +28,8 @@
> > #include <sys/types.h>
> > #include <sys/stat.h>
> > #include <fcntl.h>
> >+#include <stdlib.h>
> >+
> > #include "util/util.h"
> > #include "util/sss_utf8.h"
> > #include "util/murmurhash3.h"
> >@@ -1020,6 +1022,44 @@ START_TEST(test_known_service)
> > }
> > END_TEST
> > 
> >+static void convert_time_tz(void)
> Why do wee need a static wunction which does not accept any argument?
> It's better to inline it or add argument timezone and change timezone(setenv)
> inside function.
> 
> >+{
> >+    errno_t ret;
> >+    time_t unix_time;
> >+
> >+    ret = convert_time("20140801115742Z", "%Y%m%d%H%M%SZ", &unix_time);
> >+    fail_unless(ret == EOK && difftime(1406894262, unix_time) == 0);
> >+}
> >+
> >+START_TEST(test_convert_time)
> >+{
> >+    const char *format = "%Y%m%d%H%M%SZ";
> >+    time_t unix_time;
> >+    errno_t ret;
> >+    const char *orig_tz;
> >+
> >+    ret = convert_time("0", format, &unix_time);
> >+    fail_unless(ret == EINVAL);
> >+    ret = convert_time("000001010000Z", format, &unix_time);
> >+    fail_unless(ret == EINVAL);
> >+
> >+    /* test that results are still same no matter what timezone is set */
> >+    convert_time_tz();
> >+    orig_tz = getenv("TZ");
> >+
> >+    ret = setenv("TZ", "GST-1", 1);
> >+    fail_if(ret == -1);
> >+    convert_time_tz();
> >+
> >+    ret = setenv("TZ", "GST-2", 1);
> >+    fail_if(ret == -1);
> >+    convert_time_tz();
> >+
> >+    ret = setenv("TZ", orig_tz, 1);
> >+    fail_if(ret == -1);
> >+}
> >+END_TEST
> >+
> > Suite *util_suite(void)
> > {
> >     Suite *s = suite_create("util");
> >@@ -1067,10 +1107,17 @@ Suite *util_suite(void)
> >     tcase_add_test(tc_atomicio, test_atomicio_read_exact_sized_file);
> >     tcase_add_test(tc_atomicio, test_atomicio_read_from_empty_file);
> > 
> >+    TCase *tc_convert_time = tcase_create("convert_time");
> >+    tcase_add_checked_fixture (tc_convert_time,
>                                ^
>                                extra space
> 
> >+                               ck_leak_check_setup,
> >+                               ck_leak_check_teardown);
> >+    tcase_add_test(tc_convert_time, test_convert_time);
> >+
> >     suite_add_tcase (s, tc_util);
> >     suite_add_tcase (s, tc_utf8);
> >     suite_add_tcase (s, tc_mh3);
> >     suite_add_tcase (s, tc_atomicio);
> >+    suite_add_tcase (s, tc_convert_time);
> > 
> >     return s;
> > }
> >diff --git a/src/util/util.c b/src/util/util.c
> >index 613c559bb2002686c7833642d0946e46e5a9b5d6..eb3002fd4dde5b88a6595aee7186bae8d7d773d2 100644
> >--- a/src/util/util.c
> >+++ b/src/util/util.c
> >@@ -18,6 +18,7 @@
> >     along with this program.  If not, see <http://www.gnu.org/licenses/>.
> > */
> > 
> >+#include "config.h"
> > #include <ctype.h>
> > #include <netdb.h>
> > #include <poll.h>
> >@@ -26,6 +27,7 @@
> > #include <arpa/inet.h>
> > #include <talloc.h>
> > #include <dhash.h>
> >+#include <time.h>
> > 
> > #include "util/util.h"
> > #include "util/sss_utf8.h"
> >@@ -904,3 +906,40 @@ errno_t sss_fd_nonblocking(int fd)
> > 
> >     return EOK;
> > }
> >+
> >+/* Convert GeneralizedTime (http://en.wikipedia.org/wiki/GeneralizedTime)
> >+ * to unix time (seconds since epoch). Use UTC time zone.
> >+ */
> >+errno_t convert_time(const char *str, const char *format, time_t *unix_time)
> >+{
> >+    char *end;
> >+    struct tm tm;
> >+
> >+    memset(&tm, 0, sizeof(tm));
> >+
> >+    end = strptime(str, format, &tm);
> >+    /* not all characters from format were matched */
> >+    if (end == NULL) {
> >+        DEBUG(SSSDBG_TRACE_INTERNAL,
> >+              "String [%s] failed to match format [%s].\n", str, format);
> >+        return EINVAL;
> >+    }
> >+
> >+    /* str is 'longer' than format */
> >+    if (*end != '\0') {
> >+        DEBUG(SSSDBG_TRACE_INTERNAL,
> >+              "String [%s] is longer than format [%s].\n", str, format);
> >+        return EINVAL;
> >+    }
> >+
> >+    *unix_time = mktime(&tm);
> >+    if (*unix_time == -1) {
> >+        DEBUG(SSSDBG_TRACE_INTERNAL,
> >+              "mktime failed to convert [%s].\n", str);
> >+        return EINVAL;
> >+    }
> >+
> >+    tzset();
> >+    *unix_time -= timezone;
>   We prefer to touch output argument just once. (just set output argumetn with
>   local variable.
> 
>   The 1st benefit is that function is not poluted with dereferencing of pointer
>   (code is nicer). The second benefit is that you set default vale just once.
>   It is not case in this function.
> 
> 
> >+    return EOK;
> >+}
> >diff --git a/src/util/util.h b/src/util/util.h
> >index 60dbf9381c5fe26e7d42d51c6f9c7df6e3ebc4be..bc23d7bc5d6307f63a480c5faaeaa98ca921bd46 100644
> >--- a/src/util/util.h
> >+++ b/src/util/util.h
> >@@ -641,4 +641,7 @@ int set_seuser(const char *login_name, const char *seuser_name,
> >                const char *mlsrange);
> > int del_seuser(const char *login_name);
> > 
> >+/* convert time from generalized form to unix time */
> >+errno_t convert_time(const char *str, const char *format, time_t *unix_time);
>  Please try to prefix this function. I know it's part of internal library,
>  but the name is very general and in theory can conflic with function in other
>  libraries/ (prefix sss_ or s3_ is fine)

Prefix and rename, please :-)

errno_t sss_utc_to_time_t() ?

btw do we need to have this function in src/util? Is it ever going to be
used anywhere else?

> 
> 
> The output argumet shout be prefixed with underscore (_).
> So it is obviout which pointer is input and which is output argument.
> 
> 
> > #endif /* __SSSD_UTIL_H__ */
> >-- 
> >2.1.0
> >
> 
> >From 9bb77a8cb8501d7827da8457d434dc31321aca50 Mon Sep 17 00:00:00 2001
> >From: Pavel Reichl <preichl at redhat.com>
> >Date: Tue, 20 Jan 2015 18:34:44 -0500
> >Subject: [PATCH 3/3] SDAP: Lock out ssh keys when account naturally expires
> >
> >Resolves:
> >https://fedorahosted.org/sssd/ticket/2534
> >---
> > Makefile.am                      |   3 +-
> > src/providers/ldap/sdap_access.c | 106 ++++++++++++++++++++++++++++++++++-----
> > src/providers/ldap/sdap_access.h |   1 +
> > 3 files changed, 96 insertions(+), 14 deletions(-)
> >
> >diff --git a/Makefile.am b/Makefile.am
> >index 2da86572752d0702b8983f4cc647188c8cc81382..e780b7098cc853dfaaa4ae4d830cc410fa94eb80 100644
> >--- a/Makefile.am
> >+++ b/Makefile.am
> >@@ -2383,7 +2383,8 @@ libsss_ldap_common_la_SOURCES = \
> >     src/providers/ldap/sdap_domain.c \
> >     src/providers/ldap/sdap.c \
> >     src/util/user_info_msg.c \
> >-    src/util/sss_ldap.c
> >+    src/util/sss_ldap.c \
> >+    src/util/util.c
> 
> The file src/util/util.c is part of internal library libsss_util.so
> It's better to link this module with library rather then add it to source file.
> 
> > libsss_ldap_common_la_CFLAGS = \
> >     $(KRB5_CFLAGS)
> > libsss_ldap_common_la_LIBADD = \
> >diff --git a/src/providers/ldap/sdap_access.c b/src/providers/ldap/sdap_access.c
> >index e09e6b8fe55e8e8bae9ff7f46e815595cb938971..39a6f4397f83b2ca560d0fb883002a97caf73c74 100644
> >--- a/src/providers/ldap/sdap_access.c
> >+++ b/src/providers/ldap/sdap_access.c
> >@@ -1568,7 +1568,9 @@ errno_t sdap_access_lock_step(struct tevent_req *req)
> >     errno_t ret;
> >     struct tevent_req *subreq;
> >     struct sdap_access_lock_req_ctx *state;
> >-    const char *attrs[] = { SYSDB_LDAP_ACCESS_LOCKED_TIME, NULL };
> >+    const char *attrs[] = { SYSDB_LDAP_ACCESS_LOCKED_TIME,
> >+                            SYSDB_LDAP_ACESS_LOCKOUT_DURATION,
> >+                            NULL };
> > 
> >     state = tevent_req_data(req, struct sdap_access_lock_req_ctx);
> > 
> >@@ -1597,15 +1599,86 @@ done:
> >     return ret;
> > }
> > 
> >+static errno_t
> >+decide_if_account_is_locked(bool locked_only_by_admin,
> >+                            const char *pwdAccountLockedTime,
> >+                            const char *pwdAccountLockedDurationTime,
> >+                            bool *locked)
>                               output argumet should be prefixed with "_"

Also is_account_locked() would be a shorter name :-)

> >+{
> >+    errno_t ret;
> >+    time_t lock_time;
> >+    time_t duration;
> >+    time_t now;
> >+
> >+    /* Default action is to consider account to be locked. */
> >+    *locked = true;
> It's more readable if code does not touch output argument very often.
> Functions is nicer if stars "*" are not used very often.
> 
> 
> >+
> >+    /* account is permanently locked */
> >+    if (strcasecmp(pwdAccountLockedTime,
> >+                   PERMANENTLY_LOCKED_ACCOUNT) == 0) {
> >+        goto done;
> return variable ret is not initialized.
> 
> @see warnigs
> Error: UNINIT (CWE-457): [#def1]
> sssd-1.12.90/src/providers/ldap/sdap_access.c:1620: var_decl: Declaring variable "ret" without initializer.
> sssd-1.12.90/src/providers/ldap/sdap_access.c:1680: uninit_use: Using uninitialized value "ret".
> 
> Error: CLANG_WARNING: [#def2]
> sssd-1.12.90/src/providers/ldap/sdap_access.c:1680:5: warning: Undefined or garbage value returned to caller
> #    return ret;
> #    ^~~~~~~~~~
> 
> Error: COMPILER_WARNING: [#def4]
> sssd-1.12.90/src/providers/ldap/sdap_access.c: scope_hint: In function 'sdap_access_lock_step_done'
> sssd-1.12.90/src/providers/ldap/sdap_access.c:1758:16: warning: 'ret' may be used uninitialized in this function [-Wmaybe-uninitialized]
> #             if (ret != EOK) {
> #                
> 
> >+    }
> >+
> >+    if (locked_only_by_admin) {
> >+        /* We do *not* care about exact value of account locked time, we
> >+         * only *do* care if the value is equal to
> >+         * PERMANENTLY_LOCKED_ACCOUNT, which means that account is locked
> >+         * permanently.
> >+         */
> >+        DEBUG(SSSDBG_TRACE_FUNC,
> >+              "Account is beeing blocked by password policy, "
> >+              "but value: [%s] value is ignored by SSSD.\n",
> >+              pwdAccountLockedTime);
> >+        *locked = false;
> >+    } else {
> >+        /* Account may be locked out from natural reasons (too many attempts,
> >+         * expired password). In this case, pwdAccountLockedTime is also set,
> >+         * to the time of lock out.
> >+         */
> >+        ret = convert_time(pwdAccountLockedTime, "%Y%m%d%H%M%SZ",
> >+                           &lock_time);
> >+        if (ret != EOK) {
> >+            DEBUG(SSSDBG_TRACE_FUNC, "convert_time() failed with %d:%s.\n",
> >+                  ret, sss_strerror(ret));
> >+            goto done;
> >+        }
> >+
> >+        now = time(NULL);
> >+
> >+        /* Account was NOT locked in past. */
> >+        if (difftime(lock_time, now) > 0.0) {
> >+            *locked = false;
> >+        } else if (pwdAccountLockedDurationTime != NULL) {
> >+            errno = 0;
> >+            duration = strtol(pwdAccountLockedDurationTime, NULL, 0);

I think we already have a utility function for this in
src/util/strtonum.c, please use it.

> >+            if (errno) {
> >+                ret = errno;
> >+                goto done;
> >+            }
> >+            /* Lockout has expired */
> >+            if (duration != 0 && difftime(now, lock_time) > duration) {
> >+                *locked = false;
> >+            }
> >+        }
> >+    }
> >+
> >+    ret = EOK;
> >+
> >+done:
> >+    return ret;
> >+}
> >+
> > static void sdap_access_lock_step_done(struct tevent_req *subreq)
> > {
> >     int ret, tret, dp_error;
> >     size_t num_results;
> >     bool locked = false;
> >     const char *pwdAccountLockedTime;
> >+    const char *pwdAccountLockedDurationTime;
> >     struct sysdb_attrs **results;
> >     struct tevent_req *req;
> >     struct sdap_access_lock_req_ctx *state;
> >+    bool pwd_admin_locked_only;
> > 
> >     req = tevent_req_callback_data(subreq, struct tevent_req);
> >     state = tevent_req_data(req, struct sdap_access_lock_req_ctx);
> >@@ -1613,6 +1686,9 @@ static void sdap_access_lock_step_done(struct tevent_req *subreq)
> >     ret = sdap_get_generic_recv(subreq, state, &num_results, &results);
> >     talloc_zfree(subreq);
> > 
> >+    pwd_admin_locked_only = dp_opt_get_bool(state->opts->basic,
> >+                                            SDAP_PWDLOCKOUT_ADMIN_LOCKED_ONLY);
> >+
> I have already commented it in 1st patch that IMHO we do not need this option
> at all.
> 
> If other developers agree we need that option then please move it to the place
> where we DO NEED it. Because it is used just once but initialized far far away
> from place where it is used.
> 
> There is another warning from static analyser.
> I think iit's false possitive because we needn't test output variable of
> dp_opt_get_bool.
> 
> 
> Error: CHECKED_RETURN (CWE-252): [#def3]
> sssd-1.12.90/src/providers/ldap/sdap_access.c:1701: check_return: Calling "_dp_opt_get_bool" without checking return value (as is done elsewhere 48 out of 67 times).
> sssd-1.12.90/src/providers/ad/ad_common.c:1170: example_checked: Example 1: "_dp_opt_get_bool(ad_ctx->ad_options->basic, AD_ENABLE_GC, <anonymous>)" has its value checked in "_dp_opt_get_bool(ad_ctx->ad_options->basic, AD_ENABLE_GC, <anonymous>)".
> sssd-1.12.90/src/providers/ad/ad_dyndns.c:48: example_checked: Example 2: "_dp_opt_get_bool(ad_opts->dyndns_ctx->opts, DP_OPT_DYNDNS_UPDATE, <anonymous>)" has its value checked in "_dp_opt_get_bool(ad_opts->dyndns_ctx->opts, DP_OPT_DYNDNS_UPDATE, <anonymous>) == 0".
> sssd-1.12.90/src/providers/ad/ad_id.c:230: example_checked: Example 3: "_dp_opt_get_bool(ad_ctx->ad_options->basic, AD_ENABLE_GC, <anonymous>)" has its value checked in "_dp_opt_get_bool(ad_ctx->ad_options->basic, AD_ENABLE_GC, <anonymous>)".
> sssd-1.12.90/src/providers/ad/ad_init.c:235: example_checked: Example 4: "_dp_opt_get_bool(ad_options->basic, AD_ENABLE_DNS_SITES, <anonymous>)" has its value checked in "_dp_opt_get_bool(ad_options->basic, AD_ENABLE_DNS_SITES, <anonymous>)".
> sssd-1.12.90/src/providers/ipa/ipa_init.c:332: example_checked: Example 5: "_dp_opt_get_bool(ipa_options->basic, IPA_ENABLE_DNS_SITES, <anonymous>)" has its value checked in "_dp_opt_get_bool(ipa_options->basic, IPA_ENABLE_DNS_SITES, <anonymous>)".
> sssd-1.12.90/src/providers/ldap/sdap_access.c:1754: unchecked_value: Using value "pwd_admin_locked_only" as a function argument without checking appropriately.
> 
> 
> >     ret = sdap_id_op_done(state->sdap_op, ret, &dp_error);
> >     if (ret != EOK) {
> >         if (dp_error == DP_ERR_OK) {
> >@@ -1653,22 +1729,26 @@ static void sdap_access_lock_step_done(struct tevent_req *subreq)
> >         ret = ERR_INTERNAL;
> >         goto done;
> >     } else { /* Ok, we got a single reply */
> >+        ret = sysdb_attrs_get_string(results[0], SYSDB_LDAP_ACESS_LOCKOUT_DURATION,
> >+                                     &pwdAccountLockedDurationTime);
> >+        if (ret != EOK) {
> >+            /* This attribute might not be set even if account is locked */
> >+            pwdAccountLockedDurationTime = NULL;
> >+        }
> >+
> >         ret = sysdb_attrs_get_string(results[0], SYSDB_LDAP_ACCESS_LOCKED_TIME,
> >                                      &pwdAccountLockedTime);
> >         if (ret == EOK) {
> >-            /* We do *not* care about exact value of account locked time, we
> >-             * only *do* care if the value is equal to
> >-             * PERMANENTLY_LOCKED_ACCOUNT, which means that account is locked
> >-             * permanently.
> >-             */
> >-            if (strcasecmp(pwdAccountLockedTime,
> >-                           PERMANENTLY_LOCKED_ACCOUNT) == 0) {
> >+            ret = decide_if_account_is_locked(pwd_admin_locked_only,
> >+                                              pwdAccountLockedTime,
> >+                                              pwdAccountLockedDurationTime,
> >+                                              &locked);
> >+            if (ret != EOK) {
> >+                DEBUG(SSSDBG_MINOR_FAILURE,
> >+                      "decide_if_account_is_locked failed: %d:[%s]. "
> >+                      "Account will be considered to be locked.\n",
> >+                      ret, sss_strerror(ret));
> >                 locked = true;
> >-            } else {
> >-                DEBUG(SSSDBG_TRACE_FUNC,
> >-                      "Account of: %s is beeing blocked by password policy, "
> >-                      "but value: [%s] value is ignored by SSSD.\n",
> >-                      state->username, pwdAccountLockedTime);
> >             }
> >         } else {
> >             /* Attribute SYSDB_LDAP_ACCESS_LOCKED_TIME in not be present unless
> >diff --git a/src/providers/ldap/sdap_access.h b/src/providers/ldap/sdap_access.h
> >index f085e619961198b887d65ed5ee0bc5cdd90d1b20..3e59b9b2f4851a87c01f3e353c11b3bdf9bb4ff7 100644
> >--- a/src/providers/ldap/sdap_access.h
> >+++ b/src/providers/ldap/sdap_access.h
> >@@ -35,6 +35,7 @@
> > #define SYSDB_LDAP_ACCESS_CACHED_LOCKOUT "ldap_access_lockout_allow"
> > /* names of ppolicy attributes */
> > #define SYSDB_LDAP_ACCESS_LOCKED_TIME "pwdAccountLockedTime"
> >+#define SYSDB_LDAP_ACESS_LOCKOUT_DURATION "pwdLockoutDuration"
> > #define SYSDB_LDAP_ACCESS_LOCKOUT "pwdLockout"
> > 
> > #define LDAP_ACCESS_FILTER_NAME "filter"
> >-- 
> >2.1.0
> 
> Patch works as expexted.

Thank you for testing, I only read the patches, didn't do any testing
yet.

> 
> Tested with 3 different values of pwdAccountLockedTime
> 
> dn: uid=testuser1,ou=Users,dc=example,dc=com
> changetype: modify
> replace: pwdAccountLockedTime
> pwdAccountLockedTime: 000001010000Z
> 
> dn: uid=testuser1,ou=Users,dc=example,dc=com
> changetype: modify
> replace: pwdAccountLockedTime
> pwdAccountLockedTime: 20150310003750Z
> 
> dn: uid=testuser1,ou=Users,dc=example,dc=com
> changetype: modify
> replace: pwdAccountLockedTime
> pwdAccountLockedTime: 20150301003750Z
> 
> LS



More information about the sssd-devel mailing list