From d611cc597822049b1bd091b6bf2f136e07ae53cf Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Tue, 28 Apr 2015 15:54:45 +0200 Subject: SSL support when talking to ADS --- openssl.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 2 deletions(-) (limited to 'openssl.c') diff --git a/openssl.c b/openssl.c index 32c7bca..c8e4142 100644 --- a/openssl.c +++ b/openssl.c @@ -2,6 +2,7 @@ #include "helper.h" static BOOL initDone = FALSE; +static const EVP_MD *sha1 = NULL; void ssl_printErrors(char *bailMsg) { @@ -19,6 +20,8 @@ BOOL ssl_init() SSL_load_error_strings(); SSL_library_init(); OpenSSL_add_all_algorithms(); + sha1 = EVP_get_digestbyname("sha1"); + if (sha1 == NULL) ssl_printErrors("Could not load SHA-1 digest\n"); return TRUE; } @@ -29,13 +32,26 @@ SSL_CTX* ssl_newServerCtx(char *certfile, char *keyfile) SSL_CTX *ctx = SSL_CTX_new(m); if (ctx == NULL) ssl_printErrors("newServerCtx: ctx is NULL"); SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2); + SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3); SSL_CTX_use_certificate_file(ctx, certfile, SSL_FILETYPE_PEM); SSL_CTX_use_PrivateKey_file(ctx, keyfile, SSL_FILETYPE_PEM); if (!SSL_CTX_check_private_key(ctx)) ssl_printErrors("Could not load cert/private key"); + SSL_CTX_set_mode(ctx, SSL_MODE_ENABLE_PARTIAL_WRITE); return ctx; } -SSL *ssl_startAccept(int clientFd, SSL_CTX *ctx) +SSL_CTX* ssl_newClientCtx() +{ + const SSL_METHOD *m = SSLv23_client_method(); + if (m == NULL) ssl_printErrors("newClientCtx: method is NULL"); + SSL_CTX *ctx = SSL_CTX_new(m); + if (ctx == NULL) ssl_printErrors("newClientCtx: ctx is NULL"); + SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2); + SSL_CTX_set_mode(ctx, SSL_MODE_ENABLE_PARTIAL_WRITE); + return ctx; +} + +SSL *ssl_new(int clientFd, SSL_CTX *ctx) { SSL *ssl = SSL_new(ctx); if (ssl == NULL) { @@ -47,7 +63,6 @@ SSL *ssl_startAccept(int clientFd, SSL_CTX *ctx) SSL_free(ssl); return NULL; } - SSL_set_mode(ssl, SSL_MODE_ENABLE_PARTIAL_WRITE); return ssl; } @@ -66,3 +81,45 @@ BOOL ssl_acceptClient(epoll_client_t *client) return FALSE; } +BOOL ssl_connectServer(epoll_server_t *server) +{ + if (server->sslConnected) return TRUE; + int ret = SSL_connect(server->ssl); + if (ret == 1) { + if (!ssl_checkCertificateHash(server)) { + printf("Warning: Fingerprint of %s doesn't match value given in config, refusing to talk to server!\n", server->serverData->addr); + return FALSE; + } + server->sslConnected = TRUE; + return TRUE; + } + if (ret < 0) { + int err = SSL_get_error(server->ssl, ret); + if (SSL_BLOCKED(err)) return TRUE; + } + return FALSE; +} + +BOOL ssl_checkCertificateHash(epoll_server_t *server) +{ + if (server->ssl == NULL) { + printf("Bug: Asked to check certificate of non-SSL connection\n"); + return FALSE; + } + for (int i = 0; i < FINGERPRINTLEN; ++i) { + if (server->serverData->fingerprint[i] != 0) { + unsigned char md[EVP_MAX_MD_SIZE]; + unsigned int n = 20; + X509 *cert = SSL_get_peer_certificate(server->ssl); + if (cert == NULL) { + printf("Warning: Server %s has no certificate!\n", server->serverData->addr); + return FALSE; + } + X509_free(cert); + X509_digest(cert, sha1, md, &n); + return n == 20 && memcmp(md, server->serverData->fingerprint, n) == 0; + } + } + return TRUE; +} + -- cgit v1.2.3-55-g7522