From 98be4f0858e7c38f18b73fda6949edf7790bcad6 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Fri, 3 Jul 2015 14:05:11 +0200
Subject: [PATCH 35/37] pam_sss: add sc support
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
---
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 3b3841a2c66b46d78855164099684ef2ac98ed77..f0a7a076cf38a4efc8befcc2fb835ae26e9415a4 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 e4fa83e12c71bb05dd329686cf2d2df6323ff3bd..431f5dc62655dd1e6901f16f72dcad9703f037ac 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: "));
}
--
2.4.3