Fixes: https://fedorahosted.org/sssd/ticket/1021
Signed-off-by: Daniel Gollub <[email protected]> Reviewed-by: Sven-Thorsten Dietrich <[email protected]> --- src/providers/data_provider.h | 1 + src/responder/pam/pamsrv_cmd.c | 44 +++++++++++++++++++++++++++++++++++++++++- src/sss_client/pam_sss.c | 29 ++++++++++++++++++++++++++-- src/sss_client/sss_cli.h | 1 + 4 files changed, 72 insertions(+), 3 deletions(-) diff --git a/src/providers/data_provider.h b/src/providers/data_provider.h index ebb4fad..0abfd0f 100644 --- a/src/providers/data_provider.h +++ b/src/providers/data_provider.h @@ -170,6 +170,7 @@ struct pam_data { char *tty; char *ruser; char *rhost; + char **requested_domains; struct sss_auth_token *authtok; struct sss_auth_token *newauthtok; uint32_t cli_pid; diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c index 140d541..c6539e5 100644 --- a/src/responder/pam/pamsrv_cmd.c +++ b/src/responder/pam/pamsrv_cmd.c @@ -44,6 +44,26 @@ enum pam_verbosity { static void pam_reply(struct pam_auth_req *preq); +static bool is_domain_requested(struct pam_data *pd, const char *domain_name) +{ + int i; + + /* If none specific domains got requested via pam, all domains are allowed. + * Which mimics the default/original behaviour. + */ + if (!pd->requested_domains) + return true; + + for (i = 0; pd->requested_domains[i]; i++) { + if (strcmp(domain_name, pd->requested_domains[i])) + continue; + + return true; + } + + return false; +} + static int extract_authtok_v2(struct sss_auth_token *tok, size_t data_size, uint8_t *body, size_t blen, size_t *c) @@ -146,6 +166,7 @@ static int pam_parse_in_data_v2(struct sss_domain_info *domains, int ret; uint32_t start; uint32_t terminator; + char *requested_domains; if (blen < 4*sizeof(uint32_t)+2) { DEBUG(SSSDBG_CRIT_FAILURE, "Received data is invalid.\n"); @@ -202,6 +223,16 @@ static int pam_parse_in_data_v2(struct sss_domain_info *domains, ret = extract_string(&pd->rhost, size, body, blen, &c); if (ret != EOK) return ret; break; + case SSS_PAM_ITEM_REQUESTED_DOMAINS: + ret = extract_string(&requested_domains, size, body, blen, &c); + if (ret != EOK) return ret; + ret = split_on_separator(pd, requested_domains, ',', true, true, + &pd->requested_domains, NULL); + if (ret != EOK) { + DEBUG(1, ("Failed to parse requested_domains list!\n")); + return ret; + } + break; case SSS_PAM_ITEM_CLI_PID: ret = extract_uint32_t(&pd->cli_pid, size, body, blen, &c); @@ -836,12 +867,22 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd) ret = ENOENT; goto done; } + + /* skip this domain if not requested */ + if (!is_domain_requested(pd, dom->name)) { + ret = ENOENT; + goto done; + } } else { for (dom = preq->cctx->rctx->domains; dom; dom = get_next_domain(dom, false)) { if (dom->fqnames) continue; + /* skip this domain if not requested */ + if (!is_domain_requested(pd, dom->name)) + continue; + ncret = sss_ncache_check_user(pctx->ncache, pctx->neg_timeout, dom, pd->user); if (ncret == ENOENT) { @@ -856,7 +897,8 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd) "User [%s@%s] filtered out (negative cache). " "Trying next domain.\n", pd->user, dom->name); } - if (!dom) { + + if (!dom || !is_domain_requested(pd, dom->name)) { ret = ENOENT; goto done; } diff --git a/src/sss_client/pam_sss.c b/src/sss_client/pam_sss.c index d2502d1..4d76bd2 100644 --- a/src/sss_client/pam_sss.c +++ b/src/sss_client/pam_sss.c @@ -58,6 +58,7 @@ #define PW_RESET_MSG_MAX_SIZE 4096 #define OPT_RETRY_KEY "retry=" +#define OPT_DOMAINS_KEY "domains=" struct pam_items { const char* pam_service; @@ -81,6 +82,8 @@ struct pam_items { pid_t cli_pid; const char *login_name; char *domain_name; + const char *requested_domains; + size_t requested_domains_size; }; #define DEBUG_MGS_LEN 1024 @@ -246,6 +249,9 @@ static int pack_message_v3(struct pam_items *pi, size_t *size, len += pi->pam_newauthtok != NULL ? 3*sizeof(uint32_t) + pi->pam_newauthtok_size : 0; len += 3*sizeof(uint32_t); /* cli_pid */ + len += *pi->requested_domains != '\0' ? + 2*sizeof(uint32_t) + pi->requested_domains_size : 0; + buf = malloc(len); if (buf == NULL) { @@ -271,6 +277,9 @@ static int pack_message_v3(struct pam_items *pi, size_t *size, rp += add_string_item(SSS_PAM_ITEM_RHOST, pi->pam_rhost, pi->pam_rhost_size, &buf[rp]); + rp += add_string_item(SSS_PAM_ITEM_REQUESTED_DOMAINS, pi->requested_domains, pi->requested_domains_size, + &buf[rp]); + rp += add_uint32_t_item(SSS_PAM_ITEM_CLI_PID, (uint32_t) pi->cli_pid, &buf[rp]); @@ -1061,6 +1070,9 @@ static int get_pam_items(pam_handle_t *pamh, struct pam_items *pi) pi->domain_name = NULL; + if (pi->requested_domains == NULL) pi->requested_domains=""; + pi->requested_domains_size=strlen(pi->requested_domains)+1; + return PAM_SUCCESS; } @@ -1080,6 +1092,7 @@ static void print_pam_items(struct pam_items *pi) D(("Authtok: %s", CHECK_AND_RETURN_PI_STRING(pi->pam_authtok))); D(("Newauthtok: %s", CHECK_AND_RETURN_PI_STRING(pi->pam_newauthtok))); D(("Cli_PID: %d", pi->cli_pid)); + D(("Requested domains: %s", pi->requested_domains)); } static int send_and_receive(pam_handle_t *pamh, struct pam_items *pi, @@ -1271,7 +1284,8 @@ static int prompt_new_password(pam_handle_t *pamh, struct pam_items *pi) } static void eval_argv(pam_handle_t *pamh, int argc, const char **argv, - uint32_t *flags, int *retries, bool *quiet_mode) + uint32_t *flags, int *retries, bool *quiet_mode, + const char **domains) { char *ep; @@ -1284,6 +1298,14 @@ static void eval_argv(pam_handle_t *pamh, int argc, const char **argv, *flags |= FLAGS_USE_FIRST_PASS; } else if (strcmp(*argv, "use_authtok") == 0) { *flags |= FLAGS_USE_AUTHTOK; + } else if (strncmp(*argv, OPT_DOMAINS_KEY, strlen(OPT_DOMAINS_KEY)) == 0) { + if (*(*argv+strlen(OPT_DOMAINS_KEY)) == '\0') { + logger(pamh, LOG_ERR, "Missing argument to option domains."); + *domains = '\0'; + } else { + *domains = *argv+strlen(OPT_DOMAINS_KEY); + } + } else if (strncmp(*argv, OPT_RETRY_KEY, strlen(OPT_RETRY_KEY)) == 0) { if (*(*argv+6) == '\0') { logger(pamh, LOG_ERR, "Missing argument to option retry."); @@ -1443,12 +1465,15 @@ static int pam_sss(enum sss_cli_command task, pam_handle_t *pamh, bool retry = false; bool quiet_mode = false; int retries = 0; + const char *domains = NULL; bindtextdomain(PACKAGE, LOCALEDIR); D(("Hello pam_sssd: %d", task)); - eval_argv(pamh, argc, argv, &flags, &retries, &quiet_mode); + eval_argv(pamh, argc, argv, &flags, &retries, &quiet_mode, &domains); + + pi.requested_domains = domains; ret = get_pam_items(pamh, &pi); if (ret != PAM_SUCCESS) { diff --git a/src/sss_client/sss_cli.h b/src/sss_client/sss_cli.h index 16a08e1..15f8322 100644 --- a/src/sss_client/sss_cli.h +++ b/src/sss_client/sss_cli.h @@ -314,6 +314,7 @@ enum pam_item_type { SSS_PAM_ITEM_NEWAUTHTOK, SSS_PAM_ITEM_CLI_LOCALE, SSS_PAM_ITEM_CLI_PID, + SSS_PAM_ITEM_REQUESTED_DOMAINS, }; #define SSS_NSS_MAX_ENTRIES 256 -- 1.9.1 _______________________________________________ sssd-devel mailing list [email protected] https://lists.fedorahosted.org/mailman/listinfo/sssd-devel
