223 lines
5.8 KiB
Diff
223 lines
5.8 KiB
Diff
CHANGES | 4 ++
|
|
lib/nss.c | 151 +++++++++++++++++++++++++++++++++---------------------------
|
|
2 files changed, 87 insertions(+), 68 deletions(-)
|
|
|
|
diff --git a/CHANGES b/CHANGES
|
|
index 7433364..7928690 100644
|
|
--- a/CHANGES
|
|
+++ b/CHANGES
|
|
@@ -6,6 +6,10 @@
|
|
|
|
Changelog
|
|
|
|
+Kamil Dudka (11 May 2010)
|
|
+- CRL support in libcurl-NSS has been completely broken. Now it works. Original
|
|
+ bug report: https://bugzilla.redhat.com/581926
|
|
+
|
|
Kamil Dudka (24 Apr 2010)
|
|
- Fixed test536 in order to not fail with threaded DNS resolver and tweaked
|
|
comments in certain examples using curl_multi_fdset().
|
|
diff --git a/lib/nss.c b/lib/nss.c
|
|
index addb94b..5e94d31 100644
|
|
--- a/lib/nss.c
|
|
+++ b/lib/nss.c
|
|
@@ -63,6 +63,7 @@
|
|
#include <secport.h>
|
|
#include <certdb.h>
|
|
#include <base64.h>
|
|
+#include <cert.h>
|
|
|
|
#include "curl_memory.h"
|
|
#include "rawstr.h"
|
|
@@ -79,6 +80,7 @@
|
|
PRFileDesc *PR_ImportTCPSocket(PRInt32 osfd);
|
|
|
|
PRLock * nss_initlock = NULL;
|
|
+PRLock * nss_crllock = NULL;
|
|
|
|
volatile int initialized = 0;
|
|
|
|
@@ -411,78 +413,90 @@ static int nss_load_cert(struct ssl_connect_data *ssl,
|
|
return 1;
|
|
}
|
|
|
|
-static int nss_load_crl(const char* crlfilename, PRBool ascii)
|
|
+/* add given CRL to cache if it is not already there */
|
|
+static SECStatus nss_cache_crl(SECItem *crlDER)
|
|
{
|
|
- PRFileDesc *infile;
|
|
- PRStatus prstat;
|
|
- PRFileInfo info;
|
|
- PRInt32 nb;
|
|
- int rv;
|
|
- SECItem crlDER;
|
|
- CERTSignedCrl *crl=NULL;
|
|
- PK11SlotInfo *slot=NULL;
|
|
-
|
|
- infile = PR_Open(crlfilename,PR_RDONLY,0);
|
|
- if (!infile) {
|
|
- return 0;
|
|
+ CERTCertDBHandle *db = CERT_GetDefaultCertDB();
|
|
+ CERTSignedCrl *crl = SEC_FindCrlByDERCert(db, crlDER, 0);
|
|
+ if(crl) {
|
|
+ /* CRL already cached */
|
|
+ SEC_DestroyCrl(crl);
|
|
+ SECITEM_FreeItem(crlDER, PR_FALSE);
|
|
+ return SECSuccess;
|
|
}
|
|
- crlDER.data = NULL;
|
|
- prstat = PR_GetOpenFileInfo(infile,&info);
|
|
- if (prstat!=PR_SUCCESS)
|
|
- return 0;
|
|
- if (ascii) {
|
|
- SECItem filedata;
|
|
- char *asc,*body;
|
|
- filedata.data = NULL;
|
|
- if (!SECITEM_AllocItem(NULL,&filedata,info.size))
|
|
- return 0;
|
|
- nb = PR_Read(infile,filedata.data,info.size);
|
|
- if (nb!=info.size)
|
|
- return 0;
|
|
- asc = (char*)filedata.data;
|
|
- if (!asc)
|
|
- return 0;
|
|
|
|
- body=strstr(asc,"-----BEGIN");
|
|
- if (body != NULL) {
|
|
- char *trailer=NULL;
|
|
- asc = body;
|
|
- body = PORT_Strchr(asc,'\n');
|
|
- if (!body)
|
|
- body = PORT_Strchr(asc,'\r');
|
|
- if (body)
|
|
- trailer = strstr(++body,"-----END");
|
|
- if (trailer!=NULL)
|
|
- *trailer='\0';
|
|
- else
|
|
- return 0;
|
|
- }
|
|
- else {
|
|
- body = asc;
|
|
- }
|
|
- rv = ATOB_ConvertAsciiToItem(&crlDER,body);
|
|
- PORT_Free(filedata.data);
|
|
- if (rv)
|
|
- return 0;
|
|
+ /* acquire lock before call of CERT_CacheCRL() */
|
|
+ PR_Lock(nss_crllock);
|
|
+ if(SECSuccess != CERT_CacheCRL(db, crlDER)) {
|
|
+ /* unable to cache CRL */
|
|
+ PR_Unlock(nss_crllock);
|
|
+ SECITEM_FreeItem(crlDER, PR_FALSE);
|
|
+ return SECFailure;
|
|
}
|
|
- else {
|
|
- if (!SECITEM_AllocItem(NULL,&crlDER,info.size))
|
|
- return 0;
|
|
- nb = PR_Read(infile,crlDER.data,info.size);
|
|
- if (nb!=info.size)
|
|
- return 0;
|
|
+
|
|
+ /* we need to clear session cache, so that the CRL could take effect */
|
|
+ SSL_ClearSessionCache();
|
|
+ PR_Unlock(nss_crllock);
|
|
+ return SECSuccess;
|
|
+}
|
|
+
|
|
+static SECStatus nss_load_crl(const char* crlfilename)
|
|
+{
|
|
+ PRFileDesc *infile;
|
|
+ PRFileInfo info;
|
|
+ SECItem filedata = { 0, NULL, 0 };
|
|
+ SECItem crlDER = { 0, NULL, 0 };
|
|
+ char *body;
|
|
+
|
|
+ infile = PR_Open(crlfilename, PR_RDONLY, 0);
|
|
+ if(!infile)
|
|
+ return SECFailure;
|
|
+
|
|
+ if(PR_SUCCESS != PR_GetOpenFileInfo(infile, &info))
|
|
+ goto fail;
|
|
+
|
|
+ if(!SECITEM_AllocItem(NULL, &filedata, info.size + /* zero ended */ 1))
|
|
+ goto fail;
|
|
+
|
|
+ if(info.size != PR_Read(infile, filedata.data, info.size))
|
|
+ goto fail;
|
|
+
|
|
+ /* place a trailing zero right after the visible data */
|
|
+ body = (char*)filedata.data;
|
|
+ body[--filedata.len] = '\0';
|
|
+
|
|
+ body = strstr(body, "-----BEGIN");
|
|
+ if(body) {
|
|
+ /* assume ASCII */
|
|
+ char *trailer;
|
|
+ char *begin = PORT_Strchr(body, '\n');
|
|
+ if(!begin)
|
|
+ begin = PORT_Strchr(body, '\r');
|
|
+ if(!begin)
|
|
+ goto fail;
|
|
+
|
|
+ trailer = strstr(++begin, "-----END");
|
|
+ if(!trailer)
|
|
+ goto fail;
|
|
+
|
|
+ /* retrieve DER from ASCII */
|
|
+ *trailer = '\0';
|
|
+ if(ATOB_ConvertAsciiToItem(&crlDER, begin))
|
|
+ goto fail;
|
|
+
|
|
+ SECITEM_FreeItem(&filedata, PR_FALSE);
|
|
}
|
|
+ else
|
|
+ /* assume DER */
|
|
+ crlDER = filedata;
|
|
|
|
- slot = PK11_GetInternalKeySlot();
|
|
- crl = PK11_ImportCRL(slot,&crlDER,
|
|
- NULL,SEC_CRL_TYPE,
|
|
- NULL,CRL_IMPORT_DEFAULT_OPTIONS,
|
|
- NULL,(CRL_DECODE_DEFAULT_OPTIONS|
|
|
- CRL_DECODE_DONT_COPY_DER));
|
|
- if (slot) PK11_FreeSlot(slot);
|
|
- if (!crl) return 0;
|
|
- SEC_DestroyCrl(crl);
|
|
- return 1;
|
|
+ PR_Close(infile);
|
|
+ return nss_cache_crl(&crlDER);
|
|
+
|
|
+fail:
|
|
+ PR_Close(infile);
|
|
+ SECITEM_FreeItem(&filedata, PR_FALSE);
|
|
+ return SECFailure;
|
|
}
|
|
|
|
static int nss_load_key(struct connectdata *conn, int sockindex,
|
|
@@ -889,6 +903,7 @@ int Curl_nss_init(void)
|
|
if (nss_initlock == NULL) {
|
|
PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 256);
|
|
nss_initlock = PR_NewLock();
|
|
+ nss_crllock = PR_NewLock();
|
|
}
|
|
|
|
/* We will actually initialize NSS later */
|
|
@@ -918,6 +933,7 @@ void Curl_nss_cleanup(void)
|
|
PR_Unlock(nss_initlock);
|
|
|
|
PR_DestroyLock(nss_initlock);
|
|
+ PR_DestroyLock(nss_crllock);
|
|
nss_initlock = NULL;
|
|
|
|
initialized = 0;
|
|
@@ -1244,8 +1260,7 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
|
|
data->set.ssl.CApath ? data->set.ssl.CApath : "none");
|
|
|
|
if (data->set.ssl.CRLfile) {
|
|
- int rc = nss_load_crl(data->set.ssl.CRLfile, PR_FALSE);
|
|
- if (!rc) {
|
|
+ if(SECSuccess != nss_load_crl(data->set.ssl.CRLfile)) {
|
|
curlerr = CURLE_SSL_CRL_BADFILE;
|
|
goto error;
|
|
}
|