|
|
841ac7 |
From 6b7ce87976ebba7b3c1aea24dbf91486ec5de2ed Mon Sep 17 00:00:00 2001
|
|
|
841ac7 |
From: Sumit Bose <sbose@redhat.com>
|
|
|
841ac7 |
Date: Wed, 27 Mar 2019 09:48:42 +0100
|
|
|
841ac7 |
Subject: [PATCH 18/21] pam_sss: use configured prompting
|
|
|
841ac7 |
|
|
|
841ac7 |
If the responds of SSSD's PAM responder contains a prompt_config
|
|
|
841ac7 |
structure use the content to prompt the user for credentials.
|
|
|
841ac7 |
|
|
|
841ac7 |
Related to https://pagure.io/SSSD/sssd/issue/3264
|
|
|
841ac7 |
|
|
|
841ac7 |
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
|
|
|
841ac7 |
(cherry picked with fixes from commit fc26b4a82d4a92b29cf321fba8dbec52c3bff8d6)
|
|
|
841ac7 |
---
|
|
|
841ac7 |
src/sss_client/pam_message.h | 2 +
|
|
|
841ac7 |
src/sss_client/pam_sss.c | 136 +++++++++++++++++++++++++++++------
|
|
|
841ac7 |
src/sss_client/sss_cli.h | 3 +
|
|
|
841ac7 |
3 files changed, 119 insertions(+), 22 deletions(-)
|
|
|
841ac7 |
|
|
|
841ac7 |
diff --git a/src/sss_client/pam_message.h b/src/sss_client/pam_message.h
|
|
|
841ac7 |
index 11526a80a..c87162479 100644
|
|
|
841ac7 |
--- a/src/sss_client/pam_message.h
|
|
|
841ac7 |
+++ b/src/sss_client/pam_message.h
|
|
|
841ac7 |
@@ -64,6 +64,8 @@ struct pam_items {
|
|
|
841ac7 |
bool user_name_hint;
|
|
|
841ac7 |
struct cert_auth_info *cert_list;
|
|
|
841ac7 |
struct cert_auth_info *selected_cert;
|
|
|
841ac7 |
+
|
|
|
841ac7 |
+ struct prompt_config **pc;
|
|
|
841ac7 |
};
|
|
|
841ac7 |
|
|
|
841ac7 |
int pack_message_v3(struct pam_items *pi, size_t *size, uint8_t **buffer);
|
|
|
841ac7 |
diff --git a/src/sss_client/pam_sss.c b/src/sss_client/pam_sss.c
|
|
|
841ac7 |
index 59081cc67..ab9b7478e 100644
|
|
|
841ac7 |
--- a/src/sss_client/pam_sss.c
|
|
|
841ac7 |
+++ b/src/sss_client/pam_sss.c
|
|
|
841ac7 |
@@ -205,6 +205,9 @@ static void overwrite_and_free_pam_items(struct pam_items *pi)
|
|
|
841ac7 |
free_cert_list(pi->cert_list);
|
|
|
841ac7 |
pi->cert_list = NULL;
|
|
|
841ac7 |
pi->selected_cert = NULL;
|
|
|
841ac7 |
+
|
|
|
841ac7 |
+ pc_list_free(pi->pc);
|
|
|
841ac7 |
+ pi->pc = NULL;
|
|
|
841ac7 |
}
|
|
|
841ac7 |
|
|
|
841ac7 |
static int null_strcmp(const char *s1, const char *s2) {
|
|
|
841ac7 |
@@ -1163,6 +1166,16 @@ static int eval_response(pam_handle_t *pamh, size_t buflen, uint8_t *buf,
|
|
|
841ac7 |
D(("Password prompting available."));
|
|
|
841ac7 |
pi->password_prompting = true;
|
|
|
841ac7 |
break;
|
|
|
841ac7 |
+ case SSS_PAM_PROMPT_CONFIG:
|
|
|
841ac7 |
+ if (pi->pc == NULL) {
|
|
|
841ac7 |
+ ret = pc_list_from_response(len, &buf[p], &pi->pc);
|
|
|
841ac7 |
+ if (ret != EOK) {
|
|
|
841ac7 |
+ D(("Failed to parse prompting data, using defaults"));
|
|
|
841ac7 |
+ pc_list_free(pi->pc);
|
|
|
841ac7 |
+ pi->pc = NULL;
|
|
|
841ac7 |
+ }
|
|
|
841ac7 |
+ }
|
|
|
841ac7 |
+ break;
|
|
|
841ac7 |
default:
|
|
|
841ac7 |
D(("Unknown response type [%d]", type));
|
|
|
841ac7 |
}
|
|
|
841ac7 |
@@ -1256,6 +1269,8 @@ static int get_pam_items(pam_handle_t *pamh, uint32_t flags,
|
|
|
841ac7 |
pi->cert_list = NULL;
|
|
|
841ac7 |
pi->selected_cert = NULL;
|
|
|
841ac7 |
|
|
|
841ac7 |
+ pi->pc = NULL;
|
|
|
841ac7 |
+
|
|
|
841ac7 |
return PAM_SUCCESS;
|
|
|
841ac7 |
}
|
|
|
841ac7 |
|
|
|
841ac7 |
@@ -1558,6 +1573,37 @@ done:
|
|
|
841ac7 |
return ret;
|
|
|
841ac7 |
}
|
|
|
841ac7 |
|
|
|
841ac7 |
+static int prompt_2fa_single(pam_handle_t *pamh, struct pam_items *pi,
|
|
|
841ac7 |
+ const char *prompt)
|
|
|
841ac7 |
+{
|
|
|
841ac7 |
+ int ret;
|
|
|
841ac7 |
+ char *answer = NULL;
|
|
|
841ac7 |
+
|
|
|
841ac7 |
+ ret = do_pam_conversation(pamh, PAM_PROMPT_ECHO_OFF, prompt, NULL, &answer);
|
|
|
841ac7 |
+ if (ret != PAM_SUCCESS) {
|
|
|
841ac7 |
+ D(("do_pam_conversation failed."));
|
|
|
841ac7 |
+ return ret;
|
|
|
841ac7 |
+ }
|
|
|
841ac7 |
+
|
|
|
841ac7 |
+ if (answer == NULL) {
|
|
|
841ac7 |
+ pi->pam_authtok = NULL;
|
|
|
841ac7 |
+ pi->pam_authtok_type = SSS_AUTHTOK_TYPE_EMPTY;
|
|
|
841ac7 |
+ pi->pam_authtok_size=0;
|
|
|
841ac7 |
+ } else {
|
|
|
841ac7 |
+ pi->pam_authtok = strdup(answer);
|
|
|
841ac7 |
+ _pam_overwrite((void *)answer);
|
|
|
841ac7 |
+ free(answer);
|
|
|
841ac7 |
+ answer=NULL;
|
|
|
841ac7 |
+ if (pi->pam_authtok == NULL) {
|
|
|
841ac7 |
+ return PAM_BUF_ERR;
|
|
|
841ac7 |
+ }
|
|
|
841ac7 |
+ pi->pam_authtok_type = SSS_AUTHTOK_TYPE_2FA_SINGLE;
|
|
|
841ac7 |
+ pi->pam_authtok_size=strlen(pi->pam_authtok);
|
|
|
841ac7 |
+ }
|
|
|
841ac7 |
+
|
|
|
841ac7 |
+ return PAM_SUCCESS;
|
|
|
841ac7 |
+}
|
|
|
841ac7 |
+
|
|
|
841ac7 |
#define SC_PROMPT_FMT "PIN for %s"
|
|
|
841ac7 |
|
|
|
841ac7 |
#ifndef discard_const
|
|
|
841ac7 |
@@ -2014,6 +2060,48 @@ static void eval_argv(pam_handle_t *pamh, int argc, const char **argv,
|
|
|
841ac7 |
return;
|
|
|
841ac7 |
}
|
|
|
841ac7 |
|
|
|
841ac7 |
+static int prompt_by_config(pam_handle_t *pamh, struct pam_items *pi)
|
|
|
841ac7 |
+{
|
|
|
841ac7 |
+ size_t c;
|
|
|
841ac7 |
+ int ret;
|
|
|
841ac7 |
+
|
|
|
841ac7 |
+ if (pi->pc == NULL || *pi->pc == NULL) {
|
|
|
841ac7 |
+ return EINVAL;
|
|
|
841ac7 |
+ }
|
|
|
841ac7 |
+
|
|
|
841ac7 |
+ for (c = 0; pi->pc[c] != NULL; c++) {
|
|
|
841ac7 |
+ switch (pc_get_type(pi->pc[c])) {
|
|
|
841ac7 |
+ case PC_TYPE_PASSWORD:
|
|
|
841ac7 |
+ ret = prompt_password(pamh, pi, pc_get_password_prompt(pi->pc[c]));
|
|
|
841ac7 |
+ break;
|
|
|
841ac7 |
+ case PC_TYPE_2FA:
|
|
|
841ac7 |
+ ret = prompt_2fa(pamh, pi, pc_get_2fa_1st_prompt(pi->pc[c]),
|
|
|
841ac7 |
+ pc_get_2fa_2nd_prompt(pi->pc[c]));
|
|
|
841ac7 |
+ break;
|
|
|
841ac7 |
+ case PC_TYPE_2FA_SINGLE:
|
|
|
841ac7 |
+ ret = prompt_2fa_single(pamh, pi,
|
|
|
841ac7 |
+ pc_get_2fa_single_prompt(pi->pc[c]));
|
|
|
841ac7 |
+ break;
|
|
|
841ac7 |
+ case PC_TYPE_SC_PIN:
|
|
|
841ac7 |
+ ret = prompt_sc_pin(pamh, pi);
|
|
|
841ac7 |
+ /* Todo: add extra string option */
|
|
|
841ac7 |
+ break;
|
|
|
841ac7 |
+ default:
|
|
|
841ac7 |
+ ret = EINVAL;
|
|
|
841ac7 |
+ }
|
|
|
841ac7 |
+
|
|
|
841ac7 |
+ /* If not credential where given try the next type otherwise we are
|
|
|
841ac7 |
+ * done. */
|
|
|
841ac7 |
+ if (ret == PAM_SUCCESS && pi->pam_authtok_size == 0) {
|
|
|
841ac7 |
+ continue;
|
|
|
841ac7 |
+ }
|
|
|
841ac7 |
+
|
|
|
841ac7 |
+ break;
|
|
|
841ac7 |
+ }
|
|
|
841ac7 |
+
|
|
|
841ac7 |
+ return ret;
|
|
|
841ac7 |
+}
|
|
|
841ac7 |
+
|
|
|
841ac7 |
static int get_authtok_for_authentication(pam_handle_t *pamh,
|
|
|
841ac7 |
struct pam_items *pi,
|
|
|
841ac7 |
uint32_t flags)
|
|
|
841ac7 |
@@ -2032,30 +2120,34 @@ static int get_authtok_for_authentication(pam_handle_t *pamh,
|
|
|
841ac7 |
}
|
|
|
841ac7 |
pi->pam_authtok_size = strlen(pi->pam_authtok);
|
|
|
841ac7 |
} else {
|
|
|
841ac7 |
- if (flags & FLAGS_USE_2FA
|
|
|
841ac7 |
- || (pi->otp_vendor != NULL && pi->otp_token_id != NULL
|
|
|
841ac7 |
- && pi->otp_challenge != NULL)) {
|
|
|
841ac7 |
- if (pi->password_prompting) {
|
|
|
841ac7 |
- ret = prompt_2fa(pamh, pi, _("First Factor: "),
|
|
|
841ac7 |
- _("Second Factor (optional): "));
|
|
|
841ac7 |
- } else {
|
|
|
841ac7 |
- ret = prompt_2fa(pamh, pi, _("First Factor: "),
|
|
|
841ac7 |
- _("Second Factor: "));
|
|
|
841ac7 |
- }
|
|
|
841ac7 |
- } else if (pi->cert_list != NULL) {
|
|
|
841ac7 |
- if (pi->cert_list->next == NULL) {
|
|
|
841ac7 |
- /* Only one certificate */
|
|
|
841ac7 |
- pi->selected_cert = pi->cert_list;
|
|
|
841ac7 |
- } else {
|
|
|
841ac7 |
- ret = prompt_multi_cert(pamh, pi);
|
|
|
841ac7 |
- if (ret != 0) {
|
|
|
841ac7 |
- D(("Failed to select certificate"));
|
|
|
841ac7 |
- return PAM_AUTHTOK_ERR;
|
|
|
841ac7 |
+ if (pi->pc != NULL) {
|
|
|
841ac7 |
+ ret = prompt_by_config(pamh, pi);
|
|
|
841ac7 |
+ } else {
|
|
|
841ac7 |
+ if (flags & FLAGS_USE_2FA
|
|
|
841ac7 |
+ || (pi->otp_vendor != NULL && pi->otp_token_id != NULL
|
|
|
841ac7 |
+ && pi->otp_challenge != NULL)) {
|
|
|
841ac7 |
+ if (pi->password_prompting) {
|
|
|
841ac7 |
+ ret = prompt_2fa(pamh, pi, _("First Factor: "),
|
|
|
841ac7 |
+ _("Second Factor (optional): "));
|
|
|
841ac7 |
+ } else {
|
|
|
841ac7 |
+ ret = prompt_2fa(pamh, pi, _("First Factor: "),
|
|
|
841ac7 |
+ _("Second Factor: "));
|
|
|
841ac7 |
}
|
|
|
841ac7 |
+ } else if (pi->cert_list != NULL) {
|
|
|
841ac7 |
+ if (pi->cert_list->next == NULL) {
|
|
|
841ac7 |
+ /* Only one certificate */
|
|
|
841ac7 |
+ pi->selected_cert = pi->cert_list;
|
|
|
841ac7 |
+ } else {
|
|
|
841ac7 |
+ ret = prompt_multi_cert(pamh, pi);
|
|
|
841ac7 |
+ if (ret != 0) {
|
|
|
841ac7 |
+ D(("Failed to select certificate"));
|
|
|
841ac7 |
+ return PAM_AUTHTOK_ERR;
|
|
|
841ac7 |
+ }
|
|
|
841ac7 |
+ }
|
|
|
841ac7 |
+ ret = prompt_sc_pin(pamh, pi);
|
|
|
841ac7 |
+ } else {
|
|
|
841ac7 |
+ ret = prompt_password(pamh, pi, _("Password: "));
|
|
|
841ac7 |
}
|
|
|
841ac7 |
- ret = prompt_sc_pin(pamh, pi);
|
|
|
841ac7 |
- } else {
|
|
|
841ac7 |
- ret = prompt_password(pamh, pi, _("Password: "));
|
|
|
841ac7 |
}
|
|
|
841ac7 |
if (ret != PAM_SUCCESS) {
|
|
|
841ac7 |
D(("failed to get password from user"));
|
|
|
841ac7 |
diff --git a/src/sss_client/sss_cli.h b/src/sss_client/sss_cli.h
|
|
|
841ac7 |
index 23ef21608..24b24a91b 100644
|
|
|
841ac7 |
--- a/src/sss_client/sss_cli.h
|
|
|
841ac7 |
+++ b/src/sss_client/sss_cli.h
|
|
|
841ac7 |
@@ -469,6 +469,9 @@ enum response_type {
|
|
|
841ac7 |
SSS_PAM_CERT_INFO_WITH_HINT, /**< Same as SSS_PAM_CERT_INFO but user name
|
|
|
841ac7 |
* might be missing and should be prompted
|
|
|
841ac7 |
* for. */
|
|
|
841ac7 |
+ SSS_PAM_PROMPT_CONFIG, /**< Contains data which controls which credentials
|
|
|
841ac7 |
+ * are expected and how the user is prompted for
|
|
|
841ac7 |
+ * them. */
|
|
|
841ac7 |
};
|
|
|
841ac7 |
|
|
|
841ac7 |
/**
|
|
|
841ac7 |
--
|
|
|
841ac7 |
2.19.1
|
|
|
841ac7 |
|