nss: use human-readable error messages provided by NSS

Bug: http://lists.baseurl.org/pipermail/yum-devel/2012-January/009002.html
This commit is contained in:
Kamil Dudka 2012-05-21 16:19:12 +02:00
parent a03100c357
commit 72f4b534c4
2 changed files with 59 additions and 72 deletions

View File

@ -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:

128
lib/nss.c
View 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;
}