mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Ensure that ipa-otpd bind auths validate an OTP
Before this patch, if the user was configured for either OTP or password it was possible to do a 1FA authentication through ipa-otpd. Because this correctly respected the configuration, it is not a security error. However, once we begin to insert authentication indicators into the Kerberos tickets, we cannot allow 1FA authentications through this code path. Otherwise the ticket would contain a 2FA indicator when only 1FA was actually performed. To solve this problem, we have ipa-otpd send a critical control during the bind operation which informs the LDAP server that it *MUST* validate an OTP token for authentication to be successful. Next, we implement support for this control in the ipa-pwd-extop plugin. The end result is that the bind operation will always fail if the control is present and no OTP is validated. https://fedorahosted.org/freeipa/ticket/433 Reviewed-By: Sumit Bose <sbose@redhat.com>
This commit is contained in:
committed by
Martin Basti
parent
cd9bc84240
commit
168a6c7d47
@@ -26,9 +26,12 @@
|
||||
*/
|
||||
|
||||
#include "internal.h"
|
||||
#include "../ipa-slapi-plugins/ipa-pwd-extop/otpctrl.h"
|
||||
|
||||
static void on_bind_writable(verto_ctx *vctx, verto_ev *ev)
|
||||
{
|
||||
LDAPControl control = { OTP_REQUIRED_OID, {}, true };
|
||||
LDAPControl *ctrls[] = { &control, NULL };
|
||||
struct otpd_queue *push = &ctx.stdio.responses;
|
||||
const krb5_data *data;
|
||||
struct berval cred;
|
||||
@@ -55,7 +58,7 @@ static void on_bind_writable(verto_ctx *vctx, verto_ev *ev)
|
||||
cred.bv_val = data->data;
|
||||
cred.bv_len = data->length;
|
||||
i = ldap_sasl_bind(verto_get_private(ev), item->user.dn, LDAP_SASL_SIMPLE,
|
||||
&cred, NULL, NULL, &item->msgid);
|
||||
&cred, ctrls, NULL, &item->msgid);
|
||||
if (i != LDAP_SUCCESS) {
|
||||
otpd_log_err(errno, "Unable to initiate bind: %s", ldap_err2string(i));
|
||||
verto_break(ctx.vctx);
|
||||
|
||||
@@ -55,6 +55,9 @@
|
||||
*/
|
||||
#define OTP_SYNC_REQUEST_OID "2.16.840.1.113730.3.8.10.6"
|
||||
|
||||
/* This control has no data. */
|
||||
#define OTP_REQUIRED_OID "2.16.840.1.113730.3.8.10.7"
|
||||
|
||||
bool otpctrl_present(Slapi_PBlock *pb, const char *oid);
|
||||
|
||||
bool otpctrl_sync_handle(const struct otp_config *cfg, Slapi_PBlock *pb,
|
||||
|
||||
@@ -1172,7 +1172,7 @@ done:
|
||||
* validation.
|
||||
*/
|
||||
static bool ipapwd_pre_bind_otp(const char *bind_dn, Slapi_Entry *entry,
|
||||
struct berval *creds)
|
||||
struct berval *creds, bool otpreq)
|
||||
{
|
||||
uint32_t auth_types;
|
||||
|
||||
@@ -1204,10 +1204,10 @@ static bool ipapwd_pre_bind_otp(const char *bind_dn, Slapi_Entry *entry,
|
||||
return false;
|
||||
}
|
||||
|
||||
/* If the user has no active tokens, succeed. */
|
||||
/* With no tokens, succeed if tokens aren't required. */
|
||||
if (tokens[0] == NULL) {
|
||||
otp_token_free_array(tokens);
|
||||
return true;
|
||||
return !otpreq;
|
||||
}
|
||||
|
||||
if (otp_token_validate_berval(tokens, creds, NULL)) {
|
||||
@@ -1218,7 +1218,7 @@ static bool ipapwd_pre_bind_otp(const char *bind_dn, Slapi_Entry *entry,
|
||||
otp_token_free_array(tokens);
|
||||
}
|
||||
|
||||
return auth_types & OTP_CONFIG_AUTH_TYPE_PASSWORD;
|
||||
return (auth_types & OTP_CONFIG_AUTH_TYPE_PASSWORD) && !otpreq;
|
||||
}
|
||||
|
||||
static int ipapwd_authenticate(const char *dn, Slapi_Entry *entry,
|
||||
@@ -1394,6 +1394,7 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
|
||||
char *dn = NULL;
|
||||
int method = 0;
|
||||
bool syncreq;
|
||||
bool otpreq;
|
||||
int ret = 0;
|
||||
time_t current_time;
|
||||
time_t expire_time;
|
||||
@@ -1451,7 +1452,8 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
|
||||
|
||||
/* Try to do OTP first. */
|
||||
syncreq = otpctrl_present(pb, OTP_SYNC_REQUEST_OID);
|
||||
if (!syncreq && !ipapwd_pre_bind_otp(dn, entry, credentials))
|
||||
otpreq = otpctrl_present(pb, OTP_REQUIRED_OID);
|
||||
if (!syncreq && !ipapwd_pre_bind_otp(dn, entry, credentials, otpreq))
|
||||
goto invalid_creds;
|
||||
|
||||
/* Ensure that there is a password. */
|
||||
@@ -1488,6 +1490,7 @@ int ipapwd_pre_init(Slapi_PBlock *pb)
|
||||
int ret;
|
||||
|
||||
slapi_register_supported_control(OTP_SYNC_REQUEST_OID, SLAPI_OPERATION_BIND);
|
||||
slapi_register_supported_control(OTP_REQUIRED_OID, SLAPI_OPERATION_BIND);
|
||||
|
||||
ret = slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01);
|
||||
if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&ipapwd_plugin_desc);
|
||||
|
||||
Reference in New Issue
Block a user