curl/curl-7.20.1-crl.patch

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;
}