205 lines
8.6 KiB
Diff
205 lines
8.6 KiB
Diff
|
From 0aac71d726bda4af3ba141bed7707512cda7fd9a Mon Sep 17 00:00:00 2001
|
||
|
From: Joshua Roys <roysjosh@gmail.com>
|
||
|
Date: Mon, 14 May 2012 10:23:34 -0400
|
||
|
Subject: [PATCH 13/19] Simple implementation of Netscape password warning
|
||
|
expiration control
|
||
|
|
||
|
---
|
||
|
src/providers/ldap/sdap_async_connection.c | 96 +++++++++++++++++++++-------
|
||
|
src/util/sss_ldap.h | 8 +++
|
||
|
2 files changed, 82 insertions(+), 22 deletions(-)
|
||
|
|
||
|
diff --git a/src/providers/ldap/sdap_async_connection.c b/src/providers/ldap/sdap_async_connection.c
|
||
|
index e933e296b7df20ff8d034c2a11745b5c68b25e65..efd9cd8cc7205e4cb838523b0311ffd50805d590 100644
|
||
|
--- a/src/providers/ldap/sdap_async_connection.c
|
||
|
+++ b/src/providers/ldap/sdap_async_connection.c
|
||
|
@@ -26,6 +26,7 @@
|
||
|
#include "util/util.h"
|
||
|
#include "util/sss_krb5.h"
|
||
|
#include "util/sss_ldap.h"
|
||
|
+#include "util/strtonum.h"
|
||
|
#include "providers/ldap/sdap_async_private.h"
|
||
|
#include "providers/ldap/ldap_common.h"
|
||
|
|
||
|
@@ -541,7 +542,9 @@ static void simple_bind_done(struct sdap_op *op,
|
||
|
struct simple_bind_state *state = tevent_req_data(req,
|
||
|
struct simple_bind_state);
|
||
|
char *errmsg = NULL;
|
||
|
- int ret;
|
||
|
+ char *nval;
|
||
|
+ errno_t ret;
|
||
|
+ int lret;
|
||
|
LDAPControl **response_controls;
|
||
|
int c;
|
||
|
ber_int_t pp_grace;
|
||
|
@@ -555,30 +558,33 @@ static void simple_bind_done(struct sdap_op *op,
|
||
|
|
||
|
state->reply = talloc_steal(state, reply);
|
||
|
|
||
|
- ret = ldap_parse_result(state->sh->ldap, state->reply->msg,
|
||
|
+ lret = ldap_parse_result(state->sh->ldap, state->reply->msg,
|
||
|
&state->result, NULL, &errmsg, NULL,
|
||
|
&response_controls, 0);
|
||
|
- if (ret != LDAP_SUCCESS) {
|
||
|
- DEBUG(2, ("ldap_parse_result failed (%d)\n", state->op->msgid));
|
||
|
+ if (lret != LDAP_SUCCESS) {
|
||
|
+ DEBUG(SSSDBG_MINOR_FAILURE,
|
||
|
+ ("ldap_parse_result failed (%d)\n", state->op->msgid));
|
||
|
ret = EIO;
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
if (response_controls == NULL) {
|
||
|
- DEBUG(5, ("Server returned no controls.\n"));
|
||
|
+ DEBUG(SSSDBG_TRACE_LIBS, ("Server returned no controls.\n"));
|
||
|
state->ppolicy = NULL;
|
||
|
} else {
|
||
|
for (c = 0; response_controls[c] != NULL; c++) {
|
||
|
- DEBUG(9, ("Server returned control [%s].\n",
|
||
|
- response_controls[c]->ldctl_oid));
|
||
|
+ DEBUG(SSSDBG_TRACE_INTERNAL,
|
||
|
+ ("Server returned control [%s].\n",
|
||
|
+ response_controls[c]->ldctl_oid));
|
||
|
if (strcmp(response_controls[c]->ldctl_oid,
|
||
|
LDAP_CONTROL_PASSWORDPOLICYRESPONSE) == 0) {
|
||
|
- ret = ldap_parse_passwordpolicy_control(state->sh->ldap,
|
||
|
+ lret = ldap_parse_passwordpolicy_control(state->sh->ldap,
|
||
|
response_controls[c],
|
||
|
&pp_expire, &pp_grace,
|
||
|
&pp_error);
|
||
|
- if (ret != LDAP_SUCCESS) {
|
||
|
- DEBUG(1, ("ldap_parse_passwordpolicy_control failed.\n"));
|
||
|
+ if (lret != LDAP_SUCCESS) {
|
||
|
+ DEBUG(SSSDBG_MINOR_FAILURE,
|
||
|
+ ("ldap_parse_passwordpolicy_control failed.\n"));
|
||
|
ret = EIO;
|
||
|
goto done;
|
||
|
}
|
||
|
@@ -586,9 +592,10 @@ static void simple_bind_done(struct sdap_op *op,
|
||
|
DEBUG(7, ("Password Policy Response: expire [%d] grace [%d] "
|
||
|
"error [%s].\n", pp_expire, pp_grace,
|
||
|
ldap_passwordpolicy_err2txt(pp_error)));
|
||
|
- state->ppolicy = talloc(state, struct sdap_ppolicy_data);
|
||
|
+ if (!state->ppolicy)
|
||
|
+ state->ppolicy = talloc_zero(state,
|
||
|
+ struct sdap_ppolicy_data);
|
||
|
if (state->ppolicy == NULL) {
|
||
|
- DEBUG(1, ("talloc failed.\n"));
|
||
|
ret = ENOMEM;
|
||
|
goto done;
|
||
|
}
|
||
|
@@ -596,36 +603,81 @@ static void simple_bind_done(struct sdap_op *op,
|
||
|
state->ppolicy->expire = pp_expire;
|
||
|
if (state->result == LDAP_SUCCESS) {
|
||
|
if (pp_error == PP_changeAfterReset) {
|
||
|
- DEBUG(4, ("Password was reset. "
|
||
|
- "User must set a new password.\n"));
|
||
|
+ DEBUG(SSSDBG_TRACE_LIBS,
|
||
|
+ ("Password was reset. "
|
||
|
+ "User must set a new password.\n"));
|
||
|
state->result = LDAP_X_SSSD_PASSWORD_EXPIRED;
|
||
|
} else if (pp_grace > 0) {
|
||
|
- DEBUG(4, ("Password expired. "
|
||
|
- "[%d] grace logins remaining.\n", pp_grace));
|
||
|
+ DEBUG(SSSDBG_TRACE_LIBS,
|
||
|
+ ("Password expired. "
|
||
|
+ "[%d] grace logins remaining.\n",
|
||
|
+ pp_grace));
|
||
|
} else if (pp_expire > 0) {
|
||
|
- DEBUG(4, ("Password will expire in [%d] seconds.\n",
|
||
|
- pp_expire));
|
||
|
+ DEBUG(SSSDBG_TRACE_LIBS,
|
||
|
+ ("Password will expire in [%d] seconds.\n",
|
||
|
+ pp_expire));
|
||
|
}
|
||
|
} else if (state->result == LDAP_INVALID_CREDENTIALS &&
|
||
|
pp_error == PP_passwordExpired) {
|
||
|
- DEBUG(4,
|
||
|
+ DEBUG(SSSDBG_TRACE_LIBS,
|
||
|
("Password expired user must set a new password.\n"));
|
||
|
state->result = LDAP_X_SSSD_PASSWORD_EXPIRED;
|
||
|
}
|
||
|
+ } else if (strcmp(response_controls[c]->ldctl_oid,
|
||
|
+ LDAP_CONTROL_PWEXPIRED) == 0) {
|
||
|
+ DEBUG(SSSDBG_TRACE_LIBS,
|
||
|
+ ("Password expired user must set a new password.\n"));
|
||
|
+ state->result = LDAP_X_SSSD_PASSWORD_EXPIRED;
|
||
|
+ } else if (strcmp(response_controls[c]->ldctl_oid,
|
||
|
+ LDAP_CONTROL_PWEXPIRING) == 0) {
|
||
|
+ /* ignore controls with suspiciously long values */
|
||
|
+ if (response_controls[c]->ldctl_value.bv_len > 32) {
|
||
|
+ continue;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!state->ppolicy) {
|
||
|
+ state->ppolicy = talloc(state, struct sdap_ppolicy_data);
|
||
|
+ }
|
||
|
+
|
||
|
+ if (state->ppolicy == NULL) {
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+ /* ensure that bv_val is a null-terminated string */
|
||
|
+ nval = talloc_strndup(NULL,
|
||
|
+ response_controls[c]->ldctl_value.bv_val,
|
||
|
+ response_controls[c]->ldctl_value.bv_len);
|
||
|
+ if (nval == NULL) {
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+ state->ppolicy->expire = strtouint32(nval, NULL, 10);
|
||
|
+ ret = errno;
|
||
|
+ talloc_zfree(nval);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_MINOR_FAILURE,
|
||
|
+ ("Could not convert control response to an integer. ",
|
||
|
+ "[%s]\n", strerror(ret)));
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ DEBUG(SSSDBG_TRACE_LIBS,
|
||
|
+ ("Password will expire in [%d] seconds.\n",
|
||
|
+ state->ppolicy->expire));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- DEBUG(3, ("Bind result: %s(%d), %s\n",
|
||
|
+ DEBUG(SSSDBG_TRACE_FUNC, ("Bind result: %s(%d), %s\n",
|
||
|
sss_ldap_err2string(state->result), state->result,
|
||
|
errmsg ? errmsg : "no errmsg set"));
|
||
|
|
||
|
- ret = LDAP_SUCCESS;
|
||
|
+ ret = EOK;
|
||
|
done:
|
||
|
ldap_controls_free(response_controls);
|
||
|
ldap_memfree(errmsg);
|
||
|
|
||
|
- if (ret == LDAP_SUCCESS) {
|
||
|
+ if (ret == EOK) {
|
||
|
tevent_req_done(req);
|
||
|
} else {
|
||
|
tevent_req_error(req, ret);
|
||
|
diff --git a/src/util/sss_ldap.h b/src/util/sss_ldap.h
|
||
|
index 8a69b832965bf5ad23986a9b64cb5252cc3b1999..46829259aedcf4a4f2ba3f94fc059c343c0e9ba6 100644
|
||
|
--- a/src/util/sss_ldap.h
|
||
|
+++ b/src/util/sss_ldap.h
|
||
|
@@ -29,6 +29,14 @@
|
||
|
|
||
|
#define LDAP_X_SSSD_PASSWORD_EXPIRED 0x555D
|
||
|
|
||
|
+#ifndef LDAP_CONTROL_PWEXPIRED
|
||
|
+#define LDAP_CONTROL_PWEXPIRED "2.16.840.1.113730.3.4.4"
|
||
|
+#endif
|
||
|
+
|
||
|
+#ifndef LDAP_CONTROL_PWEXPIRING
|
||
|
+#define LDAP_CONTROL_PWEXPIRING "2.16.840.1.113730.3.4.5"
|
||
|
+#endif
|
||
|
+
|
||
|
#ifdef LDAP_OPT_DIAGNOSTIC_MESSAGE
|
||
|
#define SDAP_DIAGNOSTIC_MESSAGE LDAP_OPT_DIAGNOSTIC_MESSAGE
|
||
|
#else
|
||
|
--
|
||
|
1.7.10.1
|
||
|
|