cURL / Mailing Lists / curl-library / Single Mail

curl-library

[PATCH] nss: use human-readable error messages provided by NSS

From: Kamil Dudka <kdudka_at_redhat.com>
Date: Fri, 25 May 2012 14:27:43 +0200

Bug: http://lists.baseurl.org/pipermail/yum-devel/2012-January/009002.html

---
 RELEASE-NOTES |    3 +-
 lib/nss.c     |  128 +++++++++++++++++++++++++-------------------------------
 2 files changed, 59 insertions(+), 72 deletions(-)
diff --git a/RELEASE-NOTES b/RELEASE-NOTES
index c41ebb9..3352e8f 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 885a120..d60b184 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;
   }
-- 
1.7.1
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette:  http://curl.haxx.se/mail/etiquette.html
Received on 2012-05-25