summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPavel Reichl <preichl@redhat.com>2015-01-20 18:34:44 -0500
committerJakub Hrozek <jhrozek@redhat.com>2015-03-06 13:48:47 +0100
commit39dad5421f792c699f341556dc4fb80e82a47ed0 (patch)
treecc4312d948041508b83f5afb07b75c9e975bfd33 /src
parent8f9459bd92ab2b8878f3ca5d2bc5b6c57e808d76 (diff)
downloadsssd-39dad5421f792c699f341556dc4fb80e82a47ed0.tar.gz
sssd-39dad5421f792c699f341556dc4fb80e82a47ed0.tar.xz
sssd-39dad5421f792c699f341556dc4fb80e82a47ed0.zip
SDAP: Lock out ssh keys when account naturally expires
Resolves: https://fedorahosted.org/sssd/ticket/2534 Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
Diffstat (limited to 'src')
-rw-r--r--src/man/sssd-ldap.5.xml14
-rw-r--r--src/providers/ldap/ldap_init.c2
-rw-r--r--src/providers/ldap/sdap_access.c316
-rw-r--r--src/providers/ldap/sdap_access.h3
4 files changed, 245 insertions, 90 deletions
diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml
index 9fbc47487..00da3964a 100644
--- a/src/man/sssd-ldap.5.xml
+++ b/src/man/sssd-ldap.5.xml
@@ -1955,6 +1955,20 @@ ldap_access_filter = (employeeType=admin)
be set for this feature to work.
</para>
<para>
+ <emphasis>ppolicy</emphasis>: use account locking.
+ If set, this option denies access in case that ldap
+ attribute 'pwdAccountLockedTime' is present and has
+ value of '000001010000Z' or represents any time in the past.
+ The value of 'pwdAccountLockedTime' attribute
+ must end with 'Z' as only UTC time zone is
+ currently suported. Please see the option
+ ldap_pwdlockout_dn.
+
+ Please note that 'access_provider = ldap' must
+ be set for this feature to work.
+ </para>
+
+ <para>
<emphasis>expire</emphasis>: use
ldap_account_expire_policy
</para>
diff --git a/src/providers/ldap/ldap_init.c b/src/providers/ldap/ldap_init.c
index 8d5619779..cebd548a4 100644
--- a/src/providers/ldap/ldap_init.c
+++ b/src/providers/ldap/ldap_init.c
@@ -432,6 +432,8 @@ int sssm_ldap_access_init(struct be_ctx *bectx,
} else if (strcasecmp(order_list[c],
LDAP_ACCESS_EXPIRE_POLICY_RENEW_NAME) == 0) {
access_ctx->access_rule[c] = LDAP_ACCESS_EXPIRE_POLICY_RENEW;
+ } else if (strcasecmp(order_list[c], LDAP_ACCESS_PPOLICY_NAME) == 0) {
+ access_ctx->access_rule[c] = LDAP_ACCESS_PPOLICY;
} else {
DEBUG(SSSDBG_CRIT_FAILURE,
"Unexpected access rule name [%s].\n", order_list[c]);
diff --git a/src/providers/ldap/sdap_access.c b/src/providers/ldap/sdap_access.c
index dd2fb6b92..4a45ff419 100644
--- a/src/providers/ldap/sdap_access.c
+++ b/src/providers/ldap/sdap_access.c
@@ -32,6 +32,7 @@
#include <errno.h>
#include "util/util.h"
+#include "util/strtonum.h"
#include "db/sysdb.h"
#include "providers/ldap/ldap_common.h"
#include "providers/ldap/sdap.h"
@@ -44,6 +45,12 @@
#define PERMANENTLY_LOCKED_ACCOUNT "000001010000Z"
#define MALFORMED_FILTER "Malformed access control filter [%s]\n"
+enum sdap_pwpolicy_mode {
+ PWP_LOCKOUT_ONLY,
+ PWP_LOCKOUT_EXPIRE,
+ PWP_SENTINEL,
+};
+
static errno_t perform_pwexpire_policy(TALLOC_CTX *mem_ctx,
struct sss_domain_info *domain,
struct pam_data *pd,
@@ -59,14 +66,15 @@ static errno_t sdap_get_basedn_user_entry(struct ldb_message *user_entry,
const char **_basedn);
static struct tevent_req *
-sdap_access_lock_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct be_ctx *be_ctx,
- struct sss_domain_info *domain,
- struct sdap_access_ctx *access_ctx,
- struct sdap_id_conn_ctx *conn,
- const char *username,
- struct ldb_message *user_entry);
+sdap_access_ppolicy_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct be_ctx *be_ctx,
+ struct sss_domain_info *domain,
+ struct sdap_access_ctx *access_ctx,
+ struct sdap_id_conn_ctx *conn,
+ const char *username,
+ struct ldb_message *user_entry,
+ enum sdap_pwpolicy_mode pwpol_mod);
static struct tevent_req *sdap_access_filter_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
@@ -79,7 +87,7 @@ static struct tevent_req *sdap_access_filter_send(TALLOC_CTX *mem_ctx,
static errno_t sdap_access_filter_recv(struct tevent_req *req);
-static errno_t sdap_access_lock_recv(struct tevent_req *req);
+static errno_t sdap_access_ppolicy_recv(struct tevent_req *req);
static errno_t sdap_account_expired(struct sdap_access_ctx *access_ctx,
struct pam_data *pd,
@@ -205,14 +213,34 @@ static errno_t sdap_access_check_next_rule(struct sdap_access_req_ctx *state,
return EOK;
case LDAP_ACCESS_LOCKOUT:
- subreq = sdap_access_lock_send(state, state->ev, state->be_ctx,
- state->domain,
- state->access_ctx,
- state->conn,
- state->pd->user,
- state->user_entry);
+ subreq = sdap_access_ppolicy_send(state, state->ev, state->be_ctx,
+ state->domain,
+ state->access_ctx,
+ state->conn,
+ state->pd->user,
+ state->user_entry,
+ PWP_LOCKOUT_ONLY);
if (subreq == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE, "sdap_access_lock_send failed.\n");
+ DEBUG(SSSDBG_CRIT_FAILURE, "sdap_access_ppolicy_send failed.\n");
+ return ENOMEM;
+ }
+
+ state->ac_type = SDAP_ACCESS_CONTROL_PPOLICY_LOCK;
+
+ tevent_req_set_callback(subreq, sdap_access_done, req);
+ return EAGAIN;
+
+ case LDAP_ACCESS_PPOLICY:
+ subreq = sdap_access_ppolicy_send(state, state->ev, state->be_ctx,
+ state->domain,
+ state->access_ctx,
+ state->conn,
+ state->pd->user,
+ state->user_entry,
+ PWP_LOCKOUT_EXPIRE);
+ if (subreq == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "sdap_access_ppolicy_send failed.\n");
return ENOMEM;
}
@@ -302,7 +330,7 @@ static void sdap_access_done(struct tevent_req *subreq)
ret = sdap_access_filter_recv(subreq);
break;
case SDAP_ACCESS_CONTROL_PPOLICY_LOCK:
- ret = sdap_access_lock_recv(subreq);
+ ret = sdap_access_ppolicy_recv(subreq);
break;
default:
ret = EINVAL;
@@ -779,8 +807,8 @@ struct sdap_access_filter_req_ctx {
static errno_t sdap_access_decide_offline(bool cached_ac);
static int sdap_access_filter_retry(struct tevent_req *req);
-static void sdap_access_lock_connect_done(struct tevent_req *subreq);
-static errno_t sdap_access_lock_get_lockout_step(struct tevent_req *req);
+static void sdap_access_ppolicy_connect_done(struct tevent_req *subreq);
+static errno_t sdap_access_ppolicy_get_lockout_step(struct tevent_req *req);
static void sdap_access_filter_connect_done(struct tevent_req *subreq);
static void sdap_access_filter_done(struct tevent_req *req);
static struct tevent_req *sdap_access_filter_send(TALLOC_CTX *mem_ctx,
@@ -1255,12 +1283,12 @@ static errno_t sdap_access_host(struct ldb_message *user_entry)
return ret;
}
-static void sdap_access_lock_get_lockout_done(struct tevent_req *subreq);
-static int sdap_access_lock_retry(struct tevent_req *req);
-static errno_t sdap_access_lock_step(struct tevent_req *req);
-static void sdap_access_lock_step_done(struct tevent_req *subreq);
+static void sdap_access_ppolicy_get_lockout_done(struct tevent_req *subreq);
+static int sdap_access_ppolicy_retry(struct tevent_req *req);
+static errno_t sdap_access_ppolicy_step(struct tevent_req *req);
+static void sdap_access_ppolicy_step_done(struct tevent_req *subreq);
-struct sdap_access_lock_req_ctx {
+struct sdap_access_ppolicy_req_ctx {
const char *username;
const char *filter;
struct tevent_context *ev;
@@ -1276,24 +1304,26 @@ struct sdap_access_lock_req_ctx {
/* default DNs to ppolicy */
const char **ppolicy_dns;
unsigned int ppolicy_dns_index;
+ enum sdap_pwpolicy_mode pwpol_mode;
};
static struct tevent_req *
-sdap_access_lock_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct be_ctx *be_ctx,
- struct sss_domain_info *domain,
- struct sdap_access_ctx *access_ctx,
- struct sdap_id_conn_ctx *conn,
- const char *username,
- struct ldb_message *user_entry)
+sdap_access_ppolicy_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct be_ctx *be_ctx,
+ struct sss_domain_info *domain,
+ struct sdap_access_ctx *access_ctx,
+ struct sdap_id_conn_ctx *conn,
+ const char *username,
+ struct ldb_message *user_entry,
+ enum sdap_pwpolicy_mode pwpol_mode)
{
- struct sdap_access_lock_req_ctx *state;
+ struct sdap_access_ppolicy_req_ctx *state;
struct tevent_req *req;
errno_t ret;
req = tevent_req_create(mem_ctx,
- &state, struct sdap_access_lock_req_ctx);
+ &state, struct sdap_access_ppolicy_req_ctx);
if (req == NULL) {
return NULL;
}
@@ -1306,9 +1336,10 @@ sdap_access_lock_send(TALLOC_CTX *mem_ctx,
state->access_ctx = access_ctx;
state->domain = domain;
state->ppolicy_dns_index = 0;
+ state->pwpol_mode = pwpol_mode;
DEBUG(SSSDBG_TRACE_FUNC,
- "Performing access lock check for user [%s]\n", username);
+ "Performing access ppolicy check for user [%s]\n", username);
state->cached_access = ldb_msg_find_attr_as_bool(
user_entry, SYSDB_LDAP_ACCESS_CACHED_LOCKOUT, false);
@@ -1326,7 +1357,7 @@ sdap_access_lock_send(TALLOC_CTX *mem_ctx,
goto done;
}
- DEBUG(SSSDBG_TRACE_FUNC, "Checking lock against LDAP\n");
+ DEBUG(SSSDBG_TRACE_FUNC, "Checking ppolicy against LDAP\n");
state->sdap_op = sdap_id_op_create(state,
state->conn->conn_cache);
@@ -1336,7 +1367,7 @@ sdap_access_lock_send(TALLOC_CTX *mem_ctx,
goto done;
}
- ret = sdap_access_lock_retry(req);
+ ret = sdap_access_ppolicy_retry(req);
if (ret != EOK) {
goto done;
}
@@ -1353,21 +1384,22 @@ done:
return req;
}
-static int sdap_access_lock_retry(struct tevent_req *req)
+static int sdap_access_ppolicy_retry(struct tevent_req *req)
{
- struct sdap_access_lock_req_ctx *state;
+ struct sdap_access_ppolicy_req_ctx *state;
struct tevent_req *subreq;
int ret;
- state = tevent_req_data(req, struct sdap_access_lock_req_ctx);
+ state = tevent_req_data(req, struct sdap_access_ppolicy_req_ctx);
subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret);
if (!subreq) {
DEBUG(SSSDBG_OP_FAILURE,
- "sdap_id_op_connect_send failed: %d (%s)\n", ret, strerror(ret));
+ "sdap_id_op_connect_send failed: %d (%s)\n",
+ ret, sss_strerror(ret));
return ret;
}
- tevent_req_set_callback(subreq, sdap_access_lock_connect_done, req);
+ tevent_req_set_callback(subreq, sdap_access_ppolicy_connect_done, req);
return EOK;
}
@@ -1394,15 +1426,15 @@ get_default_ppolicy_dns(TALLOC_CTX *mem_ctx, struct sdap_domain *sdom)
return ppolicy_dns;
}
-static void sdap_access_lock_connect_done(struct tevent_req *subreq)
+static void sdap_access_ppolicy_connect_done(struct tevent_req *subreq)
{
struct tevent_req *req;
- struct sdap_access_lock_req_ctx *state;
+ struct sdap_access_ppolicy_req_ctx *state;
int ret, dp_error;
const char *ppolicy_dn;
req = tevent_req_callback_data(subreq, struct tevent_req);
- state = tevent_req_data(req, struct sdap_access_lock_req_ctx);
+ state = tevent_req_data(req, struct sdap_access_ppolicy_req_ctx);
ret = sdap_id_op_connect_recv(subreq, &dp_error);
talloc_zfree(subreq);
@@ -1428,7 +1460,7 @@ static void sdap_access_lock_connect_done(struct tevent_req *subreq)
state->ppolicy_dns = talloc_array(state, const char*, 2);
if (state->ppolicy_dns == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Could not allocate ppolicy_dns.\n");
- tevent_req_error(req, ERR_ACCESS_DENIED);
+ tevent_req_error(req, ERR_INTERNAL);
return;
}
@@ -1442,7 +1474,7 @@ static void sdap_access_lock_connect_done(struct tevent_req *subreq)
state->ppolicy_dns = get_default_ppolicy_dns(state, state->opts->sdom);
if (state->ppolicy_dns == NULL) {
- tevent_req_error(req, ERR_ACCESS_DENIED);
+ tevent_req_error(req, ERR_INTERNAL);
return;
}
}
@@ -1450,28 +1482,33 @@ static void sdap_access_lock_connect_done(struct tevent_req *subreq)
/* Connection to LDAP succeeded
* Send 'pwdLockout' request
*/
- ret = sdap_access_lock_get_lockout_step(req);
+ ret = sdap_access_ppolicy_get_lockout_step(req);
if (ret != EOK && ret != EAGAIN) {
DEBUG(SSSDBG_CRIT_FAILURE,
- "sdap_access_lock_get_lockout_step failed: [%d][%s]\n",
- ret, strerror(ret));
- tevent_req_error(req, ERR_ACCESS_DENIED);
+ "sdap_access_ppolicy_get_lockout_step failed: [%d][%s]\n",
+ ret, sss_strerror(ret));
+ tevent_req_error(req, ERR_INTERNAL);
return;
}
+
+ if (ret == EOK) {
+ tevent_req_done(req);
+ }
}
static errno_t
-sdap_access_lock_get_lockout_step(struct tevent_req *req)
+sdap_access_ppolicy_get_lockout_step(struct tevent_req *req)
{
const char *attrs[] = { SYSDB_LDAP_ACCESS_LOCKOUT, NULL };
- struct sdap_access_lock_req_ctx *state;
+ struct sdap_access_ppolicy_req_ctx *state;
struct tevent_req *subreq;
errno_t ret;
- state = tevent_req_data(req, struct sdap_access_lock_req_ctx);
+ state = tevent_req_data(req, struct sdap_access_ppolicy_req_ctx);
/* no more DNs to try */
if (state->ppolicy_dns[state->ppolicy_dns_index] == NULL) {
+ DEBUG(SSSDBG_TRACE_FUNC, "No more DNs to try.\n");
ret = EOK;
goto done;
}
@@ -1493,14 +1530,13 @@ sdap_access_lock_get_lockout_step(struct tevent_req *req)
false);
if (subreq == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Could not start LDAP communication\n");
- tevent_req_error(req, EIO);
ret = EIO;
goto done;
}
/* try next basedn */
state->ppolicy_dns_index++;
- tevent_req_set_callback(subreq, sdap_access_lock_get_lockout_done, req);
+ tevent_req_set_callback(subreq, sdap_access_ppolicy_get_lockout_done, req);
ret = EAGAIN;
@@ -1508,17 +1544,17 @@ done:
return ret;
}
-static void sdap_access_lock_get_lockout_done(struct tevent_req *subreq)
+static void sdap_access_ppolicy_get_lockout_done(struct tevent_req *subreq)
{
int ret, tret, dp_error;
size_t num_results;
bool pwdLockout = false;
struct sysdb_attrs **results;
struct tevent_req *req;
- struct sdap_access_lock_req_ctx *state;
+ struct sdap_access_ppolicy_req_ctx *state;
req = tevent_req_callback_data(subreq, struct tevent_req);
- state = tevent_req_data(req, struct sdap_access_lock_req_ctx);
+ state = tevent_req_data(req, struct sdap_access_ppolicy_req_ctx);
ret = sdap_get_generic_recv(subreq, state, &num_results, &results);
talloc_zfree(subreq);
@@ -1536,7 +1572,7 @@ static void sdap_access_lock_get_lockout_done(struct tevent_req *subreq)
/* Didn't find ppolicy attribute */
if (num_results < 1) {
/* Try using next $search_base */
- ret = sdap_access_lock_get_lockout_step(req);
+ ret = sdap_access_ppolicy_get_lockout_step(req);
if (ret == EOK) {
/* No more search bases to try */
DEBUG(SSSDBG_CONF_SETTINGS,
@@ -1545,8 +1581,9 @@ static void sdap_access_lock_get_lockout_done(struct tevent_req *subreq)
} else {
if (ret != EAGAIN) {
DEBUG(SSSDBG_CRIT_FAILURE,
- "sdap_access_lock_get_lockout_step failed: [%d][%s]\n",
- ret, strerror(ret));
+ "sdap_access_ppolicy_get_lockout_step failed: "
+ "[%d][%s]\n",
+ ret, sss_strerror(ret));
}
goto done;
}
@@ -1567,7 +1604,7 @@ static void sdap_access_lock_get_lockout_done(struct tevent_req *subreq)
if (ret != EOK) {
DEBUG(SSSDBG_MINOR_FAILURE,
"Error reading %s: [%s]\n", SYSDB_LDAP_ACCESS_LOCKOUT,
- strerror(ret));
+ sss_strerror(ret));
ret = ERR_INTERNAL;
goto done;
}
@@ -1578,11 +1615,11 @@ static void sdap_access_lock_get_lockout_done(struct tevent_req *subreq)
"Password policy is enabled on LDAP server.\n");
/* ppolicy is enabled => find out if account is locked */
- ret = sdap_access_lock_step(req);
+ ret = sdap_access_ppolicy_step(req);
if (ret != EOK && ret != EAGAIN) {
DEBUG(SSSDBG_CRIT_FAILURE,
- "sdap_access_lock_step failed: [%d][%s].\n",
- ret, strerror(ret));
+ "sdap_access_ppolicy_step failed: [%d][%s].\n",
+ ret, sss_strerror(ret));
}
goto done;
} else {
@@ -1623,14 +1660,16 @@ done:
}
}
-errno_t sdap_access_lock_step(struct tevent_req *req)
+errno_t sdap_access_ppolicy_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 };
+ struct sdap_access_ppolicy_req_ctx *state;
+ 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);
+ state = tevent_req_data(req, struct sdap_access_ppolicy_req_ctx);
subreq = sdap_get_generic_send(state,
state->ev,
@@ -1645,30 +1684,114 @@ errno_t sdap_access_lock_step(struct tevent_req *req)
false);
if (subreq == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE, "sdap_access_lock_send failed.\n");
+ DEBUG(SSSDBG_CRIT_FAILURE, "sdap_access_ppolicy_send failed.\n");
ret = ENOMEM;
goto done;
}
- tevent_req_set_callback(subreq, sdap_access_lock_step_done, req);
+ tevent_req_set_callback(subreq, sdap_access_ppolicy_step_done, req);
ret = EAGAIN;
done:
return ret;
}
-static void sdap_access_lock_step_done(struct tevent_req *subreq)
+static errno_t
+is_account_locked(const char *pwdAccountLockedTime,
+ const char *pwdAccountLockedDurationTime,
+ enum sdap_pwpolicy_mode pwpol_mode,
+ const char *username,
+ bool *_locked)
+{
+ errno_t ret;
+ time_t lock_time;
+ time_t duration;
+ time_t now;
+ bool locked;
+
+ /* Default action is to consider account to be locked. */
+ locked = true;
+
+ /* account is permanently locked */
+ if (strcasecmp(pwdAccountLockedTime,
+ PERMANENTLY_LOCKED_ACCOUNT) == 0) {
+ ret = EOK;
+ goto done;
+ }
+
+ switch(pwpol_mode) {
+ case PWP_LOCKOUT_ONLY:
+ /* 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 of: %s is beeing blocked by password policy, "
+ "but value: [%s] value is ignored by SSSD.\n",
+ username, pwdAccountLockedTime);
+ locked = false;
+ break;
+ case PWP_LOCKOUT_EXPIRE:
+ /* 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 = sss_utc_to_time_t(pwdAccountLockedTime, "%Y%m%d%H%M%SZ",
+ &lock_time);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_TRACE_FUNC, "sss_utc_to_time_t 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 = strtouint32(pwdAccountLockedDurationTime, NULL, 0);
+ if (errno) {
+ ret = errno;
+ goto done;
+ }
+ /* Lockout has expired */
+ if (duration != 0 && difftime(now, lock_time) > duration) {
+ locked = false;
+ }
+ }
+ break;
+ case PWP_SENTINEL:
+ default:
+ DEBUG(SSSDBG_MINOR_FAILURE,
+ "Unexpected value of password policy mode: %d.\n", pwpol_mode);
+ }
+
+ ret = EOK;
+
+done:
+ if (ret == EOK) {
+ *_locked = locked;
+ }
+
+ return ret;
+}
+
+static void sdap_access_ppolicy_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;
+ struct sdap_access_ppolicy_req_ctx *state;
req = tevent_req_callback_data(subreq, struct tevent_req);
- state = tevent_req_data(req, struct sdap_access_lock_req_ctx);
+ state = tevent_req_data(req, struct sdap_access_ppolicy_req_ctx);
ret = sdap_get_generic_recv(subreq, state, &num_results, &results);
talloc_zfree(subreq);
@@ -1677,7 +1800,7 @@ static void sdap_access_lock_step_done(struct tevent_req *subreq)
if (ret != EOK) {
if (dp_error == DP_ERR_OK) {
/* retry */
- tret = sdap_access_lock_retry(req);
+ tret = sdap_access_ppolicy_retry(req);
if (tret == EOK) {
return;
}
@@ -1700,7 +1823,7 @@ static void sdap_access_lock_step_done(struct tevent_req *subreq)
if (num_results < 1) {
DEBUG(SSSDBG_CONF_SETTINGS,
"User [%s] was not found with the specified filter. "
- "Denying access.\n", state->username);
+ "Denying access.\n", state->username);
} else if (results == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "num_results > 0, but results is NULL\n");
ret = ERR_INTERNAL;
@@ -1713,22 +1836,35 @@ 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 = is_account_locked(pwdAccountLockedTime,
+ pwdAccountLockedDurationTime,
+ state->pwpol_mode,
+ state->username,
+ &locked);
+ if (ret != EOK) {
+ if (ret == ERR_TIMESPEC_NOT_SUPPORTED) {
+ DEBUG(SSSDBG_MINOR_FAILURE,
+ "timezone specifier in ppolicy is not supported\n");
+ } else {
+ DEBUG(SSSDBG_MINOR_FAILURE,
+ "is_account_locked failed: %d:[%s].\n",
+ ret, sss_strerror(ret));
+ }
+
+ DEBUG(SSSDBG_MINOR_FAILURE,
+ "Account will be considered to be locked.\n");
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
@@ -1774,7 +1910,7 @@ done:
}
}
-static errno_t sdap_access_lock_recv(struct tevent_req *req)
+static errno_t sdap_access_ppolicy_recv(struct tevent_req *req)
{
TEVENT_REQ_RETURN_ON_ERROR(req);
diff --git a/src/providers/ldap/sdap_access.h b/src/providers/ldap/sdap_access.h
index a8c663910..6e637be56 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"
@@ -45,6 +46,7 @@
#define LDAP_ACCESS_SERVICE_NAME "authorized_service"
#define LDAP_ACCESS_HOST_NAME "host"
#define LDAP_ACCESS_LOCK_NAME "lockout"
+#define LDAP_ACCESS_PPOLICY_NAME "ppolicy"
#define LDAP_ACCOUNT_EXPIRE_SHADOW "shadow"
#define LDAP_ACCOUNT_EXPIRE_AD "ad"
@@ -63,6 +65,7 @@ enum ldap_access_rule {
LDAP_ACCESS_EXPIRE_POLICY_REJECT,
LDAP_ACCESS_EXPIRE_POLICY_WARN,
LDAP_ACCESS_EXPIRE_POLICY_RENEW,
+ LDAP_ACCESS_PPOLICY,
LDAP_ACCESS_LAST
};