Skip to content

Commit

Permalink
Add CRL (Certificate Revocation List) verification for TLS
Browse files Browse the repository at this point in the history
CRL verification was added in the proto tls module. By adding this
feature revoked client certificates can be detected during the TLS
process, thus permitting a robust security mechanism. The following
parameters where added to the proto tls module in the configuration
script: crl_dir and crl_check_all. The crl_dir parameter specifies the
directory which contains the CRL files (multiple CRL files can be
added).
The crl_check_all parameter must be 0 or 1 and specifies whether all the
certificates from the chain are verified against a CRL or not.
By default, CRL verification is enabled only for client certificates
(or when crl_check_all is 0). If crl_check_all is 1 then the
issuer (chain) certificates are also verified against the given CRL
files.
  • Loading branch information
chiforbogdan committed Aug 24, 2015
1 parent 33ab7b2 commit 5503634
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 0 deletions.
94 changes: 94 additions & 0 deletions modules/proto_tls/proto_tls.c
Expand Up @@ -46,6 +46,7 @@
#include <netinet/tcp.h>
#include <netinet/ip.h>
#include <unistd.h>
#include <dirent.h>

#include "../../dprint.h"
#include "../../mem/shm_mem.h"
Expand Down Expand Up @@ -127,6 +128,8 @@ static param_export_t params[] = {
{ "require_cert", STR_PARAM|USE_FUNC_PARAM, (void*)tlsp_set_require },
{ "certificate", STR_PARAM|USE_FUNC_PARAM, (void*)tlsp_set_certificate},
{ "private_key", STR_PARAM|USE_FUNC_PARAM, (void*)tlsp_set_pk },
{ "crl_check_all", STR_PARAM|USE_FUNC_PARAM, (void*)tlsp_set_crl_check },
{ "crl_dir", STR_PARAM|USE_FUNC_PARAM, (void*)tlsp_set_crldir },
{ "ca_list", STR_PARAM|USE_FUNC_PARAM, (void*)tlsp_set_calist },
{ "ca_dir", STR_PARAM|USE_FUNC_PARAM, (void*)tlsp_set_cadir },
{ "ciphers_list", STR_PARAM|USE_FUNC_PARAM, (void*)tlsp_set_cplist },
Expand Down Expand Up @@ -832,6 +835,87 @@ static int load_certificate(SSL_CTX * ctx, char *filename)
return 0;
}

static int load_crl(SSL_CTX * ctx, char *crl_directory, int crl_check_all)
{
DIR *d;
struct dirent *dir;
int crl_added = 0;
LM_DBG("Loading CRL from directory\n");

/*Get X509 store from SSL context*/
X509_STORE *store = SSL_CTX_get_cert_store(ctx);
if(!store) {
LM_ERR("Unable to get X509 store from ssl context\n");
return -1;
}

/*Parse directory*/
d = opendir(crl_directory);
if(!d) {
LM_ERR("Unable to open crl directory '%s'\n", crl_directory);
return -1;
}

while ((dir = readdir(d)) != NULL) {
/*Skip if not regular file*/
if (dir->d_type != DT_REG)
continue;

/*Create filename*/
char* filename = (char*) pkg_malloc(sizeof(char)*(strlen(crl_directory)+strlen(dir->d_name)+2));
if (!filename) {
LM_ERR("Unable to allocate crl filename\n");
closedir(d);
return -1;
}
strcpy(filename,crl_directory);
if(filename[strlen(filename)-1] != '/')
strcat(filename,"/");
strcat(filename,dir->d_name);

/*Get CRL content*/
FILE *fp = fopen(filename,"r");
pkg_free(filename);
if(!fp)
continue;

X509_CRL *crl = PEM_read_X509_CRL(fp, NULL, NULL, NULL);
fclose(fp);
if(!crl)
continue;

/*Add CRL to X509 store*/
if (X509_STORE_add_crl(store, crl) == 1)
crl_added++;
else
LM_ERR("Unable to add crl to ssl context\n");

X509_CRL_free(crl);
}
closedir(d);

if (!crl_added) {
LM_ERR("No suitable CRL files found in directory %s\n", crl_directory);
return -1;
}

/*Enable CRL checking*/
X509_VERIFY_PARAM *param;
param = X509_VERIFY_PARAM_new();

int flags = X509_V_FLAG_CRL_CHECK;
if(crl_check_all)
flags |= X509_V_FLAG_CRL_CHECK_ALL;

X509_VERIFY_PARAM_set_flags(param, flags);

SSL_CTX_set1_param(ctx, param);
X509_VERIFY_PARAM_free(param);

return 0;
}



