diff options
-rw-r--r-- | RELEASE-NOTES | 3 | ||||
-rw-r--r-- | lib/nss.c | 128 |
2 files changed, 59 insertions, 72 deletions
diff --git a/RELEASE-NOTES b/RELEASE-NOTES index c41ebb9b0..3352e8f8b 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -9,6 +9,7 @@ Curl and libcurl 7.26.1 This release includes the following changes: + o nss: use human-readable error messages provided by NSS o This release includes the following bugfixes: @@ -28,4 +29,4 @@ advice from friends like these: References to bug reports and discussions on issues: -
\ No newline at end of file + @@ -186,6 +186,11 @@ static const char* nss_error_to_name(PRErrorCode code) return "unknown error"; } +static void nss_print_error_message(struct SessionHandle *data, PRUint32 err) +{ + failf(data, "%s", PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT)); +} + static SECStatus set_ciphers(struct SessionHandle *data, PRFileDesc * model, char *cipher_list) { @@ -612,61 +617,6 @@ static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig, return SSL_AuthCertificate(CERT_GetDefaultCertDB(), fd, checksig, isServer); } -static SECStatus BadCertHandler(void *arg, PRFileDesc *sock) -{ - SECStatus result = SECFailure; - struct connectdata *conn = (struct connectdata *)arg; - PRErrorCode err = PR_GetError(); - CERTCertificate *cert = NULL; - char *subject, *subject_cn, *issuer; - - conn->data->set.ssl.certverifyresult=err; - cert = SSL_PeerCertificate(sock); - subject = CERT_NameToAscii(&cert->subject); - subject_cn = CERT_GetCommonName(&cert->subject); - issuer = CERT_NameToAscii(&cert->issuer); - CERT_DestroyCertificate(cert); - - switch(err) { - case SEC_ERROR_CA_CERT_INVALID: - infof(conn->data, "Issuer certificate is invalid: '%s'\n", issuer); - break; - case SEC_ERROR_UNTRUSTED_ISSUER: - infof(conn->data, "Certificate is signed by an untrusted issuer: '%s'\n", - issuer); - break; - case SSL_ERROR_BAD_CERT_DOMAIN: - if(conn->data->set.ssl.verifyhost) { - failf(conn->data, "SSL: certificate subject name '%s' does not match " - "target host name '%s'", subject_cn, conn->host.dispname); - } - else { - result = SECSuccess; - infof(conn->data, "warning: SSL: certificate subject name '%s' does not " - "match target host name '%s'\n", subject_cn, conn->host.dispname); - } - break; - case SEC_ERROR_EXPIRED_CERTIFICATE: - infof(conn->data, "Remote Certificate has expired.\n"); - break; - case SEC_ERROR_UNKNOWN_ISSUER: - infof(conn->data, "Peer's certificate issuer is not recognized: '%s'\n", - issuer); - break; - default: - infof(conn->data, "Bad certificate received. Subject = '%s', " - "Issuer = '%s'\n", subject, issuer); - break; - } - if(result == SECSuccess) - infof(conn->data, "SSL certificate verify ok.\n"); - PR_Free(subject); - PR_Free(subject_cn); - PR_Free(issuer); - - return result; -} - /** * Inform the application that the handshake is complete. */ @@ -728,6 +678,31 @@ static void display_conn_info(struct connectdata *conn, PRFileDesc *sock) return; } +static SECStatus BadCertHandler(void *arg, PRFileDesc *sock) +{ + struct connectdata *conn = (struct connectdata *)arg; + struct SessionHandle *data = conn->data; + PRErrorCode err = PR_GetError(); + CERTCertificate *cert; + + /* remember the cert verification result */ + data->set.ssl.certverifyresult = err; + + if(err == SSL_ERROR_BAD_CERT_DOMAIN && !data->set.ssl.verifyhost) + /* we are asked not to verify the host name */ + return SECSuccess; + + /* print only info about the cert, the error is printed off the callback */ + cert = SSL_PeerCertificate(sock); + if(cert) { + infof(data, "Server certificate:\n"); + display_cert_info(data, cert); + CERT_DestroyCertificate(cert); + } + + return SECFailure; +} + /** * * Check that the Peer certificate's issuer certificate matches the one found @@ -1108,20 +1083,17 @@ int Curl_nss_close_all(struct SessionHandle *data) return 0; } -/* handle client certificate related errors if any; return false otherwise */ -static bool handle_cc_error(PRInt32 err, struct SessionHandle *data) +/* return true if the given error code is related to a client certificate */ +static bool is_cc_error(PRInt32 err) { switch(err) { case SSL_ERROR_BAD_CERT_ALERT: - failf(data, "SSL error: SSL_ERROR_BAD_CERT_ALERT"); return true; case SSL_ERROR_REVOKED_CERT_ALERT: - failf(data, "SSL error: SSL_ERROR_REVOKED_CERT_ALERT"); return true; case SSL_ERROR_EXPIRED_CERT_ALERT: - failf(data, "SSL error: SSL_ERROR_EXPIRED_CERT_ALERT"); return true; default: @@ -1460,10 +1432,14 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) data->state.ssl_connect_retry = FALSE; err = PR_GetError(); - if(handle_cc_error(err, data)) + if(is_cc_error(err)) curlerr = CURLE_SSL_CERTPROBLEM; - else - infof(data, "NSS error %d (%s)\n", err, nss_error_to_name(err)); + + /* print the error number and error string */ + infof(data, "NSS error %d (%s)\n", err, nss_error_to_name(err)); + + /* print a human-readable message describing the error if available */ + nss_print_error_message(data, err); if(model) PR_Close(model); @@ -1496,12 +1472,17 @@ static ssize_t nss_send(struct connectdata *conn, /* connection data */ PRInt32 err = PR_GetError(); if(err == PR_WOULD_BLOCK_ERROR) *curlcode = CURLE_AGAIN; - else if(handle_cc_error(err, conn->data)) - *curlcode = CURLE_SSL_CERTPROBLEM; else { + /* print the error number and error string */ const char *err_name = nss_error_to_name(err); - failf(conn->data, "SSL write: error %d (%s)", err, err_name); - *curlcode = CURLE_SEND_ERROR; + infof(conn->data, "SSL write: error %d (%s)\n", err, err_name); + + /* print a human-readable message describing the error if available */ + nss_print_error_message(conn->data, err); + + *curlcode = (is_cc_error(err)) + ? CURLE_SSL_CERTPROBLEM + : CURLE_SEND_ERROR; } return -1; } @@ -1523,12 +1504,17 @@ static ssize_t nss_recv(struct connectdata * conn, /* connection data */ if(err == PR_WOULD_BLOCK_ERROR) *curlcode = CURLE_AGAIN; - else if(handle_cc_error(err, conn->data)) - *curlcode = CURLE_SSL_CERTPROBLEM; else { + /* print the error number and error string */ const char *err_name = nss_error_to_name(err); - failf(conn->data, "SSL read: errno %d (%s)", err, err_name); - *curlcode = CURLE_RECV_ERROR; + infof(conn->data, "SSL read: errno %d (%s)\n", err, err_name); + + /* print a human-readable message describing the error if available */ + nss_print_error_message(conn->data, err); + + *curlcode = (is_cc_error(err)) + ? CURLE_SSL_CERTPROBLEM + : CURLE_RECV_ERROR; } return -1; } |