summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/responder/pam/pamsrv.h5
-rw-r--r--src/responder/pam/pamsrv_cmd.c2
-rw-r--r--src/tests/cmocka/test_pam_srv.c188
3 files changed, 194 insertions, 1 deletions
diff --git a/src/responder/pam/pamsrv.h b/src/responder/pam/pamsrv.h
index 59831f2e7..64a7d8573 100644
--- a/src/responder/pam/pamsrv.h
+++ b/src/responder/pam/pamsrv.h
@@ -95,4 +95,9 @@ errno_t add_pam_cert_response(struct pam_data *pd, const char *user,
const char *token_name);
bool may_do_cert_auth(struct pam_ctx *pctx, struct pam_data *pd);
+
+errno_t
+pam_set_last_online_auth_with_curr_token(struct sss_domain_info *domain,
+ const char *username,
+ uint64_t value);
#endif /* __PAMSRV_H__ */
diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c
index 4bb3e27b1..80095cc0b 100644
--- a/src/responder/pam/pamsrv_cmd.c
+++ b/src/responder/pam/pamsrv_cmd.c
@@ -1925,7 +1925,7 @@ struct sss_cmd_table *get_pam_cmds(void)
return sss_cmds;
}
-static errno_t
+errno_t
pam_set_last_online_auth_with_curr_token(struct sss_domain_info *domain,
const char *username,
uint64_t value)
diff --git a/src/tests/cmocka/test_pam_srv.c b/src/tests/cmocka/test_pam_srv.c
index 30fbbc6ea..f3fbf907a 100644
--- a/src/tests/cmocka/test_pam_srv.c
+++ b/src/tests/cmocka/test_pam_srv.c
@@ -71,6 +71,9 @@
"zotpoBIZmdH+ipYsu58HohHVlM9Wi5H4QmiiXl+Soldkq7eXYlafcmT7wv8+cKwz" \
"Nz0Tm3+eYpFqRo3skr6QzXi525Jkg3r6r+kkhxU=" \
+static char CACHED_AUTH_TIMEOUT_STR[] = "2";
+static const int CACHED_AUTH_TIMEOUT = 2;
+
struct pam_test_ctx {
struct sss_test_ctx *tctx;
struct sss_domain_info *subdom;
@@ -82,6 +85,7 @@ struct pam_test_ctx {
int ncache_hits;
int exp_pam_status;
+ bool provider_contacted;
};
/* Must be global because it is needed in some wrappers */
@@ -301,6 +305,26 @@ static int pam_test_setup(void **state)
return 0;
}
+static int pam_cached_test_setup(void **state)
+{
+ struct sss_test_conf_param dom_params[] = {
+ { "enumerate", "false" },
+ { "cache_credentials", "true" },
+ { "cached_auth_timeout", CACHED_AUTH_TIMEOUT_STR },
+ { NULL, NULL }, /* Sentinel */
+ };
+
+ struct sss_test_conf_param pam_params[] = {
+ { "p11_child_timeout", "30" },
+ { NULL, NULL }, /* Sentinel */
+ };
+
+ test_pam_setup(dom_params, pam_params, state);
+
+ pam_test_setup_common();
+ return 0;
+}
+
static int pam_test_teardown(void **state)
{
int ret;
@@ -383,6 +407,7 @@ static void set_cmd_cb(cmd_cb_fn_t fn)
int __wrap_pam_dp_send_req(struct pam_auth_req *preq, int timeout)
{
+ pam_test_ctx->provider_contacted = true;
/* Set expected status */
preq->pd->pam_status = pam_test_ctx->exp_pam_status;
@@ -620,6 +645,13 @@ static int test_pam_successful_offline_auth_check(uint32_t status,
return test_pam_simple_check(status, body, blen);
}
+static int test_pam_successful_cached_auth_check(uint32_t status,
+ uint8_t *body, size_t blen)
+{
+ pam_test_ctx->exp_pam_status = PAM_SUCCESS;
+ return test_pam_simple_check(status, body, blen);
+}
+
static int test_pam_wrong_pw_offline_auth_check(uint32_t status,
uint8_t *body, size_t blen)
{
@@ -814,6 +846,144 @@ void test_pam_preauth(void **state)
assert_int_equal(ret, EOK);
}
+/* Cached on-line authentication */
+
+static void common_test_pam_cached_auth(const char *pwd)
+{
+ int ret;
+
+ mock_input_pam(pam_test_ctx, "pamuser", pwd, NULL);
+
+ will_return(__wrap_sss_packet_get_cmd, SSS_PAM_AUTHENTICATE);
+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
+
+ pam_test_ctx->exp_pam_status = PAM_SUCCESS;
+ set_cmd_cb(test_pam_successful_cached_auth_check);
+
+ ret = sss_cmd_execute(pam_test_ctx->cctx, SSS_PAM_AUTHENTICATE,
+ pam_test_ctx->pam_cmds);
+ assert_int_equal(ret, EOK);
+
+ /* Wait until the test finishes with EOK */
+ ret = test_ev_loop(pam_test_ctx->tctx);
+ assert_int_equal(ret, EOK);
+}
+
+void test_pam_cached_auth_success(void **state)
+{
+ int ret;
+
+ common_test_pam_cached_auth("12345");
+
+ /* Back end should be contacted */
+ assert_true(pam_test_ctx->provider_contacted);
+
+ ret = sysdb_cache_password(pam_test_ctx->tctx->dom, "pamuser", "12345");
+ assert_int_equal(ret, EOK);
+
+ /* Reset before next call */
+ pam_test_ctx->provider_contacted = false;
+
+ common_test_pam_cached_auth("12345");
+
+ /* Back end should not be contacted */
+ assert_false(pam_test_ctx->provider_contacted);
+}
+
+void test_pam_cached_auth_wrong_pw(void **state)
+{
+ int ret;
+
+ ret = sysdb_cache_password(pam_test_ctx->tctx->dom, "pamuser", "12345");
+ assert_int_equal(ret, EOK);
+
+ ret = pam_set_last_online_auth_with_curr_token(pam_test_ctx->tctx->dom,
+ "pamuser", time(NULL));
+ assert_int_equal(ret, EOK);
+
+ common_test_pam_cached_auth("11111");
+
+ /* Back end should be contacted */
+ assert_true(pam_test_ctx->provider_contacted);
+}
+
+/* test cached_auth_timeout option */
+void test_pam_cached_auth_opt_timeout(void **state)
+{
+ int ret;
+ uint64_t last_online;
+
+ ret = sysdb_cache_password(pam_test_ctx->tctx->dom, "pamuser", "12345");
+ assert_int_equal(ret, EOK);
+
+ last_online = time(NULL) - CACHED_AUTH_TIMEOUT - 1;
+ ret = pam_set_last_online_auth_with_curr_token(pam_test_ctx->tctx->dom,
+ "pamuser",
+ last_online);
+ assert_int_equal(ret, EOK);
+
+ common_test_pam_cached_auth("12345");
+
+ /* Back end should be contacted */
+ assert_true(pam_test_ctx->provider_contacted);
+}
+
+/* too long since last on-line authentication */
+void test_pam_cached_auth_timeout(void **state)
+{
+ int ret;
+
+ ret = sysdb_cache_password(pam_test_ctx->tctx->dom, "pamuser", "12345");
+ assert_int_equal(ret, EOK);
+
+ ret = pam_set_last_online_auth_with_curr_token(pam_test_ctx->tctx->dom,
+ "pamuser", 0);
+ assert_int_equal(ret, EOK);
+
+ common_test_pam_cached_auth("12345");
+
+ /* Back end should be contacted */
+ assert_true(pam_test_ctx->provider_contacted);
+}
+
+void test_pam_cached_auth_success_combined_pw_with_cached_2fa(void **state)
+{
+ int ret;
+
+ common_test_pam_cached_auth("12345678");
+
+ assert_true(pam_test_ctx->provider_contacted);
+
+ ret = sysdb_cache_password_ex(pam_test_ctx->tctx->dom, "pamuser",
+ "12345678", SSS_AUTHTOK_TYPE_2FA, 5);
+ assert_int_equal(ret, EOK);
+
+ /* Reset before next call */
+ pam_test_ctx->provider_contacted = false;
+
+ common_test_pam_cached_auth("12345678");
+
+ assert_false(pam_test_ctx->provider_contacted);
+}
+
+void test_pam_cached_auth_failed_combined_pw_with_cached_2fa(void **state)
+{
+ int ret;
+
+ ret = sysdb_cache_password_ex(pam_test_ctx->tctx->dom, "pamuser",
+ "12345678", SSS_AUTHTOK_TYPE_2FA, 5);
+ assert_int_equal(ret, EOK);
+ ret = pam_set_last_online_auth_with_curr_token(pam_test_ctx->tctx->dom,
+ "pamuser", time(NULL));
+ assert_int_equal(ret, EOK);
+
+ common_test_pam_cached_auth("1111abcde");
+
+ assert_true(pam_test_ctx->provider_contacted);
+}
+
+/* Off-line authentication */
+
void test_pam_offline_auth_no_hash(void **state)
{
int ret;
@@ -1474,6 +1644,24 @@ int main(int argc, const char *argv[])
pam_test_setup, pam_test_teardown),
cmocka_unit_test_setup_teardown(test_pam_preauth_no_logon_name,
pam_test_setup, pam_test_teardown),
+ cmocka_unit_test_setup_teardown(test_pam_cached_auth_success,
+ pam_cached_test_setup,
+ pam_test_teardown),
+ cmocka_unit_test_setup_teardown(test_pam_cached_auth_wrong_pw,
+ pam_cached_test_setup,
+ pam_test_teardown),
+ cmocka_unit_test_setup_teardown(test_pam_cached_auth_opt_timeout,
+ pam_cached_test_setup,
+ pam_test_teardown),
+ cmocka_unit_test_setup_teardown(test_pam_cached_auth_timeout,
+ pam_cached_test_setup,
+ pam_test_teardown),
+ cmocka_unit_test_setup_teardown(test_pam_cached_auth_success_combined_pw_with_cached_2fa,
+ pam_cached_test_setup,
+ pam_test_teardown),
+ cmocka_unit_test_setup_teardown(test_pam_cached_auth_failed_combined_pw_with_cached_2fa,
+ pam_cached_test_setup,
+ pam_test_teardown),
/* p11_child is not built without NSS */
#ifdef HAVE_NSS
cmocka_unit_test_setup_teardown(test_pam_preauth_cert_nocert,