From 0bd0d4e6db2093186e91aa023865f16c793854e2 Mon Sep 17 00:00:00 2001 From: Dirk Engling Date: Wed, 25 May 2022 00:23:08 +0200 Subject: Make tls engine runtime configurable --- vchat-client.c | 5 +-- vchat-commands.c | 2 +- vchat-config.h | 1 + vchat-connection.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++------ vchat-connection.h | 2 + vchat-tls.c | 73 ++++++++++++++++------------------- vchat-tls.h | 27 ++++++++++--- vchat.h | 3 +- 8 files changed, 159 insertions(+), 64 deletions(-) diff --git a/vchat-client.c b/vchat-client.c index d1afaa2..a22df94 100755 --- a/vchat-client.c +++ b/vchat-client.c @@ -430,7 +430,7 @@ void versions() { puts(vchat_us_version); puts(vchat_cm_version); puts(vchat_tls_version); - puts(vchat_tls_version_external); + puts(vchat_tls_version_external()); } /* main - d'oh */ @@ -443,9 +443,6 @@ int main(int argc, char **argv) { loadconfig(GLOBAL_CONFIG_FILE); loadconfig(getstroption(CF_CONFIGFILE)); - /* make SSL version used visible */ - vchat_tls_get_version_external(); - /* parse commandline */ while (cmdsunparsed) { pchar = getopt(argc, argv, "C:F:lzs:p:c:n:f:kKL:hv"); diff --git a/vchat-commands.c b/vchat-commands.c index 9aa3abd..3ef3132 100755 --- a/vchat-commands.c +++ b/vchat-commands.c @@ -449,7 +449,7 @@ void command_version(char *tail) { writeout(vchat_us_version); writeout(vchat_cm_version); writeout(vchat_tls_version); - writeout(vchat_tls_version_external); + writeout(vchat_tls_version_external()); showout(); } diff --git a/vchat-config.h b/vchat-config.h index 56e0b60..24365dc 100755 --- a/vchat-config.h +++ b/vchat-config.h @@ -43,6 +43,7 @@ static volatile configoption configoptions[] = { {CF_PINFINGER, CO_INT, "pinfinger", (char *) 0, (char *)-1, { NULL } }, {CF_ENCODING, CO_STR, "encoding", NULL, NULL, { .pstr = &encoding }}, {CF_USESSL, CO_INT, "usessl", (char *) 1, (char *)-1, { NULL } }, + {CF_TLSLIB, CO_STR, "tlslib", "mbedtls", NULL, { NULL } }, {CF_IGNSSL, CO_INT, "ignssl", (char *) 0, (char *)-1, { NULL } }, {CF_VERIFYSSL, CO_INT, "verifyssl", (char *) 2, (char *)-1, { NULL } }, {CF_USECERT, CO_INT, "usecert", (char *) 1, (char *)-1, { NULL } }, diff --git a/vchat-connection.c b/vchat-connection.c index 165ed9b..4680b6e 100644 --- a/vchat-connection.c +++ b/vchat-connection.c @@ -35,6 +35,9 @@ static int serverfd = -1; unsigned int want_tcp_keepalive = 0; +enum { TLS_ENGINE_UNSET, TLS_ENGINE_OPENSSL, TLS_ENGINE_MBEDTLS }; +static int _engine = TLS_ENGINE_UNSET; + #define STAGING_SIZE 16384 #define RECEIVEBUF_SIZE 4096 @@ -87,6 +90,7 @@ int vc_connect(const char *server, const char *port) { /* pointer to tilde-expanded certificate/keyfile-names */ char *certfile, *cafile; + int result = -1, want_openssl = !strcmp(getstroption(CF_TLSLIB), "openssl"); /* Connect to the server */ serverfd = connect_tcp_socket(server, port); @@ -100,8 +104,35 @@ int vc_connect(const char *server, const char *port) { if (!getintoption(CF_USESSL)) return 0; +#ifdef TLS_LIB_OPENSSL + _engine = TLS_ENGINE_OPENSSL; +#endif +#ifdef TLS_LIB_MBEDTLS + /* Make mbedtls default unless mbedtls is configured */ + if (!want_openssl || _engine == TLS_ENGINE_UNSET) + _engine = TLS_ENGINE_MBEDTLS; +#endif + + if (_engine == TLS_ENGINE_UNSET) { + writecf(FS_ERR, "Error: tls requested but no tls engine compiled in."); + return -1; + } + + if (want_openssl && _engine == TLS_ENGINE_MBEDTLS) + writecf(FS_SERV, "Warning: tls engine openssl requested but openssl engine not compiled in. Using mbedtls"); + + if (!want_openssl && _engine == TLS_ENGINE_OPENSSL) + writecf(FS_SERV, "Warning: tls engine mbedtls requested but mbedts engine not compiled in. Using openssl"); + /* If SSL is requested, get our ssl-BIO running */ - vc_init_x509store(&vc_store); +#ifdef TLS_LIB_OPENSSL + if (_engine == TLS_ENGINE_OPENSSL) + vc_openssl_init_x509store(&vc_store); +#endif +#ifdef TLS_LIB_MBEDTLS + if (_engine == TLS_ENGINE_MBEDTLS) + vc_mbedtls_init_x509store(&vc_store); +#endif /* get name of certificate file */ certfile = get_tilde_expanded(CF_CERTFILE); @@ -127,14 +158,30 @@ int vc_connect(const char *server, const char *port) { free(cafile); /* upgrade our plain BIO to ssl */ - int result = vc_tls_connect(serverfd, &vc_store); +#ifdef TLS_LIB_OPENSSL + if (_engine == TLS_ENGINE_OPENSSL) + result = vc_openssl_connect(serverfd, &vc_store); +#endif +#ifdef TLS_LIB_MBEDTLS + if (_engine == TLS_ENGINE_MBEDTLS) + result = vc_mbedtls_connect(serverfd, &vc_store); +#endif vc_cleanup_x509store(&vc_store); if (result) { close(serverfd); serverfd = -1; errno = EIO; - vc_tls_cleanup(); +#ifdef TLS_LIB_OPENSSL + if (_engine == TLS_ENGINE_OPENSSL) + vc_openssl_cleanup(); +#endif +#ifdef TLS_LIB_MBEDTLS + if (_engine == TLS_ENGINE_MBEDTLS) + vc_mbedtls_cleanup(); +#endif + + _engine = TLS_ENGINE_UNSET; snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_CANTCONNECT), server, port); writechan(tmpstr); return -1; @@ -175,27 +222,42 @@ void vc_disconnect() { close(serverfd); serverfd = -1; } - vc_tls_cleanup(); +#ifdef TLS_LIB_OPENSSL + if (_engine == TLS_ENGINE_OPENSSL) + vc_openssl_cleanup(); +#endif +#ifdef TLS_LIB_MBEDTLS + if (_engine == TLS_ENGINE_MBEDTLS) + vc_mbedtls_cleanup(); +#endif + + _engine = TLS_ENGINE_UNSET; loggedin = 0; } void vc_sendmessage(const char *msg) { static char staging[STAGING_SIZE]; - size_t sent, len = snprintf(staging, sizeof(staging), "%s\r\n", msg); + size_t sent = 0, len = snprintf(staging, sizeof(staging), "%s\r\n", msg); #ifdef DEBUG /* debugging? log network output! */ fprintf(dumpfile, ">| (%zd) %s\n", len - 2, msg); #endif - if (getintoption(CF_USESSL)) - sent = vc_tls_sendmessage(staging, len); - else + if (getintoption(CF_USESSL)) { +#ifdef TLS_LIB_OPENSSL + if (_engine == TLS_ENGINE_OPENSSL) + sent = vc_openssl_sendmessage(staging, len); +#endif +#ifdef TLS_LIB_MBEDTLS + if (_engine == TLS_ENGINE_MBEDTLS) + sent = vc_mbedtls_sendmessage(staging, len); +#endif + } else sent = write(serverfd, staging, len); if (sent != len) writecf(FS_ERR, "Message sending fuzzy."); } - /* get data from servers connection */ int vc_receive(void) { /* offset in buffer (for linebreaks at packet borders) */ @@ -203,12 +265,19 @@ int vc_receive(void) { static size_t buf_fill; char *endmsg; size_t freebytes = sizeof(buf) - buf_fill; - ssize_t bytes; + ssize_t bytes = 0; if (!getintoption(CF_USESSL)) bytes = read(serverfd, buf + buf_fill, freebytes); else - bytes = vc_tls_receivemessage(buf + buf_fill, freebytes); +#ifdef TLS_LIB_OPENSSL + if (_engine == TLS_ENGINE_OPENSSL) + bytes = vc_openssl_receivemessage(buf + buf_fill, freebytes); +#endif +#ifdef TLS_LIB_MBEDTLS + if (_engine == TLS_ENGINE_MBEDTLS) + bytes = vc_mbedtls_receivemessage(buf + buf_fill, freebytes); +#endif /* Our tls functions may require retries with handshakes etc, this is * signalled by -2 */ @@ -255,3 +324,22 @@ int vc_receive(void) { } return 0; } + +const char *vchat_tls_version_external() { +#ifdef TLS_LIB_OPENSSL + char *openssl_version = vc_openssl_version(); +#else + char *openssl_version = strdup("not installed"); +#endif +#ifdef TLS_LIB_MBEDTLS + char *mbedtls_version = vc_mbedtls_version(); +#else + char *mbedtls_version = strdup("not installed"); +#endif + + snprintf(tmpstr, TMPSTRSIZE, "Module plain v0.1\nModule openssl version: %s\nModule mbedtls version: %s", openssl_version, mbedtls_version); + + free(openssl_version); + free(mbedtls_version); + return tmpstr; +} diff --git a/vchat-connection.h b/vchat-connection.h index 2889c82..766dc0a 100644 --- a/vchat-connection.h +++ b/vchat-connection.h @@ -7,3 +7,5 @@ void vc_sendmessage(const char *message); int vc_receive(); int vc_poll(); void vc_disconnect(); + +const char *vchat_tls_version_external(); diff --git a/vchat-tls.c b/vchat-tls.c index d2f3b01..f326b91 100755 --- a/vchat-tls.c +++ b/vchat-tls.c @@ -28,8 +28,6 @@ const char *vchat_tls_version = "vchat-tls.c $Id$"; -const char *vchat_tls_version_external = - "Unknown implementation; version unknown"; /* Helpers to work with vc_x509store_t used by all tls libs */ void vc_cleanup_x509store(vc_x509store_t *store) { @@ -133,15 +131,6 @@ cleanup_happy: return 0; } -#if defined(TLS_LIB_OPENSSL) && defined(TLS_LIB_MBEDTLS) -#error \ - "Both TLS_LIB_OPENSSL and TLS_LIB_MBEDTLS are defined. Please select only one." -#endif -#if !defined(TLS_LIB_OPENSSL) && !defined(TLS_LIB_MBEDTLS) -#error \ - "Neither TLS_LIB_OPENSSL nor TLS_LIB_MBEDTLS are defined. Please select exactly one." -#endif - #ifdef TLS_LIB_OPENSSL #include @@ -152,13 +141,13 @@ cleanup_happy: #include #include -void vchat_tls_get_version_external() { +char *vc_openssl_version() { snprintf(tmpstr, sizeof(tmpstr), "OpenSSL %s with %s", SSLeay_version(SSLEAY_VERSION), SSLeay_version(SSLEAY_CFLAGS)); - vchat_tls_version_external = strdup(tmpstr); + return strdup(tmpstr); } -void vc_init_x509store(vc_x509store_t *store) { +void vc_openssl_init_x509store(vc_x509store_t *store) { static int sslinit; if (!sslinit++) { SSL_library_init(); @@ -243,7 +232,7 @@ static SSL_CTX *vc_create_sslctx(vc_x509store_t *vc_store) { return (ctx); } -int vc_tls_connect(int serverfd, vc_x509store_t *vc_store) { +int vc_openssl_connect(int serverfd, vc_x509store_t *vc_store) { SSL_CTX *ctx = vc_create_sslctx(vc_store); X509 *peercert = NULL; BIO *ssl_conn = NULL; @@ -261,6 +250,10 @@ int vc_tls_connect(int serverfd, vc_x509store_t *vc_store) { long j; + writecf(FS_SERV, "[SOCKET CONNECTED ]"); + writecf(FS_SERV, "[UPGRADING TO TLS ]"); + writecf(FS_SERV, "[TLS ENGINE OPENSSL ]"); + if (!ctx) goto all_errors; @@ -286,13 +279,13 @@ int vc_tls_connect(int serverfd, vc_x509store_t *vc_store) { cipher = SSL_get_current_cipher(sslp); if (cipher) { char cipher_desc[TMPSTRSIZE]; - snprintf(tmpstr, TMPSTRSIZE, "[SSL CIPHER ] %s", + snprintf(tmpstr, TMPSTRSIZE, "[SSL CIPHER ] %s", SSL_CIPHER_description(cipher, cipher_desc, TMPSTRSIZE)); writecf(FS_SERV, tmpstr); } else { snprintf( tmpstr, TMPSTRSIZE, - "[SSL ERROR ] Cipher not known / SSL object can't be queried!"); + "[SSL ERROR ] Cipher not known / SSL object can't be queried!"); writecf(FS_ERR, tmpstr); } @@ -302,10 +295,10 @@ int vc_tls_connect(int serverfd, vc_x509store_t *vc_store) { goto ssl_error; /* show basic information about peer cert */ - snprintf(tmpstr, TMPSTRSIZE, "[SSL SUBJECT ] %s", + snprintf(tmpstr, TMPSTRSIZE, "[SSL SUBJECT ] %s", X509_NAME_oneline(X509_get_subject_name(peercert), 0, 0)); writecf(FS_SERV, tmpstr); - snprintf(tmpstr, TMPSTRSIZE, "[SSL ISSUER ] %s", + snprintf(tmpstr, TMPSTRSIZE, "[SSL ISSUER ] %s", X509_NAME_oneline(X509_get_issuer_name(peercert), 0, 0)); writecf(FS_SERV, tmpstr); @@ -318,7 +311,7 @@ int vc_tls_connect(int serverfd, vc_x509store_t *vc_store) { fp += sprintf(fp, "%02X:", fingerprint_bin[j]); assert(fp > fingerprint); fp[-1] = 0; - snprintf(tmpstr, TMPSTRSIZE, "[SSL FINGERPRINT ] %s (from server)", + snprintf(tmpstr, TMPSTRSIZE, "[SSL FINGERPRINT ] %s (from server)", fingerprint); writecf(FS_SERV, tmpstr); @@ -333,12 +326,12 @@ int vc_tls_connect(int serverfd, vc_x509store_t *vc_store) { return 0; if (getintoption(CF_IGNSSL)) { - writecf(FS_ERR, "[SSL VERIFY ERROR ] FAILURE IGNORED!!!"); + writecf(FS_ERR, "[SSL VERIFY ERROR ] FAILURE IGNORED!!!"); return 0; } ssl_error: - snprintf(tmpstr, TMPSTRSIZE, "[SSL CONNECT ERROR] %s", + snprintf(tmpstr, TMPSTRSIZE, "[SSL CONNECT ERROR ] %s", ERR_error_string(ERR_get_error(), NULL)); writecf(FS_ERR, tmpstr); all_errors: @@ -396,18 +389,18 @@ X509_STORE *vc_x509store_create(vc_x509store_t *vc_store) { int vc_verify_callback(int ok, X509_STORE_CTX *store) { if (!ok) { - snprintf(tmpstr, TMPSTRSIZE, "[SSL VERIFY ERROR ] %s", + snprintf(tmpstr, TMPSTRSIZE, "[SSL VERIFY ERROR ] %s", X509_verify_cert_error_string(X509_STORE_CTX_get_error(store))); writecf(FS_ERR, tmpstr); } return (ok | getintoption(CF_IGNSSL)); } -ssize_t vc_tls_sendmessage(const void *buf, size_t size) { +ssize_t vc_openssl_sendmessage(const void *buf, size_t size) { return BIO_write(server_conn, buf, size); } -ssize_t vc_tls_receivemessage(void *buf, size_t size) { +ssize_t vc_openssl_receivemessage(void *buf, size_t size) { ssize_t received = (ssize_t)BIO_read(server_conn, buf, size); if (received != 0) return received; @@ -416,7 +409,7 @@ ssize_t vc_tls_receivemessage(void *buf, size_t size) { return 0; } -void vc_tls_cleanup() { +void vc_openssl_cleanup() { BIO_free_all(server_conn); server_conn = NULL; } @@ -451,9 +444,9 @@ typedef struct { } mbedstate; static mbedstate _mbedtls_state; -void vchat_tls_get_version_external() { +char *vc_mbedtls_version() { snprintf(tmpstr, sizeof(tmpstr), "%s", MBEDTLS_VERSION_STRING_FULL); - vchat_tls_version_external = strdup(tmpstr); + return strdup(tmpstr); } static int static_tcp_recv(void *ctx, unsigned char *buf, size_t len) { @@ -463,16 +456,13 @@ static int static_tcp_send(void *ctx, const unsigned char *buf, size_t len) { return send((int)(intptr_t)ctx, buf, len, 0); } static int map_openssl_suite(char *openssl_name); -void vc_init_x509store(vc_x509store_t *store) { - static int sslinit; - if (!sslinit++) { - mbedtls_entropy_init(&_mbedtls_state._entropy); - mbedtls_ctr_drbg_init(&_mbedtls_state._ctr_drbg); +void vc_mbedtls_init_x509store(vc_x509store_t *store) { + mbedtls_entropy_init(&_mbedtls_state._entropy); + mbedtls_ctr_drbg_init(&_mbedtls_state._ctr_drbg); - mbedtls_ctr_drbg_seed(&_mbedtls_state._ctr_drbg, mbedtls_entropy_func, - &_mbedtls_state._entropy, - (const unsigned char *)DRBG_PERS, sizeof(DRBG_PERS)); - } + mbedtls_ctr_drbg_seed(&_mbedtls_state._ctr_drbg, mbedtls_entropy_func, + &_mbedtls_state._entropy, + (const unsigned char *)DRBG_PERS, sizeof(DRBG_PERS)); memset(store, 0, sizeof(vc_x509store_t)); /* We want to make verifying the peer the default */ @@ -485,7 +475,7 @@ static void vc_tls_report_error(int error, char *message) { writecf(FS_ERR, tmpstr); } -int vc_tls_connect(int serverfd, vc_x509store_t *vc_store) { +int vc_mbedtls_connect(int serverfd, vc_x509store_t *vc_store) { /* Some aliases for shorter references */ mbedstate *s = &_mbedtls_state; mbedtls_ssl_config *conf = &_mbedtls_state._conf; @@ -502,6 +492,7 @@ int vc_tls_connect(int serverfd, vc_x509store_t *vc_store) { writecf(FS_SERV, "[SOCKET CONNECTED ]"); writecf(FS_SERV, "[UPGRADING TO TLS ]"); + writecf(FS_SERV, "[TLS ENGINE MBEDTLS ]"); if ((ret = mbedtls_ssl_config_defaults(conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, @@ -688,11 +679,11 @@ int vc_tls_connect(int serverfd, vc_x509store_t *vc_store) { return 0; } -ssize_t vc_tls_sendmessage(const void *buf, size_t size) { +ssize_t vc_mbedtls_sendmessage(const void *buf, size_t size) { return mbedtls_ssl_write(&_mbedtls_state._ssl, buf, size); } -ssize_t vc_tls_receivemessage(void *buf, size_t size) { +ssize_t vc_mbedtls_receivemessage(void *buf, size_t size) { ssize_t received = (ssize_t)mbedtls_ssl_read(&_mbedtls_state._ssl, buf, size); switch (received) { case MBEDTLS_ERR_SSL_WANT_READ: @@ -709,7 +700,7 @@ ssize_t vc_tls_receivemessage(void *buf, size_t size) { } } -void vc_tls_cleanup() { +void vc_mbedtls_cleanup() { mbedtls_x509_crt_free(&_mbedtls_state._cacert); mbedtls_x509_crt_free(&_mbedtls_state._cert); mbedtls_pk_free(&_mbedtls_state._key); diff --git a/vchat-tls.h b/vchat-tls.h index 17d2687..5399820 100755 --- a/vchat-tls.h +++ b/vchat-tls.h @@ -14,7 +14,6 @@ struct vc_x509store_t { }; typedef struct vc_x509store_t vc_x509store_t; -void vc_init_x509store(vc_x509store_t *); void vc_x509store_set_pkeycb(vc_x509store_t *, vc_askpass_cb_t); void vc_x509store_setflags(vc_x509store_t *, int); void vc_x509store_setkeyfile(vc_x509store_t *, char *); @@ -25,10 +24,28 @@ void vc_x509store_setcapath(vc_x509store_t *, char *); void vc_x509store_setcrlfile(vc_x509store_t *, char *); void vc_cleanup_x509store(vc_x509store_t *s); -int vc_tls_connect(int serverfd, vc_x509store_t *); -ssize_t vc_tls_sendmessage(const void *buf, size_t size); -ssize_t vc_tls_receivemessage(void *buf, size_t size); -void vc_tls_cleanup(); +#if !defined(TLS_LIB_OPENSSL) && !defined(TLS_LIB_MBEDTLS) +#error \ + "Neither TLS_LIB_OPENSSL nor TLS_LIB_MBEDTLS are defined. Please select exactly one." +#endif + +#ifdef TLS_LIB_OPENSSL +void vc_openssl_init_x509store(vc_x509store_t *); +int vc_openssl_connect(int serverfd, vc_x509store_t *); +ssize_t vc_openssl_sendmessage(const void *buf, size_t size); +ssize_t vc_openssl_receivemessage(void *buf, size_t size); +void vc_openssl_cleanup(); +char *vc_openssl_version(); +#endif + +#ifdef TLS_LIB_MBEDTLS +void vc_mbedtls_init_x509store(vc_x509store_t *); +int vc_mbedtls_connect(int serverfd, vc_x509store_t *); +ssize_t vc_mbedtls_sendmessage(const void *buf, size_t size); +ssize_t vc_mbedtls_receivemessage(void *buf, size_t size); +void vc_mbedtls_cleanup(); +char *vc_mbedtls_version(); +#endif #define VC_X509S_USE_CAFILE 0x01 #define VC_X509S_USE_CAPATH 0x02 diff --git a/vchat.h b/vchat.h index dbd5a9f..412566a 100755 --- a/vchat.h +++ b/vchat.h @@ -44,6 +44,7 @@ typedef enum { CF_FINGERPRINT, CF_PINFINGER, CF_USESSL, + CF_TLSLIB, CF_IGNSSL, CF_VERIFYSSL, CF_USECERT, @@ -243,5 +244,3 @@ typedef struct { /* vchat-tls.c */ extern const char *vchat_tls_version; -extern const char *vchat_tls_version_external; -void vchat_tls_get_version_external(); -- cgit v1.2.3