From 2b62d5a414b8b7dba4f714dc5033e28dc4b1f4fe Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Tue, 15 Mar 2016 14:29:02 +0100 Subject: PAM: Use qualified names internally in the PAM responder The name is converted from whatever we receive on input to the internal format before processing the data further. Reviewed-by: Sumit Bose --- Makefile.am | 2 +- src/responder/pam/pamsrv_cmd.c | 42 +++++++++++------ src/responder/pam/pamsrv_p11.c | 17 +++++-- src/tests/cmocka/test_pam_srv.c | 101 +++++++++++++++++++++++++++++----------- 4 files changed, 114 insertions(+), 48 deletions(-) diff --git a/Makefile.am b/Makefile.am index d5659affb..72cecd48e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -256,7 +256,7 @@ if HAVE_CMOCKA responder_cache_req-tests \ test_sbus_opath \ test_fo_srv \ - #pam-srv-tests \ + pam-srv-tests \ test_ipa_subdom_util \ test_tools_colondb \ test_krb5_wait_queue \ diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c index 22a1872a2..3a35c3f08 100644 --- a/src/responder/pam/pamsrv_cmd.c +++ b/src/responder/pam/pamsrv_cmd.c @@ -1096,6 +1096,7 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd) struct pam_ctx *pctx = talloc_get_type(cctx->rctx->pvt_ctx, struct pam_ctx); struct tevent_req *req; + char *name = NULL; preq = talloc_zero(cctx, struct pam_auth_req); if (!preq) { @@ -1147,8 +1148,16 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd) goto done; } + name = sss_resp_create_fqname(preq, pctx->rctx, preq->domain, + preq->pd->name_is_upn, + preq->pd->user); + if (name == NULL) { + return ENOMEM; + } + ncret = sss_ncache_check_user(pctx->rctx->ncache, - preq->domain, pd->user); + preq->domain, name); + talloc_free(name); if (ncret == EEXIST) { /* User found in the negative cache */ ret = ENOENT; @@ -1160,8 +1169,16 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd) dom = get_next_domain(dom, 0)) { if (dom->fqnames) continue; + name = sss_resp_create_fqname(preq, pctx->rctx, dom, + preq->pd->name_is_upn, + preq->pd->user); + if (name == NULL) { + return ENOMEM; + } + ncret = sss_ncache_check_user(pctx->rctx->ncache, - dom, pd->user); + dom, name); + talloc_free(name); if (ncret == ENOENT) { /* User not found in the negative cache * Proceed with PAM actions @@ -1441,17 +1458,11 @@ static int pam_check_user_search(struct pam_auth_req *preq) preq->domain = dom; talloc_free(name); - name = sss_get_cased_name(preq, preq->pd->user, - dom->case_sensitive); - if (!name) { - return ENOMEM; - } - name = sss_reverse_replace_space(preq, name, - pctx->rctx->override_space); + name = sss_resp_create_fqname(preq, pctx->rctx, dom, + preq->pd->name_is_upn, + preq->pd->user); if (name == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, - "sss_reverse_replace_space failed\n"); return ENOMEM; } @@ -1474,8 +1485,7 @@ static int pam_check_user_search(struct pam_auth_req *preq) /* Entry is still valid, get it from the sysdb */ } - DEBUG(SSSDBG_CONF_SETTINGS, - "Requesting info for [%s@%s]\n", name, dom->name); + DEBUG(SSSDBG_CONF_SETTINGS, "Requesting info for [%s]\n", name); if (dom->sysdb == NULL) { DEBUG(SSSDBG_FATAL_FAILURE, @@ -1511,7 +1521,8 @@ static int pam_check_user_search(struct pam_auth_req *preq) if (ret == ENOENT) { if (preq->check_provider == false) { /* set negative cache only if not result of cache check */ - ret = sss_ncache_set_user(pctx->rctx->ncache, false, dom, name); + ret = sss_ncache_set_user(pctx->rctx->ncache, + false, dom, preq->pd->user); if (ret != EOK) { /* Should not be fatal, just slower next time */ DEBUG(SSSDBG_MINOR_FAILURE, @@ -1834,7 +1845,8 @@ static void pam_dom_forwarder(struct pam_auth_req *preq) } /* pam_check_user_search() calls pd_set_primary_name() is the search - * was successful, so pd->user contains the canonical name as well */ + * was successful, so pd->user contains the canonical sysdb name + * as well */ if (strcmp(cert_user, preq->pd->user) == 0) { preq->pd->pam_status = PAM_SUCCESS; diff --git a/src/responder/pam/pamsrv_p11.c b/src/responder/pam/pamsrv_p11.c index 8a9497a09..a2514f6a1 100644 --- a/src/responder/pam/pamsrv_p11.c +++ b/src/responder/pam/pamsrv_p11.c @@ -508,7 +508,7 @@ errno_t pam_check_cert_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, * Settings Daemon to determine the name of the token used for login */ #define PKCS11_LOGIN_TOKEN_ENV_NAME "PKCS11_LOGIN_TOKEN_NAME" -errno_t add_pam_cert_response(struct pam_data *pd, const char *user, +errno_t add_pam_cert_response(struct pam_data *pd, const char *sysdb_username, const char *token_name) { uint8_t *msg = NULL; @@ -517,24 +517,33 @@ errno_t add_pam_cert_response(struct pam_data *pd, const char *user, size_t msg_len; size_t slot_len; int ret; + char *username; - if (user == NULL || token_name == NULL) { + if (sysdb_username == NULL || token_name == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Missing mandatory user or slot name.\n"); return EINVAL; } - user_len = strlen(user) + 1; + ret = sss_parse_internal_fqname(pd, sysdb_username, &username, NULL); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Cannot parse [%s]\n", sysdb_username); + return ret; + } + + user_len = strlen(username) + 1; slot_len = strlen(token_name) + 1; msg_len = user_len + slot_len; msg = talloc_zero_size(pd, msg_len); if (msg == NULL) { DEBUG(SSSDBG_OP_FAILURE, "talloc_zero_size failed.\n"); + talloc_free(username); return ENOMEM; } - memcpy(msg, user, user_len); + memcpy(msg, username, user_len); memcpy(msg + user_len, token_name, slot_len); + talloc_free(username); ret = pam_add_response(pd, SSS_PAM_CERT_INFO, msg_len, msg); talloc_free(msg); diff --git a/src/tests/cmocka/test_pam_srv.c b/src/tests/cmocka/test_pam_srv.c index 4d53c22d8..5de092d0f 100644 --- a/src/tests/cmocka/test_pam_srv.c +++ b/src/tests/cmocka/test_pam_srv.c @@ -86,6 +86,9 @@ struct pam_test_ctx { int ncache_hits; int exp_pam_status; bool provider_contacted; + + const char *pam_user_fqdn; + const char *wrong_user_fqdn; }; /* Must be global because it is needed in some wrappers */ @@ -269,9 +272,22 @@ static void pam_test_setup_common(void) { errno_t ret; + pam_test_ctx->pam_user_fqdn = \ + sss_create_internal_fqname(pam_test_ctx, + "pamuser", + pam_test_ctx->tctx->dom->name); + assert_non_null(pam_test_ctx->pam_user_fqdn); + + pam_test_ctx->wrong_user_fqdn = \ + sss_create_internal_fqname(pam_test_ctx, + "wronguser", + pam_test_ctx->tctx->dom->name); + assert_non_null(pam_test_ctx->wrong_user_fqdn); + /* Prime the cache with a valid user */ ret = sysdb_add_user(pam_test_ctx->tctx->dom, - "pamuser", 123, 456, "pam user", + pam_test_ctx->pam_user_fqdn, + 123, 456, "pam user", "/home/pamuser", "/bin/sh", NULL, NULL, 300, 0); assert_int_equal(ret, EOK); @@ -286,8 +302,9 @@ static void pam_test_setup_common(void) /* Prime the cache with a user for wrong matches */ ret = sysdb_add_user(pam_test_ctx->tctx->dom, - "wronguser", 321, 654, "wrong user", - "/home/wringuser", "/bin/sh", NULL, + pam_test_ctx->wrong_user_fqdn, + 321, 654, "wrong user", + "/home/wronguser", "/bin/sh", NULL, NULL, 300, 0); assert_int_equal(ret, EOK); @@ -379,10 +396,12 @@ static int pam_test_teardown(void **state) { int ret; - ret = sysdb_delete_user(pam_test_ctx->tctx->dom, "pamuser", 0); + ret = sysdb_delete_user(pam_test_ctx->tctx->dom, + pam_test_ctx->pam_user_fqdn, 0); assert_int_equal(ret, EOK); - ret = sysdb_delete_user(pam_test_ctx->tctx->dom, "wronguser", 0); + ret = sysdb_delete_user(pam_test_ctx->tctx->dom, + pam_test_ctx->wrong_user_fqdn, 0); assert_int_equal(ret, EOK); talloc_free(pam_test_ctx); @@ -943,7 +962,9 @@ void test_pam_cached_auth_success(void **state) /* Back end should be contacted */ assert_true(pam_test_ctx->provider_contacted); - ret = sysdb_cache_password(pam_test_ctx->tctx->dom, "pamuser", "12345"); + ret = sysdb_cache_password(pam_test_ctx->tctx->dom, + pam_test_ctx->pam_user_fqdn, + "12345"); assert_int_equal(ret, EOK); /* Reset before next call */ @@ -959,11 +980,14 @@ void test_pam_cached_auth_wrong_pw(void **state) { int ret; - ret = sysdb_cache_password(pam_test_ctx->tctx->dom, "pamuser", "12345"); + ret = sysdb_cache_password(pam_test_ctx->tctx->dom, + pam_test_ctx->pam_user_fqdn, + "12345"); assert_int_equal(ret, EOK); ret = pam_set_last_online_auth_with_curr_token(pam_test_ctx->tctx->dom, - "pamuser", time(NULL)); + pam_test_ctx->pam_user_fqdn, + time(NULL)); assert_int_equal(ret, EOK); common_test_pam_cached_auth("11111"); @@ -978,12 +1002,14 @@ 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"); + ret = sysdb_cache_password(pam_test_ctx->tctx->dom, + pam_test_ctx->pam_user_fqdn, + "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", + pam_test_ctx->pam_user_fqdn, last_online); assert_int_equal(ret, EOK); @@ -998,11 +1024,14 @@ void test_pam_cached_auth_timeout(void **state) { int ret; - ret = sysdb_cache_password(pam_test_ctx->tctx->dom, "pamuser", "12345"); + ret = sysdb_cache_password(pam_test_ctx->tctx->dom, + pam_test_ctx->pam_user_fqdn, + "12345"); assert_int_equal(ret, EOK); ret = pam_set_last_online_auth_with_curr_token(pam_test_ctx->tctx->dom, - "pamuser", 0); + pam_test_ctx->pam_user_fqdn, + 0); assert_int_equal(ret, EOK); common_test_pam_cached_auth("12345"); @@ -1019,7 +1048,8 @@ void test_pam_cached_auth_success_combined_pw_with_cached_2fa(void **state) assert_true(pam_test_ctx->provider_contacted); - ret = sysdb_cache_password_ex(pam_test_ctx->tctx->dom, "pamuser", + ret = sysdb_cache_password_ex(pam_test_ctx->tctx->dom, + pam_test_ctx->pam_user_fqdn, "12345678", SSS_AUTHTOK_TYPE_2FA, 5); assert_int_equal(ret, EOK); @@ -1035,11 +1065,13 @@ 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", + ret = sysdb_cache_password_ex(pam_test_ctx->tctx->dom, + pam_test_ctx->pam_user_fqdn, "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)); + pam_test_ctx->pam_user_fqdn, + time(NULL)); assert_int_equal(ret, EOK); common_test_pam_cached_auth("1111abcde"); @@ -1075,7 +1107,8 @@ void test_pam_offline_auth_success(void **state) int ret; ret = sysdb_cache_password(pam_test_ctx->tctx->dom, - "pamuser@"TEST_DOM_NAME, "12345"); + pam_test_ctx->pam_user_fqdn, + "12345"); assert_int_equal(ret, EOK); mock_input_pam(pam_test_ctx, "pamuser", "12345", NULL); @@ -1099,7 +1132,9 @@ void test_pam_offline_auth_wrong_pw(void **state) { int ret; - ret = sysdb_cache_password(pam_test_ctx->tctx->dom, "pamuser@"TEST_DOM_NAME, "12345"); + ret = sysdb_cache_password(pam_test_ctx->tctx->dom, + pam_test_ctx->pam_user_fqdn, + "12345"); assert_int_equal(ret, EOK); mock_input_pam(pam_test_ctx, "pamuser", "11111", NULL); @@ -1124,7 +1159,8 @@ void test_pam_offline_auth_success_2fa(void **state) int ret; ret = sysdb_cache_password(pam_test_ctx->tctx->dom, - "pamuser@"TEST_DOM_NAME, "12345"); + pam_test_ctx->pam_user_fqdn, + "12345"); assert_int_equal(ret, EOK); mock_input_pam(pam_test_ctx, "pamuser", "12345", "abcde"); @@ -1149,7 +1185,8 @@ void test_pam_offline_auth_failed_2fa(void **state) int ret; ret = sysdb_cache_password(pam_test_ctx->tctx->dom, - "pamuser@"TEST_DOM_NAME, "12345"); + pam_test_ctx->pam_user_fqdn, + "12345"); assert_int_equal(ret, EOK); mock_input_pam(pam_test_ctx, "pamuser", "11111", "abcde"); @@ -1174,7 +1211,8 @@ void test_pam_offline_auth_success_2fa_with_cached_2fa(void **state) int ret; ret = sysdb_cache_password_ex(pam_test_ctx->tctx->dom, - "pamuser@"TEST_DOM_NAME, "12345", + pam_test_ctx->pam_user_fqdn, + "12345", SSS_AUTHTOK_TYPE_2FA, 5); assert_int_equal(ret, EOK); @@ -1200,7 +1238,8 @@ void test_pam_offline_auth_failed_2fa_with_cached_2fa(void **state) int ret; ret = sysdb_cache_password_ex(pam_test_ctx->tctx->dom, - "pamuser@"TEST_DOM_NAME, "12345", + pam_test_ctx->pam_user_fqdn, + "12345", SSS_AUTHTOK_TYPE_2FA, 5); assert_int_equal(ret, EOK); @@ -1226,7 +1265,8 @@ void test_pam_offline_auth_success_pw_with_cached_2fa(void **state) int ret; ret = sysdb_cache_password_ex(pam_test_ctx->tctx->dom, - "pamuser@"TEST_DOM_NAME, "12345", + pam_test_ctx->pam_user_fqdn, + "12345", SSS_AUTHTOK_TYPE_2FA, 5); assert_int_equal(ret, EOK); @@ -1252,7 +1292,8 @@ void test_pam_offline_auth_failed_pw_with_cached_2fa(void **state) int ret; ret = sysdb_cache_password_ex(pam_test_ctx->tctx->dom, - "pamuser@"TEST_DOM_NAME, "12345", + pam_test_ctx->pam_user_fqdn, + "12345", SSS_AUTHTOK_TYPE_2FA, 5); assert_int_equal(ret, EOK); @@ -1278,7 +1319,7 @@ void test_pam_offline_auth_success_combined_pw_with_cached_2fa(void **state) int ret; ret = sysdb_cache_password_ex(pam_test_ctx->tctx->dom, - "pamuser@"TEST_DOM_NAME, + pam_test_ctx->pam_user_fqdn, "12345678", SSS_AUTHTOK_TYPE_2FA, 5); assert_int_equal(ret, EOK); @@ -1304,7 +1345,7 @@ void test_pam_offline_auth_failed_combined_pw_with_cached_2fa(void **state) int ret; ret = sysdb_cache_password_ex(pam_test_ctx->tctx->dom, - "pamuser@"TEST_DOM_NAME, + pam_test_ctx->pam_user_fqdn, "12345678", SSS_AUTHTOK_TYPE_2FA, 5); assert_int_equal(ret, EOK); @@ -1330,7 +1371,7 @@ void test_pam_offline_auth_failed_wrong_2fa_size_with_cached_2fa(void **state) int ret; ret = sysdb_cache_password_ex(pam_test_ctx->tctx->dom, - "pamuser@"TEST_DOM_NAME, + pam_test_ctx->pam_user_fqdn, "12345678", SSS_AUTHTOK_TYPE_2FA, 5); assert_int_equal(ret, EOK); @@ -1458,7 +1499,9 @@ static int test_lookup_by_cert_cb(void *pvt) talloc_free(der); assert_int_equal(ret, EOK); - ret = sysdb_set_user_attr(pam_test_ctx->tctx->dom, "pamuser", attrs, + ret = sysdb_set_user_attr(pam_test_ctx->tctx->dom, + pam_test_ctx->pam_user_fqdn, + attrs, LDB_FLAG_MOD_ADD); assert_int_equal(ret, EOK); } @@ -1484,7 +1527,9 @@ static int test_lookup_by_cert_wrong_user_cb(void *pvt) talloc_free(der); assert_int_equal(ret, EOK); - ret = sysdb_set_user_attr(pam_test_ctx->tctx->dom, "wronguser", attrs, + ret = sysdb_set_user_attr(pam_test_ctx->tctx->dom, + pam_test_ctx->wrong_user_fqdn, + attrs, LDB_FLAG_MOD_ADD); assert_int_equal(ret, EOK); } -- cgit