174 lines
6.1 KiB
Diff
174 lines
6.1 KiB
Diff
|
From d87a4bdeaa480ce5a2effe33e8e93cea5de715c9 Mon Sep 17 00:00:00 2001
|
||
|
From: Sumit Bose <sbose@redhat.com>
|
||
|
Date: Fri, 27 Mar 2015 15:20:13 +0100
|
||
|
Subject: [PATCH 112/114] 2FA offline auth
|
||
|
MIME-Version: 1.0
|
||
|
Content-Type: text/plain; charset=UTF-8
|
||
|
Content-Transfer-Encoding: 8bit
|
||
|
|
||
|
Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
|
||
|
(cherry picked from commit 219f5b698fa72c0d5a8da2b0dd99daec3f924c94)
|
||
|
---
|
||
|
src/db/sysdb_ops.c | 77 ++++++++++++++++++++++++++++++++++++++++--
|
||
|
src/responder/pam/pamsrv_cmd.c | 35 +++++++++++++++++--
|
||
|
2 files changed, 107 insertions(+), 5 deletions(-)
|
||
|
|
||
|
diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c
|
||
|
index 083d2778c97fe4d6149e4fc030885c482c511105..ed936e0fbe4451e9813402466d4850f0f586c1f5 100644
|
||
|
--- a/src/db/sysdb_ops.c
|
||
|
+++ b/src/db/sysdb_ops.c
|
||
|
@@ -3155,6 +3155,76 @@ done:
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
+static errno_t check_for_combined_2fa_password(struct sss_domain_info *domain,
|
||
|
+ struct ldb_message *ldb_msg,
|
||
|
+ const char *password,
|
||
|
+ const char *userhash)
|
||
|
+{
|
||
|
+
|
||
|
+ unsigned int cached_authtok_type;
|
||
|
+ unsigned int cached_fa2_len;
|
||
|
+ char *short_pw;
|
||
|
+ char *comphash;
|
||
|
+ size_t pw_len;
|
||
|
+ TALLOC_CTX *tmp_ctx;
|
||
|
+ int ret;
|
||
|
+
|
||
|
+ cached_authtok_type = ldb_msg_find_attr_as_uint(ldb_msg,
|
||
|
+ SYSDB_CACHEDPWD_TYPE,
|
||
|
+ SSS_AUTHTOK_TYPE_EMPTY);
|
||
|
+ if (cached_authtok_type != SSS_AUTHTOK_TYPE_2FA) {
|
||
|
+ DEBUG(SSSDBG_TRACE_LIBS, "Wrong authtok type.\n");
|
||
|
+ return EINVAL;
|
||
|
+ }
|
||
|
+
|
||
|
+ cached_fa2_len = ldb_msg_find_attr_as_uint(ldb_msg, SYSDB_CACHEDPWD_FA2_LEN,
|
||
|
+ 0);
|
||
|
+ if (cached_fa2_len == 0) {
|
||
|
+ DEBUG(SSSDBG_TRACE_LIBS, "Second factor size not available.\n");
|
||
|
+ return EINVAL;
|
||
|
+ }
|
||
|
+
|
||
|
+ pw_len = strlen(password);
|
||
|
+ if (pw_len < cached_fa2_len + domain->cache_credentials_min_ff_length) {
|
||
|
+ DEBUG(SSSDBG_TRACE_LIBS, "Password too short.\n");
|
||
|
+ return EINVAL;
|
||
|
+ }
|
||
|
+
|
||
|
+ tmp_ctx = talloc_new(NULL);
|
||
|
+ if (tmp_ctx == NULL) {
|
||
|
+ DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
|
||
|
+ return ENOMEM;
|
||
|
+ }
|
||
|
+
|
||
|
+ short_pw = talloc_strndup(tmp_ctx, password, (pw_len - cached_fa2_len));
|
||
|
+ if (short_pw == NULL) {
|
||
|
+ DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n");
|
||
|
+ ret = ENOMEM;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = s3crypt_sha512(tmp_ctx, short_pw, userhash, &comphash);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_CONF_SETTINGS, "Failed to create password hash.\n");
|
||
|
+ ret = ERR_INTERNAL;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (strcmp(userhash, comphash) != 0) {
|
||
|
+ DEBUG(SSSDBG_MINOR_FAILURE,
|
||
|
+ "Hash of shorten password does not match.\n");
|
||
|
+ ret = ERR_AUTH_FAILED;
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+
|
||
|
+ ret = EOK;
|
||
|
+
|
||
|
+done:
|
||
|
+ talloc_free(tmp_ctx);
|
||
|
+
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
int sysdb_cache_auth(struct sss_domain_info *domain,
|
||
|
const char *name,
|
||
|
const char *password,
|
||
|
@@ -3168,7 +3238,8 @@ int sysdb_cache_auth(struct sss_domain_info *domain,
|
||
|
SYSDB_LAST_LOGIN, SYSDB_LAST_ONLINE_AUTH,
|
||
|
"lastCachedPasswordChange",
|
||
|
"accountExpires", SYSDB_FAILED_LOGIN_ATTEMPTS,
|
||
|
- SYSDB_LAST_FAILED_LOGIN, NULL };
|
||
|
+ SYSDB_LAST_FAILED_LOGIN, SYSDB_CACHEDPWD_TYPE,
|
||
|
+ SYSDB_CACHEDPWD_FA2_LEN, NULL };
|
||
|
struct ldb_message *ldb_msg;
|
||
|
const char *userhash;
|
||
|
char *comphash;
|
||
|
@@ -3279,7 +3350,9 @@ int sysdb_cache_auth(struct sss_domain_info *domain,
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
- if (strcmp(userhash, comphash) == 0) {
|
||
|
+ if (strcmp(userhash, comphash) == 0
|
||
|
+ || check_for_combined_2fa_password(domain, ldb_msg,
|
||
|
+ password, userhash) == EOK) {
|
||
|
/* TODO: probable good point for audit logging */
|
||
|
DEBUG(SSSDBG_CONF_SETTINGS, "Hashes do match!\n");
|
||
|
authentication_successful = true;
|
||
|
diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c
|
||
|
index c7eb697f29b6de9f7edaaf7715a58d2b7afdc733..e8d2b65fe429bcb390f33ef994934f9b82b1a4b7 100644
|
||
|
--- a/src/responder/pam/pamsrv_cmd.c
|
||
|
+++ b/src/responder/pam/pamsrv_cmd.c
|
||
|
@@ -528,6 +528,34 @@ static void pam_reply_delay(struct tevent_context *ev, struct tevent_timer *te,
|
||
|
pam_reply(preq);
|
||
|
}
|
||
|
|
||
|
+static errno_t get_password_for_cache_auth(struct sss_auth_token *authtok,
|
||
|
+ const char **password)
|
||
|
+{
|
||
|
+ int ret;
|
||
|
+ size_t pw_len;
|
||
|
+ const char *fa2;
|
||
|
+ size_t fa2_len;
|
||
|
+
|
||
|
+ switch (sss_authtok_get_type(authtok)) {
|
||
|
+ case SSS_AUTHTOK_TYPE_PASSWORD:
|
||
|
+ ret = sss_authtok_get_password(authtok, password, NULL);
|
||
|
+ break;
|
||
|
+ case SSS_AUTHTOK_TYPE_2FA:
|
||
|
+ ret = sss_authtok_get_2fa(authtok, password, &pw_len, &fa2, &fa2_len);
|
||
|
+ break;
|
||
|
+ default:
|
||
|
+ DEBUG(SSSDBG_FATAL_FAILURE, "Unsupported auth token type [%d].\n",
|
||
|
+ sss_authtok_get_type(authtok));
|
||
|
+ ret = EINVAL;
|
||
|
+ }
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_FATAL_FAILURE, "Failed to get password.\n");
|
||
|
+ return ret;
|
||
|
+ }
|
||
|
+
|
||
|
+ return EOK;
|
||
|
+}
|
||
|
+
|
||
|
static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd);
|
||
|
static void pam_handle_cached_login(struct pam_auth_req *preq, int ret,
|
||
|
time_t expire_date, time_t delayed_until);
|
||
|
@@ -586,9 +614,10 @@ static void pam_reply(struct pam_auth_req *preq)
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
- ret = sss_authtok_get_password(pd->authtok, &password, NULL);
|
||
|
- if (ret) {
|
||
|
- DEBUG(SSSDBG_FATAL_FAILURE, "Failed to get password.\n");
|
||
|
+ ret = get_password_for_cache_auth(pd->authtok, &password);
|
||
|
+ if (ret != EOK) {
|
||
|
+ DEBUG(SSSDBG_FATAL_FAILURE,
|
||
|
+ "get_password_and_type_for_cache_auth failed.\n");
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
--
|
||
|
2.4.0
|
||
|
|