Commit 3c40ec18 authored by Philipp Schafft's avatar Philipp Schafft 🦁

Feature: Expose TLS options via config file.

This exposes TLS options of libshout via config file.
Documentation has been updated but example config files have been
left out. They should be updated as well. Keeping in mind not to
blow them up too much.

See: #2152
parent e2d1f68d
......@@ -138,6 +138,11 @@
port
password
mount
tls-mode
ca-directory
ca-certificate
allowed-ciphers
client-certificate
yp
resample
downmix
......@@ -167,6 +172,41 @@
they must begin with / and for the sake of certain listening clients should
end with the .ogg extension.
</div>
<h4>tls-mode</h4>
<div class=indentedbox>
Controls if the server should use a encrypted and authenticated connection
to the Icecast server. Supported modes are "auto" (default mode) in which
TLS is used if supported by the server, "auto_no_plain" in which TLS is forced
but modes supported by the server is still autodetected, "RFC2818" which uses
TLS sockets and "RFC2817" to use the HTTP "Upgrade:" mechanism.
<b>This requires TLS support compiled into libshout.</b>
</div>
<h4>ca-directory</h4>
<div class=indentedbox>
This sets the directory holding certificates of certification authorities used
to verify the server. Default is to use operating system's defaults.
<b>This requires TLS support compiled into libshout.</b>
</div>
<h4>ca-certificate</h4>
<div class=indentedbox>
In contrast to the ca-directory option this allows to set a single certificate used
to verify the server. Default is to use operating system's defaults.
<b>This requires TLS support compiled into libshout.</b>
</div>
<h4>allowed-ciphers</h4>
<div class=indentedbox>
For encrypted and authenticated connections this controls what ciphers may be used.
Do not set this option if you do not really know what you are doing. This can easily
break setup and security.
<b>This requires TLS support compiled into libshout.</b>
</div>
<h4>client-certificate</h4>
<div class=indentedbox>
On a TLS connection the client can authenticate to the server using a certificate.
This option allows to set such an certificate. This is a file in PEM format
containing both the certificate as well as the private key.
<b>This requires TLS support compiled into libshout.</b>
</div>
<h4>yp</h4>
<div class=indentedbox>
By default streams will not be advertised on a YP server unless this is set,
......
......@@ -42,6 +42,13 @@
#define DEFAULT_PLAYLIST_MODULE "playlist"
#define DEFAULT_HOSTNAME "localhost"
#define DEFAULT_PORT 8000
#if SHOUT_TLS
#define DEFAULT_TLS SHOUT_TLS_AUTO
#define DEFAULT_CA_DIRECTORY NULL /* NULL = use system default */
#define DEFAULT_CA_CERTIFICATE NULL /* NULL = use system default */
#define DEFAULT_ALLOWED_CIPHERS NULL /* must be NULL according to libshout specs */
#define DEFAULT_CLIENT_CERTIFICATE NULL /* NULL = no client cert */
#endif
#define DEFAULT_PASSWORD "password"
#define DEFAULT_USERNAME NULL
#define DEFAULT_MOUNT "/stream.ogg"
......@@ -89,6 +96,21 @@
(x) = (char *)xmlGetProp(node, p);\
} while (0)
#if SHOUT_TLS
#define SET_TLSMODE(x) \
do {\
char *tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);\
if (tmp) {\
if (strcasecmp(tmp,"DISABLED")==0)(x) = SHOUT_TLS_DISABLED;\
else if (strcasecmp(tmp,"AUTO")==0)(x) = SHOUT_TLS_AUTO;\
else if (strcasecmp(tmp,"AUTO_NO_PLAIN")==0)(x) = SHOUT_TLS_AUTO_NO_PLAIN;\
else if (strcasecmp(tmp,"RFC2818")==0)(x) = SHOUT_TLS_RFC2818;\
else if (strcasecmp(tmp,"RFC2817")==0)(x) = SHOUT_TLS_RFC2817;\
xmlFree(tmp);\
}\
} while (0)
#endif
/* this is the global config variable */
config_t *ices_config;
......@@ -116,6 +138,12 @@ void config_free_instance(instance_t *instance)
if (instance->password) xmlFree(instance->password);
if (instance->user) xmlFree(instance->user);
if (instance->mount) xmlFree(instance->mount);
#if SHOUT_TLS
if (instance->ca_directory) xmlFree(instance->ca_directory);
if (instance->ca_certificate) xmlFree(instance->ca_certificate);
if (instance->allowed_ciphers) xmlFree(instance->allowed_ciphers);
if (instance->client_certificate) xmlFree(instance->client_certificate);
#endif
if (instance->queue)
{
thread_mutex_destroy(&instance->queue->lock);
......@@ -127,6 +155,13 @@ static void _set_instance_defaults(instance_t *instance)
{
instance->hostname = xmlStrdup(DEFAULT_HOSTNAME);
instance->port = DEFAULT_PORT;
#if SHOUT_TLS
instance->tls = DEFAULT_TLS;
instance->ca_directory = DEFAULT_CA_DIRECTORY;
instance->ca_certificate = DEFAULT_CA_CERTIFICATE;
instance->allowed_ciphers = DEFAULT_ALLOWED_CIPHERS;
instance->client_certificate = DEFAULT_CLIENT_CERTIFICATE;
#endif
instance->password = xmlStrdup(DEFAULT_PASSWORD);
instance->user = DEFAULT_USERNAME;
instance->mount = xmlStrdup(DEFAULT_MOUNT);
......@@ -245,6 +280,18 @@ static void _parse_instance(config_t *config, xmlDocPtr doc, xmlNodePtr node)
SET_STRING(instance->hostname);
else if (strcmp(node->name, "port") == 0)
SET_INT(instance->port);
#if SHOUT_TLS
else if (strcmp(node->name, "tls-mode") == 0)
SET_TLSMODE(instance->tls);
else if (strcmp(node->name, "ca-directory") == 0)
SET_STRING(instance->ca_directory);
else if (strcmp(node->name, "ca-certificate") == 0)
SET_STRING(instance->ca_certificate);
else if (strcmp(node->name, "allowed-ciphers") == 0)
SET_STRING(instance->allowed_ciphers);
else if (strcmp(node->name, "client-certificate") == 0)
SET_STRING(instance->client_certificate);
#endif
else if (strcmp(node->name, "password") == 0)
SET_STRING(instance->password);
else if (strcmp(node->name, "username") == 0)
......
......@@ -33,6 +33,13 @@ typedef struct _instance_tag
{
char *hostname;
int port;
#if SHOUT_TLS
int tls;
char *ca_directory;
char *ca_certificate;
char *allowed_ciphers;
char *client_certificate;
#endif
char *password;
char *user;
char *mount;
......
......@@ -80,6 +80,44 @@ void *ices_instance_stream(void *arg)
}
shout_set_port(sdsc->shout, stream->port);
#if SHOUT_TLS
if (!(shout_set_tls(sdsc->shout, stream->tls)) == SHOUTERR_SUCCESS) {
LOG_ERROR1("libshout error: %s\n", shout_get_error(sdsc->shout));
stream->died = 1;
return NULL;
}
if (stream->ca_directory)
if (!(shout_set_ca_directory(sdsc->shout, stream->ca_directory)) == SHOUTERR_SUCCESS) {
LOG_ERROR1("libshout error: %s\n", shout_get_error(sdsc->shout));
stream->died = 1;
return NULL;
}
if (stream->ca_certificate)
if (!(shout_set_ca_certificate(sdsc->shout, stream->ca_certificate)) == SHOUTERR_SUCCESS) {
LOG_ERROR1("libshout error: %s\n", shout_get_error(sdsc->shout));
stream->died = 1;
return NULL;
}
if (stream->allowed_ciphers)
if (!(shout_set_allowed_ciphers(sdsc->shout, stream->allowed_ciphers)) == SHOUTERR_SUCCESS) {
LOG_ERROR1("libshout error: %s\n", shout_get_error(sdsc->shout));
stream->died = 1;
return NULL;
}
if (stream->client_certificate)
if (!(shout_set_client_certificate(sdsc->shout, stream->client_certificate)) == SHOUTERR_SUCCESS) {
LOG_ERROR1("libshout error: %s\n", shout_get_error(sdsc->shout));
stream->died = 1;
return NULL;
}
#endif
if (!(shout_set_password(sdsc->shout, stream->password)) == SHOUTERR_SUCCESS) {
LOG_ERROR1("libshout error: %s\n", shout_get_error(sdsc->shout));
stream->died = 1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment