0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose SSSD - certificate handling utils - NSS version
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose Copyright (C) Sumit Bose <sbose@redhat.com> 2015
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose This program is free software; you can redistribute it and/or modify
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose it under the terms of the GNU General Public License as published by
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose the Free Software Foundation; either version 3 of the License, or
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose (at your option) any later version.
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose This program is distributed in the hope that it will be useful,
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose but WITHOUT ANY WARRANTY; without even the implied warranty of
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose GNU General Public License for more details.
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose You should have received a copy of the GNU General Public License
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose along with this program. If not, see <http://www.gnu.org/licenses/>.
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose#define NS_CERT_HEADER "-----BEGIN CERTIFICATE-----"
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose#define NS_CERT_TRAILER "-----END CERTIFICATE-----"
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose#define NS_CERT_HEADER_LEN ((sizeof NS_CERT_HEADER) - 1)
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose#define NS_CERT_TRAILER_LEN ((sizeof NS_CERT_TRAILER) - 1)
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Boseerrno_t sss_cert_der_to_pem(TALLOC_CTX *mem_ctx, const uint8_t *der_blob,
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose /* initialize NSS if needed */
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose DEBUG(SSSDBG_OP_FAILURE, "nspr_nss_init failed.\n");
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose cert = CERT_NewTempCertificate(handle, &der_item, NULL, PR_FALSE, PR_TRUE);
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose DEBUG(SSSDBG_OP_FAILURE, "CERT_NewTempCertificate failed.\n");
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose ascii_crlf = BTOA_DataToAscii(cert->derCert.data, cert->derCert.len);
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose DEBUG(SSSDBG_OP_FAILURE, "BTOA_DataToAscii failed.\n");
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose ascii_lf = talloc_size(mem_ctx, ascii_crlf_len * sizeof(char));
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose for (c = 0; c < ascii_crlf_len; c++) {
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose pem_cert_str = talloc_asprintf(mem_ctx, "%s\n%s\n%s\n", NS_CERT_HEADER,
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Boseerrno_t sss_cert_pem_to_der(TALLOC_CTX *mem_ctx, const char *pem,
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose unsigned int der_size; /* unsigned int to match 2nd parameter of
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose ATOB_AsciiToData */
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose /* initialize NSS if needed */
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose DEBUG(SSSDBG_OP_FAILURE, "nspr_nss_init failed.\n");
5231ba679402eeb0705a3ecd41f97fdd67d42a69David Kupka if ((pem = strstr(pem, NS_CERT_HEADER)) == NULL) {
5231ba679402eeb0705a3ecd41f97fdd67d42a69David Kupka DEBUG(SSSDBG_CRIT_FAILURE, "Missing PEM header.");
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose if (pem_len <= NS_CERT_HEADER_LEN + NS_CERT_TRAILER_LEN) {
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose DEBUG(SSSDBG_CRIT_FAILURE, "PEM data too short.\n");
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose DEBUG(SSSDBG_CRIT_FAILURE, "Missing newline in PEM data.\n");
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose if (strncmp(pe, NS_CERT_TRAILER, NS_CERT_TRAILER_LEN) != 0) {
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose DEBUG(SSSDBG_CRIT_FAILURE, "Wrong PEM trailer.\n");
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n");
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose DEBUG(SSSDBG_OP_FAILURE, "ATOB_AsciiToData failed.\n");
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose cert = CERT_NewTempCertificate(handle, &der_item, NULL, PR_FALSE, PR_TRUE);
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose DEBUG(SSSDBG_OP_FAILURE, "CERT_NewTempCertificate failed.\n");
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose *_der_blob = talloc_memdup(mem_ctx, cert->derCert.data,
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose DEBUG(SSSDBG_OP_FAILURE, "talloc_memdup failed.\n");
4de84af23db74e13e867985c9093f394c9fa8d51Sumit Bose#define SSH_RSA_HEADER_LEN (sizeof(SSH_RSA_HEADER) - 1)
4de84af23db74e13e867985c9093f394c9fa8d51Sumit Boseerrno_t cert_to_ssh_key(TALLOC_CTX *mem_ctx, const char *ca_db,
4de84af23db74e13e867985c9093f394c9fa8d51Sumit Bose /* initialize NSS with context, we might have already called
4de84af23db74e13e867985c9093f394c9fa8d51Sumit Bose * NSS_NoDB_Init() but for validation we need to have access to a DB with
4de84af23db74e13e867985c9093f394c9fa8d51Sumit Bose * the trusted issuer cert. Only NSS_InitContext will really open the DB
4de84af23db74e13e867985c9093f394c9fa8d51Sumit Bose * in this case. I'm not sure about how long validation might need e.g. if
4de84af23db74e13e867985c9093f394c9fa8d51Sumit Bose * CRLs or OSCP is enabled, maybe it would be better to run validation in
346d6d8bf5fdb446921d754c07c8a7d913a048d5René Genz * p11_child? */
4de84af23db74e13e867985c9093f394c9fa8d51Sumit Bose nss_ctx = NSS_InitContext(ca_db, "", "", SECMOD_DB, ¶meters,
4de84af23db74e13e867985c9093f394c9fa8d51Sumit Bose DEBUG(SSSDBG_OP_FAILURE, "NSS_InitContext 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",
4de84af23db74e13e867985c9093f394c9fa8d51Sumit Bose cert = CERT_NewTempCertificate(handle, &der_item, NULL, PR_FALSE, PR_TRUE);
4de84af23db74e13e867985c9093f394c9fa8d51Sumit Bose DEBUG(SSSDBG_OP_FAILURE, "CERT_NewTempCertificate failed.\n");
53ef8f81b60929a6c866efdd133627e7d7d61705Sumit Bose rv_verify = CERT_VerifyCertificateNow(handle, cert, PR_TRUE,
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
53ef8f81b60929a6c866efdd133627e7d7d61705Sumit Bose "CERT_DisableOCSPDefaultResponder failed: [%d].\n",
aa35995ef056aa8ae052a47c62c6750b7adf065eSumit Bose DEBUG(SSSDBG_CRIT_FAILURE, "CERT_VerifyCertificateNow failed [%d].\n",
4de84af23db74e13e867985c9093f394c9fa8d51Sumit Bose DEBUG(SSSDBG_OP_FAILURE, "CERT_ExtractPublicKey failed.\n");
4de84af23db74e13e867985c9093f394c9fa8d51Sumit Bose "Expected RSA public key, found unsupported [%d].\n",
346d6d8bf5fdb446921d754c07c8a7d913a048d5René Genz /* Looks like nss drops the leading 00 which AFAIK is added to make sure
8b2bd0587af6ed6bbd7eab7a332ec88de6b7c36cSumit Bose * the bigint is handled as positive number if the leading bit is set. */
8b2bd0587af6ed6bbd7eab7a332ec88de6b7c36cSumit Bose if (cert_pub_key->u.rsa.publicExponent.data[0] & 0x80) {
8b2bd0587af6ed6bbd7eab7a332ec88de6b7c36cSumit Bose if (cert_pub_key->u.rsa.modulus.data[0] & 0x80) {
4de84af23db74e13e867985c9093f394c9fa8d51Sumit Bose DEBUG(SSSDBG_OP_FAILURE, "talloc_size failed.\n");
4de84af23db74e13e867985c9093f394c9fa8d51Sumit Bose SAFEALIGN_SET_UINT32(buf, htobe32(SSH_RSA_HEADER_LEN), &c);
4de84af23db74e13e867985c9093f394c9fa8d51Sumit Bose safealign_memcpy(&buf[c], SSH_RSA_HEADER, SSH_RSA_HEADER_LEN, &c);
8b2bd0587af6ed6bbd7eab7a332ec88de6b7c36cSumit Bose SAFEALIGN_SETMEM_VALUE(&buf[c], '\0', unsigned char, &c);
4de84af23db74e13e867985c9093f394c9fa8d51Sumit Bose safealign_memcpy(&buf[c], cert_pub_key->u.rsa.publicExponent.data,
8b2bd0587af6ed6bbd7eab7a332ec88de6b7c36cSumit Bose SAFEALIGN_SETMEM_VALUE(&buf[c], '\0', unsigned char, &c);
4de84af23db74e13e867985c9093f394c9fa8d51Sumit Bose safealign_memcpy(&buf[c], cert_pub_key->u.rsa.modulus.data,
4de84af23db74e13e867985c9093f394c9fa8d51Sumit Bose DEBUG(SSSDBG_OP_FAILURE, "NSS_ShutdownContext failed [%d].\n",