1
0
mirror of https://github.com/moparisthebest/curl synced 2024-12-21 23:58:49 -05:00

- 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

@ -8,6 +8,9 @@
Daniel Stenberg (6 Jun 2008)
- Axel Tillequin and Arnaud Ebalard added support for CURLOPT_CRLFILE, for
OpenSSL, NSS and GnuTLS-built libcurls.
- Added CURLINFO_PRIMARY_IP as a new information retrievable with
curl_easy_getinfo. It returns a pointer to a string with the most recently
used IP address. Modified test case 500 to also verify this feature. The

View File

@ -2,7 +2,7 @@ Curl and libcurl 7.18.3
Public curl releases: 106
Command line options: 126
curl_easy_setopt() options: 150
curl_easy_setopt() options: 151
Public functions in libcurl: 58
Public web site mirrors: 37
Known libcurl bindings: 36
@ -11,6 +11,7 @@ Curl and libcurl 7.18.3
This release includes the following changes:
o Added CURLINFO_PRIMARY_IP
o Added CURLOPT_CRLFILE
This release includes the following bugfixes:
@ -31,6 +32,6 @@ New curl mirrors:
This release would not have looked like this without help, code, reports and
advice from friends like these:
Lenny Rachitsky
Lenny Rachitsky, Axel Tillequin, Arnaud Ebalard
Thanks! (and sorry if I forgot to mention someone)

View File

@ -5,9 +5,6 @@ To be addressed before 7.18.3 (planned release: August 2008)
140 - Arnaud Ebalard and Axel Tillequin's CRL support and issuer check patches
141 - The sponsored feature CURLINFO_PRIMARY_IP that returns the IP address
as a string for the most recently used connection.
144 - Help apps use 64bit/LFS libcurl!
145 -

View File

@ -1452,6 +1452,24 @@ in combination with the \fICURLOPT_SSL_VERIFYPEER\fP option. If
indicate an accessible path. The \fICURLOPT_CAPATH\fP function apparently
does not work in Windows due to some limitation in openssl. This option is
OpenSSL-specific and does nothing if libcurl is built to use GnuTLS.
.IP CURLOPT_CRLFILE
Pass a char * to a zero terminated string naming a file with the concatenation
of CRL (in PEM format) to use in the certificate validation that occurs during
the SSL exchange.
When curl is built to use NSS or GnuTLS, there is no way to influence the use
of CRL passed to help in the verification process. When libcurl is built with
OpenSSL support, X509_V_FLAG_CRL_CHECK and X509_V_FLAG_CRL_CHECK_ALL are both
set, requiring CRL check against all the elements of the certificate chain if
a CRL file is passed.
This option makes sense only when used in combination with the
\fICURLOPT_SSL_VERIFYPEER\fP option.
A specific error code (CURLE_SSL_CRL_BADFILE) is defined with the option. It
is returned when the SSL exchange fails because the CRL file cannot be loaded.
Note that a failure in certificate verification due to a revocation information
found in the CRL does not trigger this specific error.
.IP CURLOPT_RANDOM_FILE
Pass a char * to a zero terminated file name. The file will be used to read
from to seed the random engine for SSL. The more random the specified file is,

View File

@ -212,6 +212,8 @@ Failed to shut down the SSL connection
Socket is not ready for send/recv wait till it's ready and try again. This
return code is only returned from \fIcurl_easy_recv(3)\fP and
\fIcurl_easy_send(3)\fP (Added in 7.18.2)
.IP "CURLE_SSL_CRL_BADFILE (82)"
Failed to load CRL file (Added in 7.18.3)
.IP "CURLE_OBSOLETE*"
These error codes will never be returned. They used to be used in an old libcurl
version and are currently unused.

View File

@ -452,7 +452,10 @@ typedef enum {
CURLE_SSL_SHUTDOWN_FAILED, /* 80 - Failed to shut down the SSL
connection */
CURLE_AGAIN, /* 81 - socket is not ready for send/recv,
wait till it's ready and try again */
wait till it's ready and try again (Added
in 7.18.2) */
CURLE_SSL_CRL_BADFILE, /* 82 - could not load CRL file, missing or
wrong format (Added in 7.18.3) */
CURL_LAST /* never use! */
} CURLcode;
@ -1200,6 +1203,9 @@ typedef enum {
CINIT(SEEKFUNCTION, FUNCTIONPOINT, 167),
CINIT(SEEKDATA, OBJECTPOINT, 168),
/* CRL file */
CINIT(CRLFILE, OBJECTPOINT, 169),
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;

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