Mercurial > ~mikael > mcabber > hg
diff mcabber/connwrap/connwrap.c @ 938:40175f3dcef7
SSL server certificate verification
This patch enables SSL server certificate verification.
author | Jefferson Ogata <ogata@antibozo.net> |
---|---|
date | Sat, 08 Jul 2006 23:32:49 +0200 |
parents | 89aeb8fdd215 |
children | 6be62425dc38 |
line wrap: on
line diff
--- a/mcabber/connwrap/connwrap.c Sat Jul 08 22:07:30 2006 +0200 +++ b/mcabber/connwrap/connwrap.c Sat Jul 08 23:32:49 2006 +0200 @@ -33,6 +33,106 @@ static SSL_CTX *ctx = 0; +/* verify > 0 indicates verify depth as well */ +static int verify = -1; +static const char *cafile = NULL; +static const char *capath = NULL; +static const char *cipherlist = NULL; +static const char *peer = NULL; +static const char *sslerror = NULL; + +static int verify_cb(int preverify_ok, X509_STORE_CTX *cx) +{ + X509 *cert; + X509_NAME *nm; + int lastpos; + + if(!preverify_ok) { + long err = X509_STORE_CTX_get_error(cx); + + sslerror = X509_verify_cert_error_string(err); + return 0; + } + + if (peer == NULL) + return 1; + + if ((cert = X509_STORE_CTX_get_current_cert(cx)) == NULL) { + sslerror = "internal SSL error"; + return 0; + } + + /* We only want to look at the peername if we're working on the peer + * certificate. */ + if (cert != cx->cert) + return 1; + + if ((nm = X509_get_subject_name (cert)) == NULL) { + sslerror = "internal SSL error"; + return 0; + } + + for(lastpos = -1; ; ) { + X509_NAME_ENTRY *e; + ASN1_STRING *a; + ASN1_STRING *p; + int match; + + lastpos = X509_NAME_get_index_by_NID(nm, NID_commonName, lastpos); + if (lastpos == -1) + break; + if ((e = X509_NAME_get_entry(nm, lastpos)) == NULL) { + sslerror = "internal SSL error"; + return 0; + } + if ((a = X509_NAME_ENTRY_get_data(e)) == NULL) { + sslerror = "internal SSL error"; + return 0; + } + if ((p = ASN1_STRING_type_new(ASN1_STRING_type(a))) == NULL) { + sslerror = "internal SSL error"; + return 0; + } + (void) ASN1_STRING_set(p, peer, -1); + match = !ASN1_STRING_cmp(a, p); + ASN1_STRING_free(p); + if(match) + return 1; + } + + sslerror = "server certificate cn mismatch"; + return 0; +} + +static void init(void) { + if(ctx) + return; + + SSL_library_init(); + SSL_load_error_strings(); + +#ifdef HAVE_SSLEAY + SSLeay_add_all_algorithms(); +#else + OpenSSL_add_all_algorithms(); +#endif + + /* May need to use distinct SSLEAY bindings below... */ + + //ctx = SSL_CTX_new(SSLv23_method()); + ctx = SSL_CTX_new(SSLv23_client_method()); + if(cipherlist) + (void)SSL_CTX_set_cipher_list(ctx, cipherlist); + if(cafile || capath) + (void)SSL_CTX_load_verify_locations(ctx, cafile, capath); + if(verify) { + SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_cb); + if(verify > 0) + SSL_CTX_set_verify_depth(ctx, verify); + } else + SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); +} + typedef struct { int fd; SSL *ssl; } sslsock; static sslsock *socks = 0; @@ -54,22 +154,11 @@ p = &socks[sockcount-1]; - if(!ctx) { - SSL_library_init(); - SSL_load_error_strings(); - -#ifdef HAVE_SSLEAY - SSLeay_add_all_algorithms(); -#else - OpenSSL_add_all_algorithms(); -#endif - - //ctx = SSL_CTX_new(SSLv23_method()); - ctx = SSL_CTX_new(SSLv23_client_method()); - } + init (); p->ssl = SSL_new(ctx); SSL_set_fd(p->ssl, p->fd = fd); + sslerror = NULL; return p; } @@ -95,6 +184,26 @@ sockcount = nsockcount; } +void cw_set_ssl_options(int sslverify, const char *sslcafile, const char *sslcapath, const char *sslciphers, const char *sslpeer) { + verify = sslverify; + cafile = sslcafile; + capath = sslcapath; + cipherlist = sslciphers; + peer = sslpeer; +} + +const char *cw_get_ssl_error(void) { + return sslerror; +} + +#else + +void cw_set_ssl_options(int sslverify, const char *sslcafile, const char *sslcapath, const char *sslciphers, const char *sslpeer) { } + +const char *cw_get_ssl_error(void) { + return NULL; +} + #endif static char *bindaddr = 0, *proxyhost = 0, *proxyuser = 0, *proxypass = 0;