summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSumit Bose <sbose@redhat.com>2017-02-22 17:58:15 +0100
committerJakub Hrozek <jhrozek@redhat.com>2017-02-23 10:15:11 +0100
commitead25e32c52c8c2f5fd9abd179e9e81de58f9ca3 (patch)
treedb5939116e6d35e6486266c7112c3ff0c81deb80
parent82c5971fafe6063a90289ebba08035fc49ae8590 (diff)
downloadsssd-ead25e32c52c8c2f5fd9abd179e9e81de58f9ca3.tar.gz
sssd-ead25e32c52c8c2f5fd9abd179e9e81de58f9ca3.tar.xz
sssd-ead25e32c52c8c2f5fd9abd179e9e81de58f9ca3.zip
p11: return name of PKCS#11 module and key id to pam_sss
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-rw-r--r--src/p11_child/p11_child_nss.c55
-rw-r--r--src/responder/pam/pamsrv.h6
-rw-r--r--src/responder/pam/pamsrv_cmd.c8
-rw-r--r--src/responder/pam/pamsrv_p11.c86
-rw-r--r--src/sss_client/pam_message.h2
-rw-r--r--src/sss_client/pam_sss.c49
-rw-r--r--src/tests/cmocka/test_pam_srv.c33
7 files changed, 221 insertions, 18 deletions
diff --git a/src/p11_child/p11_child_nss.c b/src/p11_child/p11_child_nss.c
index 84772692e..f165b58e6 100644
--- a/src/p11_child/p11_child_nss.c
+++ b/src/p11_child/p11_child_nss.c
@@ -72,13 +72,15 @@ static char *password_passthrough(PK11SlotInfo *slot, PRBool retry, void *arg)
int do_work(TALLOC_CTX *mem_ctx, const char *nss_db, const char *slot_name_in,
enum op_mode mode, const char *pin,
struct cert_verify_opts *cert_verify_opts,
- char **cert, char **token_name_out)
+ char **cert, char **token_name_out, char **module_name_out,
+ char **key_id_out)
{
int ret;
SECStatus rv;
NSSInitContext *nss_ctx;
SECMODModuleList *mod_list;
SECMODModuleList *mod_list_item;
+ SECMODModule *module;
const char *slot_name;
const char *token_name;
uint32_t flags = NSS_INIT_READONLY
@@ -91,6 +93,7 @@ int do_work(TALLOC_CTX *mem_ctx, const char *nss_db, const char *slot_name_in,
PK11SlotInfo *slot = NULL;
CK_SLOT_ID slot_id;
SECMODModuleID module_id;
+ const char *module_name;
CERTCertList *cert_list = NULL;
CERTCertListNode *cert_list_node;
const PK11DefaultArrayEntry friendly_attr = { "Publicly-readable certs",
@@ -105,6 +108,8 @@ int do_work(TALLOC_CTX *mem_ctx, const char *nss_db, const char *slot_name_in,
CERTCertificate *found_cert = NULL;
PK11SlotList *list = NULL;
PK11SlotListElement *le;
+ SECItem *key_id = NULL;
+ char *key_id_str = NULL;
nss_ctx = NSS_InitContext(nss_db, "", "", SECMOD_DB, &parameters, flags);
@@ -187,8 +192,11 @@ int do_work(TALLOC_CTX *mem_ctx, const char *nss_db, const char *slot_name_in,
module_id = PK11_GetModuleID(slot);
slot_name = PK11_GetSlotName(slot);
token_name = PK11_GetTokenName(slot);
- DEBUG(SSSDBG_TRACE_ALL, "Found [%s] in slot [%s][%d] of module [%d].\n",
- token_name, slot_name, (int) slot_id, (int) module_id);
+ module = PK11_GetModule(slot);
+ module_name = module->dllName == NULL ? "NSS-Internal" : module->dllName;
+
+ DEBUG(SSSDBG_TRACE_ALL, "Found [%s] in slot [%s][%d] of module [%d][%s].\n",
+ token_name, slot_name, (int) slot_id, (int) module_id, module_name);
if (PK11_IsFriendly(slot)) {
DEBUG(SSSDBG_TRACE_ALL, "Token is friendly.\n");
@@ -346,6 +354,7 @@ int do_work(TALLOC_CTX *mem_ctx, const char *nss_db, const char *slot_name_in,
DEBUG(SSSDBG_TRACE_ALL, "No certificate found.\n");
*cert = NULL;
*token_name_out = NULL;
+ *module_name_out = NULL;
ret = EOK;
goto done;
}
@@ -412,6 +421,30 @@ int do_work(TALLOC_CTX *mem_ctx, const char *nss_db, const char *slot_name_in,
"Certificate verified and validated.\n");
}
+ key_id = PK11_GetLowLevelKeyIDForCert(slot, found_cert, NULL);
+ if (key_id == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "PK11_GetLowLevelKeyIDForCert failed [%d].\n",
+ PR_GetError());
+ ret = EINVAL;
+ goto done;
+ }
+
+ key_id_str = CERT_Hexify(key_id, PR_FALSE);
+ if (key_id_str == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "CERT_Hexify failed [%d].\n", PR_GetError());
+ ret = ENOMEM;
+ goto done;
+ }
+
+ DEBUG(SSSDBG_TRACE_ALL, "Found certificate has key id [%s].\n", key_id_str);
+
+ *key_id_out = talloc_strdup(mem_ctx, key_id_str);
+ if (*key_id_out == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to copy key id.\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
*cert = sss_base64_encode(mem_ctx, found_cert->derCert.data,
found_cert->derCert.len);
if (*cert == NULL) {
@@ -427,6 +460,13 @@ int do_work(TALLOC_CTX *mem_ctx, const char *nss_db, const char *slot_name_in,
goto done;
}
+ *module_name_out = talloc_strdup(mem_ctx, module_name);
+ if (*module_name_out == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to copy module_name_out name.\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
ret = EOK;
done:
@@ -438,6 +478,9 @@ done:
CERT_DestroyCertList(cert_list);
}
+ SECITEM_FreeItem(key_id, PR_TRUE);
+ PORT_Free(key_id_str);
+
PORT_Free(signed_random_value.data);
rv = NSS_ShutdownContext(nss_ctx);
@@ -502,6 +545,8 @@ int main(int argc, const char *argv[])
char *pin = NULL;
char *slot_name_in = NULL;
char *token_name_out = NULL;
+ char *module_name_out = NULL;
+ char *key_id_out = NULL;
char *nss_db = NULL;
struct cert_verify_opts *cert_verify_opts;
char *verify_opts = NULL;
@@ -665,7 +710,7 @@ int main(int argc, const char *argv[])
}
ret = do_work(main_ctx, nss_db, slot_name_in, mode, pin, cert_verify_opts,
- &cert, &token_name_out);
+ &cert, &token_name_out, &module_name_out, &key_id_out);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "do_work failed.\n");
goto fail;
@@ -673,6 +718,8 @@ int main(int argc, const char *argv[])
if (cert != NULL) {
fprintf(stdout, "%s\n", token_name_out);
+ fprintf(stdout, "%s\n", module_name_out);
+ fprintf(stdout, "%s\n", key_id_out);
fprintf(stdout, "%s\n", cert);
}
diff --git a/src/responder/pam/pamsrv.h b/src/responder/pam/pamsrv.h
index 389888eca..7860a99a8 100644
--- a/src/responder/pam/pamsrv.h
+++ b/src/responder/pam/pamsrv.h
@@ -92,10 +92,12 @@ struct tevent_req *pam_check_cert_send(TALLOC_CTX *mem_ctx,
const char *verify_opts,
struct pam_data *pd);
errno_t pam_check_cert_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
- char **cert, char **token_name);
+ char **cert, char **token_name, char **module_name,
+ char **key_id);
errno_t add_pam_cert_response(struct pam_data *pd, const char *user,
- const char *token_name);
+ const char *token_name, const char *module_name,
+ const char *key_id);
bool may_do_cert_auth(struct pam_ctx *pctx, struct pam_data *pd);
diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c
index 529c74f70..6b7a9493b 100644
--- a/src/responder/pam/pamsrv_cmd.c
+++ b/src/responder/pam/pamsrv_cmd.c
@@ -1401,7 +1401,9 @@ static void pam_forwarder_cert_cb(struct tevent_req *req)
struct pam_ctx *pctx =
talloc_get_type(preq->cctx->rctx->pvt_ctx, struct pam_ctx);
- ret = pam_check_cert_recv(req, preq, &cert, &preq->token_name);
+ ret = pam_check_cert_recv(req, preq, &cert, &preq->token_name,
+ &preq->module_name,
+ &preq->key_id);
talloc_free(req);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "get_cert request failed.\n");
@@ -2051,7 +2053,9 @@ static void pam_dom_forwarder(struct pam_auth_req *preq)
}
ret = add_pam_cert_response(preq->pd, cert_user,
- preq->token_name);
+ preq->token_name,
+ preq->module_name,
+ preq->key_id);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "add_pam_cert_response failed.\n");
preq->pd->pam_status = PAM_AUTHINFO_UNAVAIL;
diff --git a/src/responder/pam/pamsrv_p11.c b/src/responder/pam/pamsrv_p11.c
index 570bfe09d..365300b90 100644
--- a/src/responder/pam/pamsrv_p11.c
+++ b/src/responder/pam/pamsrv_p11.c
@@ -133,7 +133,8 @@ static errno_t get_p11_child_write_buffer(TALLOC_CTX *mem_ctx,
static errno_t parse_p11_child_response(TALLOC_CTX *mem_ctx, uint8_t *buf,
ssize_t buf_len, char **_cert,
- char **_token_name)
+ char **_token_name, char **_module_name,
+ char **_key_id)
{
int ret;
TALLOC_CTX *tmp_ctx = NULL;
@@ -141,6 +142,8 @@ static errno_t parse_p11_child_response(TALLOC_CTX *mem_ctx, uint8_t *buf,
uint8_t *pn;
char *cert = NULL;
char *token_name = NULL;
+ char *module_name = NULL;
+ char *key_id = NULL;
if (buf_len < 0) {
DEBUG(SSSDBG_CRIT_FAILURE,
@@ -187,6 +190,54 @@ static errno_t parse_p11_child_response(TALLOC_CTX *mem_ctx, uint8_t *buf,
}
if (pn == p) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "Missing module name in p11_child response.\n");
+ ret = EINVAL;
+ goto done;
+ }
+
+ module_name = talloc_strndup(tmp_ctx, (char *) p, (pn - p));
+ if (module_name == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n");
+ ret = ENOMEM;
+ goto done;
+ }
+ DEBUG(SSSDBG_TRACE_ALL, "Found module name [%s].\n", module_name);
+
+ p = ++pn;
+ pn = memchr(p, '\n', buf_len - (p - buf));
+ if (pn == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "Missing new-line in p11_child response.\n");
+ ret = EINVAL;
+ goto done;
+ }
+
+ if (pn == p) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "Missing key id in p11_child response.\n");
+ ret = EINVAL;
+ goto done;
+ }
+
+ key_id = talloc_strndup(tmp_ctx, (char *) p, (pn - p));
+ if (key_id == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n");
+ ret = ENOMEM;
+ goto done;
+ }
+ DEBUG(SSSDBG_TRACE_ALL, "Found key id [%s].\n", key_id);
+
+ p = pn + 1;
+ pn = memchr(p, '\n', buf_len - (p - buf));
+ if (pn == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "Missing new-line in p11_child response.\n");
+ ret = EINVAL;
+ goto done;
+ }
+
+ if (pn == p) {
DEBUG(SSSDBG_OP_FAILURE, "Missing cert in p11_child response.\n");
ret = EINVAL;
goto done;
@@ -206,6 +257,8 @@ done:
if (ret == EOK) {
*_token_name = talloc_steal(mem_ctx, token_name);
*_cert = talloc_steal(mem_ctx, cert);
+ *_module_name = talloc_steal(mem_ctx, module_name);
+ *_key_id = talloc_steal(mem_ctx, key_id);
}
talloc_free(tmp_ctx);
@@ -222,6 +275,8 @@ struct pam_check_cert_state {
struct child_io_fds *io;
char *cert;
char *token_name;
+ char *module_name;
+ char *key_id;
};
static void p11_child_write_done(struct tevent_req *subreq);
@@ -296,6 +351,7 @@ struct tevent_req *pam_check_cert_send(TALLOC_CTX *mem_ctx,
state->child_status = EFAULT;
state->cert = NULL;
state->token_name = NULL;
+ state->module_name = NULL;
state->io = talloc(state, struct child_io_fds);
if (state->io == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "talloc failed.\n");
@@ -459,7 +515,8 @@ static void p11_child_done(struct tevent_req *subreq)
PIPE_FD_CLOSE(state->io->read_from_child_fd);
ret = parse_p11_child_response(state, buf, buf_len, &state->cert,
- &state->token_name);
+ &state->token_name, &state->module_name,
+ &state->key_id);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "parse_p11_child_respose failed.\n");
tevent_req_error(req, ret);
@@ -486,7 +543,8 @@ static void p11_child_timeout(struct tevent_context *ev,
}
errno_t pam_check_cert_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
- char **cert, char **token_name)
+ char **cert, char **token_name, char **module_name,
+ char **key_id)
{
struct pam_check_cert_state *state =
tevent_req_data(req, struct pam_check_cert_state);
@@ -501,6 +559,14 @@ errno_t pam_check_cert_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
*token_name = talloc_steal(mem_ctx, state->token_name);
}
+ if (module_name != NULL) {
+ *module_name = talloc_steal(mem_ctx, state->module_name);
+ }
+
+ if (key_id != NULL) {
+ *key_id = talloc_steal(mem_ctx, state->key_id);
+ }
+
return EOK;
}
@@ -513,23 +579,29 @@ errno_t pam_check_cert_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
#define PKCS11_LOGIN_TOKEN_ENV_NAME "PKCS11_LOGIN_TOKEN_NAME"
errno_t add_pam_cert_response(struct pam_data *pd, const char *sysdb_username,
- const char *token_name)
+ const char *token_name, const char *module_name,
+ const char *key_id)
{
uint8_t *msg = NULL;
char *env = NULL;
size_t user_len;
size_t msg_len;
size_t slot_len;
+ size_t module_len;
+ size_t key_id_len;
int ret;
- if (sysdb_username == NULL || token_name == NULL) {
+ if (sysdb_username == NULL || token_name == NULL || module_name == NULL
+ || key_id == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Missing mandatory user or slot name.\n");
return EINVAL;
}
user_len = strlen(sysdb_username) + 1;
slot_len = strlen(token_name) + 1;
- msg_len = user_len + slot_len;
+ module_len = strlen(module_name) + 1;
+ key_id_len = strlen(key_id) + 1;
+ msg_len = user_len + slot_len + module_len + key_id_len;
msg = talloc_zero_size(pd, msg_len);
if (msg == NULL) {
@@ -546,6 +618,8 @@ errno_t add_pam_cert_response(struct pam_data *pd, const char *sysdb_username,
* being I think using sysdb_username is fine. */
memcpy(msg, sysdb_username, user_len);
memcpy(msg + user_len, token_name, slot_len);
+ memcpy(msg + user_len + slot_len, module_name, module_len);
+ memcpy(msg + user_len + slot_len + module_len, key_id, key_id_len);
ret = pam_add_response(pd, SSS_PAM_CERT_INFO, msg_len, msg);
talloc_free(msg);
diff --git a/src/sss_client/pam_message.h b/src/sss_client/pam_message.h
index 34889e074..3f4a770ac 100644
--- a/src/sss_client/pam_message.h
+++ b/src/sss_client/pam_message.h
@@ -61,6 +61,8 @@ struct pam_items {
char *cert_user;
char *token_name;
+ char *module_name;
+ char *key_id;
};
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 8f97af77e..fa30889e7 100644
--- a/src/sss_client/pam_sss.c
+++ b/src/sss_client/pam_sss.c
@@ -162,6 +162,12 @@ static void overwrite_and_free_pam_items(struct pam_items *pi)
free(pi->token_name);
pi->token_name = NULL;
+
+ free(pi->module_name);
+ pi->module_name = NULL;
+
+ free(pi->key_id);
+ pi->key_id = NULL;
}
static int null_strcmp(const char *s1, const char *s2) {
@@ -1019,10 +1025,47 @@ static int eval_response(pam_handle_t *pamh, size_t buflen, uint8_t *buf,
pi->token_name = strdup((char *) &buf[p + offset]);
if (pi->token_name == NULL) {
D(("strdup failed"));
+ free(pi->cert_user);
+ pi->cert_user = NULL;
+ break;
+ }
+
+ offset += strlen(pi->token_name) + 1;
+ if (offset >= len) {
+ D(("Cert message size mismatch"));
+ free(pi->cert_user);
+ pi->cert_user = NULL;
+ free(pi->token_name);
+ pi->token_name = NULL;
+ break;
+ }
+ free(pi->module_name);
+ pi->module_name = strdup((char *) &buf[p + offset]);
+ if (pi->module_name == NULL) {
+ D(("strdup failed"));
+ break;
+ }
+
+ offset += strlen(pi->module_name) + 1;
+ if (offset >= len) {
+ D(("Cert message size mismatch"));
+ free(pi->cert_user);
+ pi->cert_user = NULL;
+ free(pi->token_name);
+ pi->token_name = NULL;
+ free(pi->module_name);
+ pi->module_name = NULL;
+ break;
+ }
+ free(pi->key_id);
+ pi->key_id = strdup((char *) &buf[p + offset]);
+ if (pi->key_id == NULL) {
+ D(("strdup failed"));
break;
}
- D(("cert user: [%s] token name: [%s]", pi->cert_user,
- pi->token_name));
+ D(("cert user: [%s] token name: [%s] module: [%s] key id: [%s]",
+ pi->cert_user, pi->token_name, pi->module_name,
+ pi->key_id));
break;
case SSS_PASSWORD_PROMPTING:
D(("Password prompting available."));
@@ -1120,6 +1163,8 @@ static int get_pam_items(pam_handle_t *pamh, uint32_t flags,
pi->cert_user = NULL;
pi->token_name = NULL;
+ pi->module_name = NULL;
+ pi->key_id = NULL;
return PAM_SUCCESS;
}
diff --git a/src/tests/cmocka/test_pam_srv.c b/src/tests/cmocka/test_pam_srv.c
index 6b91f49c6..cbc1d0367 100644
--- a/src/tests/cmocka/test_pam_srv.c
+++ b/src/tests/cmocka/test_pam_srv.c
@@ -48,6 +48,8 @@
#define NSS_DB "sql:"NSS_DB_PATH
#define TEST_TOKEN_NAME "SSSD Test Token"
+#define TEST_MODULE_NAME "NSS-Internal"
+#define TEST_KEY_ID "6822EDDD231DAB8DBCD83721BE16A13DD0E31C08"
#define TEST_TOKEN_CERT \
"MIIECTCCAvGgAwIBAgIBCDANBgkqhkiG9w0BAQsFADA0MRIwEAYDVQQKDAlJUEEu" \
"REVWRUwxHjAcBgNVBAMMFUNlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0xNTA2MjMx" \
@@ -668,7 +670,10 @@ static int test_pam_cert_check_gdm_smartcard(uint32_t status, uint8_t *body,
assert_int_equal(val, SSS_PAM_CERT_INFO);
SAFEALIGN_COPY_UINT32(&val, body + rp, &rp);
- assert_int_equal(val, (sizeof("pamuser@"TEST_DOM_NAME) + sizeof(TEST_TOKEN_NAME)));
+ assert_int_equal(val, (sizeof("pamuser@"TEST_DOM_NAME)
+ + sizeof(TEST_TOKEN_NAME)
+ + sizeof(TEST_MODULE_NAME)
+ + sizeof(TEST_KEY_ID)));
assert_int_equal(*(body + rp + sizeof("pamuser@"TEST_DOM_NAME) - 1), 0);
assert_string_equal(body + rp, "pamuser@"TEST_DOM_NAME);
@@ -676,7 +681,17 @@ static int test_pam_cert_check_gdm_smartcard(uint32_t status, uint8_t *body,
assert_int_equal(*(body + rp + sizeof(TEST_TOKEN_NAME) - 1), 0);
assert_string_equal(body + rp, TEST_TOKEN_NAME);
+ rp += sizeof(TEST_TOKEN_NAME);
+ assert_int_equal(*(body + rp + sizeof(TEST_MODULE_NAME) - 1), 0);
+ assert_string_equal(body + rp, TEST_MODULE_NAME);
+ rp += sizeof(TEST_MODULE_NAME);
+
+ assert_int_equal(*(body + rp + sizeof(TEST_KEY_ID) - 1), 0);
+ assert_string_equal(body + rp, TEST_KEY_ID);
+ rp += sizeof(TEST_KEY_ID);
+
+ assert_int_equal(rp, blen);
return EOK;
}
@@ -707,7 +722,10 @@ static int test_pam_cert_check(uint32_t status, uint8_t *body, size_t blen)
assert_int_equal(val, SSS_PAM_CERT_INFO);
SAFEALIGN_COPY_UINT32(&val, body + rp, &rp);
- assert_int_equal(val, (sizeof("pamuser@"TEST_DOM_NAME) + sizeof(TEST_TOKEN_NAME)));
+ assert_int_equal(val, (sizeof("pamuser@"TEST_DOM_NAME)
+ + sizeof(TEST_TOKEN_NAME)
+ + sizeof(TEST_MODULE_NAME)
+ + sizeof(TEST_KEY_ID)));
assert_int_equal(*(body + rp + sizeof("pamuser@"TEST_DOM_NAME) - 1), 0);
assert_string_equal(body + rp, "pamuser@"TEST_DOM_NAME);
@@ -715,6 +733,17 @@ static int test_pam_cert_check(uint32_t status, uint8_t *body, size_t blen)
assert_int_equal(*(body + rp + sizeof(TEST_TOKEN_NAME) - 1), 0);
assert_string_equal(body + rp, TEST_TOKEN_NAME);
+ rp += sizeof(TEST_TOKEN_NAME);
+
+ assert_int_equal(*(body + rp + sizeof(TEST_MODULE_NAME) - 1), 0);
+ assert_string_equal(body + rp, TEST_MODULE_NAME);
+ rp += sizeof(TEST_MODULE_NAME);
+
+ assert_int_equal(*(body + rp + sizeof(TEST_KEY_ID) - 1), 0);
+ assert_string_equal(body + rp, TEST_KEY_ID);
+ rp += sizeof(TEST_KEY_ID);
+
+ assert_int_equal(rp, blen);
return EOK;
}