aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2008-06-06 18:40:21 +0000
committerDaniel Stenberg <daniel@haxx.se>2008-06-06 18:40:21 +0000
commit3fe8251dfbb533803e25cc38365114b28c5a1c85 (patch)
treef6023109232d4fd990d5c2a4bcc4479e55367ee3 /lib
parent930a45e7a93c964ec224bdddb59f97479b7e4a5d (diff)
- Axel Tillequin and Arnaud Ebalard added support for CURLOPT_CRLFILE, for
OpenSSL, NSS and GnuTLS-built libcurls.
Diffstat (limited to 'lib')
-rw-r--r--lib/gtls.c15
-rw-r--r--lib/nss.c77
-rw-r--r--lib/ssluse.c26
-rw-r--r--lib/strerror.c3
-rw-r--r--lib/url.c9
-rw-r--r--lib/urldata.h2
6 files changed, 132 insertions, 0 deletions
diff --git a/lib/gtls.c b/lib/gtls.c
index 80100b4ed..e9e410243 100644
--- a/lib/gtls.c
+++ b/lib/gtls.c
@@ -271,6 +271,21 @@ Curl_gtls_connect(struct connectdata *conn,
rc, data->set.ssl.CAfile);
}
+ if(data->set.ssl.CRLfile) {
+ /* set the CRL list file */
+ rc = gnutls_certificate_set_x509_crl_file(conn->ssl[sockindex].cred,
+ data->set.ssl.CRLfile,
+ GNUTLS_X509_FMT_PEM);
+ if(rc < 0) {
+ failf(data, "error reading crl file %s (%s)\n",
+ data->set.ssl.CRLfile, gnutls_strerror(rc));
+ return CURLE_SSL_CRL_BADFILE;
+ }
+ else
+ infof(data, "found %d CRL in %s\n",
+ rc, data->set.ssl.CRLfile);
+ }
+
/* Initialize TLS session as a client */
rc = gnutls_init(&conn->ssl[sockindex].session, GNUTLS_CLIENT);
if(rc) {
diff --git a/lib/nss.c b/lib/nss.c
index 20f8770d2..a5fc795f8 100644
--- a/lib/nss.c
+++ b/lib/nss.c
@@ -59,6 +59,9 @@
#include <sslproto.h>
#include <prtypes.h>
#include <pk11pub.h>
+#include <prio.h>
+#include <secitem.h>
+#include <secport.h>
#include "memory.h"
#include "easyif.h" /* for Curl_convert_from_utf8 prototype */
@@ -362,6 +365,69 @@ done:
return 1;
}
+static int nss_load_crl(char* crlfilename, PRBool ascii)
+{
+ 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;
+ }
+ 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;
+ }
+ if ((body=strstr(asc,"-----BEGIN")) != 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;
+ }
+ else {
+ if (!SECITEM_AllocItem(NULL,&crlDER,info.size)) return 0;
+ nb = PR_Read(infile,crlDER.data,info.size);
+ if (nb!=info.size) return 0;
+ }
+
+ 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;
+}
+
static int nss_load_key(struct connectdata *conn, char *key_file)
{
#ifdef HAVE_PK11_CREATEGENERICOBJECT
@@ -955,6 +1021,17 @@ CURLcode Curl_nss_connect(struct connectdata * conn, int sockindex)
data->set.ssl.CAfile ? data->set.ssl.CAfile : "none",
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) {
+ curlerr = CURLE_SSL_CRL_BADFILE;
+ goto error;
+ }
+ infof(data,
+ " CRLfile: %s\n",
+ data->set.ssl.CRLfile ? data->set.ssl.CRLfile : "none");
+ }
+
if(data->set.str[STRING_CERT]) {
char *n;
char *nickname;
diff --git a/lib/ssluse.c b/lib/ssluse.c
index b0d7fd038..f14ad344e 100644
--- a/lib/ssluse.c
+++ b/lib/ssluse.c
@@ -1293,6 +1293,7 @@ ossl_connect_step1(struct connectdata *conn,
struct SessionHandle *data = conn->data;
SSL_METHOD_QUAL SSL_METHOD *req_method=NULL;
void *ssl_sessionid=NULL;
+ X509_LOOKUP *lookup=NULL;
curl_socket_t sockfd = conn->sock[sockindex];
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
@@ -1429,6 +1430,31 @@ ossl_connect_step1(struct connectdata *conn,
data->set.str[STRING_SSL_CAPATH] ? data->set.str[STRING_SSL_CAPATH]:
"none");
}
+
+ if (data->set.str[STRING_SSL_CRLFILE]) {
+ /* tell SSL where to find CRL file that is used to check certificate
+ * revocation */
+ lookup=X509_STORE_add_lookup(connssl->ctx->cert_store,X509_LOOKUP_file());
+ if ( !lookup ||
+ (X509_load_crl_file(lookup,data->set.str[STRING_SSL_CRLFILE],
+ X509_FILETYPE_PEM)!=1) ) {
+ failf(data,"error loading CRL file :\n"
+ " CRLfile: %s\n",
+ data->set.str[STRING_SSL_CRLFILE]?
+ data->set.str[STRING_SSL_CRLFILE]: "none");
+ return CURLE_SSL_CRL_BADFILE;
+ }
+ else {
+ /* Everything is fine. */
+ infof(data, "successfully load CRL file:\n");
+ X509_STORE_set_flags(connssl->ctx->cert_store,
+ X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
+ }
+ infof(data,
+ " CRLfile: %s\n", data->set.str[STRING_SSL_CRLFILE] ?
+ data->set.str[STRING_SSL_CRLFILE]: "none");
+ }
+
/* SSL always tries to verify the peer, this only says whether it should
* fail to connect if the verification fails, or if it should continue
* anyway. In the latter case the result of the verification is checked with
diff --git a/lib/strerror.c b/lib/strerror.c
index fe5a76df5..03b01582c 100644
--- a/lib/strerror.c
+++ b/lib/strerror.c
@@ -222,6 +222,9 @@ curl_easy_strerror(CURLcode error)
case CURLE_SSL_SHUTDOWN_FAILED:
return "Failed to shut down the SSL connection";
+ case CURLE_SSL_CRL_BADFILE:
+ return "Failed to load CRL file (path? access rights?, format?)";
+
case CURLE_SEND_FAIL_REWIND:
return "Send failed since rewinding of the data stream failed";
diff --git a/lib/url.c b/lib/url.c
index 906792332..0e71cede0 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -1811,6 +1811,14 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
result = setstropt(&data->set.str[STRING_SSL_CAPATH],
va_arg(param, char *));
break;
+ case CURLOPT_CRLFILE:
+ /*
+ * Set CRL file info for SSL connection. Specify file name of the CRL
+ * to check certificates revocation
+ */
+ result = setstropt(&data->set.str[STRING_SSL_CRLFILE],
+ va_arg(param, char *));
+ break;
case CURLOPT_TELNETOPTIONS:
/*
* Set a linked list of telnet options
@@ -3951,6 +3959,7 @@ static CURLcode CreateConnection(struct SessionHandle *data,
*/
data->set.ssl.CApath = data->set.str[STRING_SSL_CAPATH];
data->set.ssl.CAfile = data->set.str[STRING_SSL_CAFILE];
+ data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE];
data->set.ssl.random_file = data->set.str[STRING_SSL_RANDOM_FILE];
data->set.ssl.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
data->set.ssl.cipher_list = data->set.str[STRING_SSL_CIPHER_LIST];
diff --git a/lib/urldata.h b/lib/urldata.h
index 1f9d3ebd2..def598b41 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -212,6 +212,7 @@ struct ssl_config_data {
2: CN must match hostname */
char *CApath; /* certificate dir (doesn't work on windows) */
char *CAfile; /* cerficate to verify peer against */
+ char *CRLfile; /* CRL to check cerficate revocation */
char *random_file; /* path to file containing "random" data */
char *egdsocket; /* path to file containing the EGD daemon socket */
char *cipher_list; /* list of ciphers to use */
@@ -1317,6 +1318,7 @@ enum dupstring {
STRING_USERAGENT, /* User-Agent string */
STRING_USERPWD, /* <user:password>, if used */
STRING_SSH_HOST_PUBLIC_KEY_MD5, /* md5 of host public key in ascii hex */
+ STRING_SSL_CRLFILE, /* crl file to check certificate */
/* -- end of strings -- */
STRING_LAST /* not used, just an end-of-list marker */