From ec2f2a97e4bba274a8abea0a91e37b49cee6f89b Mon Sep 17 00:00:00 2001 From: Marcel Poul Date: Thu, 12 Jan 2012 15:18:18 +0000 Subject: [PATCH] server hostname check on certificate extensions --- emi.canl.canl-c/src/canl.c | 2 +- emi.canl.canl-c/src/canl_locl.h | 2 +- emi.canl.canl-c/src/canl_ssl.c | 55 +++++++++++++++++++++++++++++++++++------ 3 files changed, 49 insertions(+), 10 deletions(-) diff --git a/emi.canl.canl-c/src/canl.c b/emi.canl.canl-c/src/canl.c index 6deae88..10179e0 100644 --- a/emi.canl.canl-c/src/canl.c +++ b/emi.canl.canl-c/src/canl.c @@ -156,7 +156,7 @@ canl_io_connect(canl_ctx cc, canl_io_handler io, const char *host, const char *s if (err) goto end; - err = ssl_connect(glb_cc, io_cc, timeout); //TODO timeout + err = ssl_connect(glb_cc, io_cc, timeout, host); //TODO timeout if (err) goto end; diff --git a/emi.canl.canl-c/src/canl_locl.h b/emi.canl.canl-c/src/canl_locl.h index 974e3d0..951fe1e 100644 --- a/emi.canl.canl-c/src/canl_locl.h +++ b/emi.canl.canl-c/src/canl_locl.h @@ -101,7 +101,7 @@ int asyn_getservbyname(int a_family, asyn_result *ares_result,char const *name, struct timeval *timeout); int ssl_client_init(glb_ctx *cc, io_handler *io); int ssl_server_init(glb_ctx *cc); -int ssl_connect(glb_ctx *cc, io_handler *io, struct timeval *timeout); +int ssl_connect(glb_ctx *cc, io_handler *io, struct timeval *timeout, const char * host); int ssl_accept(glb_ctx *cc, io_handler *io, struct timeval *timeout); int ssl_read(glb_ctx *cc, io_handler *io, void *buffer, size_t size, diff --git a/emi.canl.canl-c/src/canl_ssl.c b/emi.canl.canl-c/src/canl_ssl.c index 7a345f1..c702b54 100644 --- a/emi.canl.canl-c/src/canl_ssl.c +++ b/emi.canl.canl-c/src/canl_ssl.c @@ -6,7 +6,7 @@ static int do_ssl_connect( glb_ctx *cc, io_handler *io, struct timeval *timeout); static int do_ssl_accept( glb_ctx *cc, io_handler *io, struct timeval *timeout); -static int check_hostname_cert(glb_ctx *cc, io_handler *io); +static int check_hostname_cert(glb_ctx *cc, io_handler *io, const char *host); #ifdef DEBUG static void dbg_print_ssl_error(int errorcode); #endif @@ -223,7 +223,7 @@ end: return 0; } -int ssl_connect(glb_ctx *cc, io_handler *io, struct timeval *timeout) +int ssl_connect(glb_ctx *cc, io_handler *io, struct timeval *timeout, const char * host) { int err = 0, flags; @@ -247,23 +247,62 @@ int ssl_connect(glb_ctx *cc, io_handler *io, struct timeval *timeout) goto end; } /*check server hostname on the certificate*/ - err = check_hostname_cert(cc, io); + err = check_hostname_cert(cc, io, host); end: return err; } -static int check_hostname_cert(glb_ctx *cc, io_handler *io) +static int check_hostname_cert(glb_ctx *cc, io_handler *io, const char *host) { X509 * serv_cert = NULL; - /*if voms extensions are present, hostname has to correspond*/ + X509_EXTENSION *ext = NULL; + int i = 0; + GENERAL_NAMES *ialt = NULL; + unsigned char *pBuffer = NULL; + int correspond = 0; + struct sockaddr *addr = NULL; + socklen_t addrlen = 0; + + /*if extensions are present, hostname has to correspond + * to subj. alt. name*/ serv_cert = SSL_get_peer_certificate(io->s_ctx->ssl_io); - /* ... */ - + i = X509_get_ext_by_NID(serv_cert, NID_subject_alt_name, -1); + if (i >= 0) { + /* subj. alt. name extention present */ + if(!(ext = X509_get_ext(serv_cert, i)) || + !(ialt = X509V3_EXT_d2i(ext)) ) + goto end; + for(i = 0; i < sk_GENERAL_NAME_num(ialt); i++) { + const GENERAL_NAME *gen = sk_GENERAL_NAME_value(ialt, i); + switch (gen->type) { + case GEN_DNS: + ASN1_STRING_to_UTF8((unsigned char**)&pBuffer, gen->d.ia5); +#ifdef DEBUG + printf(" %s",pBuffer); +#endif + if (!strcmp(pBuffer, host)) { //TODO substr maybe + correspond = 1; + OPENSSL_free(pBuffer); + pBuffer = NULL; + goto end; + } + OPENSSL_free(pBuffer); + pBuffer = NULL; + break; + } + } + } /*else hostname has to correspond to subject*/ +end: X509_free(serv_cert); - return 0; + if (correspond) + return 0; + else { + return set_error(cc, CANL_ERR_criticalExtensionError, canl_error, + "Cannot validate server hostname" ); //TODO check + } } int ssl_accept(glb_ctx *cc, io_handler *io, -- 1.8.2.3