p11_child_nss.c revision a24954cc19285b197fb287bfa7aa01949c92b17d
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose Helper child to commmunicate with SmartCard via NSS
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose Sumit Bose <sbose@redhat.com>
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose Copyright (C) 2015 Red Hat
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose This program is free software; you can redistribute it and/or modify
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose it under the terms of the GNU General Public License as published by
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose the Free Software Foundation; either version 3 of the License, or
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose (at your option) any later version.
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose This program is distributed in the hope that it will be useful,
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose but WITHOUT ANY WARRANTY; without even the implied warranty of
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose GNU General Public License for more details.
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose You should have received a copy of the GNU General Public License
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose along with this program. If not, see <http://www.gnu.org/licenses/>.
45726939a48e605b0166521f94300ae04981a3a7Sumit Bosestatic char *password_passthrough(PK11SlotInfo *slot, PRBool retry, void *arg)
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose /* give up if 1) no password was supplied, or 2) the password has already
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose * been rejected once by this token. */
45726939a48e605b0166521f94300ae04981a3a7Sumit Boseint do_work(TALLOC_CTX *mem_ctx, const char *nss_db, const char *slot_name_in,
ead25e32c52c8c2f5fd9abd179e9e81de58f9ca3Sumit Bose char **cert, char **token_name_out, char **module_name_out,
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose const PK11DefaultArrayEntry friendly_attr = { "Publicly-readable certs",
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose nss_ctx = NSS_InitContext(nss_db, "", "", SECMOD_DB, ¶meters, flags);
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose DEBUG(SSSDBG_OP_FAILURE, "NSS_InitContext failed [%d].\n",
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose DEBUG(SSSDBG_TRACE_ALL, "Default Module List:\n");
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose for (mod_list_item = mod_list; mod_list_item != NULL;
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose for (mod_list_item = mod_list; mod_list_item != NULL;
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose for (mod_list_item = mod_list; mod_list_item != NULL;
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose DEBUG(SSSDBG_OP_FAILURE, "PK11_FindSlotByName failed for [%s]: [%d].\n",
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_TRUE,
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose DEBUG(SSSDBG_OP_FAILURE, "PK11_GetAllTokens failed.\n");
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose "Description [%s] Manufacturer [%s] flags [%lu].\n",
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose slInfo.slotDescription, slInfo.manufacturerID, slInfo.flags);
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose if (rv == SECSuccess && (slInfo.flags & CKF_REMOVABLE_DEVICE)) {
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose DEBUG(SSSDBG_OP_FAILURE, "No removable slots found.\n");
ead25e32c52c8c2f5fd9abd179e9e81de58f9ca3Sumit Bose module_name = module->dllName == NULL ? "NSS-Internal" : module->dllName;
ead25e32c52c8c2f5fd9abd179e9e81de58f9ca3Sumit Bose DEBUG(SSSDBG_TRACE_ALL, "Found [%s] in slot [%s][%d] of module [%d][%s].\n",
ead25e32c52c8c2f5fd9abd179e9e81de58f9ca3Sumit Bose token_name, slot_name, (int) slot_id, (int) module_id, module_name);
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose "Token is NOT friendly.\n");
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose DEBUG(SSSDBG_TRACE_ALL, "Trying to switch to friendly to read certificate.\n");
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose rv = PK11_UpdateSlotAttribute(slot, &friendly_attr, PR_TRUE);
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose "PK11_UpdateSlotAttribute failed, continue.\n");
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose /* TODO: check PK11_ProtectedAuthenticationPath() and return the result */
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose rv = PK11_Authenticate(slot, PR_FALSE, discard_const(pin));
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose DEBUG(SSSDBG_OP_FAILURE, "PK11_Authenticate failed: [%d].\n",
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose "Login required but no pin available, continue.\n");
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose DEBUG(SSSDBG_TRACE_ALL, "Login NOT required.\n");
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose DEBUG(SSSDBG_OP_FAILURE, "PK11_ListCertsInSlot failed: [%d].\n",
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose cert_list_node = CERT_LIST_NEXT(cert_list_node)) {
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose DEBUG(SSSDBG_TRACE_ALL, "--- empty cert list node ---\n");
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose rv = CERT_FilterCertListByUsage(cert_list, certUsageSSLClient, PR_FALSE);
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose DEBUG(SSSDBG_OP_FAILURE, "CERT_FilterCertListByUsage failed: [%d].\n",
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose DEBUG(SSSDBG_OP_FAILURE, "CERT_FilterCertListForUserCerts failed: [%d].\n",
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose DEBUG(SSSDBG_OP_FAILURE, "CERT_GetDefaultCertDB failed: [%d].\n",
544a20de7667f05c1a406c4dea0706b0ab507430Sumit Bose DEBUG(SSSDBG_OP_FAILURE, "CERT_EnableOCSPChecking failed: [%d].\n",
53ef8f81b60929a6c866efdd133627e7d7d61705Sumit Bose if (cert_verify_opts->ocsp_default_responder != NULL
53ef8f81b60929a6c866efdd133627e7d7d61705Sumit Bose && cert_verify_opts->ocsp_default_responder_signing_cert != NULL) {
53ef8f81b60929a6c866efdd133627e7d7d61705Sumit Bose cert_verify_opts->ocsp_default_responder_signing_cert);
53ef8f81b60929a6c866efdd133627e7d7d61705Sumit Bose "CERT_SetOCSPDefaultResponder failed: [%d].\n",
53ef8f81b60929a6c866efdd133627e7d7d61705Sumit Bose "CERT_EnableOCSPDefaultResponder failed: [%d].\n",
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose DEBUG(SSSDBG_TRACE_ALL, "Filtered certificates:\n");
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose cert_list_node = CERT_LIST_NEXT(cert_list_node)) {
aa35995ef056aa8ae052a47c62c6750b7adf065eSumit Bose rv = CERT_VerifyCertificateNow(handle, cert_list_node->cert,
aa35995ef056aa8ae052a47c62c6750b7adf065eSumit Bose "Certificate [%s][%s] not valid [%d], skipping.\n",
aa35995ef056aa8ae052a47c62c6750b7adf065eSumit Bose cert_list_node->cert->subjectName, PR_GetError());
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose DEBUG(SSSDBG_TRACE_ALL, "More than one certificate found, " \
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose "using just the first one.\n");
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose DEBUG(SSSDBG_TRACE_ALL, "--- empty cert list node ---\n");
53ef8f81b60929a6c866efdd133627e7d7d61705Sumit Bose /* Disable OCSP default responder so that NSS can shutdown properly */
53ef8f81b60929a6c866efdd133627e7d7d61705Sumit Bose && cert_verify_opts->ocsp_default_responder != NULL
53ef8f81b60929a6c866efdd133627e7d7d61705Sumit Bose && cert_verify_opts->ocsp_default_responder_signing_cert != NULL) {
53ef8f81b60929a6c866efdd133627e7d7d61705Sumit Bose "CERT_DisableOCSPDefaultResponder failed: [%d].\n",
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose DEBUG(SSSDBG_TRACE_ALL, "No certificate found.\n");
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose rv = PK11_GenerateRandom(random_value, sizeof(random_value));
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose "PK11_GenerateRandom failed [%d].\n", PR_GetError());
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose priv_key = PK11_FindPrivateKeyFromCert(slot, found_cert, NULL);
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose "PK11_FindPrivateKeyFromCert failed [%d]." \
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose algtag = SEC_GetSignatureAlgorithmOidTag(priv_key->keyType,
de1131abe5ba7aaeb59f81fc3a9cd2a71c0b52ddLukas Slebodnik "SEC_GetSignatureAlgorithmOidTag failed [%d].\n",
de1131abe5ba7aaeb59f81fc3a9cd2a71c0b52ddLukas Slebodnik DEBUG(SSSDBG_OP_FAILURE, "SEC_SignData failed [%d].\n",
de1131abe5ba7aaeb59f81fc3a9cd2a71c0b52ddLukas Slebodnik "CERT_ExtractPublicKey failed [%d].\n", PR_GetError());
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose rv = VFY_VerifyData(random_value, sizeof(random_value),
de1131abe5ba7aaeb59f81fc3a9cd2a71c0b52ddLukas Slebodnik DEBUG(SSSDBG_OP_FAILURE, "VFY_VerifyData failed [%d].\n",
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose "Certificate verified and validated.\n");
ead25e32c52c8c2f5fd9abd179e9e81de58f9ca3Sumit Bose key_id = PK11_GetLowLevelKeyIDForCert(slot, found_cert, NULL);
ead25e32c52c8c2f5fd9abd179e9e81de58f9ca3Sumit Bose DEBUG(SSSDBG_OP_FAILURE, "PK11_GetLowLevelKeyIDForCert failed [%d].\n",
ead25e32c52c8c2f5fd9abd179e9e81de58f9ca3Sumit Bose DEBUG(SSSDBG_OP_FAILURE, "CERT_Hexify failed [%d].\n", PR_GetError());
ead25e32c52c8c2f5fd9abd179e9e81de58f9ca3Sumit Bose DEBUG(SSSDBG_TRACE_ALL, "Found certificate has key id [%s].\n", key_id_str);
ead25e32c52c8c2f5fd9abd179e9e81de58f9ca3Sumit Bose *key_id_out = talloc_strdup(mem_ctx, key_id_str);
ead25e32c52c8c2f5fd9abd179e9e81de58f9ca3Sumit Bose DEBUG(SSSDBG_CRIT_FAILURE, "Failed to copy key id.\n");
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose *cert = sss_base64_encode(mem_ctx, found_cert->derCert.data,
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose DEBUG(SSSDBG_OP_FAILURE, "sss_base64_encode failed.\n");
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose *token_name_out = talloc_strdup(mem_ctx, token_name);
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose DEBUG(SSSDBG_CRIT_FAILURE, "Failed to copy slot name.\n");
ead25e32c52c8c2f5fd9abd179e9e81de58f9ca3Sumit Bose *module_name_out = talloc_strdup(mem_ctx, module_name);
ead25e32c52c8c2f5fd9abd179e9e81de58f9ca3Sumit Bose DEBUG(SSSDBG_CRIT_FAILURE, "Failed to copy module_name_out name.\n");
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose DEBUG(SSSDBG_OP_FAILURE, "NSS_ShutdownContext failed [%d].\n",
45726939a48e605b0166521f94300ae04981a3a7Sumit Bosestatic errno_t p11c_recv_data(TALLOC_CTX *mem_ctx, int fd, char **pin)
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose str = talloc_strndup(mem_ctx, (char *) buf, len);
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n");
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose "Input contains additional data, only PIN expected.\n");
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose {"debug-level", 'd', POPT_ARG_INT, &debug_level, 0,
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose {"debug-timestamps", 0, POPT_ARG_INT, &debug_timestamps, 0,
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose {"debug-microseconds", 0, POPT_ARG_INT, &debug_microseconds, 0,
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose _("An open file descriptor for the debug logs"), NULL},
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose {"debug-to-stderr", 0, POPT_ARG_NONE | POPT_ARGFLAG_DOC_HIDDEN,
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose _("Send the debug output to stderr directly."), NULL },
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose {"auth", 0, POPT_ARG_NONE, NULL, 'a', _("Run in auth mode"), NULL},
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose {"pre", 0, POPT_ARG_NONE, NULL, 'p', _("Run in pre-auth mode"), NULL},
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose {"pin", 0, POPT_ARG_NONE, NULL, 'i', _("Expect PIN on stdin"), NULL},
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose {"keypad", 0, POPT_ARG_NONE, NULL, 'k', _("Expect PIN on keypad"),
544a20de7667f05c1a406c4dea0706b0ab507430Sumit Bose {"verify", 0, POPT_ARG_STRING, &verify_opts, 0 , _("Tune validation"),
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose {"nssdb", 0, POPT_ARG_STRING, &nss_db, 0, _("NSS DB to use"),
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose /* Set debug level to invalid value so we can decide if -d 0 was used. */
3be9e26dcd169d44ae105f1b8a0674464c700b77Sumit Bose * This child can run as root or as sssd user relying on policy kit to
3be9e26dcd169d44ae105f1b8a0674464c700b77Sumit Bose * grant access to pcscd. This means that no setuid or setgid bit must be
3be9e26dcd169d44ae105f1b8a0674464c700b77Sumit Bose * set on the binary. We still should make sure to run with a restrictive
3be9e26dcd169d44ae105f1b8a0674464c700b77Sumit Bose * umask but do not have to make additional precautions like clearing the
3be9e26dcd169d44ae105f1b8a0674464c700b77Sumit Bose * environment. This would allow to use e.g. pkcs11-spy.so for further
3be9e26dcd169d44ae105f1b8a0674464c700b77Sumit Bose * debugging.
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose pc = poptGetContext(argv[0], argc, argv, long_options, 0);
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose "\n--auth and --pre are mutually exclusive and " \
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose "should be only used once.\n\n");
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose "\n--auth and --pre are mutually exclusive and " \
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose "should be only used once.\n\n");
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose fprintf(stderr, "\n--pin and --keypad are mutually exclusive " \
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose "and should be only used once.\n\n");
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose fprintf(stderr, "\n--pin and --keypad are mutually exclusive " \
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose "and should be only used once.\n\n");
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose fprintf(stderr, "\nMissing NSS DB --nssdb must be specified.\n\n");
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose "either --auth or --pre must be specified.\n\n");
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose } else if (mode == OP_AUTH && pin_mode == PIN_NONE) {
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose fprintf(stderr, "\nMissing pin mode for authentication, " \
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose "either --pin or --keypad must be specified.\n");
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose debug_prg_name = talloc_asprintf(NULL, "[sssd[p11_child[%d]]]", getpid());
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf failed.\n");
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose DEBUG(SSSDBG_CRIT_FAILURE, "set_debug_file_from_fd failed.\n");
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose DEBUG(SSSDBG_TRACE_FUNC, "p11_child started.\n");
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose DEBUG(SSSDBG_TRACE_INTERNAL, "Running in [%s] mode.\n",
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose : (mode == OP_PREAUTH ? "pre-auth" : "unknown"));
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose "Running with effective IDs: [%"SPRIuid"][%"SPRIgid"].\n",
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose "Running with real IDs [%"SPRIuid"][%"SPRIgid"].\n",
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new failed.\n");
aa35995ef056aa8ae052a47c62c6750b7adf065eSumit Bose ret = parse_cert_verify_opts(main_ctx, verify_opts, &cert_verify_opts);
aa35995ef056aa8ae052a47c62c6750b7adf065eSumit Bose DEBUG(SSSDBG_FATAL_FAILURE, "Failed to parse verifiy option.\n");
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose ret = p11c_recv_data(main_ctx, STDIN_FILENO, &pin);
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose DEBUG(SSSDBG_FATAL_FAILURE, "Failed to read pin.\n");
aa35995ef056aa8ae052a47c62c6750b7adf065eSumit Bose ret = do_work(main_ctx, nss_db, slot_name_in, mode, pin, cert_verify_opts,
ead25e32c52c8c2f5fd9abd179e9e81de58f9ca3Sumit Bose &cert, &token_name_out, &module_name_out, &key_id_out);
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose DEBUG(SSSDBG_CRIT_FAILURE, "p11_child failed!\n");