[SSSD] [PATCH] TESTS: extend PAM responder unit test

Lukas Slebodnik lslebodn at redhat.com
Tue Nov 10 16:00:58 UTC 2015


On (05/11/15 17:01), Pavel Reichl wrote:
>On 11/05/2015 09:17 AM, Lukas Slebodnik wrote:
>>Let's image following use case:
>>* cached authentication is enabled.
>>* user "pamuser" has never authenticated to the machine and thus
>>   password is not cached
>>* for the first time the the data provider should be contacted.
>>   ( storing cached password is done in DP, so you still need to
>>     call sysdb_cache_password)
>>* cached authentication shoudl be used for second following authentication.
>>   and attribute lastOnlineAuthWithCurrentToken should be set be 1st
>>   authentication so you needn't call pam_set_last_online_auth_with_curr_token.
>>
>>This test-case would test that attribute lastOnlineAuthWithCurrentToken is
>>properly set.
>>
>>Is it clear?
>
>I hope so, thanks.
>
>Updated patches attached.

>From 931190aa5faca0833fe285c6815ab955fd706f2d Mon Sep 17 00:00:00 2001
>From: Pavel Reichl <preichl at redhat.com>
>Date: Tue, 20 Oct 2015 08:07:02 -0400
>Subject: [PATCH 1/2] pam-srv-tests: split pam_test_setup() so it can be reused
>
>Split pam_test_setup() so domain and pam parameters can be easily set
>distinctly for each test.
>
>Resolves:
>https://fedorahosted.org/sssd/ticket/2697
>---
ACK

>From c9d24e577470f3b459c79f7653e7866754266a57 Mon Sep 17 00:00:00 2001
>From: Pavel Reichl <preichl at redhat.com>
>Date: Tue, 20 Oct 2015 09:10:30 -0400
>Subject: [PATCH 2/2] pam-srv-tests: Add UT for cached 'online' auth.
>
>Extend PAM responder unit test to check 'online' cached authentication.
>
>Resolves:
>https://fedorahosted.org/sssd/ticket/2697
>---
> src/responder/pam/pamsrv.h      |   5 ++
> src/responder/pam/pamsrv_cmd.c  |   2 +-
> src/tests/cmocka/test_pam_srv.c | 195 ++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 201 insertions(+), 1 deletion(-)
>
>diff --git a/src/responder/pam/pamsrv.h b/src/responder/pam/pamsrv.h
>index 59831f2e73f923053e53cad838fac715330546dd..64a7d85735ac3eb20e4504899916a49a280d4959 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 4bb3e27b102584656e32546f9ad0035750eaeb06..80095cc0bf1c4c92dd04344c069b666ab76a3714 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 30fbbc6eaafa7828afd7c37d5bbb581851e5bd97..8a8aa4a7e472242a7b640dd5772d6bbf39640a04 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=" \
> 
>+#define CACHED_AUTH_TIMEOUT_STR "2"
>+#define CACHED_AUTH_TIMEOUT 2
It's more type safe to use constants.
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"},
                                     ^
                                     missing space

>+        { 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,151 @@ 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);
>+
>+    ret = pam_set_last_online_auth_with_curr_token(pam_test_ctx->tctx->dom,
>+                                                   "pamuser", time(NULL));
>+    assert_int_equal(ret, EOK);
We needn't call pam_set_last_online_auth_with_curr_token here
becuase attribute was set in the first authentication.
   common_test_pam_cached_auth()
We have to call sysdb_cache_password becuase it is done on data_provider side

>+    /* 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);
>+    ret = pam_set_last_online_auth_with_curr_token(pam_test_ctx->tctx->dom,
>+                                                   "pamuser", time(NULL));
>+    assert_int_equal(ret, EOK);
The same case as in test_pam_cached_auth_success.
Calling this function is redundant here.
My intention was to test that this attribute is properly stored to cache
in pam responder.

>+
>+    /* 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;
>@@ -1421,6 +1598,24 @@ int main(int argc, const char *argv[])
>     };
> 
>     const struct CMUnitTest tests[] = {
>+        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),
In most cases we add unit test to the end of array.
I tried it and all test passed.

Please fix small issues and you have my ACK.

LS


More information about the sssd-devel mailing list