From 711a96064e7c102a3b7552794b066578e53baaab Mon Sep 17 00:00:00 2001 From: Greg Veldman Date: Thu, 3 Oct 2019 08:37:03 +0100 Subject: [PATCH] ITS#9055 Accept previous token --- contrib/slapd-modules/passwd/totp/slapd-totp.c | 15 ++++++++++++++- contrib/slapd-modules/passwd/totp/slapo-totp.5 | 7 +++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/contrib/slapd-modules/passwd/totp/slapd-totp.c b/contrib/slapd-modules/passwd/totp/slapd-totp.c index 0821d28212..57407e4ac8 100644 --- a/contrib/slapd-modules/passwd/totp/slapd-totp.c +++ b/contrib/slapd-modules/passwd/totp/slapd-totp.c @@ -479,7 +479,6 @@ static int chk_totp( out.mv_val = outbuf; out.mv_len = sizeof(outbuf); generate(&key, t, DIGITS, &out, mech); - memset(key.mv_val, 0, key.mv_len); /* compare */ if (out.mv_len != cred->bv_len) { @@ -489,7 +488,21 @@ static int chk_totp( rc = memcmp(out.mv_val, cred->bv_val, out.mv_len) ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK; + /* If current value doesn't match, try again with previous value + * but only if the most recent login is older than the previous + * time step but still set */ + if (rc == LUTIL_PASSWD_ERR && told < t - 1 && told > 0) { + out.mv_val = outbuf; + out.mv_len = sizeof(outbuf); + generate(&key, t - 1, DIGITS, &out, mech); + /* compare */ + if (out.mv_len != cred->bv_len) + goto out; + rc = memcmp(out.mv_val, cred->bv_val, out.mv_len) ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK; + } + out: + memset(key.mv_val, 0, key.mv_len); ber_memfree(key.mv_val); return rc; } diff --git a/contrib/slapd-modules/passwd/totp/slapo-totp.5 b/contrib/slapd-modules/passwd/totp/slapo-totp.5 index 08843bb94e..daf064efd4 100644 --- a/contrib/slapd-modules/passwd/totp/slapo-totp.5 +++ b/contrib/slapd-modules/passwd/totp/slapo-totp.5 @@ -72,6 +72,13 @@ services. The time step is hard-coded to thirty seconds. This should be OK for many use cases, but it would be nice if the value could be changed with a configuration keyword or in an attribute value. +However, after one successful initial authentication (to verify +the clocks on the server and the user's prover are in sync) the TOTP +value of the previous time window may also be used to successfully +authenticate, provided no successful bind has been performed already +in the current or previous time window. This eliminates false +negatives caused by user or network delays +entering or transmitting the TOTP value. The authenticator code that is generated is hard-coded to a length of six digits. While in most cases