summaryrefslogtreecommitdiffstats
path: root/lib/libshout-idjc/src/tls.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libshout-idjc/src/tls.c')
-rw-r--r--lib/libshout-idjc/src/tls.c306
1 files changed, 155 insertions, 151 deletions
diff --git a/lib/libshout-idjc/src/tls.c b/lib/libshout-idjc/src/tls.c
index e0e5c1a5f0..034238aafd 100644
--- a/lib/libshout-idjc/src/tls.c
+++ b/lib/libshout-idjc/src/tls.c
@@ -20,228 +20,232 @@
*/
#ifdef HAVE_CONFIG_H
- #include <config.h>
+# include <config.h>
#endif
-#include <shout/shout.h>
+#include <shoutidjc/shout.h>
#include <string.h>
#include "shout_private.h"
#ifndef XXX_HAVE_X509_check_host
-#include <ctype.h>
+# include <ctype.h>
#endif
struct _shout_tls {
- SSL_CTX *ssl_ctx;
- SSL *ssl;
- int ssl_ret;
- /* only pointers into self, don't need to free them */
- sock_t socket;
- const char *host;
- const char *ca_directory;
- const char *ca_file;
- const char *allowed_ciphers;
- const char *client_certificate;
+ SSL_CTX *ssl_ctx;
+ SSL *ssl;
+ int ssl_ret;
+ /* only pointers into self, don't need to free them */
+ sock_t socket;
+ const char *host;
+ const char *ca_directory;
+ const char *ca_file;
+ const char *allowed_ciphers;
+ const char *client_certificate;
};
shout_tls_t *shout_tls_new(shout_t *self, sock_t socket)
{
- shout_tls_t *tls = calloc(1, sizeof(shout_tls_t));
- if (!tls)
- return NULL;
-
- tls->socket = socket;
- tls->host = self->host;
- tls->ca_directory = self->ca_directory;
- tls->ca_file = self->ca_file;
- tls->allowed_ciphers = self->allowed_ciphers;
- tls->client_certificate = self->client_certificate;
-
- return tls;
+ shout_tls_t *tls = calloc(1, sizeof(shout_tls_t));
+ if (!tls)
+ return NULL;
+
+ tls->socket = socket;
+ tls->host = self->host;
+ tls->ca_directory = self->ca_directory;
+ tls->ca_file = self->ca_file;
+ tls->allowed_ciphers = self->allowed_ciphers;
+ tls->client_certificate = self->client_certificate;
+
+ return tls;
}
static inline int tls_setup(shout_tls_t *tls)
{
- const SSL_METHOD *meth;
+ const SSL_METHOD *meth;
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER)
- SSL_library_init();
- SSL_load_error_strings();
- SSLeay_add_all_algorithms();
- SSLeay_add_ssl_algorithms();
+ SSL_library_init();
+ SSL_load_error_strings();
+ SSLeay_add_all_algorithms();
+ SSLeay_add_ssl_algorithms();
- meth = SSLv23_client_method();
+ meth = SSLv23_client_method();
#else
- meth = TLS_client_method();
+ meth = TLS_client_method();
#endif
- if (!meth)
- goto error;
+ if (!meth)
+ goto error;
- tls->ssl_ctx = SSL_CTX_new(meth);
- if (!tls->ssl_ctx)
- goto error;
+ tls->ssl_ctx = SSL_CTX_new(meth);
+ if (!tls->ssl_ctx)
+ goto error;
- SSL_CTX_set_default_verify_paths(tls->ssl_ctx);
- SSL_CTX_load_verify_locations(tls->ssl_ctx, tls->ca_file, tls->ca_directory);
+ SSL_CTX_set_default_verify_paths(tls->ssl_ctx);
+ SSL_CTX_load_verify_locations(tls->ssl_ctx, tls->ca_file, tls->ca_directory);
- SSL_CTX_set_verify(tls->ssl_ctx, SSL_VERIFY_NONE, NULL);
+ SSL_CTX_set_verify(tls->ssl_ctx, SSL_VERIFY_NONE, NULL);
- if (tls->client_certificate) {
- if (SSL_CTX_use_certificate_file(tls->ssl_ctx, tls->client_certificate, SSL_FILETYPE_PEM) != 1)
- goto error;
- if (SSL_CTX_use_PrivateKey_file(tls->ssl_ctx, tls->client_certificate, SSL_FILETYPE_PEM) != 1)
- goto error;
- }
+ if (tls->client_certificate) {
+ if (SSL_CTX_use_certificate_file(tls->ssl_ctx, tls->client_certificate, SSL_FILETYPE_PEM) != 1)
+ goto error;
+ if (SSL_CTX_use_PrivateKey_file(tls->ssl_ctx, tls->client_certificate, SSL_FILETYPE_PEM) != 1)
+ goto error;
+ }
- if (SSL_CTX_set_cipher_list(tls->ssl_ctx, tls->allowed_ciphers) <= 0)
- goto error;
+ if (SSL_CTX_set_cipher_list(tls->ssl_ctx, tls->allowed_ciphers) <= 0)
+ goto error;
- SSL_CTX_set_mode(tls->ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
- SSL_CTX_set_mode(tls->ssl_ctx, SSL_MODE_AUTO_RETRY);
+ SSL_CTX_set_mode(tls->ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
+ SSL_CTX_set_mode(tls->ssl_ctx, SSL_MODE_AUTO_RETRY);
- tls->ssl = SSL_new(tls->ssl_ctx);
- if (!tls->ssl)
- goto error;
+ tls->ssl = SSL_new(tls->ssl_ctx);
+ if (!tls->ssl)
+ goto error;
- if (!SSL_set_fd(tls->ssl, tls->socket))
- goto error;
+ if (!SSL_set_fd(tls->ssl, tls->socket))
+ goto error;
- SSL_set_tlsext_host_name(tls->ssl, tls->host);
- SSL_set_connect_state(tls->ssl);
- tls->ssl_ret = SSL_connect(tls->ssl);
+ SSL_set_tlsext_host_name(tls->ssl, tls->host);
+ SSL_set_connect_state(tls->ssl);
+ tls->ssl_ret = SSL_connect(tls->ssl);
- return SHOUTERR_SUCCESS;
+ return SHOUTERR_SUCCESS;
- error:
- if (tls->ssl)
- SSL_free(tls->ssl);
- if (tls->ssl_ctx)
- SSL_CTX_free(tls->ssl_ctx);
- return SHOUTERR_UNSUPPORTED;
+error:
+ if (tls->ssl)
+ SSL_free(tls->ssl);
+ if (tls->ssl_ctx)
+ SSL_CTX_free(tls->ssl_ctx);
+ return SHOUTERR_UNSUPPORTED;
}
#ifndef XXX_HAVE_X509_check_host
static inline int tls_check_pattern(const char *key, const char *pattern)
{
- for (; *key && *pattern; key++) {
- if (*pattern == '*') {
- for (; *pattern == '*'; pattern++);
- for (; *key && *key != '.'; key++);
- if (!*pattern && !*key)
- return 1;
- if (!*pattern || !*key)
- return 0;
- }
-
- if (tolower(*key) != tolower(*pattern))
- return 0;
- pattern++;
- }
-
- return *key == 0 && *pattern == 0;
+ for (; *key && *pattern; key++) {
+ if (*pattern == '*') {
+ for (; *pattern == '*'; pattern++) ;
+ for (; *key && *key != '.'; key++) ;
+ if (!*pattern && !*key)
+ return 1;
+ if (!*pattern || !*key)
+ return 0;
+ }
+
+ if (tolower(*key) != tolower(*pattern))
+ return 0;
+ pattern++;
+ }
+ return *key == 0 && *pattern == 0;
}
+
static inline int tls_check_host(X509 *cert, const char *hostname)
{
- char common_name[256] = "";
- X509_NAME *xname = X509_get_subject_name(cert);
- X509_NAME_ENTRY *xentry;
- ASN1_STRING *sdata;
- int i, j;
- int ret;
-
- ret = X509_NAME_get_text_by_NID(xname, NID_commonName, common_name, sizeof(common_name));
- if (ret < 1 || (size_t)ret >= (sizeof(common_name)-1))
- return SHOUTERR_TLSBADCERT;
-
- if (!tls_check_pattern(hostname, common_name))
- return SHOUTERR_TLSBADCERT;
-
- /* check for inlined \0, see https://www.blackhat.com/html/bh-usa-09/bh-usa-09-archives.html#Marlinspike */
- for (i = -1; ; i = j) {
- j = X509_NAME_get_index_by_NID(xname, NID_commonName, i);
- if (j == -1)
- break;
- }
-
- xentry = X509_NAME_get_entry(xname, i);
- sdata = X509_NAME_ENTRY_get_data(xentry);
-
- if ((size_t)ASN1_STRING_length(sdata) != strlen(common_name))
- return SHOUTERR_TLSBADCERT;
-
- return SHOUTERR_SUCCESS;
+ char common_name[256] = "";
+ X509_NAME *xname = X509_get_subject_name(cert);
+ X509_NAME_ENTRY *xentry;
+ ASN1_STRING *sdata;
+ int i, j;
+ int ret;
+
+ ret = X509_NAME_get_text_by_NID(xname, NID_commonName, common_name, sizeof(common_name));
+ if (ret < 1 || (size_t)ret >= (sizeof(common_name)-1))
+ return SHOUTERR_TLSBADCERT;
+
+ if (!tls_check_pattern(hostname, common_name))
+ return SHOUTERR_TLSBADCERT;
+
+ /* check for inlined \0,
+ * see https://www.blackhat.com/html/bh-usa-09/bh-usa-09-archives.html#Marlinspike
+ */
+ for (i = -1; ; i = j) {
+ j = X509_NAME_get_index_by_NID(xname, NID_commonName, i);
+ if (j == -1)
+ break;
+ }
+
+ xentry = X509_NAME_get_entry(xname, i);
+ sdata = X509_NAME_ENTRY_get_data(xentry);
+
+ if ((size_t)ASN1_STRING_length(sdata) != strlen(common_name))
+ return SHOUTERR_TLSBADCERT;
+
+ return SHOUTERR_SUCCESS;
}
#endif
static inline int tls_check_cert(shout_tls_t *tls)
{
- X509 *cert = SSL_get_peer_certificate(tls->ssl);
- int cert_ok = 0;
- if (!cert)
- return SHOUTERR_TLSBADCERT;
+ X509 *cert = SSL_get_peer_certificate(tls->ssl);
+ int cert_ok = 0;
+ if (!cert)
+ return SHOUTERR_TLSBADCERT;
- do {
- if (SSL_get_verify_result(tls->ssl) != X509_V_OK)
- break;
+ do {
+ if (SSL_get_verify_result(tls->ssl) != X509_V_OK)
+ break;
#ifdef XXX_HAVE_X509_check_host
- if (X509_check_host(cert, tls->host, 0, 0, NULL) != 1)
- break;
+ if (X509_check_host(cert, tls->host, 0, 0, NULL) != 1)
+ break;
#else
- if (tls_check_host(cert, tls->host) != SHOUTERR_SUCCESS)
- break;
+ if (tls_check_host(cert, tls->host) != SHOUTERR_SUCCESS)
+ break;
#endif
- /* ok, all test passed... */
- cert_ok = 1;
- } while (0);
+ /* ok, all test passed... */
+ cert_ok = 1;
+ } while (0);
- X509_free(cert);
- return cert_ok ? SHOUTERR_SUCCESS : SHOUTERR_TLSBADCERT;
+ X509_free(cert);
+ return cert_ok ? SHOUTERR_SUCCESS : SHOUTERR_TLSBADCERT;
}
static inline int tls_setup_process(shout_tls_t *tls)
{
- if (SSL_is_init_finished(tls->ssl))
- return tls_check_cert(tls);
- tls->ssl_ret = SSL_connect(tls->ssl);
- if (SSL_is_init_finished(tls->ssl))
- return tls_check_cert(tls);
- return SHOUTERR_BUSY;
+ if (SSL_is_init_finished(tls->ssl))
+ return tls_check_cert(tls);
+ tls->ssl_ret = SSL_connect(tls->ssl);
+ if (SSL_is_init_finished(tls->ssl))
+ return tls_check_cert(tls);
+ return SHOUTERR_BUSY;
}
int shout_tls_try_connect(shout_tls_t *tls)
{
- if (!tls->ssl)
- tls_setup(tls);
- if (tls->ssl)
- return tls_setup_process(tls);
- return SHOUTERR_UNSUPPORTED;
+ if (!tls->ssl)
+ tls_setup(tls);
+ if (tls->ssl)
+ return tls_setup_process(tls);
+ return SHOUTERR_UNSUPPORTED;
}
-int shout_tls_close(shout_tls_t *tls) {
- if (tls->ssl) {
- SSL_shutdown(tls->ssl);
- SSL_free(tls->ssl);
- }
- if (tls->ssl_ctx)
- SSL_CTX_free(tls->ssl_ctx);
- free(tls);
- return SHOUTERR_SUCCESS;
+
+int shout_tls_close(shout_tls_t *tls)
+{
+ if (tls->ssl) {
+ SSL_shutdown(tls->ssl);
+ SSL_free(tls->ssl);
+ }
+ if (tls->ssl_ctx)
+ SSL_CTX_free(tls->ssl_ctx);
+ free(tls);
+ return SHOUTERR_SUCCESS;
}
ssize_t shout_tls_read(shout_tls_t *tls, void *buf, size_t len)
{
- return tls->ssl_ret = SSL_read(tls->ssl, buf, len);
+ return tls->ssl_ret = SSL_read(tls->ssl, buf, len);
}
ssize_t shout_tls_write(shout_tls_t *tls, const void *buf, size_t len)
{
- return tls->ssl_ret = SSL_write(tls->ssl, buf, len);
+ return tls->ssl_ret = SSL_write(tls->ssl, buf, len);
}
int shout_tls_recoverable(shout_tls_t *tls)
{
- int error = SSL_get_error(tls->ssl, tls->ssl_ret);
- if (error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE)
- return 1;
- return 0;
+ int error = SSL_get_error(tls->ssl, tls->ssl_ret);
+ if (error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE)
+ return 1;
+ return 0;
}