From 5242964d275d0b2e96c9b0d1f8a9958c85d566fc Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Fri, 3 Jul 2015 14:05:11 +0200 Subject: pam_sss: add sc support Reviewed-by: Jakub Hrozek --- src/sss_client/pam_message.h | 3 ++ src/sss_client/pam_sss.c | 94 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 96 insertions(+), 1 deletion(-) diff --git a/src/sss_client/pam_message.h b/src/sss_client/pam_message.h index 3b3841a2c..f0a7a076c 100644 --- a/src/sss_client/pam_message.h +++ b/src/sss_client/pam_message.h @@ -56,6 +56,9 @@ struct pam_items { char *otp_token_id; char *otp_challenge; char *first_factor; + + char *cert_user; + char *token_name; }; int pack_message_v3(struct pam_items *pi, size_t *size, uint8_t **buffer); diff --git a/src/sss_client/pam_sss.c b/src/sss_client/pam_sss.c index e4fa83e12..431f5dc62 100644 --- a/src/sss_client/pam_sss.c +++ b/src/sss_client/pam_sss.c @@ -155,6 +155,12 @@ static void overwrite_and_free_pam_items(struct pam_items *pi) free(pi->otp_challenge); pi->otp_challenge = NULL; + + free(pi->cert_user); + pi->cert_user = NULL; + + free(pi->token_name); + pi->token_name = NULL; } static int null_strcmp(const char *s1, const char *s2) { @@ -922,7 +928,7 @@ static int eval_response(pam_handle_t *pamh, size_t buflen, uint8_t *buf, break; case SSS_PAM_OTP_INFO: if (buf[p + (len - 1)] != '\0') { - D(("system info does not end with \\0.")); + D(("otp info does not end with \\0.")); break; } @@ -959,6 +965,33 @@ static int eval_response(pam_handle_t *pamh, size_t buflen, uint8_t *buf, } break; + case SSS_PAM_CERT_INFO: + if (buf[p + (len - 1)] != '\0') { + D(("cert info does not end with \\0.")); + break; + } + + pi->cert_user = strdup((char *) &buf[p]); + if (pi->cert_user == NULL) { + D(("strdup failed")); + break; + } + + offset = strlen(pi->cert_user) + 1; + if (offset >= len) { + D(("Cert message size mismatch")); + free(pi->cert_user); + pi->cert_user = NULL; + break; + } + pi->token_name = strdup((char *) &buf[p + offset]); + if (pi->token_name == NULL) { + D(("strdup failed")); + break; + } + D(("cert user: [%s] token name: [%s]", pi->cert_user, + pi->token_name)); + break; default: D(("Unknown response type [%d]", type)); } @@ -1039,6 +1072,9 @@ static int get_pam_items(pam_handle_t *pamh, struct pam_items *pi) pi->otp_token_id = NULL; pi->otp_challenge = NULL; + pi->cert_user = NULL; + pi->token_name = NULL; + return PAM_SUCCESS; } @@ -1345,6 +1381,60 @@ done: return ret; } +#define SC_PROMPT_FMT "PIN for %s for user %s" +static int prompt_sc_pin(pam_handle_t *pamh, struct pam_items *pi) +{ + int ret; + char *answer = NULL; + char *prompt; + size_t size; + + if (pi->token_name == NULL || *pi->token_name == '\0' + || pi->cert_user == NULL || *pi->cert_user == '\0') { + return EINVAL; + } + + size = sizeof(SC_PROMPT_FMT) + strlen(pi->token_name) + + strlen(pi->cert_user); + prompt = malloc(size); + if (prompt == NULL) { + D(("malloc failed.")); + return ENOMEM; + } + + ret = snprintf(prompt, size, SC_PROMPT_FMT, pi->token_name, pi->cert_user); + if (ret < 0 || ret >= size) { + D(("snprintf failed.")); + free(prompt); + return EFAULT; + } + + ret = do_pam_conversation(pamh, PAM_PROMPT_ECHO_OFF, prompt, NULL, &answer); + free(prompt); + if (ret != PAM_SUCCESS) { + D(("do_pam_conversation failed.")); + return ret; + } + + if (answer == NULL) { + pi->pam_authtok = NULL; + pi->pam_authtok_type = SSS_AUTHTOK_TYPE_EMPTY; + pi->pam_authtok_size=0; + } else { + pi->pam_authtok = strdup(answer); + _pam_overwrite((void *)answer); + free(answer); + answer=NULL; + if (pi->pam_authtok == NULL) { + return PAM_BUF_ERR; + } + pi->pam_authtok_type = SSS_AUTHTOK_TYPE_SC_PIN; + pi->pam_authtok_size=strlen(pi->pam_authtok); + } + + return PAM_SUCCESS; +} + static int prompt_new_password(pam_handle_t *pamh, struct pam_items *pi) { int ret; @@ -1458,6 +1548,8 @@ static int get_authtok_for_authentication(pam_handle_t *pamh, && pi->otp_challenge != NULL)) { ret = prompt_2fa(pamh, pi, _("First Factor: "), _("Second Factor: ")); + } else if (pi->cert_user != NULL) { + ret = prompt_sc_pin(pamh, pi); } else { ret = prompt_password(pamh, pi, _("Password: ")); } -- cgit