From a864fbf47a4f4d8c1e7f3c61af37e55ab8ecd403 Mon Sep 17 00:00:00 2001 From: Philipp Schafft Date: Sun, 6 Nov 2016 16:02:11 +0000 Subject: [PATCH] Make tls mode more configureable --- src/cfgfile.c | 36 +++++++++++++++++++++++++++++++++++- src/cfgfile.h | 2 +- src/connection.c | 17 +++++++++++++---- src/connection.h | 2 ++ 4 files changed, 51 insertions(+), 6 deletions(-) diff --git a/src/cfgfile.c b/src/cfgfile.c index a15307ca..66c424e3 100644 --- a/src/cfgfile.c +++ b/src/cfgfile.c @@ -234,6 +234,40 @@ static inline int __parse_public(const char *str) return util_str_to_bool(str); } +/* This converts TLS mode strings to (tlsmode_t). + * In older versions of Icecast2 this was just a bool. + * So we need to handle boolean values as well. + * See also: util_str_to_bool(). + */ +static tlsmode_t str_to_tlsmode(const char *str) { + /* consider NULL and empty strings as auto mode */ + if (!str || !*str) + return ICECAST_TLSMODE_AUTO; + + if (strcasecmp(str, "disabled") == 0) { + return ICECAST_TLSMODE_DISABLED; + } else if (strcasecmp(str, "auto") == 0) { + return ICECAST_TLSMODE_AUTO; + } else if (strcasecmp(str, "auto_no_plain") == 0) { + return ICECAST_TLSMODE_AUTO_NO_PLAIN; + } else if (strcasecmp(str, "rfc2817") == 0) { + return ICECAST_TLSMODE_RFC2817; + } else if (strcasecmp(str, "rfc2818") == 0 || + /* boolean-style values */ + strcasecmp(str, "true") == 0 || + strcasecmp(str, "yes") == 0 || + strcasecmp(str, "on") == 0 ) { + return ICECAST_TLSMODE_RFC2818; + } + + /* old style numbers: consider everyting non-zero RFC2818 */ + if (atoi(str)) + return ICECAST_TLSMODE_RFC2818; + + /* we default to auto mode */ + return ICECAST_TLSMODE_AUTO; +} + static void __append_old_style_auth(auth_stack_t **stack, const char *name, const char *type, @@ -1678,7 +1712,7 @@ static void _parse_listen_socket(xmlDocPtr doc, } else if (xmlStrcmp(node->name, XMLSTR("tls")) == 0 || xmlStrcmp(node->name, XMLSTR("ssl")) == 0) { tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); - listener->tls = util_str_to_bool(tmp); + listener->tls = str_to_tlsmode(tmp); if(tmp) xmlFree(tmp); } else if (xmlStrcmp(node->name, XMLSTR("shoutcast-compat")) == 0) { diff --git a/src/cfgfile.h b/src/cfgfile.h index e9a9ea42..f8e99322 100644 --- a/src/cfgfile.h +++ b/src/cfgfile.h @@ -172,7 +172,7 @@ typedef struct _listener_t { char *bind_address; int shoutcast_compat; char *shoutcast_mount; - int tls; + tlsmode_t tls; } listener_t; typedef struct ice_config_tag { diff --git a/src/connection.c b/src/connection.c index b9108d48..19ff4be9 100644 --- a/src/connection.c +++ b/src/connection.c @@ -445,7 +445,7 @@ static void process_request_queue (void) int len = PER_CLIENT_REFBUF_SIZE - 1 - node->offset; char *buf = client->refbuf->data + node->offset; - if (client->con->tlsmode == ICECAST_TLSMODE_AUTO) { + if (client->con->tlsmode == ICECAST_TLSMODE_AUTO || client->con->tlsmode == ICECAST_TLSMODE_AUTO_NO_PLAIN) { if (recv(client->con->sock, &peak, 1, MSG_PEEK) == 1) { if (peak == 0x16) { /* TLS Record Protocol Content type 0x16 == Handshake */ connection_uses_tls(client->con); @@ -549,7 +549,8 @@ static client_queue_t *create_client_node(client_t *client) if (listener) { if (listener->shoutcast_compat) node->shoutcast = 1; - if (listener->tls && tls_ok) + client->con->tlsmode = listener->tls; + if (listener->tls == ICECAST_TLSMODE_RFC2818 && tls_ok) connection_uses_tls(client->con); if (listener->shoutcast_mount) node->shoutcast_mount = strdup(listener->shoutcast_mount); @@ -1339,8 +1340,16 @@ static void _handle_connection(void) upgrade = httpp_getvar(parser, "upgrade"); connection = httpp_getvar(parser, "connection"); - if (upgrade && connection && strstr(upgrade, "TLS/1.0") != NULL && strcasecmp(connection, "upgrade") == 0) { - client_send_101(client, ICECAST_REUSE_UPGRADETLS); + if (upgrade && connection && strcasecmp(connection, "upgrade") == 0) { + if (client->con->tlsmode == ICECAST_TLSMODE_DISABLED || strstr(upgrade, "TLS/1.0") == NULL) { + client_send_error(client, 400, 1, "Can not upgrade protocol"); + continue; + } else { + client_send_101(client, ICECAST_REUSE_UPGRADETLS); + continue; + } + } else if (client->con->tlsmode != ICECAST_TLSMODE_DISABLED && client->con->tlsmode != ICECAST_TLSMODE_AUTO && !client->con->tls) { + client_send_426(client, ICECAST_REUSE_UPGRADETLS); continue; } diff --git a/src/connection.h b/src/connection.h index 8ce486b9..271b0dea 100644 --- a/src/connection.h +++ b/src/connection.h @@ -33,6 +33,8 @@ typedef enum _tlsmode_tag { ICECAST_TLSMODE_DISABLED = 0, /* TLS mode is to be detected */ ICECAST_TLSMODE_AUTO, + /* Like ICECAST_TLSMODE_AUTO but enforces TLS */ + ICECAST_TLSMODE_AUTO_NO_PLAIN, /* TLS via HTTP Upgrade:-header [RFC2817] */ ICECAST_TLSMODE_RFC2817, /* TLS for transport layer like HTTPS [RFC2818] does */