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