nss: load libnssckbi.so if no other trust is specified

The module contains a more comprehensive set of trust information than
supported by nss-pem, because libnssckbi.so also includes information
about distrusted certificates.

Reviewed-by: Kai Engert
Closes #1414
This commit is contained in:
Kamil Dudka 2017-04-10 17:40:30 +02:00
Родитель fab3d1ec65
Коммит e3e8d0204b
2 изменённых файлов: 48 добавлений и 8 удалений

Просмотреть файл

@ -40,6 +40,11 @@ is assumed to be stored, as established at build time.
If curl is built against the NSS SSL library, the NSS PEM PKCS#11 module
(libnsspem.so) needs to be available for this option to work properly.
Starting with curl-7.55.0, if both \fICURLOPT_CAINFO(3)\fP and
\fICURLOPT_CAPATH(3)\fP are unset, NSS-linked libcurl tries to load
libnssckbi.so, which contains a more comprehensive set of trust information
than supported by nss-pem, because libnssckbi.so also includes information
about distrusted certificates.
(iOS and macOS only) If curl is built against Secure Transport, then this
option is supported for backward compatibility with other SSL engines, but it

Просмотреть файл

@ -81,6 +81,7 @@
static PRLock *nss_initlock = NULL;
static PRLock *nss_crllock = NULL;
static PRLock *nss_findslot_lock = NULL;
static PRLock *nss_trustload_lock = NULL;
static struct curl_llist nss_crl_list;
static NSSInitContext *nss_context = NULL;
static volatile int initialized = 0;
@ -209,6 +210,9 @@ static const cipher_s cipherlist[] = {
static const char *pem_library = "libnsspem.so";
static SECMODModule *pem_module = NULL;
static const char *trust_library = "libnssckbi.so";
static SECMODModule *trust_module = NULL;
/* NSPR I/O layer we use to detect blocking direction during SSL handshake */
static PRDescIdentity nspr_io_identity = PR_INVALID_IO_LAYER;
static PRIOMethods nspr_io_methods;
@ -1355,6 +1359,7 @@ int Curl_nss_init(void)
nss_initlock = PR_NewLock();
nss_crllock = PR_NewLock();
nss_findslot_lock = PR_NewLock();
nss_trustload_lock = PR_NewLock();
}
/* We will actually initialize NSS later */
@ -1394,6 +1399,7 @@ void Curl_nss_cleanup(void)
SSL_ClearSessionCache();
nss_unload_module(&pem_module);
nss_unload_module(&trust_module);
NSS_ShutdownContext(nss_context);
nss_context = NULL;
}
@ -1406,6 +1412,7 @@ void Curl_nss_cleanup(void)
PR_DestroyLock(nss_initlock);
PR_DestroyLock(nss_crllock);
PR_DestroyLock(nss_findslot_lock);
PR_DestroyLock(nss_trustload_lock);
nss_initlock = NULL;
initialized = 0;
@ -1527,12 +1534,44 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn,
struct Curl_easy *data = conn->data;
const char *cafile = SSL_CONN_CONFIG(CAfile);
const char *capath = SSL_CONN_CONFIG(CApath);
bool use_trust_module;
CURLcode result = CURLE_OK;
if(cafile) {
CURLcode result = nss_load_cert(&conn->ssl[sockindex], cafile, PR_TRUE);
if(result)
return result;
/* treat empty string as unset */
if(cafile && !cafile[0])
cafile = NULL;
if(capath && !capath[0])
capath = NULL;
infof(data, " CAfile: %s\n CApath: %s\n",
cafile ? cafile : "none",
capath ? capath : "none");
/* load libnssckbi.so if no other trust roots were specified */
use_trust_module = !cafile && !capath;
PR_Lock(nss_trustload_lock);
if(use_trust_module && !trust_module) {
/* libnssckbi.so needed but not yet loaded --> load it! */
result = nss_load_module(&trust_module, trust_library, "trust");
infof(data, "%s %s\n", (result) ? "failed to load" : "loaded",
trust_library);
if(result == CURLE_FAILED_INIT)
/* make the error non-fatal if we are not going to verify peer */
result = CURLE_SSL_CACERT_BADFILE;
}
else if(!use_trust_module && trust_module) {
/* libnssckbi.so not needed but already loaded --> unload it! */
infof(data, "unloading %s\n", trust_library);
nss_unload_module(&trust_module);
}
PR_Unlock(nss_trustload_lock);
if(cafile)
result = nss_load_cert(&conn->ssl[sockindex], cafile, PR_TRUE);
if(result)
return result;
if(capath) {
struct_stat st;
@ -1566,10 +1605,6 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn,
infof(data, "warning: CURLOPT_CAPATH not a directory (%s)\n", capath);
}
infof(data, " CAfile: %s\n CApath: %s\n",
cafile ? cafile : "none",
capath ? capath : "none");
return CURLE_OK;
}