aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--RELEASE-NOTES3
-rw-r--r--lib/nss.c128
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
+
diff --git a/lib/nss.c b/lib/nss.c
index 885a120bb..d60b18479 100644
--- a/lib/nss.c
+++ b/lib/nss.c
@@ -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;
}