diff options
author | Daniel Stenberg <daniel@haxx.se> | 2008-06-06 18:40:21 +0000 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2008-06-06 18:40:21 +0000 |
commit | 3fe8251dfbb533803e25cc38365114b28c5a1c85 (patch) | |
tree | f6023109232d4fd990d5c2a4bcc4479e55367ee3 /lib | |
parent | 930a45e7a93c964ec224bdddb59f97479b7e4a5d (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.c | 15 | ||||
-rw-r--r-- | lib/nss.c | 77 | ||||
-rw-r--r-- | lib/ssluse.c | 26 | ||||
-rw-r--r-- | lib/strerror.c | 3 | ||||
-rw-r--r-- | lib/url.c | 9 | ||||
-rw-r--r-- | lib/urldata.h | 2 |
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) { @@ -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"; @@ -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 */ |