/*
* Load a caList, to be used to verify the client's certificate.
Expand Down Expand Up @@ -980,6 +1064,16 @@ static int init_tls_domains(struct tls_domain *d)
if (load_certificate(d->ctx, d->cert_file) < 0)
return -1;

/**
* load crl from directory
*/
if (!d->crl_directory) {
LM_NOTICE("no crl for tls, using none");
} else {
if(load_crl(d->ctx, d->crl_directory, d->crl_check_all) < 0)
return -1;
}

/*
* load ca
*/
Expand Down
2 changes: 2 additions & 0 deletions modules/proto_tls/tls_config.c
Expand Up @@ -48,6 +48,8 @@ int tls_method = TLS_USE_SSLv23;
int tls_verify_client_cert = 1;
int tls_verify_server_cert = 1;
int tls_require_client_cert = 1;
/* disable CRL validation for all the certificates from the chain */
int crl_check_all = 0;
/* default location of certificates */
char *tls_cert_file = TLS_CERT_FILE;
char *tls_pkey_file = TLS_PKEY_FILE;
Expand Down
1 change: 1 addition & 0 deletions modules/proto_tls/tls_config.h
Expand Up @@ -53,6 +53,7 @@ extern int tls_method;
extern int tls_verify_client_cert;
extern int tls_verify_server_cert;
extern int tls_require_client_cert;
extern int crl_check_all;
extern char *tls_cert_file;
extern char *tls_pkey_file;
extern char *tls_ca_file;
Expand Down
1 change: 1 addition & 0 deletions modules/proto_tls/tls_domain.c
Expand Up @@ -216,6 +216,7 @@ struct tls_domain *tls_new_domain( str *id, int type)
memcpy( d->id.s, id->s, id->len);

d->type = type;
d->crl_check_all = crl_check_all;

if (type & TLS_DOMAIN_SRV) {
d->verify_cert = tls_verify_client_cert;
Expand Down
2 changes: 2 additions & 0 deletions modules/proto_tls/tls_domain.h
Expand Up @@ -63,8 +63,10 @@ struct tls_domain {
SSL_CTX *ctx;
int verify_cert;
int require_client_cert;
int crl_check_all;
char *cert_file;
char *pkey_file;
char *crl_directory;
char *ca_file;
char *tmp_dh_file;
char *tls_ec_curve;
Expand Down
27 changes: 27 additions & 0 deletions modules/proto_tls/tls_params.c
Expand Up @@ -253,6 +253,33 @@ int tlsp_set_require(modparam_t type, void *in)
return 1;
}

int tlsp_set_crl_check(modparam_t type, void *in)
{
str id;
str val;
unsigned int check;

split_param_val( (char*)in, &id, &val);

if (str2int( &val, &check)!=0) {
LM_ERR("option is not a number [%s]\n",val.s);
return -1;
}

set_domain_attr( id, crl_check_all, check);
return 1;
}

int tlsp_set_crldir(modparam_t type, void *in)
{
str id;
str val;

split_param_val( (char*)in, &id, &val);

set_domain_attr( id, crl_directory, val.s);
return 1;
}

int tlsp_set_certificate(modparam_t type, void *in)
{
Expand Down
4 changes: 4 additions & 0 deletions modules/proto_tls/tls_params.h
Expand Up @@ -52,10 +52,14 @@ int tlsp_set_verify(modparam_t type, void *val);

int tlsp_set_require(modparam_t type, void *val);

int tlsp_set_crl_check(modparam_t type, void *val);

int tlsp_set_certificate(modparam_t type, void *val);

int tlsp_set_pk(modparam_t type, void *val);

int tlsp_set_crldir(modparam_t type, void *val);

int tlsp_set_calist(modparam_t type, void *val);

int tlsp_set_cadir(modparam_t type, void *val);
Expand Down

0 comments on commit 5503634

Please sign in to comment.