diff --git a/0001-NSS-crypto-policy-sets-minimum-RSA-and-DSA-key-size-.patch b/0001-NSS-crypto-policy-sets-minimum-RSA-and-DSA-key-size-.patch new file mode 100644 index 0000000..8e19e28 --- /dev/null +++ b/0001-NSS-crypto-policy-sets-minimum-RSA-and-DSA-key-size-.patch @@ -0,0 +1,293 @@ +From fd17f002b2f4150a1fddc2582a21c6c03933a28a Mon Sep 17 00:00:00 2001 +From: Rob Crittenden +Date: Fri, 23 Feb 2018 10:43:44 -0500 +Subject: [PATCH] NSS crypto policy sets minimum RSA and DSA key size to 2048 + +Remove keys < 2048 for the NSS tests. This affects some of the +OpenSSL tests as well where they run in a combined loop. + +Where it was not invasive to do I left the 1024/1536 for OpenSSL. +--- + tests/001-keyiread-dsa/expected.out | 6 +++--- + tests/001-keyiread-dsa/run.sh | 2 +- + tests/001-keyiread-rsa/expected.out | 2 -- + tests/001-keyiread-rsa/run.sh | 2 +- + tests/001-keyiread/expected.out | 2 -- + tests/001-keyiread/run.sh | 2 +- + tests/002-keygen-rsa/expected.out | 6 ------ + tests/002-keygen-rsa/run.sh | 2 +- + tests/002-keygen/expected.out | 18 ------------------ + tests/002-keygen/run.sh | 2 +- + tests/003-csrgen-rsa/expected.out | 6 ------ + tests/003-csrgen-rsa/run.sh | 4 ++-- + tests/003-csrgen/expected.out | 8 -------- + tests/003-csrgen/run.sh | 4 ++-- + tests/004-selfsign-rsa/expected.out | 2 -- + tests/004-selfsign-rsa/run.sh | 2 +- + tests/004-selfsign/expected.out | 2 -- + tests/004-selfsign/run.sh | 2 +- + 18 files changed, 14 insertions(+), 60 deletions(-) + +diff --git a/tests/001-keyiread-dsa/expected.out b/tests/001-keyiread-dsa/expected.out +index b09db0ae..50643176 100644 +--- a/tests/001-keyiread-dsa/expected.out ++++ b/tests/001-keyiread-dsa/expected.out +@@ -1,4 +1,4 @@ +-OK (DSA:1024). +-OK (DSA:1024). +-OK (DSA:1024). ++OK (DSA:2048). ++OK (DSA:2048). ++OK (DSA:2048). + Test complete. +diff --git a/tests/001-keyiread-dsa/run.sh b/tests/001-keyiread-dsa/run.sh +index 9f96b3bc..68f6d1c3 100755 +--- a/tests/001-keyiread-dsa/run.sh ++++ b/tests/001-keyiread-dsa/run.sh +@@ -5,7 +5,7 @@ cd "$tmpdir" + source "$srcdir"/functions + initnssdb "$tmpdir" + +-for size in 1024 ; do ++for size in 2048 ; do + # Generate a self-signed cert. + run_certutil -d "$tmpdir" -S -g $size -n keyi$size \ + -s "cn=T$size" -c "cn=T$size" \ +diff --git a/tests/001-keyiread-rsa/expected.out b/tests/001-keyiread-rsa/expected.out +index 727897d1..3daa51f2 100644 +--- a/tests/001-keyiread-rsa/expected.out ++++ b/tests/001-keyiread-rsa/expected.out +@@ -1,5 +1,3 @@ +-OK (RSA:1024). +-OK (RSA:1536). + OK (RSA:2048). + OK (RSA:3072). + OK (RSA:4096). +diff --git a/tests/001-keyiread-rsa/run.sh b/tests/001-keyiread-rsa/run.sh +index c7b77686..ec31c7c7 100755 +--- a/tests/001-keyiread-rsa/run.sh ++++ b/tests/001-keyiread-rsa/run.sh +@@ -5,7 +5,7 @@ cd "$tmpdir" + source "$srcdir"/functions + initnssdb "$tmpdir" + +-for size in 1024 1536 2048 3072 4096 ; do ++for size in 2048 3072 4096 ; do + # Generate a self-signed cert. + run_certutil -d "$tmpdir" -S -g $size -n keyi$size \ + -s "cn=T$size" -c "cn=T$size" \ +diff --git a/tests/001-keyiread/expected.out b/tests/001-keyiread/expected.out +index 727897d1..3daa51f2 100644 +--- a/tests/001-keyiread/expected.out ++++ b/tests/001-keyiread/expected.out +@@ -1,5 +1,3 @@ +-OK (RSA:1024). +-OK (RSA:1536). + OK (RSA:2048). + OK (RSA:3072). + OK (RSA:4096). +diff --git a/tests/001-keyiread/run.sh b/tests/001-keyiread/run.sh +index ce1428ed..0b31df95 100755 +--- a/tests/001-keyiread/run.sh ++++ b/tests/001-keyiread/run.sh +@@ -5,7 +5,7 @@ cd "$tmpdir" + source "$srcdir"/functions + initnssdb "$tmpdir" + +-for size in 1024 1536 2048 3072 4096 ; do ++for size in 2048 3072 4096 ; do + # Generate a self-signed cert. + run_certutil -d "$tmpdir" -S -g $size -n keyi$size \ + -s "cn=T$size" -c "cn=T$size" \ +diff --git a/tests/002-keygen-rsa/expected.out b/tests/002-keygen-rsa/expected.out +index 3e6e9f3c..f7c146d0 100644 +--- a/tests/002-keygen-rsa/expected.out ++++ b/tests/002-keygen-rsa/expected.out +@@ -1,9 +1,3 @@ +-[nss:1024] +-OK. +-OK (RSA:1024). +-[nss:1536] +-OK. +-OK (RSA:1536). + [nss:2048] + OK. + OK (RSA:2048). +diff --git a/tests/002-keygen-rsa/run.sh b/tests/002-keygen-rsa/run.sh +index 476f4127..c0c59249 100755 +--- a/tests/002-keygen-rsa/run.sh ++++ b/tests/002-keygen-rsa/run.sh +@@ -5,7 +5,7 @@ cd "$tmpdir" + source "$srcdir"/functions + initnssdb "$tmpdir" + +-for size in 1024 1536 2048 3072 4096 ; do ++for size in 2048 3072 4096 ; do + echo "[nss:$size]" + # Generate a key. + cat > entry.$size <<- EOF +diff --git a/tests/002-keygen/expected.out b/tests/002-keygen/expected.out +index dcd1af06..b8fbea56 100644 +--- a/tests/002-keygen/expected.out ++++ b/tests/002-keygen/expected.out +@@ -1,21 +1,3 @@ +-[nss:1024] +-OK. +-OK (RSA:1024). +-OK. +-OK (RSA:1024 after RSA:1024). +-OK. +-OK (RSA:1024 after RSA:1024). +-keyi1024 +-keyi1024 (candidate (next)) +-[nss:1536] +-OK. +-OK (RSA:1536). +-OK. +-OK (RSA:1536 after RSA:1536). +-OK. +-OK (RSA:1536 after RSA:1536). +-keyi1536 +-keyi1536 (candidate (next)) + [nss:2048] + OK. + OK (RSA:2048). +diff --git a/tests/002-keygen/run.sh b/tests/002-keygen/run.sh +index 08af1523..94230e6f 100755 +--- a/tests/002-keygen/run.sh ++++ b/tests/002-keygen/run.sh +@@ -7,7 +7,7 @@ scheme="${scheme:-dbm:}" + source "$srcdir"/functions + initnssdb "$scheme$tmpdir" + +-for size in 1024 1536 2048 3072 4096 ; do ++for size in 2048 3072 4096 ; do + echo "[nss:$size]" + # Generate a key. + cat > entry.$size <<- EOF +diff --git a/tests/003-csrgen-rsa/expected.out b/tests/003-csrgen-rsa/expected.out +index c9dec729..def53fe4 100644 +--- a/tests/003-csrgen-rsa/expected.out ++++ b/tests/003-csrgen-rsa/expected.out +@@ -1,10 +1,4 @@ + pk12util: PKCS12 EXPORT SUCCESSFUL +-1024 OK. +-Signature OK +-pk12util: PKCS12 EXPORT SUCCESSFUL +-1536 OK. +-Signature OK +-pk12util: PKCS12 EXPORT SUCCESSFUL + 2048 OK. + Signature OK + pk12util: PKCS12 EXPORT SUCCESSFUL +diff --git a/tests/003-csrgen-rsa/run.sh b/tests/003-csrgen-rsa/run.sh +index 4cd84084..bb8ebecb 100755 +--- a/tests/003-csrgen-rsa/run.sh ++++ b/tests/003-csrgen-rsa/run.sh +@@ -5,7 +5,7 @@ cd "$tmpdir" + source "$srcdir"/functions + initnssdb "$tmpdir" + +-for size in 1024 1536 2048 3072 4096 ; do ++for size in 2048 3072 4096 ; do + # Build a self-signed certificate. + run_certutil -d "$tmpdir" -S -g $size -n keyi$size \ + -s "cn=T$size" -c "cn=T$size" \ +@@ -147,7 +147,7 @@ iterate() { + + iteration=1 + +-for size in 1024 ; do ++for size in 2048 ; do + iterate "$size" "$subject" "$hostname" "$email" "$principal" "$ku" "$eku" "$challengepassword" "$certfname" "$ca" "$capathlen" "$crldp" "$ocsp" "$nscomment" + done + +diff --git a/tests/003-csrgen/expected.out b/tests/003-csrgen/expected.out +index 8e6cac6e..04342c0f 100644 +--- a/tests/003-csrgen/expected.out ++++ b/tests/003-csrgen/expected.out +@@ -1,13 +1,5 @@ + pk12util: PKCS12 EXPORT SUCCESSFUL + Signature OK +-minicert.openssl.1024.pem: OK +-1024 OK. +-pk12util: PKCS12 EXPORT SUCCESSFUL +-Signature OK +-minicert.openssl.1536.pem: OK +-1536 OK. +-pk12util: PKCS12 EXPORT SUCCESSFUL +-Signature OK + minicert.openssl.2048.pem: OK + 2048 OK. + pk12util: PKCS12 EXPORT SUCCESSFUL +diff --git a/tests/003-csrgen/run.sh b/tests/003-csrgen/run.sh +index 7c169ed9..31466b5c 100755 +--- a/tests/003-csrgen/run.sh ++++ b/tests/003-csrgen/run.sh +@@ -5,7 +5,7 @@ cd "$tmpdir" + source "$srcdir"/functions + initnssdb "$tmpdir" + +-for size in 1024 1536 2048 3072 4096 ; do ++for size in 2048 3072 4096 ; do + # Build a self-signed certificate. + run_certutil -d "$tmpdir" -S -g $size -n keyi$size \ + -s "cn=T$size" -c "cn=T$size" \ +@@ -199,7 +199,7 @@ iterate() { + + iteration=1 + +-for size in 1024 ; do ++for size in 2048 ; do + iterate "$size" "$subject" "$hostname" "$email" "$principal" "$ku" "$eku" "$challengepassword" "$certfname" "$ca" "$capathlen" "$crldp" "$ocsp" "$nscomment" "$subjectder" "$ipaddress" "$freshestcrl" "$no_ocsp_check" "$profile" "$ns_certtype" + done + +diff --git a/tests/004-selfsign-rsa/expected.out b/tests/004-selfsign-rsa/expected.out +index dd5029ec..0eb84ef1 100644 +--- a/tests/004-selfsign-rsa/expected.out ++++ b/tests/004-selfsign-rsa/expected.out +@@ -1,5 +1,3 @@ +-1024 OK. +-1536 OK. + 2048 OK. + 3072 OK. + 4096 OK. +diff --git a/tests/004-selfsign-rsa/run.sh b/tests/004-selfsign-rsa/run.sh +index 6f9285b6..c1dd4c80 100755 +--- a/tests/004-selfsign-rsa/run.sh ++++ b/tests/004-selfsign-rsa/run.sh +@@ -33,7 +33,7 @@ function setupca() { + EOF + } + +-for size in 1024 1536 2048 3072 4096 ; do ++for size in 2048 3072 4096 ; do + # Build a self-signed certificate. + run_certutil -d "$tmpdir" -S -g $size -n keyi$size \ + -s "cn=T$size" -c "cn=T$size" \ +diff --git a/tests/004-selfsign/expected.out b/tests/004-selfsign/expected.out +index dd5029ec..0eb84ef1 100644 +--- a/tests/004-selfsign/expected.out ++++ b/tests/004-selfsign/expected.out +@@ -1,5 +1,3 @@ +-1024 OK. +-1536 OK. + 2048 OK. + 3072 OK. + 4096 OK. +diff --git a/tests/004-selfsign/run.sh b/tests/004-selfsign/run.sh +index 7bb368ec..eb1df4ee 100755 +--- a/tests/004-selfsign/run.sh ++++ b/tests/004-selfsign/run.sh +@@ -43,7 +43,7 @@ function setupca() { + EOF + } + +-for size in 1024 1536 2048 3072 4096 ; do ++for size in 2048 3072 4096 ; do + # Build a self-signed certificate. + run_certutil -d "$tmpdir" -S -g $size -n keyi$size \ + -s "cn=T$size" -c "cn=T$size" \ +-- +2.16.2 + diff --git a/0002-Use-the-correct-slot-when-saving-certificates-in-NSS.patch b/0002-Use-the-correct-slot-when-saving-certificates-in-NSS.patch new file mode 100644 index 0000000..a5a897f --- /dev/null +++ b/0002-Use-the-correct-slot-when-saving-certificates-in-NSS.patch @@ -0,0 +1,1016 @@ +From 3da0e186904ad81dd87cf74bfae88270f14bb770 Mon Sep 17 00:00:00 2001 +From: Rob Crittenden +Date: Tue, 21 Aug 2018 17:25:21 -0400 +Subject: [PATCH 1/7] Use the correct slot when saving certificates in NSS + +Certificates were always stored in the NSS certdb. +--- + src/certsave-n.c | 915 ++++++++++++++++++++++++++++--------------------------- + 1 file changed, 474 insertions(+), 441 deletions(-) + +diff --git a/src/certsave-n.c b/src/certsave-n.c +index 8e15a18a..af176ce5 100644 +--- a/src/certsave-n.c ++++ b/src/certsave-n.c +@@ -92,7 +92,11 @@ cm_certsave_n_main(int fd, struct cm_store_ca *ca, struct cm_store_entry *entry, + SECStatus error; + SECItem *item, subject; + char *p, *q, *pin; ++ const char *token; + const char *es; ++ PK11SlotList *slotlist; ++ PK11SlotListElement *sle; ++ CK_MECHANISM_TYPE mech; + NSSInitContext *ctx; + CERTCertDBHandle *certdb; + CERTCertList *certlist; +@@ -192,231 +196,253 @@ cm_certsave_n_main(int fd, struct cm_store_ca *ca, struct cm_store_entry *entry, + } + _exit(CM_CERTSAVE_STATUS_INTERNAL_ERROR); + } +- /* Be ready to count our uses of a PIN. */ +- memset(&cb_data, 0, sizeof(cb_data)); +- cb_data.entry = entry; +- cb_data.n_attempts = 0; +- pin = NULL; +- if (cm_pin_read_for_key(entry, &pin) != 0) { +- cm_log(1, "Error reading PIN for key store, " +- "failing to save certificate.\n"); ++ /* Find the tokens that we might use for cert storage. */ ++ mech = CKM_RSA_X_509; ++ slotlist = PK11_GetAllTokens(mech, PR_FALSE, PR_FALSE, NULL); ++ if (slotlist == NULL) { ++ cm_log(1, "Error getting list of tokens.\n"); + PORT_FreeArena(arena, PR_TRUE); +- error = NSS_ShutdownContext(ctx); +- if (error != SECSuccess) { ++ if (NSS_ShutdownContext(ctx) != SECSuccess) { + cm_log(1, "Error shutting down NSS.\n"); + } +- _exit(CM_CERTSAVE_STATUS_AUTH); ++ _exit(2); + } +- /* Set a PIN if we're supposed to be using one and aren't using +- * one yet in this database. */ +- if (PK11_NeedUserInit(PK11_GetInternalKeySlot())) { +- PK11_InitPin(PK11_GetInternalKeySlot(), NULL, +- pin ? pin : ""); +- ec = PORT_GetError(); +- if (ec != 0) { +- es = PR_ErrorToName(ec); ++ /* Walk the list looking for the requested slot, or the first one if ++ * none was requested. */ ++ if (cm_pin_read_for_cert(entry, &pin) != 0) { ++ cm_log(1, "Error reading PIN for cert db.\n"); ++ _exit(CM_SUB_STATUS_ERROR_AUTH); ++ } ++ PK11_SetPasswordFunc(&cm_pin_read_for_cert_nss_cb); ++ for (sle = slotlist->head; ++ ((sle != NULL) && (sle->slot != NULL)); ++ sle = sle->next) ++ { ++ /* Log the slot's name. */ ++ token = PK11_GetTokenName(sle->slot); ++ if (token != NULL) { ++ cm_log(3, "Found token '%s'.\n", token); + } else { +- es = NULL; ++ cm_log(3, "Found unnamed token.\n"); + } +- if (PK11_NeedUserInit(PK11_GetInternalKeySlot())) { +- if (es != NULL) { +- cm_log(1, "Key storage slot still " +- "needs user PIN to be set: " +- "%s.\n", es); +- } else { +- cm_log(1, "Key storage slot still " +- "needs user PIN to be set.\n"); +- } ++ /* If we're looking for a specific slot, and this isn't it, ++ * keep going. */ ++ if ((entry->cm_cert_token != NULL) && ++ ((token == NULL) || ++ (strcmp(entry->cm_cert_token, token) != 0))) { ++ if (token != NULL) { ++ cm_log(1, ++ "Token is named \"%s\", not \"%s\", " ++ "skipping.\n", ++ token, entry->cm_cert_token); ++ } else { ++ cm_log(1, ++ "Token is unnamed, not \"%s\", " ++ "skipping.\n", ++ entry->cm_cert_token); ++ } ++ goto next_slot; ++ } ++ /* Be ready to count our uses of a PIN. */ ++ memset(&cb_data, 0, sizeof(cb_data)); ++ cb_data.entry = entry; ++ cb_data.n_attempts = 0; ++ pin = NULL; ++ if (cm_pin_read_for_key(entry, &pin) != 0) { ++ cm_log(1, "Error reading PIN for key store, " ++ "failing to save certificate.\n"); + PORT_FreeArena(arena, PR_TRUE); + error = NSS_ShutdownContext(ctx); + if (error != SECSuccess) { + cm_log(1, "Error shutting down NSS.\n"); + } +- switch (ec) { +- case PR_NO_ACCESS_RIGHTS_ERROR: /* EACCES or EPERM */ +- _exit(CM_CERTSAVE_STATUS_PERMS); +- break; +- default: +- _exit(CM_CERTSAVE_STATUS_AUTH); +- break; +- } ++ _exit(CM_CERTSAVE_STATUS_AUTH); + } +- /* We're authenticated now, so count this as a use of +- * the PIN. */ +- if ((pin != NULL) && (strlen(pin) > 0)) { +- cb_data.n_attempts++; +- } +- } +- /* Log in, if case we need to muck around with the key +- * database. */ +- PK11_SetPasswordFunc(&cm_pin_read_for_key_nss_cb); +- error = PK11_Authenticate(PK11_GetInternalKeySlot(), PR_TRUE, +- &cb_data); +- ec = PORT_GetError(); +- if (error != SECSuccess) { +- if (ec != 0) { ++ if (PK11_NeedUserInit(sle->slot)) { ++ PK11_InitPin(sle->slot, NULL, pin ? pin : ""); ++ ec = PORT_GetError(); + es = PR_ErrorToName(ec); +- } else { +- es = NULL; +- } +- if (es != NULL) { +- cm_log(1, "Error authenticating to key store: %s.\n", +- es); +- } else { +- cm_log(1, "Error authenticating to key store.\n"); +- } +- PORT_FreeArena(arena, PR_TRUE); +- error = NSS_ShutdownContext(ctx); +- if (error != SECSuccess) { +- cm_log(1, "Error shutting down NSS.\n"); +- } +- _exit(CM_CERTSAVE_STATUS_AUTH); +- } +- if ((pin != NULL) && +- (strlen(pin) > 0) && +- (cb_data.n_attempts == 0)) { +- cm_log(1, "PIN was not needed to auth to key " +- "store, though one was provided. " +- "Treating this as an error.\n"); +- PORT_FreeArena(arena, PR_TRUE); +- error = NSS_ShutdownContext(ctx); +- if (error != SECSuccess) { +- cm_log(1, "Error shutting down NSS.\n"); +- } +- _exit(CM_CERTSAVE_STATUS_AUTH); +- } +- certdb = CERT_GetDefaultCertDB(); +- if (certdb != NULL) { +- /* Strip the header and footer. */ +- p = entry->cm_cert; +- q = NULL; +- if (p != NULL) { +- while (strncmp(p, "-----BEGIN ", 11) == 0) { +- p += strcspn(p, "\r\n"); +- p += strspn(p, "\r\n"); ++ if (PK11_NeedUserInit(sle->slot)) { ++ if (es != NULL) { ++ cm_log(1, "Key storage slot still " ++ "needs user PIN to be set: " ++ "%s.\n", es); ++ } else { ++ cm_log(1, "Key storage slot still " ++ "needs user PIN to be set.\n"); ++ } ++ PORT_FreeArena(arena, PR_TRUE); ++ error = NSS_ShutdownContext(ctx); ++ if (error != SECSuccess) { ++ cm_log(1, "Error shutting down NSS.\n"); ++ } ++ switch (ec) { ++ case PR_NO_ACCESS_RIGHTS_ERROR: /* EACCES or EPERM */ ++ _exit(CM_CERTSAVE_STATUS_PERMS); ++ break; ++ default: ++ _exit(CM_CERTSAVE_STATUS_AUTH); ++ break; ++ } + } +- q = strstr(p, "-----END"); ++ /* count this as use of the PIN */ ++ cb_data.n_attempts++; + } +- if ((q == NULL) || (*p == '\0')) { +- cm_log(1, "Unable to parse certificate.\n"); +- PORT_FreeArena(arena, PR_TRUE); +- if (NSS_ShutdownContext(ctx) != SECSuccess) { +- cm_log(1, "Error shutting down NSS.\n"); ++ if (PK11_NeedLogin(sle->slot)) { ++ error = PK11_Authenticate(sle->slot, PR_TRUE, &cb_data); ++ if (error != SECSuccess) { ++ cm_log(1, "Error authenticating to cert db for token " ++ "%s.\n", token); ++ goto next_slot; + } +- _exit(CM_CERTSAVE_STATUS_INTERNAL_ERROR); ++ cb_data.n_attempts++; + } +- /* Handle the base64 decode. */ +- item = NSSBase64_DecodeBuffer(arena, NULL, p, q - p); +- if (item == NULL) { +- cm_log(1, "Unable to decode certificate " +- "into buffer.\n"); ++ if ((pin != NULL) && ++ (strlen(pin) > 0) && ++ (cb_data.n_attempts == 0)) { ++ cm_log(1, "PIN was not needed to auth to key " ++ "store, though one was provided. " ++ "Treating this as an error.\n"); + PORT_FreeArena(arena, PR_TRUE); +- if (NSS_ShutdownContext(ctx) != SECSuccess) { ++ error = NSS_ShutdownContext(ctx); ++ if (error != SECSuccess) { + cm_log(1, "Error shutting down NSS.\n"); + } +- _exit(CM_CERTSAVE_STATUS_INTERNAL_ERROR); ++ _exit(CM_CERTSAVE_STATUS_AUTH); + } +- /* Do a "shallow" decode to pull out the subject name +- * so that we can check for a conflict. */ +- memset(&csdata, 0, sizeof(csdata)); +- if (SEC_ASN1DecodeItem(arena, &csdata, +- CERT_SignedDataTemplate, +- item) != SECSuccess) { +- cm_log(1, "Unable to decode certificate " +- "signed data into buffer.\n"); +- PORT_FreeArena(arena, PR_TRUE); +- if (NSS_ShutdownContext(ctx) != SECSuccess) { +- cm_log(1, "Error shutting down NSS.\n"); ++ certdb = CERT_GetDefaultCertDB(); ++ if (certdb != NULL) { ++ /* Strip the header and footer. */ ++ p = entry->cm_cert; ++ q = NULL; ++ if (p != NULL) { ++ while (strncmp(p, "-----BEGIN ", 11) == 0) { ++ p += strcspn(p, "\r\n"); ++ p += strspn(p, "\r\n"); ++ } ++ q = strstr(p, "-----END"); + } +- _exit(CM_CERTSAVE_STATUS_INTERNAL_ERROR); +- } +- memset(&cert, 0, sizeof(cert)); +- if (SEC_ASN1DecodeItem(arena, &cert, +- CERT_CertificateTemplate, +- &csdata.data) != SECSuccess) { +- cm_log(1, "Unable to decode certificate " +- "data into buffer.\n"); +- PORT_FreeArena(arena, PR_TRUE); +- if (NSS_ShutdownContext(ctx) != SECSuccess) { +- cm_log(1, "Error shutting down NSS.\n"); ++ if ((q == NULL) || (*p == '\0')) { ++ cm_log(1, "Unable to parse certificate.\n"); ++ PORT_FreeArena(arena, PR_TRUE); ++ if (NSS_ShutdownContext(ctx) != SECSuccess) { ++ cm_log(1, "Error shutting down NSS.\n"); ++ } ++ _exit(CM_CERTSAVE_STATUS_INTERNAL_ERROR); + } +- _exit(CM_CERTSAVE_STATUS_INTERNAL_ERROR); +- } +- subject = cert.derSubject; +- /* Ask NSS if there would be a conflict. */ +- have_trust = PR_FALSE; +- if (SEC_CertNicknameConflict(entry->cm_cert_nickname, +- &subject, +- certdb)) { +- /* Delete the certificate that's already there +- * with the nickname we want, otherwise our +- * cert with a different subject name will be +- * discarded. */ +- certlist = PK11_FindCertsFromNickname(entry->cm_cert_nickname, +- NULL); ++ /* Handle the base64 decode. */ ++ item = NSSBase64_DecodeBuffer(arena, NULL, p, q - p); ++ if (item == NULL) { ++ cm_log(1, "Unable to decode certificate " ++ "into buffer.\n"); ++ PORT_FreeArena(arena, PR_TRUE); ++ if (NSS_ShutdownContext(ctx) != SECSuccess) { ++ cm_log(1, "Error shutting down NSS.\n"); ++ } ++ _exit(CM_CERTSAVE_STATUS_INTERNAL_ERROR); ++ } ++ /* Do a "shallow" decode to pull out the subject name ++ * so that we can check for a conflict. */ ++ memset(&csdata, 0, sizeof(csdata)); ++ if (SEC_ASN1DecodeItem(arena, &csdata, ++ CERT_SignedDataTemplate, ++ item) != SECSuccess) { ++ cm_log(1, "Unable to decode certificate " ++ "signed data into buffer.\n"); ++ PORT_FreeArena(arena, PR_TRUE); ++ if (NSS_ShutdownContext(ctx) != SECSuccess) { ++ cm_log(1, "Error shutting down NSS.\n"); ++ } ++ _exit(CM_CERTSAVE_STATUS_INTERNAL_ERROR); ++ } ++ memset(&cert, 0, sizeof(cert)); ++ if (SEC_ASN1DecodeItem(arena, &cert, ++ CERT_CertificateTemplate, ++ &csdata.data) != SECSuccess) { ++ cm_log(1, "Unable to decode certificate " ++ "data into buffer.\n"); ++ PORT_FreeArena(arena, PR_TRUE); ++ if (NSS_ShutdownContext(ctx) != SECSuccess) { ++ cm_log(1, "Error shutting down NSS.\n"); ++ } ++ _exit(CM_CERTSAVE_STATUS_INTERNAL_ERROR); ++ } ++ subject = cert.derSubject; ++ /* Ask NSS if there would be a conflict. */ ++ have_trust = PR_FALSE; ++ if (SEC_CertNicknameConflict(entry->cm_cert_nickname, ++ &subject, ++ certdb)) { ++ /* Delete the certificate that's already there ++ * with the nickname we want, otherwise our ++ * cert with a different subject name will be ++ * discarded. */ ++ certlist = PK11_FindCertsFromNickname(entry->cm_cert_nickname, ++ NULL); ++ if (certlist != NULL) { ++ /* Look for certs with different ++ * subject names but the same nickname, ++ * because they've got to go. */ ++ for (node = CERT_LIST_HEAD(certlist); ++ (node != NULL) && ++ !CERT_LIST_EMPTY(certlist) && ++ !CERT_LIST_END(node, certlist); ++ node = CERT_LIST_NEXT(node)) { ++ if (!SECITEM_ItemsAreEqual(&subject, ++ &node->cert->derSubject)) { ++ cm_log(3, "Found a " ++ "certificate " ++ "with the same " ++ "nickname but " ++ "different " ++ "subject, " ++ "removing " ++ "certificate " ++ "\"%s\" with " ++ "subject " ++ "\"%s\".\n", ++ node->cert->nickname, ++ node->cert->subjectName ? ++ node->cert->subjectName : ++ ""); ++ /* Get a handle for ++ * this certificate's ++ * private key, in case ++ * we need to remove ++ * it. */ ++ privkey = PK11_FindKeyByAnyCert(node->cert, NULL); ++ privkeys = add_privkey_to_list(privkeys, privkey); ++ SEC_DeletePermCertificate(node->cert); ++ } ++ } ++ CERT_DestroyCertList(certlist); ++ } ++ } else { ++ cm_log(3, "No duplicate nickname entries.\n"); ++ } ++ /* This certificate's subject may already be present ++ * with a different nickname. Delete those, too. */ ++ certlist = CERT_CreateSubjectCertList(NULL, certdb, ++ &subject, ++ PR_FALSE, ++ PR_FALSE); + if (certlist != NULL) { +- /* Look for certs with different +- * subject names but the same nickname, +- * because they've got to go. */ ++ /* Look for certs with different nicknames but ++ * the same subject name, because those have ++ * got to go. */ ++ i = 0; + for (node = CERT_LIST_HEAD(certlist); + (node != NULL) && + !CERT_LIST_EMPTY(certlist) && + !CERT_LIST_END(node, certlist); + node = CERT_LIST_NEXT(node)) { +- if (!SECITEM_ItemsAreEqual(&subject, +- &node->cert->derSubject)) { ++ if ((node->cert->nickname != NULL) && ++ (strcmp(entry->cm_cert_nickname, ++ node->cert->nickname) != 0)) ++ { ++ i++; + cm_log(3, "Found a " +- "certificate " +- "with the same " +- "nickname but " +- "different " +- "subject, " +- "removing " +- "certificate " +- "\"%s\" with " +- "subject " +- "\"%s\".\n", +- node->cert->nickname, +- node->cert->subjectName ? +- node->cert->subjectName : +- ""); +- /* Get a handle for +- * this certificate's +- * private key, in case +- * we need to remove +- * it. */ +- privkey = PK11_FindKeyByAnyCert(node->cert, NULL); +- privkeys = add_privkey_to_list(privkeys, privkey); +- SEC_DeletePermCertificate(node->cert); +- } +- } +- CERT_DestroyCertList(certlist); +- } +- } else { +- cm_log(3, "No duplicate nickname entries.\n"); +- } +- /* This certificate's subject may already be present +- * with a different nickname. Delete those, too. */ +- certlist = CERT_CreateSubjectCertList(NULL, certdb, +- &subject, +- PR_FALSE, +- PR_FALSE); +- if (certlist != NULL) { +- /* Look for certs with different nicknames but +- * the same subject name, because those have +- * got to go. */ +- i = 0; +- for (node = CERT_LIST_HEAD(certlist); +- (node != NULL) && +- !CERT_LIST_EMPTY(certlist) && +- !CERT_LIST_END(node, certlist); +- node = CERT_LIST_NEXT(node)) { +- if ((node->cert->nickname != NULL) && +- (strcmp(entry->cm_cert_nickname, +- node->cert->nickname) != 0)) { +- i++; +- cm_log(3, "Found a " +- "certificate with a " ++ "certificate with a " + "different nickname but " + "the same subject, " + "removing certificate " +@@ -426,284 +452,291 @@ cm_certsave_n_main(int fd, struct cm_store_ca *ca, struct cm_store_entry *entry, + node->cert->subjectName ? + node->cert->subjectName : + ""); +- /* Get a handle for this +- * certificate's private key, +- * in case we need to remove +- * it. */ +- privkey = PK11_FindKeyByAnyCert(node->cert, NULL); +- privkeys = add_privkey_to_list(privkeys, privkey); +- SEC_DeletePermCertificate(node->cert); +- } else { +- /* Same nickname, and we +- * already know it has the same +- * subject name. Save its +- * trust. */ +- if (!have_trust) { +- if (CERT_GetCertTrust(node->cert, ++ /* Get a handle for this ++ * certificate's private key, ++ * in case we need to remove ++ * it. */ ++ privkey = PK11_FindKeyByAnyCert(node->cert, NULL); ++ privkeys = add_privkey_to_list(privkeys, privkey); ++ SEC_DeletePermCertificate(node->cert); ++ } else { ++ /* Same nickname, and we ++ * already know it has the same ++ * subject name. Save its ++ * trust. */ ++ if (!have_trust) { ++ if (CERT_GetCertTrust(node->cert, + &trust) == SECSuccess) { +- have_trust = PR_TRUE; ++ have_trust = PR_TRUE; ++ } + } + } + } +- } +- if (i == 0) { +- cm_log(3, "No duplicate subject name entries.\n"); +- } +- CERT_DestroyCertList(certlist); +- } else { +- cm_log(3, "No duplicate subject name entries.\n"); +- } +- /* Make one more attempt at finding an existing trust +- * value. */ +- if (!have_trust) { +- oldcert = PK11_FindCertFromNickname(entry->cm_cert_nickname, NULL); +- if (oldcert != NULL) { +- if (CERT_GetCertTrust(oldcert, +- &trust) == SECSuccess) { +- have_trust = PR_TRUE; ++ if (i == 0) { ++ cm_log(3, "No duplicate subject name entries.\n"); + } +- CERT_DestroyCertificate(oldcert); ++ CERT_DestroyCertList(certlist); ++ } else { ++ cm_log(3, "No duplicate subject name entries.\n"); + } +- } +- /* Import the certificate. */ +- returned = NULL; +- error = CERT_ImportCerts(certdb, +- certUsageUserCertImport, +- 1, &item, &returned, +- PR_TRUE, +- PR_FALSE, +- entry->cm_cert_nickname); +- ec = PORT_GetError(); +- if (error == SECSuccess) { +- /* If NSS uses SQL DB storage, CERT_ImportCerts creates +- * an incomplete internal state (the cert isn't +- * associated with the private key, and calling +- * PK11_FindKeyByAnyCert returns no result). +- * As a workaround, we import the cert again using +- * PK11_ImportCert, which magically fixes the issue. +- * See rhbz#1532188 */ +- error = PK11_ImportCert(PK11_GetInternalKeySlot(), +- returned[0], +- CK_INVALID_HANDLE, +- returned[0]->nickname, +- PR_FALSE); +- } +- if (error == SECSuccess) { +- cm_log(1, "Imported certificate \"%s\", got " +- "nickname \"%s\".\n", +- entry->cm_cert_nickname, +- returned[0]->nickname); +- status = 0; +- /* Set the trust on the new certificate, +- * perhaps matching the trust on an +- * already-present certificate with the same +- * nickname. */ ++ /* Make one more attempt at finding an existing trust ++ * value. */ + if (!have_trust) { +- memset(&trust, 0, sizeof(trust)); +- trust.sslFlags = CERTDB_USER; +- trust.emailFlags = CERTDB_USER; +- trust.objectSigningFlags = CERTDB_USER; ++ oldcert = PK11_FindCertFromNickname(entry->cm_cert_nickname, NULL); ++ if (oldcert != NULL) { ++ if (CERT_GetCertTrust(oldcert, ++ &trust) == SECSuccess) { ++ have_trust = PR_TRUE; ++ } ++ CERT_DestroyCertificate(oldcert); ++ } + } +- error = CERT_ChangeCertTrust(certdb, +- returned[0], +- &trust); ++ /* Import the certificate. */ ++ returned = NULL; ++ error = CERT_ImportCerts(certdb, ++ certUsageUserCertImport, ++ 1, &item, &returned, ++ PR_TRUE, ++ PR_FALSE, ++ entry->cm_cert_nickname); + ec = PORT_GetError(); +- if (error != SECSuccess) { ++ if (error == SECSuccess) { ++ /* If NSS uses SQL DB storage, CERT_ImportCerts creates ++ * an incomplete internal state (the cert isn't ++ * associated with the private key, and calling ++ * PK11_FindKeyByAnyCert returns no result). ++ * As a workaround, we import the cert again using ++ * PK11_ImportCert, which magically fixes the issue. ++ * See rhbz#1532188 */ ++ error = PK11_ImportCert(sle->slot, ++ returned[0], ++ CK_INVALID_HANDLE, ++ returned[0]->nickname, ++ PR_FALSE); ++ } ++ if (error == SECSuccess) { ++ cm_log(1, "Imported certificate \"%s\", got " ++ "nickname \"%s\".\n", ++ entry->cm_cert_nickname, ++ returned[0]->nickname); ++ status = 0; ++ /* Set the trust on the new certificate, ++ * perhaps matching the trust on an ++ * already-present certificate with the same ++ * nickname. */ ++ if (!have_trust) { ++ memset(&trust, 0, sizeof(trust)); ++ trust.sslFlags = CERTDB_USER; ++ trust.emailFlags = CERTDB_USER; ++ trust.objectSigningFlags = CERTDB_USER; ++ } ++ error = CERT_ChangeCertTrust(certdb, ++ returned[0], ++ &trust); ++ ec = PORT_GetError(); ++ if (error != SECSuccess) { ++ if (ec != 0) { ++ es = PR_ErrorToName(ec); ++ } else { ++ es = NULL; ++ } ++ if (es != NULL) { ++ cm_log(0, "Error setting trust " ++ "on certificate \"%s\": " ++ "%s.\n", ++ entry->cm_cert_nickname, es); ++ } else { ++ cm_log(0, "Error setting trust " ++ "on certificate \"%s\".\n", ++ entry->cm_cert_nickname); ++ } ++ } ++ /* Delete any other certificates that are there ++ * with the same nickname. While NSS's ++ * database allows duplicates so long as they ++ * have the same subject name and nickname, ++ * several APIs and many applications can't ++ * dependably find the right one among more ++ * than one. So bye-bye, old certificates. */ ++ certlist = PK11_FindCertsFromNickname(entry->cm_cert_nickname, ++ NULL); ++ if (certlist != NULL) { ++ /* Look for certs with contents. */ ++ for (node = CERT_LIST_HEAD(certlist); ++ (node != NULL) && ++ !CERT_LIST_EMPTY(certlist) && ++ !CERT_LIST_END(node, certlist); ++ node = CERT_LIST_NEXT(node)) { ++ if (!SECITEM_ItemsAreEqual(item, ++ &node->cert->derCert)) { ++ cm_log(3, "Found a " ++ "certificate " ++ "with the same " ++ "nickname and " ++ "subject, but " ++ "different " ++ "contents, " ++ "removing it.\n"); ++ /* Get a handle for ++ * this certificate's ++ * private key, in case ++ * we need to remove ++ * it. */ ++ privkey = PK11_FindKeyByAnyCert(node->cert, NULL); ++ privkeys = add_privkey_to_list(privkeys, privkey); ++ SEC_DeletePermCertificate(node->cert); ++ } ++ } ++ CERT_DestroyCertList(certlist); ++ } ++ } else { + if (ec != 0) { + es = PR_ErrorToName(ec); + } else { + es = NULL; + } + if (es != NULL) { +- cm_log(0, "Error setting trust " +- "on certificate \"%s\": " +- "%s.\n", +- entry->cm_cert_nickname, es); ++ cm_log(0, "Error importing certificate " ++ "into NSSDB \"%s\": %s.\n", ++ entry->cm_cert_storage_location, ++ es); + } else { +- cm_log(0, "Error setting trust " +- "on certificate \"%s\".\n", +- entry->cm_cert_nickname); ++ cm_log(0, "Error importing certificate " ++ "into NSSDB \"%s\".\n", ++ entry->cm_cert_storage_location); + } +- } +- /* Delete any other certificates that are there +- * with the same nickname. While NSS's +- * database allows duplicates so long as they +- * have the same subject name and nickname, +- * several APIs and many applications can't +- * dependably find the right one among more +- * than one. So bye-bye, old certificates. */ +- certlist = PK11_FindCertsFromNickname(entry->cm_cert_nickname, +- NULL); +- if (certlist != NULL) { +- /* Look for certs with contents. */ +- for (node = CERT_LIST_HEAD(certlist); +- (node != NULL) && +- !CERT_LIST_EMPTY(certlist) && +- !CERT_LIST_END(node, certlist); +- node = CERT_LIST_NEXT(node)) { +- if (!SECITEM_ItemsAreEqual(item, +- &node->cert->derCert)) { +- cm_log(3, "Found a " +- "certificate " +- "with the same " +- "nickname and " +- "subject, but " +- "different " +- "contents, " +- "removing it.\n"); +- /* Get a handle for +- * this certificate's +- * private key, in case +- * we need to remove +- * it. */ +- privkey = PK11_FindKeyByAnyCert(node->cert, NULL); +- privkeys = add_privkey_to_list(privkeys, privkey); +- SEC_DeletePermCertificate(node->cert); +- } ++ switch (ec) { ++ case PR_NO_ACCESS_RIGHTS_ERROR: /* ACCES/PERM */ ++ status = CM_CERTSAVE_STATUS_PERMS; ++ break; ++ default: ++ status = CM_CERTSAVE_STATUS_INTERNAL_ERROR; ++ break; + } +- CERT_DestroyCertList(certlist); +- } +- } else { +- if (ec != 0) { +- es = PR_ErrorToName(ec); +- } else { +- es = NULL; + } +- if (es != NULL) { +- cm_log(0, "Error importing certificate " +- "into NSSDB \"%s\": %s.\n", +- entry->cm_cert_storage_location, +- es); +- } else { +- cm_log(0, "Error importing certificate " +- "into NSSDB \"%s\".\n", +- entry->cm_cert_storage_location); +- } +- switch (ec) { +- case PR_NO_ACCESS_RIGHTS_ERROR: /* ACCES/PERM */ +- status = CM_CERTSAVE_STATUS_PERMS; +- break; +- default: +- status = CM_CERTSAVE_STATUS_INTERNAL_ERROR; +- break; ++ /* If we managed to import the certificate, mark its ++ * key for having its nickname removed. */ ++ if ((returned != NULL) && (returned[0] != NULL)) { ++ privkey = PK11_FindKeyByAnyCert(returned[0], NULL); ++ privkeys = add_privkey_to_list(privkeys, privkey); ++ CERT_DestroyCertArray(returned, 1); + } +- } +- /* If we managed to import the certificate, mark its +- * key for having its nickname removed. */ +- if ((returned != NULL) && (returned[0] != NULL)) { +- privkey = PK11_FindKeyByAnyCert(returned[0], NULL); +- privkeys = add_privkey_to_list(privkeys, privkey); +- CERT_DestroyCertArray(returned, 1); +- } +- /* In case we're rekeying, but failed, mark the +- * candidate key for name-clearing or removal, too. */ +- if ((entry->cm_key_next_marker != NULL) && +- (strlen(entry->cm_key_next_marker) > 0)) { +- p = util_build_next_nickname(entry->cm_key_nickname, +- entry->cm_key_next_marker); +- privkeylist = PK11_ListPrivKeysInSlot(PK11_GetInternalKeySlot(), p, NULL); +- if (privkeylist != NULL) { +- for (knode = PRIVKEY_LIST_HEAD(privkeylist); +- !PRIVKEY_LIST_EMPTY(privkeylist) && +- !PRIVKEY_LIST_END(knode, privkeylist); +- knode = PRIVKEY_LIST_NEXT(knode)) { +- q = PK11_GetPrivateKeyNickname(knode->key); +- if ((q != NULL) && +- (strcmp(p, q) == 0)) { +- privkey = SECKEY_CopyPrivateKey(knode->key); +- privkeys = add_privkey_to_list(privkeys, privkey); +- break; ++ /* In case we're rekeying, but failed, mark the ++ * candidate key for name-clearing or removal, too. */ ++ if ((entry->cm_key_next_marker != NULL) && ++ (strlen(entry->cm_key_next_marker) > 0)) { ++ p = util_build_next_nickname(entry->cm_key_nickname, ++ entry->cm_key_next_marker); ++ privkeylist = PK11_ListPrivKeysInSlot(sle->slot, p, NULL); ++ if (privkeylist != NULL) { ++ for (knode = PRIVKEY_LIST_HEAD(privkeylist); ++ !PRIVKEY_LIST_EMPTY(privkeylist) && ++ !PRIVKEY_LIST_END(knode, privkeylist); ++ knode = PRIVKEY_LIST_NEXT(knode)) { ++ q = PK11_GetPrivateKeyNickname(knode->key); ++ if ((q != NULL) && ++ (strcmp(p, q) == 0)) { ++ privkey = SECKEY_CopyPrivateKey(knode->key); ++ privkeys = add_privkey_to_list(privkeys, privkey); ++ break; ++ } + } ++ SECKEY_DestroyPrivateKeyList(privkeylist); + } +- SECKEY_DestroyPrivateKeyList(privkeylist); + } +- } +- if (privkeys != NULL) { +- /* Check if any certificates are still using +- * the keys that correspond to certificates +- * that we removed. */ +- for (i = 0; privkeys[i] != NULL; i++) { +- privkey = privkeys[i]; +- oldcert = PK11_GetCertFromPrivateKey(privkey); +- if (!entry->cm_key_preserve && (oldcert == NULL)) { +- /* We're not preserving +- * orphaned keys, so remove +- * this one. No need to mess +- * with its nickname first. */ +- PK11_DeleteTokenPrivateKey(privkey, PR_FALSE); +- if (error == SECSuccess) { +- cm_log(3, "Removed old key.\n"); +- } else { +- ec = PORT_GetError(); +- if (ec != 0) { +- es = PR_ErrorToName(ec); ++ if (privkeys != NULL) { ++ /* Check if any certificates are still using ++ * the keys that correspond to certificates ++ * that we removed. */ ++ for (i = 0; privkeys[i] != NULL; i++) { ++ privkey = privkeys[i]; ++ oldcert = PK11_GetCertFromPrivateKey(privkey); ++ if (!entry->cm_key_preserve && (oldcert == NULL)) { ++ /* We're not preserving ++ * orphaned keys, so remove ++ * this one. No need to mess ++ * with its nickname first. */ ++ PK11_DeleteTokenPrivateKey(privkey, PR_FALSE); ++ if (error == SECSuccess) { ++ cm_log(3, "Removed old key.\n"); + } else { +- es = NULL; ++ ec = PORT_GetError(); ++ if (ec != 0) { ++ es = PR_ErrorToName(ec); ++ } else { ++ es = NULL; ++ } ++ if (es != NULL) { ++ cm_log(0, "Failed " ++ "to remove " ++ "old key: " ++ "%s.\n", es); ++ } else { ++ cm_log(0, "Failed " ++ "to remove " ++ "old key.\n"); ++ } + } +- if (es != NULL) { +- cm_log(0, "Failed " +- "to remove " +- "old key: " +- "%s.\n", es); +- } else { +- cm_log(0, "Failed " +- "to remove " +- "old key.\n"); +- } +- } +- } else { +- /* Remove the explicit +- * nickname, so that the key +- * will have to be found using +- * the certificate's nickname, +- * and certutil will display +- * the matching certificate's +- * nickname when it's asked to +- * list the keys in the +- * database. */ +- error = PK11_SetPrivateKeyNickname(privkey, ""); +- if (error == SECSuccess) { +- cm_log(3, "Removed " +- "name from old " +- "key.\n"); + } else { +- ec = PORT_GetError(); +- if (ec != 0) { +- es = PR_ErrorToName(ec); ++ /* Remove the explicit ++ * nickname, so that the key ++ * will have to be found using ++ * the certificate's nickname, ++ * and certutil will display ++ * the matching certificate's ++ * nickname when it's asked to ++ * list the keys in the ++ * database. */ ++ error = PK11_SetPrivateKeyNickname(privkey, ""); ++ if (error == SECSuccess) { ++ cm_log(3, "Removed " ++ "name from old " ++ "key.\n"); + } else { +- es = NULL; +- } +- if (es != NULL) { +- cm_log(0, "Failed " +- "to unname " +- "old key: " +- "%s.\n", es); +- } else { +- cm_log(0, "Failed " +- "to unname " +- "old key.\n"); ++ ec = PORT_GetError(); ++ if (ec != 0) { ++ es = PR_ErrorToName(ec); ++ } else { ++ es = NULL; ++ } ++ if (es != NULL) { ++ cm_log(0, "Failed " ++ "to unname " ++ "old key: " ++ "%s.\n", es); ++ } else { ++ cm_log(0, "Failed " ++ "to unname " ++ "old key.\n"); ++ } + } ++ SECKEY_DestroyPrivateKey(privkey); ++ } ++ if (oldcert != NULL) { ++ CERT_DestroyCertificate(oldcert); + } +- SECKEY_DestroyPrivateKey(privkey); +- } +- if (oldcert != NULL) { +- CERT_DestroyCertificate(oldcert); + } ++ free(privkeys); + } +- free(privkeys); ++ } else { ++ cm_log(1, "Error getting handle to default NSS DB.\n"); + } +- } else { +- cm_log(1, "Error getting handle to default NSS DB.\n"); +- } +- PORT_FreeArena(arena, PR_TRUE); +- if (NSS_ShutdownContext(ctx) != SECSuccess) { +- cm_log(1, "Error shutting down NSS.\n"); +- } +- /* Fixup the ownership and permissions on the key and +- * certificate databases. */ +- util_set_db_entry_key_owner(entry->cm_key_storage_location, entry); +- util_set_db_entry_cert_owner(entry->cm_cert_storage_location, entry); +- } ++ PORT_FreeArena(arena, PR_TRUE); ++ if (NSS_ShutdownContext(ctx) != SECSuccess) { ++ cm_log(1, "Error shutting down NSS.\n"); ++ } ++ /* Fixup the ownership and permissions on the key and ++ * certificate databases. */ ++ util_set_db_entry_key_owner(entry->cm_key_storage_location, entry); ++ util_set_db_entry_cert_owner(entry->cm_cert_storage_location, entry); ++ break; ++next_slot: ++ if (sle == slotlist->tail) { ++ break; ++ } ++ } /* for slot loop */ ++ } /* ctx == NULL */ ++ + if (status != 0) { + _exit(status); + } +-- +2.14.4 + diff --git a/0003-Include-the-token-name-when-a-PIN-is-provided-but-is.patch b/0003-Include-the-token-name-when-a-PIN-is-provided-but-is.patch new file mode 100644 index 0000000..bba736c --- /dev/null +++ b/0003-Include-the-token-name-when-a-PIN-is-provided-but-is.patch @@ -0,0 +1,49 @@ +From c029b32c04a9a5993b9c8715fb82421fee613137 Mon Sep 17 00:00:00 2001 +From: Rob Crittenden +Date: Fri, 31 Aug 2018 10:37:12 -0400 +Subject: [PATCH 2/7] Include the token name when a PIN is provided but is + unused + +This improves the output so the user will know which token +the PIN is missing for. Theoretically it should be the token +they asked for but this will show certmogner's view of it. +--- + src/certread-n.c | 6 +++--- + src/keygen-n.c | 4 ++-- + 2 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/src/certread-n.c b/src/certread-n.c +index f2e78c07..57a38dcf 100644 +--- a/src/certread-n.c ++++ b/src/certread-n.c +@@ -259,9 +259,9 @@ cm_certread_n_main(int fd, struct cm_store_ca *ca, struct cm_store_entry *entry, + if ((pin != NULL) && + (strlen(pin) > 0) && + (cb_data.n_attempts == 0)) { +- cm_log(1, "PIN was not needed to auth to cert " +- "db, though one was provided. " +- "Treating this as an error.\n"); ++ cm_log(1, "PIN was not needed to auth to token " ++ "%s, though one was provided. " ++ "Treating this as an error.\n", token); + goto next_slot; + } + } +diff --git a/src/keygen-n.c b/src/keygen-n.c +index 8078a520..84b0bbd3 100644 +--- a/src/keygen-n.c ++++ b/src/keygen-n.c +@@ -400,8 +400,8 @@ next_slot: + (strlen(pin) > 0) && + (cb_data.n_attempts == 0)) { + cm_log(1, "PIN was not needed to auth to key " +- "store, though one was provided. " +- "Treating this as an error.\n"); ++ "store token %s, though one was provided. " ++ "Treating this as an error.\n", token); + PK11_FreeSlotList(slotlist); + error = NSS_ShutdownContext(ctx); + if (error != SECSuccess) { +-- +2.14.4 + diff --git a/0004-Add-utility-function-to-get-the-internal-token-name.patch b/0004-Add-utility-function-to-get-the-internal-token-name.patch new file mode 100644 index 0000000..ed3abde --- /dev/null +++ b/0004-Add-utility-function-to-get-the-internal-token-name.patch @@ -0,0 +1,134 @@ +From f396b19b2c222fa0a50e9bb9704059af4578e678 Mon Sep 17 00:00:00 2001 +From: Rob Crittenden +Date: Fri, 31 Aug 2018 12:08:35 -0400 +Subject: [PATCH 3/7] Add utility function to get the internal token name + +The NSS internal token is the default if no token is specified for +the cert or the key. +--- + src/certread-n.c | 6 +++++- + src/certsave-n.c | 3 +++ + src/keygen-n.c | 3 +++ + src/keyiread-n.c | 3 +++ + src/submit-n.c | 5 ++++- + src/util-n.c | 6 ++++++ + src/util-n.h | 1 + + 7 files changed, 25 insertions(+), 2 deletions(-) + +diff --git a/src/certread-n.c b/src/certread-n.c +index 57a38dcf..1d9217c6 100644 +--- a/src/certread-n.c ++++ b/src/certread-n.c +@@ -190,6 +190,9 @@ cm_certread_n_main(int fd, struct cm_store_ca *ca, struct cm_store_entry *entry, + cm_log(1, "Error reading PIN for cert db.\n"); + _exit(CM_SUB_STATUS_ERROR_AUTH); + } ++ if (entry->cm_cert_token == NULL) { ++ entry->cm_cert_token = util_internal_token_name(); ++ } + PK11_SetPasswordFunc(&cm_pin_read_for_cert_nss_cb); + for (sle = slotlist->head; + ((sle != NULL) && (sle->slot != NULL)); +@@ -253,7 +256,8 @@ cm_certread_n_main(int fd, struct cm_store_ca *ca, struct cm_store_entry *entry, + } + error = PK11_Authenticate(sle->slot, PR_TRUE, &cb_data); + if (error != SECSuccess) { +- cm_log(1, "Error authenticating to cert db.\n"); ++ cm_log(1, "certread-n: Error authenticating to cert db " ++ "slot %s.\n", PK11_GetTokenName(sle->slot)); + goto next_slot; + } + if ((pin != NULL) && +diff --git a/src/certsave-n.c b/src/certsave-n.c +index af176ce5..193309c5 100644 +--- a/src/certsave-n.c ++++ b/src/certsave-n.c +@@ -214,6 +214,9 @@ cm_certsave_n_main(int fd, struct cm_store_ca *ca, struct cm_store_entry *entry, + _exit(CM_SUB_STATUS_ERROR_AUTH); + } + PK11_SetPasswordFunc(&cm_pin_read_for_cert_nss_cb); ++ if (entry->cm_cert_token == NULL) { ++ entry->cm_cert_token = util_internal_token_name(); ++ } + for (sle = slotlist->head; + ((sle != NULL) && (sle->slot != NULL)); + sle = sle->next) +diff --git a/src/keygen-n.c b/src/keygen-n.c +index 84b0bbd3..f7fdf6c0 100644 +--- a/src/keygen-n.c ++++ b/src/keygen-n.c +@@ -272,6 +272,9 @@ cm_keygen_n_main(int fd, struct cm_store_ca *ca, struct cm_store_entry *entry, + cm_log(1, "Error locating token for key generation.\n"); + _exit(CM_SUB_STATUS_ERROR_NO_TOKEN); + } ++ if (entry->cm_cert_token == NULL) { ++ entry->cm_cert_token = util_internal_token_name(); ++ } + /* Walk the list looking for the requested slot, or the first one if + * none was requested. */ + slot = NULL; +diff --git a/src/keyiread-n.c b/src/keyiread-n.c +index 89913aa2..b8408bf1 100644 +--- a/src/keyiread-n.c ++++ b/src/keyiread-n.c +@@ -152,6 +152,9 @@ cm_keyiread_n_get_keys(struct cm_store_entry *entry, int readwrite) + _exit(CM_SUB_STATUS_ERROR_AUTH); + } + PK11_SetPasswordFunc(&cm_pin_read_for_cert_nss_cb); ++ if (entry->cm_key_token == NULL) { ++ entry->cm_key_token = util_internal_token_name(); ++ } + n_tokens = 0; + pubkey = NULL; + /* In practice, the internal slot is either a non-storage slot (in +diff --git a/src/submit-n.c b/src/submit-n.c +index 872153ea..da07d253 100644 +--- a/src/submit-n.c ++++ b/src/submit-n.c +@@ -346,6 +346,9 @@ cm_submit_n_decrypt_envelope(const unsigned char *envelope, + cm_log(1, "Error reading PIN for key storage.\n"); + goto done; + } ++ if (args->entry->cm_key_token == NULL) { ++ args->entry->cm_key_token = util_internal_token_name(); ++ } + PK11_SetPasswordFunc(&cm_pin_read_for_cert_nss_cb); + n_tokens = 0; + /* In practice, the internal slot is either a non-storage slot (in +@@ -402,7 +405,7 @@ cm_submit_n_decrypt_envelope(const unsigned char *envelope, + } + error = PK11_Authenticate(slot, PR_TRUE, &cb_data); + if (error != SECSuccess) { +- cm_log(1, "Error authenticating to token " ++ cm_log(1, "submit-n: Error authenticating to token " + "\"%s\".\n", token); + goto done; + } +diff --git a/src/util-n.c b/src/util-n.c +index 7805e58e..293e2583 100644 +--- a/src/util-n.c ++++ b/src/util-n.c +@@ -287,3 +287,9 @@ util_set_db_entry_cert_owner(const char *dbdir, struct cm_store_entry *entry) + util_set_db_owner_perms(dbdir, secmoddb, entry->cm_cert_owner, + entry->cm_cert_perms); + } ++ ++char * ++util_internal_token_name() ++{ ++ return strdup(PK11_GetTokenName(PK11_GetInternalKeySlot())); ++} +diff --git a/src/util-n.h b/src/util-n.h +index 8a918d5c..637fd4b1 100644 +--- a/src/util-n.h ++++ b/src/util-n.h +@@ -29,5 +29,6 @@ void util_set_db_entry_key_owner(const char *dbdir, + struct cm_store_entry *entry); + void util_set_db_entry_cert_owner(const char *dbdir, + struct cm_store_entry *entry); ++char * util_internal_token_name(); + + #endif +-- +2.14.4 + diff --git a/0005-Only-de-duplicate-certificates-within-the-same-token.patch b/0005-Only-de-duplicate-certificates-within-the-same-token.patch new file mode 100644 index 0000000..fb892c6 --- /dev/null +++ b/0005-Only-de-duplicate-certificates-within-the-same-token.patch @@ -0,0 +1,41 @@ +From 6ebe5695a626c6cd254b249bbebf9846bcb936c0 Mon Sep 17 00:00:00 2001 +From: Rob Crittenden +Date: Tue, 4 Sep 2018 11:06:13 -0400 +Subject: [PATCH 4/7] Only de-duplicate certificates within the same token + +certmonger may not have read/write access to tokens other than +the one it is examining so don't try to de-duplicate certificates +on other tokens. +--- + src/certsave-n.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/src/certsave-n.c b/src/certsave-n.c +index 193309c5..d0152cad 100644 +--- a/src/certsave-n.c ++++ b/src/certsave-n.c +@@ -391,8 +391,9 @@ cm_certsave_n_main(int fd, struct cm_store_ca *ca, struct cm_store_entry *entry, + !CERT_LIST_EMPTY(certlist) && + !CERT_LIST_END(node, certlist); + node = CERT_LIST_NEXT(node)) { +- if (!SECITEM_ItemsAreEqual(&subject, +- &node->cert->derSubject)) { ++ if ((!SECITEM_ItemsAreEqual(&subject, ++ &node->cert->derSubject)) && ++ (sle->slot == node->cert->slot)) { + cm_log(3, "Found a " + "certificate " + "with the same " +@@ -441,7 +442,8 @@ cm_certsave_n_main(int fd, struct cm_store_ca *ca, struct cm_store_entry *entry, + node = CERT_LIST_NEXT(node)) { + if ((node->cert->nickname != NULL) && + (strcmp(entry->cm_cert_nickname, +- node->cert->nickname) != 0)) ++ node->cert->nickname) != 0) && ++ (sle->slot == node->cert->slot)) + { + i++; + cm_log(3, "Found a " +-- +2.14.4 + diff --git a/0006-Ensure-that-an-OpenSSL-random-seed-file-exists-when-.patch b/0006-Ensure-that-an-OpenSSL-random-seed-file-exists-when-.patch new file mode 100644 index 0000000..184a651 --- /dev/null +++ b/0006-Ensure-that-an-OpenSSL-random-seed-file-exists-when-.patch @@ -0,0 +1,30 @@ +From 697dd085e7b2ce15eefc454509987270131d7f1e Mon Sep 17 00:00:00 2001 +From: Rob Crittenden +Date: Tue, 4 Sep 2018 16:59:28 -0400 +Subject: [PATCH 5/7] Ensure that an OpenSSL random seed file exists when + testing + +Otherwise some openssl command-line invocations will fail and +because of the way the tests are done the error message is not +shown. +--- + tests/Makefile.am | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/tests/Makefile.am b/tests/Makefile.am +index 4e407434..fe368dc0 100644 +--- a/tests/Makefile.am ++++ b/tests/Makefile.am +@@ -433,6 +433,9 @@ subdirs += \ + endif + + check: all ++ if [ ! -e $$HOME/.rnd ] ; then \ ++ openssl rand -writerand $$HOME/.rnd; \ ++ fi + for required in certutil cmsutil pk12util openssl diff cmp mktemp \ + dos2unix unix2dos dbus-launch ; do \ + which $$required || exit 1; \ +-- +2.14.4 + diff --git a/0006-NSS-crypto-policy-sets-minimum-RSA-and-DSA-key-size-.patch b/0006-NSS-crypto-policy-sets-minimum-RSA-and-DSA-key-size-.patch deleted file mode 100644 index 8e19e28..0000000 --- a/0006-NSS-crypto-policy-sets-minimum-RSA-and-DSA-key-size-.patch +++ /dev/null @@ -1,293 +0,0 @@ -From fd17f002b2f4150a1fddc2582a21c6c03933a28a Mon Sep 17 00:00:00 2001 -From: Rob Crittenden -Date: Fri, 23 Feb 2018 10:43:44 -0500 -Subject: [PATCH] NSS crypto policy sets minimum RSA and DSA key size to 2048 - -Remove keys < 2048 for the NSS tests. This affects some of the -OpenSSL tests as well where they run in a combined loop. - -Where it was not invasive to do I left the 1024/1536 for OpenSSL. ---- - tests/001-keyiread-dsa/expected.out | 6 +++--- - tests/001-keyiread-dsa/run.sh | 2 +- - tests/001-keyiread-rsa/expected.out | 2 -- - tests/001-keyiread-rsa/run.sh | 2 +- - tests/001-keyiread/expected.out | 2 -- - tests/001-keyiread/run.sh | 2 +- - tests/002-keygen-rsa/expected.out | 6 ------ - tests/002-keygen-rsa/run.sh | 2 +- - tests/002-keygen/expected.out | 18 ------------------ - tests/002-keygen/run.sh | 2 +- - tests/003-csrgen-rsa/expected.out | 6 ------ - tests/003-csrgen-rsa/run.sh | 4 ++-- - tests/003-csrgen/expected.out | 8 -------- - tests/003-csrgen/run.sh | 4 ++-- - tests/004-selfsign-rsa/expected.out | 2 -- - tests/004-selfsign-rsa/run.sh | 2 +- - tests/004-selfsign/expected.out | 2 -- - tests/004-selfsign/run.sh | 2 +- - 18 files changed, 14 insertions(+), 60 deletions(-) - -diff --git a/tests/001-keyiread-dsa/expected.out b/tests/001-keyiread-dsa/expected.out -index b09db0ae..50643176 100644 ---- a/tests/001-keyiread-dsa/expected.out -+++ b/tests/001-keyiread-dsa/expected.out -@@ -1,4 +1,4 @@ --OK (DSA:1024). --OK (DSA:1024). --OK (DSA:1024). -+OK (DSA:2048). -+OK (DSA:2048). -+OK (DSA:2048). - Test complete. -diff --git a/tests/001-keyiread-dsa/run.sh b/tests/001-keyiread-dsa/run.sh -index 9f96b3bc..68f6d1c3 100755 ---- a/tests/001-keyiread-dsa/run.sh -+++ b/tests/001-keyiread-dsa/run.sh -@@ -5,7 +5,7 @@ cd "$tmpdir" - source "$srcdir"/functions - initnssdb "$tmpdir" - --for size in 1024 ; do -+for size in 2048 ; do - # Generate a self-signed cert. - run_certutil -d "$tmpdir" -S -g $size -n keyi$size \ - -s "cn=T$size" -c "cn=T$size" \ -diff --git a/tests/001-keyiread-rsa/expected.out b/tests/001-keyiread-rsa/expected.out -index 727897d1..3daa51f2 100644 ---- a/tests/001-keyiread-rsa/expected.out -+++ b/tests/001-keyiread-rsa/expected.out -@@ -1,5 +1,3 @@ --OK (RSA:1024). --OK (RSA:1536). - OK (RSA:2048). - OK (RSA:3072). - OK (RSA:4096). -diff --git a/tests/001-keyiread-rsa/run.sh b/tests/001-keyiread-rsa/run.sh -index c7b77686..ec31c7c7 100755 ---- a/tests/001-keyiread-rsa/run.sh -+++ b/tests/001-keyiread-rsa/run.sh -@@ -5,7 +5,7 @@ cd "$tmpdir" - source "$srcdir"/functions - initnssdb "$tmpdir" - --for size in 1024 1536 2048 3072 4096 ; do -+for size in 2048 3072 4096 ; do - # Generate a self-signed cert. - run_certutil -d "$tmpdir" -S -g $size -n keyi$size \ - -s "cn=T$size" -c "cn=T$size" \ -diff --git a/tests/001-keyiread/expected.out b/tests/001-keyiread/expected.out -index 727897d1..3daa51f2 100644 ---- a/tests/001-keyiread/expected.out -+++ b/tests/001-keyiread/expected.out -@@ -1,5 +1,3 @@ --OK (RSA:1024). --OK (RSA:1536). - OK (RSA:2048). - OK (RSA:3072). - OK (RSA:4096). -diff --git a/tests/001-keyiread/run.sh b/tests/001-keyiread/run.sh -index ce1428ed..0b31df95 100755 ---- a/tests/001-keyiread/run.sh -+++ b/tests/001-keyiread/run.sh -@@ -5,7 +5,7 @@ cd "$tmpdir" - source "$srcdir"/functions - initnssdb "$tmpdir" - --for size in 1024 1536 2048 3072 4096 ; do -+for size in 2048 3072 4096 ; do - # Generate a self-signed cert. - run_certutil -d "$tmpdir" -S -g $size -n keyi$size \ - -s "cn=T$size" -c "cn=T$size" \ -diff --git a/tests/002-keygen-rsa/expected.out b/tests/002-keygen-rsa/expected.out -index 3e6e9f3c..f7c146d0 100644 ---- a/tests/002-keygen-rsa/expected.out -+++ b/tests/002-keygen-rsa/expected.out -@@ -1,9 +1,3 @@ --[nss:1024] --OK. --OK (RSA:1024). --[nss:1536] --OK. --OK (RSA:1536). - [nss:2048] - OK. - OK (RSA:2048). -diff --git a/tests/002-keygen-rsa/run.sh b/tests/002-keygen-rsa/run.sh -index 476f4127..c0c59249 100755 ---- a/tests/002-keygen-rsa/run.sh -+++ b/tests/002-keygen-rsa/run.sh -@@ -5,7 +5,7 @@ cd "$tmpdir" - source "$srcdir"/functions - initnssdb "$tmpdir" - --for size in 1024 1536 2048 3072 4096 ; do -+for size in 2048 3072 4096 ; do - echo "[nss:$size]" - # Generate a key. - cat > entry.$size <<- EOF -diff --git a/tests/002-keygen/expected.out b/tests/002-keygen/expected.out -index dcd1af06..b8fbea56 100644 ---- a/tests/002-keygen/expected.out -+++ b/tests/002-keygen/expected.out -@@ -1,21 +1,3 @@ --[nss:1024] --OK. --OK (RSA:1024). --OK. --OK (RSA:1024 after RSA:1024). --OK. --OK (RSA:1024 after RSA:1024). --keyi1024 --keyi1024 (candidate (next)) --[nss:1536] --OK. --OK (RSA:1536). --OK. --OK (RSA:1536 after RSA:1536). --OK. --OK (RSA:1536 after RSA:1536). --keyi1536 --keyi1536 (candidate (next)) - [nss:2048] - OK. - OK (RSA:2048). -diff --git a/tests/002-keygen/run.sh b/tests/002-keygen/run.sh -index 08af1523..94230e6f 100755 ---- a/tests/002-keygen/run.sh -+++ b/tests/002-keygen/run.sh -@@ -7,7 +7,7 @@ scheme="${scheme:-dbm:}" - source "$srcdir"/functions - initnssdb "$scheme$tmpdir" - --for size in 1024 1536 2048 3072 4096 ; do -+for size in 2048 3072 4096 ; do - echo "[nss:$size]" - # Generate a key. - cat > entry.$size <<- EOF -diff --git a/tests/003-csrgen-rsa/expected.out b/tests/003-csrgen-rsa/expected.out -index c9dec729..def53fe4 100644 ---- a/tests/003-csrgen-rsa/expected.out -+++ b/tests/003-csrgen-rsa/expected.out -@@ -1,10 +1,4 @@ - pk12util: PKCS12 EXPORT SUCCESSFUL --1024 OK. --Signature OK --pk12util: PKCS12 EXPORT SUCCESSFUL --1536 OK. --Signature OK --pk12util: PKCS12 EXPORT SUCCESSFUL - 2048 OK. - Signature OK - pk12util: PKCS12 EXPORT SUCCESSFUL -diff --git a/tests/003-csrgen-rsa/run.sh b/tests/003-csrgen-rsa/run.sh -index 4cd84084..bb8ebecb 100755 ---- a/tests/003-csrgen-rsa/run.sh -+++ b/tests/003-csrgen-rsa/run.sh -@@ -5,7 +5,7 @@ cd "$tmpdir" - source "$srcdir"/functions - initnssdb "$tmpdir" - --for size in 1024 1536 2048 3072 4096 ; do -+for size in 2048 3072 4096 ; do - # Build a self-signed certificate. - run_certutil -d "$tmpdir" -S -g $size -n keyi$size \ - -s "cn=T$size" -c "cn=T$size" \ -@@ -147,7 +147,7 @@ iterate() { - - iteration=1 - --for size in 1024 ; do -+for size in 2048 ; do - iterate "$size" "$subject" "$hostname" "$email" "$principal" "$ku" "$eku" "$challengepassword" "$certfname" "$ca" "$capathlen" "$crldp" "$ocsp" "$nscomment" - done - -diff --git a/tests/003-csrgen/expected.out b/tests/003-csrgen/expected.out -index 8e6cac6e..04342c0f 100644 ---- a/tests/003-csrgen/expected.out -+++ b/tests/003-csrgen/expected.out -@@ -1,13 +1,5 @@ - pk12util: PKCS12 EXPORT SUCCESSFUL - Signature OK --minicert.openssl.1024.pem: OK --1024 OK. --pk12util: PKCS12 EXPORT SUCCESSFUL --Signature OK --minicert.openssl.1536.pem: OK --1536 OK. --pk12util: PKCS12 EXPORT SUCCESSFUL --Signature OK - minicert.openssl.2048.pem: OK - 2048 OK. - pk12util: PKCS12 EXPORT SUCCESSFUL -diff --git a/tests/003-csrgen/run.sh b/tests/003-csrgen/run.sh -index 7c169ed9..31466b5c 100755 ---- a/tests/003-csrgen/run.sh -+++ b/tests/003-csrgen/run.sh -@@ -5,7 +5,7 @@ cd "$tmpdir" - source "$srcdir"/functions - initnssdb "$tmpdir" - --for size in 1024 1536 2048 3072 4096 ; do -+for size in 2048 3072 4096 ; do - # Build a self-signed certificate. - run_certutil -d "$tmpdir" -S -g $size -n keyi$size \ - -s "cn=T$size" -c "cn=T$size" \ -@@ -199,7 +199,7 @@ iterate() { - - iteration=1 - --for size in 1024 ; do -+for size in 2048 ; do - iterate "$size" "$subject" "$hostname" "$email" "$principal" "$ku" "$eku" "$challengepassword" "$certfname" "$ca" "$capathlen" "$crldp" "$ocsp" "$nscomment" "$subjectder" "$ipaddress" "$freshestcrl" "$no_ocsp_check" "$profile" "$ns_certtype" - done - -diff --git a/tests/004-selfsign-rsa/expected.out b/tests/004-selfsign-rsa/expected.out -index dd5029ec..0eb84ef1 100644 ---- a/tests/004-selfsign-rsa/expected.out -+++ b/tests/004-selfsign-rsa/expected.out -@@ -1,5 +1,3 @@ --1024 OK. --1536 OK. - 2048 OK. - 3072 OK. - 4096 OK. -diff --git a/tests/004-selfsign-rsa/run.sh b/tests/004-selfsign-rsa/run.sh -index 6f9285b6..c1dd4c80 100755 ---- a/tests/004-selfsign-rsa/run.sh -+++ b/tests/004-selfsign-rsa/run.sh -@@ -33,7 +33,7 @@ function setupca() { - EOF - } - --for size in 1024 1536 2048 3072 4096 ; do -+for size in 2048 3072 4096 ; do - # Build a self-signed certificate. - run_certutil -d "$tmpdir" -S -g $size -n keyi$size \ - -s "cn=T$size" -c "cn=T$size" \ -diff --git a/tests/004-selfsign/expected.out b/tests/004-selfsign/expected.out -index dd5029ec..0eb84ef1 100644 ---- a/tests/004-selfsign/expected.out -+++ b/tests/004-selfsign/expected.out -@@ -1,5 +1,3 @@ --1024 OK. --1536 OK. - 2048 OK. - 3072 OK. - 4096 OK. -diff --git a/tests/004-selfsign/run.sh b/tests/004-selfsign/run.sh -index 7bb368ec..eb1df4ee 100755 ---- a/tests/004-selfsign/run.sh -+++ b/tests/004-selfsign/run.sh -@@ -43,7 +43,7 @@ function setupca() { - EOF - } - --for size in 1024 1536 2048 3072 4096 ; do -+for size in 2048 3072 4096 ; do - # Build a self-signed certificate. - run_certutil -d "$tmpdir" -S -g $size -n keyi$size \ - -s "cn=T$size" -c "cn=T$size" \ --- -2.16.2 - diff --git a/0007-Log-test-failures-of-bad-pin.patch b/0007-Log-test-failures-of-bad-pin.patch new file mode 100644 index 0000000..45fa77b --- /dev/null +++ b/0007-Log-test-failures-of-bad-pin.patch @@ -0,0 +1,29 @@ +From e93ecadec7c868f4227e084ffb65c70a6efd7314 Mon Sep 17 00:00:00 2001 +From: Rob Crittenden +Date: Tue, 4 Sep 2018 18:12:18 -0400 +Subject: [PATCH 6/7] Log test failures of bad pin + +Previously this would show a "don't know why" failure. +--- + tests/tools/certsave.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/tests/tools/certsave.c b/tests/tools/certsave.c +index ac0f73ec..fd86a4c1 100644 +--- a/tests/tools/certsave.c ++++ b/tests/tools/certsave.c +@@ -106,6 +106,11 @@ main(int argc, char **argv) + printf("Failed to save (%s:%s), " + "filesystem permissions error.\n", + ctype, entry->cm_cert_storage_location); ++ } else ++ if (cm_certsave_pin_error(state) == 0) { ++ printf("Failed to save (%s:%s), " ++ "pin error.\n", ++ ctype, entry->cm_cert_storage_location); + } else { + printf("Failed to save (%s:%s), " + "don't know why.\n", +-- +2.14.4 + diff --git a/0008-Use-only-PK11_ImportCert-to-import-certs-not-CERT_Im.patch b/0008-Use-only-PK11_ImportCert-to-import-certs-not-CERT_Im.patch new file mode 100644 index 0000000..dd0c3fc --- /dev/null +++ b/0008-Use-only-PK11_ImportCert-to-import-certs-not-CERT_Im.patch @@ -0,0 +1,95 @@ +From 15d406ee3afbb52832d5c61a1afb735724d109a2 Mon Sep 17 00:00:00 2001 +From: Rob Crittenden +Date: Tue, 18 Sep 2018 10:21:28 -0400 +Subject: [PATCH 7/7] Use only PK11_ImportCert to import certs, not + CERT_ImportCerts + +CERT_ImportCerts always imports a given certificate into the +certificate database, whether a token is requested or not. + +Using PK11_ImportCert will import the cert, associate the key +properly and will only add the certificate to the appropriate +token. +--- + src/certsave-n.c | 37 +++++++++++-------------------------- + 1 file changed, 11 insertions(+), 26 deletions(-) + +diff --git a/src/certsave-n.c b/src/certsave-n.c +index d0152cad..fcb43148 100644 +--- a/src/certsave-n.c ++++ b/src/certsave-n.c +@@ -100,7 +100,7 @@ cm_certsave_n_main(int fd, struct cm_store_ca *ca, struct cm_store_entry *entry, + NSSInitContext *ctx; + CERTCertDBHandle *certdb; + CERTCertList *certlist; +- CERTCertificate **returned, *oldcert, cert; ++ CERTCertificate *oldcert, *newcert, cert; + CERTCertTrust trust; + CERTSignedData csdata; + CERTCertListNode *node; +@@ -497,33 +497,18 @@ cm_certsave_n_main(int fd, struct cm_store_ca *ca, struct cm_store_entry *entry, + } + } + /* Import the certificate. */ +- returned = NULL; +- error = CERT_ImportCerts(certdb, +- certUsageUserCertImport, +- 1, &item, &returned, +- PR_TRUE, +- PR_FALSE, +- entry->cm_cert_nickname); +- ec = PORT_GetError(); +- if (error == SECSuccess) { +- /* If NSS uses SQL DB storage, CERT_ImportCerts creates +- * an incomplete internal state (the cert isn't +- * associated with the private key, and calling +- * PK11_FindKeyByAnyCert returns no result). +- * As a workaround, we import the cert again using +- * PK11_ImportCert, which magically fixes the issue. +- * See rhbz#1532188 */ ++ newcert = CERT_DecodeCertFromPackage((char *)item->data, item->len); ++ if (newcert != NULL) { + error = PK11_ImportCert(sle->slot, +- returned[0], ++ newcert, + CK_INVALID_HANDLE, +- returned[0]->nickname, ++ entry->cm_cert_nickname, + PR_FALSE); + } + if (error == SECSuccess) { +- cm_log(1, "Imported certificate \"%s\", got " ++ cm_log(1, "Imported certificate with " + "nickname \"%s\".\n", +- entry->cm_cert_nickname, +- returned[0]->nickname); ++ entry->cm_cert_nickname); + status = 0; + /* Set the trust on the new certificate, + * perhaps matching the trust on an +@@ -536,7 +521,7 @@ cm_certsave_n_main(int fd, struct cm_store_ca *ca, struct cm_store_entry *entry, + trust.objectSigningFlags = CERTDB_USER; + } + error = CERT_ChangeCertTrust(certdb, +- returned[0], ++ newcert, + &trust); + ec = PORT_GetError(); + if (error != SECSuccess) { +@@ -621,10 +606,10 @@ cm_certsave_n_main(int fd, struct cm_store_ca *ca, struct cm_store_entry *entry, + } + /* If we managed to import the certificate, mark its + * key for having its nickname removed. */ +- if ((returned != NULL) && (returned[0] != NULL)) { +- privkey = PK11_FindKeyByAnyCert(returned[0], NULL); ++ if (newcert != NULL) { ++ privkey = PK11_FindKeyByAnyCert(newcert, NULL); + privkeys = add_privkey_to_list(privkeys, privkey); +- CERT_DestroyCertArray(returned, 1); ++ CERT_DestroyCertificate(newcert); + } + /* In case we're rekeying, but failed, mark the + * candidate key for name-clearing or removal, too. */ +-- +2.14.4 + diff --git a/certmonger.spec b/certmonger.spec index 3bb5729..91fc3e2 100644 --- a/certmonger.spec +++ b/certmonger.spec @@ -26,7 +26,7 @@ Name: certmonger Version: 0.79.6 -Release: 2%{?dist} +Release: 3%{?dist} Summary: Certificate status monitor and PKI enrollment client Group: System Environment/Daemons @@ -111,7 +111,14 @@ Requires(preun): /sbin/chkconfig, /sbin/service, dbus, sed Conflicts: libtevent < 0.9.13 %endif -Patch6: 0006-NSS-crypto-policy-sets-minimum-RSA-and-DSA-key-size-.patch +Patch1: 0001-NSS-crypto-policy-sets-minimum-RSA-and-DSA-key-size-.patch +Patch2: 0002-Use-the-correct-slot-when-saving-certificates-in-NSS.patch +Patch3: 0003-Include-the-token-name-when-a-PIN-is-provided-but-is.patch +Patch4: 0004-Add-utility-function-to-get-the-internal-token-name.patch +Patch5: 0005-Only-de-duplicate-certificates-within-the-same-token.patch +Patch6: 0006-Ensure-that-an-OpenSSL-random-seed-file-exists-when-.patch +Patch7: 0007-Log-test-failures-of-bad-pin.patch +Patch8: 0008-Use-only-PK11_ImportCert-to-import-certs-not-CERT_Im.patch %description Certmonger is a service which is primarily concerned with getting your @@ -119,7 +126,14 @@ system enrolled with a certificate authority (CA) and keeping it enrolled. %prep %setup -q +%patch1 -p1 +%patch2 -p1 +%patch3 -p1 +%patch4 -p1 +%patch5 -p1 %patch6 -p1 +%patch7 -p1 +%patch8 -p1 %if 0%{?rhel} > 0 # Enabled by default for RHEL for bug #765600, still disabled by default for @@ -247,6 +261,11 @@ exit 0 %endif %changelog +* Mon Oct 1 2018 Rob Crittenden - 0.79.6-3 +- Improve NSS token handling. The updated NSS crypto-policy enables all + tokens which broke requesting certificates due to the way that tokens + were managed. + * Thu Jul 12 2018 Fedora Release Engineering - 0.79.6-2 - Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild