Loading lib/nss.c +58 −93 Original line number Diff line number Diff line Loading @@ -319,6 +319,9 @@ static CURLcode nss_create_object(struct ssl_connect_data *ssl, CK_BBOOL ckfalse = CK_FALSE; CK_ATTRIBUTE attrs[/* max count of attributes */ 4]; int attr_cnt = 0; CURLcode err = (cacert) ? CURLE_SSL_CACERT_BADFILE : CURLE_SSL_CERTPROBLEM; const int slot_id = (cacert) ? 0 : 1; char *slot_name = aprintf("PEM Token #%d", slot_id); Loading @@ -328,7 +331,7 @@ static CURLcode nss_create_object(struct ssl_connect_data *ssl, slot = PK11_FindSlotByName(slot_name); free(slot_name); if(!slot) return CURLE_SSL_CERTPROBLEM; return err; PK11_SETATTRS(attrs, attr_cnt, CKA_CLASS, &obj_class, sizeof(obj_class)); PK11_SETATTRS(attrs, attr_cnt, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL)); Loading @@ -343,7 +346,7 @@ static CURLcode nss_create_object(struct ssl_connect_data *ssl, obj = PK11_CreateGenericObject(slot, attrs, attr_cnt, PR_FALSE); PK11_FreeSlot(slot); if(!obj) return CURLE_SSL_CERTPROBLEM; return err; if(!Curl_llist_insert_next(ssl->obj_list, ssl->obj_list->tail, obj)) { PK11_DestroyGenericObject(obj); Loading @@ -368,77 +371,21 @@ static void nss_destroy_object(void *user, void *ptr) } #endif static int nss_load_cert(struct ssl_connect_data *ssl, static CURLcode nss_load_cert(struct ssl_connect_data *ssl, const char *filename, PRBool cacert) { #ifdef HAVE_PK11_CREATEGENERICOBJECT /* All CA and trust objects go into slot 0. Other slots are used * for storing certificates. */ const int slot_id = (cacert) ? 0 : 1; #endif CERTCertificate *cert; char *nickname = NULL; char *n = NULL; /* If there is no slash in the filename it is assumed to be a regular * NSS nickname. */ if(is_file(filename)) { n = strrchr(filename, '/'); if(n) n++; if(!mod) return 1; } else { /* A nickname from the NSS internal database */ if(cacert) return 0; /* You can't specify an NSS CA nickname this way */ nickname = strdup(filename); if(!nickname) return 0; goto done; } CURLcode err = (cacert) ? CURLE_SSL_CACERT_BADFILE : CURLE_SSL_CERTPROBLEM; #ifdef HAVE_PK11_CREATEGENERICOBJECT nickname = aprintf("PEM Token #%d:%s", slot_id, n); if(!nickname) return 0; if(CURLE_OK != nss_create_object(ssl, CKO_CERTIFICATE, filename, cacert)) { free(nickname); return 0; } #else /* We don't have PK11_CreateGenericObject but a file-based cert was passed * in. We need to fail. */ return 0; /* libnsspem.so leaks memory if the requested file does not exist. For more * details, go to <https://bugzilla.redhat.com/734760>. */ if(is_file(filename)) return nss_create_object(ssl, CKO_CERTIFICATE, filename, cacert); #endif done: /* Double-check that the certificate or nickname requested exists in * either the token or the NSS certificate database. */ if(!cacert) { cert = PK11_FindCertFromNickname((char *)nickname, NULL); /* An invalid nickname was passed in */ if(cert == NULL) { free(nickname); PR_SetError(SEC_ERROR_UNKNOWN_CERT, 0); return 0; } CERT_DestroyCertificate(cert); } free(nickname); return 1; return err; } /* add given CRL to cache if it is not already there */ Loading Loading @@ -527,23 +474,23 @@ fail: return SECFailure; } static int nss_load_key(struct connectdata *conn, int sockindex, static CURLcode nss_load_key(struct connectdata *conn, int sockindex, char *key_file) { #ifdef HAVE_PK11_CREATEGENERICOBJECT PK11SlotInfo *slot; SECStatus status; struct ssl_connect_data *ssl = conn->ssl; (void)sockindex; /* unused */ if(CURLE_OK != nss_create_object(ssl, CKO_PRIVATE_KEY, key_file, FALSE)) { CURLcode rv = nss_create_object(ssl, CKO_PRIVATE_KEY, key_file, FALSE); if(CURLE_OK != rv) { PR_SetError(SEC_ERROR_BAD_KEY, 0); return 0; return rv; } slot = PK11_FindSlotByName("PEM Token #1"); if(!slot) return 0; return CURLE_SSL_CERTPROBLEM; /* This will force the token to be seen as re-inserted */ SECMOD_WaitForAnyTokenEvent(mod, 0, 0); Loading @@ -552,16 +499,18 @@ static int nss_load_key(struct connectdata *conn, int sockindex, status = PK11_Authenticate(slot, PR_TRUE, conn->data->set.str[STRING_KEY_PASSWD]); PK11_FreeSlot(slot); return (SECSuccess == status) ? 1 : 0; return (SECSuccess == status) ? CURLE_OK : CURLE_SSL_CERTPROBLEM; #else /* If we don't have PK11_CreateGenericObject then we can't load a file-based * key. */ (void)conn; /* unused */ (void)key_file; /* unused */ (void)sockindex; /* unused */ return 0; return CURLE_SSL_CERTPROBLEM; #endif (void)sockindex; /* unused */ } static int display_error(struct connectdata *conn, PRInt32 err, Loading @@ -580,34 +529,37 @@ static int display_error(struct connectdata *conn, PRInt32 err, return 0; /* The caller will print a generic error */ } static int cert_stuff(struct connectdata *conn, int sockindex, char *cert_file, char *key_file) static CURLcode cert_stuff(struct connectdata *conn, int sockindex, char *cert_file, char *key_file) { struct SessionHandle *data = conn->data; int rv = 0; CURLcode rv; if(cert_file) { rv = nss_load_cert(&conn->ssl[sockindex], cert_file, PR_FALSE); if(!rv) { if(CURLE_OK != rv) { if(!display_error(conn, PR_GetError(), cert_file)) failf(data, "Unable to load client cert %d.", PR_GetError()); return 0; return rv; } } if(key_file || (is_file(cert_file))) { if(key_file) rv = nss_load_key(conn, sockindex, key_file); else /* In case the cert file also has the key */ rv = nss_load_key(conn, sockindex, cert_file); if(!rv) { if(CURLE_OK != rv) { if(!display_error(conn, PR_GetError(), key_file)) failf(data, "Unable to load client key %d.", PR_GetError()); return 0; return rv; } } return 1; return CURLE_OK; } static char * nss_get_password(PK11SlotInfo * slot, PRBool retry, void *arg) Loading Loading @@ -774,7 +726,6 @@ static SECStatus check_issuer_cert(PRFileDesc *sock, cert_issuer = CERT_FindCertIssuer(cert,PR_Now(),certUsageObjectSigner); proto_win = SSL_RevealPinArg(sock); issuer = NULL; issuer = PK11_FindCertFromNickname(issuer_nickname, proto_win); if((!cert_issuer) || (!issuer)) Loading Loading @@ -1132,8 +1083,11 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn, const char *cafile = data->set.ssl.CAfile; const char *capath = data->set.ssl.CApath; if(cafile && !nss_load_cert(&conn->ssl[sockindex], cafile, PR_TRUE)) return CURLE_SSL_CACERT_BADFILE; if(cafile) { CURLcode rv = nss_load_cert(&conn->ssl[sockindex], cafile, PR_TRUE); if(CURLE_OK != rv) return rv; } if(capath) { struct_stat st; Loading @@ -1153,7 +1107,7 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn, return CURLE_OUT_OF_MEMORY; } if(!nss_load_cert(&conn->ssl[sockindex], fullpath, PR_TRUE)) if(CURLE_OK != nss_load_cert(&conn->ssl[sockindex], fullpath, PR_TRUE)) /* This is purposefully tolerant of errors so non-PEM files can * be in the same directory */ infof(data, "failed to load '%s' from CURLOPT_CAPATH\n", fullpath); Loading Loading @@ -1349,10 +1303,21 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) if(data->set.str[STRING_CERT]) { char *nickname = dup_nickname(data, STRING_CERT); if(!nickname && !cert_stuff(conn, sockindex, data->set.str[STRING_CERT], data->set.str[STRING_KEY])) if(nickname) { /* we are not going to use libnsspem.so to read the client cert */ #ifdef HAVE_PK11_CREATEGENERICOBJECT connssl->obj_clicert = NULL; #endif } else { CURLcode rv = cert_stuff(conn, sockindex, data->set.str[STRING_CERT], data->set.str[STRING_KEY]); if(CURLE_OK != rv) { /* failf() is already done in cert_stuff() */ return CURLE_SSL_CERTPROBLEM; curlerr = rv; goto error; } } /* store the nickname for SelectClientCert() called during handshake */ connssl->client_nickname = nickname; Loading Loading
lib/nss.c +58 −93 Original line number Diff line number Diff line Loading @@ -319,6 +319,9 @@ static CURLcode nss_create_object(struct ssl_connect_data *ssl, CK_BBOOL ckfalse = CK_FALSE; CK_ATTRIBUTE attrs[/* max count of attributes */ 4]; int attr_cnt = 0; CURLcode err = (cacert) ? CURLE_SSL_CACERT_BADFILE : CURLE_SSL_CERTPROBLEM; const int slot_id = (cacert) ? 0 : 1; char *slot_name = aprintf("PEM Token #%d", slot_id); Loading @@ -328,7 +331,7 @@ static CURLcode nss_create_object(struct ssl_connect_data *ssl, slot = PK11_FindSlotByName(slot_name); free(slot_name); if(!slot) return CURLE_SSL_CERTPROBLEM; return err; PK11_SETATTRS(attrs, attr_cnt, CKA_CLASS, &obj_class, sizeof(obj_class)); PK11_SETATTRS(attrs, attr_cnt, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL)); Loading @@ -343,7 +346,7 @@ static CURLcode nss_create_object(struct ssl_connect_data *ssl, obj = PK11_CreateGenericObject(slot, attrs, attr_cnt, PR_FALSE); PK11_FreeSlot(slot); if(!obj) return CURLE_SSL_CERTPROBLEM; return err; if(!Curl_llist_insert_next(ssl->obj_list, ssl->obj_list->tail, obj)) { PK11_DestroyGenericObject(obj); Loading @@ -368,77 +371,21 @@ static void nss_destroy_object(void *user, void *ptr) } #endif static int nss_load_cert(struct ssl_connect_data *ssl, static CURLcode nss_load_cert(struct ssl_connect_data *ssl, const char *filename, PRBool cacert) { #ifdef HAVE_PK11_CREATEGENERICOBJECT /* All CA and trust objects go into slot 0. Other slots are used * for storing certificates. */ const int slot_id = (cacert) ? 0 : 1; #endif CERTCertificate *cert; char *nickname = NULL; char *n = NULL; /* If there is no slash in the filename it is assumed to be a regular * NSS nickname. */ if(is_file(filename)) { n = strrchr(filename, '/'); if(n) n++; if(!mod) return 1; } else { /* A nickname from the NSS internal database */ if(cacert) return 0; /* You can't specify an NSS CA nickname this way */ nickname = strdup(filename); if(!nickname) return 0; goto done; } CURLcode err = (cacert) ? CURLE_SSL_CACERT_BADFILE : CURLE_SSL_CERTPROBLEM; #ifdef HAVE_PK11_CREATEGENERICOBJECT nickname = aprintf("PEM Token #%d:%s", slot_id, n); if(!nickname) return 0; if(CURLE_OK != nss_create_object(ssl, CKO_CERTIFICATE, filename, cacert)) { free(nickname); return 0; } #else /* We don't have PK11_CreateGenericObject but a file-based cert was passed * in. We need to fail. */ return 0; /* libnsspem.so leaks memory if the requested file does not exist. For more * details, go to <https://bugzilla.redhat.com/734760>. */ if(is_file(filename)) return nss_create_object(ssl, CKO_CERTIFICATE, filename, cacert); #endif done: /* Double-check that the certificate or nickname requested exists in * either the token or the NSS certificate database. */ if(!cacert) { cert = PK11_FindCertFromNickname((char *)nickname, NULL); /* An invalid nickname was passed in */ if(cert == NULL) { free(nickname); PR_SetError(SEC_ERROR_UNKNOWN_CERT, 0); return 0; } CERT_DestroyCertificate(cert); } free(nickname); return 1; return err; } /* add given CRL to cache if it is not already there */ Loading Loading @@ -527,23 +474,23 @@ fail: return SECFailure; } static int nss_load_key(struct connectdata *conn, int sockindex, static CURLcode nss_load_key(struct connectdata *conn, int sockindex, char *key_file) { #ifdef HAVE_PK11_CREATEGENERICOBJECT PK11SlotInfo *slot; SECStatus status; struct ssl_connect_data *ssl = conn->ssl; (void)sockindex; /* unused */ if(CURLE_OK != nss_create_object(ssl, CKO_PRIVATE_KEY, key_file, FALSE)) { CURLcode rv = nss_create_object(ssl, CKO_PRIVATE_KEY, key_file, FALSE); if(CURLE_OK != rv) { PR_SetError(SEC_ERROR_BAD_KEY, 0); return 0; return rv; } slot = PK11_FindSlotByName("PEM Token #1"); if(!slot) return 0; return CURLE_SSL_CERTPROBLEM; /* This will force the token to be seen as re-inserted */ SECMOD_WaitForAnyTokenEvent(mod, 0, 0); Loading @@ -552,16 +499,18 @@ static int nss_load_key(struct connectdata *conn, int sockindex, status = PK11_Authenticate(slot, PR_TRUE, conn->data->set.str[STRING_KEY_PASSWD]); PK11_FreeSlot(slot); return (SECSuccess == status) ? 1 : 0; return (SECSuccess == status) ? CURLE_OK : CURLE_SSL_CERTPROBLEM; #else /* If we don't have PK11_CreateGenericObject then we can't load a file-based * key. */ (void)conn; /* unused */ (void)key_file; /* unused */ (void)sockindex; /* unused */ return 0; return CURLE_SSL_CERTPROBLEM; #endif (void)sockindex; /* unused */ } static int display_error(struct connectdata *conn, PRInt32 err, Loading @@ -580,34 +529,37 @@ static int display_error(struct connectdata *conn, PRInt32 err, return 0; /* The caller will print a generic error */ } static int cert_stuff(struct connectdata *conn, int sockindex, char *cert_file, char *key_file) static CURLcode cert_stuff(struct connectdata *conn, int sockindex, char *cert_file, char *key_file) { struct SessionHandle *data = conn->data; int rv = 0; CURLcode rv; if(cert_file) { rv = nss_load_cert(&conn->ssl[sockindex], cert_file, PR_FALSE); if(!rv) { if(CURLE_OK != rv) { if(!display_error(conn, PR_GetError(), cert_file)) failf(data, "Unable to load client cert %d.", PR_GetError()); return 0; return rv; } } if(key_file || (is_file(cert_file))) { if(key_file) rv = nss_load_key(conn, sockindex, key_file); else /* In case the cert file also has the key */ rv = nss_load_key(conn, sockindex, cert_file); if(!rv) { if(CURLE_OK != rv) { if(!display_error(conn, PR_GetError(), key_file)) failf(data, "Unable to load client key %d.", PR_GetError()); return 0; return rv; } } return 1; return CURLE_OK; } static char * nss_get_password(PK11SlotInfo * slot, PRBool retry, void *arg) Loading Loading @@ -774,7 +726,6 @@ static SECStatus check_issuer_cert(PRFileDesc *sock, cert_issuer = CERT_FindCertIssuer(cert,PR_Now(),certUsageObjectSigner); proto_win = SSL_RevealPinArg(sock); issuer = NULL; issuer = PK11_FindCertFromNickname(issuer_nickname, proto_win); if((!cert_issuer) || (!issuer)) Loading Loading @@ -1132,8 +1083,11 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn, const char *cafile = data->set.ssl.CAfile; const char *capath = data->set.ssl.CApath; if(cafile && !nss_load_cert(&conn->ssl[sockindex], cafile, PR_TRUE)) return CURLE_SSL_CACERT_BADFILE; if(cafile) { CURLcode rv = nss_load_cert(&conn->ssl[sockindex], cafile, PR_TRUE); if(CURLE_OK != rv) return rv; } if(capath) { struct_stat st; Loading @@ -1153,7 +1107,7 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn, return CURLE_OUT_OF_MEMORY; } if(!nss_load_cert(&conn->ssl[sockindex], fullpath, PR_TRUE)) if(CURLE_OK != nss_load_cert(&conn->ssl[sockindex], fullpath, PR_TRUE)) /* This is purposefully tolerant of errors so non-PEM files can * be in the same directory */ infof(data, "failed to load '%s' from CURLOPT_CAPATH\n", fullpath); Loading Loading @@ -1349,10 +1303,21 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) if(data->set.str[STRING_CERT]) { char *nickname = dup_nickname(data, STRING_CERT); if(!nickname && !cert_stuff(conn, sockindex, data->set.str[STRING_CERT], data->set.str[STRING_KEY])) if(nickname) { /* we are not going to use libnsspem.so to read the client cert */ #ifdef HAVE_PK11_CREATEGENERICOBJECT connssl->obj_clicert = NULL; #endif } else { CURLcode rv = cert_stuff(conn, sockindex, data->set.str[STRING_CERT], data->set.str[STRING_KEY]); if(CURLE_OK != rv) { /* failf() is already done in cert_stuff() */ return CURLE_SSL_CERTPROBLEM; curlerr = rv; goto error; } } /* store the nickname for SelectClientCert() called during handshake */ connssl->client_nickname = nickname; Loading