- Axel Tillequin and Arnaud Ebalard added support for CURLOPT_CRLFILE, for

OpenSSL, NSS and GnuTLS-built libcurls.
This commit is contained in:
Daniel Stenberg
2008-06-06 18:40:21 +00:00
parent 930a45e7a9
commit 3fe8251dfb
12 changed files with 165 additions and 6 deletions

View File

@@ -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) {

View File

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

View File

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

View File

@@ -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";

View File

@@ -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];

View File

@@ -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 */