1
0
mirror of https://gitlab.xiph.org/xiph/ezstream.git synced 2024-11-03 04:17:18 -05:00

Update TLS configuration to match libshout requirements

This commit is contained in:
Moritz Grimm 2016-03-04 18:20:17 +01:00
parent 57749b4d73
commit a337c74ea4
8 changed files with 139 additions and 42 deletions

View File

@ -172,33 +172,52 @@ Default:
.It Sy \&<password\ /\&> .It Sy \&<password\ /\&>
.Pq Mandatory. .Pq Mandatory.
Password to authenticate with on the server. Password to authenticate with on the server.
.It Sy \&<tls\ /\&>
Configure the TLS encryption requirement for the server connection.
Possible values are:
.Pp
.Bl -tag -width 0|NO|FALSE -compact
.It Ar None
No TLS encryption will be attempted.
.It Ar May
Opportunistic TLS encryption may be used, if the server supports it
.Pq the default .
.It Ar Required
TLS encryption is required.
This is the only setting that is providing security against both passive and
active attackers.
.El
.It Sy \&<tls_cipher_suite\ /\&>
Configure allowed cipher suites for TLS.
.Pp
For example (modern cipher suites, PFS, no deprecated algorithms):
.Sy HIGH:!kRSA:!kECDH:!DH:!PKS:!aNULL:!eNULL:!3DES:!MD5:!SHA:!TLSv1 .
.Pp
Default:
.Em libshout default cipher suite
.It Sy \&<ca_dir\ /\&> .It Sy \&<ca_dir\ /\&>
Directory in which OpenSSL finds root CA certificates for validating the Directory in which OpenSSL finds root CA certificates for validating the
.Ar HTTPS .Ar HTTPS
server identity. server identity.
.Pp .Pp
Default: Default:
.Em no server validation .Em system default
.It Sy \&<ca_file\ /\&> .It Sy \&<ca_file\ /\&>
Path of a root CA bundle file for validating the Path of a root CA bundle file for validating the
.Ar HTTPS .Ar HTTPS
server identity. server identity.
.Pp .Pp
Default: Default:
.Em no server validation .Em system default
.It Sy \&<client_cert\ /\&> .It Sy \&<client_cert\ /\&>
X.503 client certificate for authentication on an X.503 client certificate and key
.Pq in PEM format containing both certificate and key in the same file
for authentication on an
.Ar HTTPS .Ar HTTPS
server. server.
.Pp .Pp
Default: Default:
.Em no client certificate authentication .Em no client certificate authentication
.It Sy \&<client_key\ /\&>
Private key that matches the public key and certificate in
.Sy \&<client_cert\ /\&> .
.Pp
Default:
.Em no client certificate authentication
.It Sy \&<reconnect_attempts\ /\&> .It Sy \&<reconnect_attempts\ /\&>
Number of reconnect attempts in case of connection issues with the server, Number of reconnect attempts in case of connection issues with the server,
or 0 or 0

View File

@ -26,9 +26,20 @@
<!-- Login password (check file permissions, or everyone can see this) --> <!-- Login password (check file permissions, or everyone can see this) -->
<password>hackme</password> <password>hackme</password>
<!--
Configure TLS encryption requirement: none, may (default), required
-->
<tls>Required</tls>
<!--
Configure allowed cipher suites for TLS other than the libshout default.
See openssl(1)/ciphers(1) for details.
-->
<tls_cipher_suite>HIGH:!kRSA:!kECDH:!DH:!PKS:!aNULL:!eNULL:!3DES:!MD5:!SHA:!TLSv1</tls_cipher_suite>
<!-- <!--
Directory to use for server certificate verification in "hash format". Directory to use for server certificate verification in "hash format".
See openssl(1)/verify(1) for details: See openssl(1)/verify(1) for details.
--> -->
<ca_dir>/etc/ssl/certs</ca_dir> <ca_dir>/etc/ssl/certs</ca_dir>
@ -38,12 +49,12 @@
--> -->
<ca_file>/etc/ssl/certs/ca-certificates.crt</ca_file> <ca_file>/etc/ssl/certs/ca-certificates.crt</ca_file>
<!-- Client certificate (with public key) for authentication --> <!--
X.503 client certificate, in PEM format, containing both certificate
(with public key) and private key in the same file, for authentication.
-->
<client_cert>/etc/ssl/ezstream.crt</client_cert> <client_cert>/etc/ssl/ezstream.crt</client_cert>
<!-- Client private key for authentication -->
<client_key>/etc/ssl/private/ezstream.key</client_key>
<!-- Number of reconnection attempts, before giving up: --> <!-- Number of reconnection attempts, before giving up: -->
<reconnect_attempts>0</reconnect_attempts> <reconnect_attempts>0</reconnect_attempts>
</server> </server>

View File

@ -366,6 +366,36 @@ cfg_set_server_password(const char *password, const char **errstrp)
return (0); return (0);
} }
int
cfg_set_server_tls(const char *tls, const char **errstrp)
{
if (!tls || !tls[0]) {
if (errstrp)
*errstrp = "empty";
return (-1);
}
if (0 == strcasecmp("may", tls))
cfg.server.tls = CFG_TLS_MAY;
else if (0 == strcasecmp("none", tls))
cfg.server.tls = CFG_TLS_NONE;
else if (0 == strcasecmp("required", tls))
cfg.server.tls = CFG_TLS_REQUIRED;
else {
if (NULL != errstrp)
*errstrp = "invalid";
return (-1);
}
return (0);
}
int
cfg_set_server_tls_cipher_suite(const char *suite, const char **errstrp)
{
SET_STRLCPY(cfg.server.tls_cipher_suite, suite, errstrp);
return (0);
}
int int
cfg_set_server_ca_dir(const char *ca_dir, const char **errstrp) cfg_set_server_ca_dir(const char *ca_dir, const char **errstrp)
{ {
@ -387,13 +417,6 @@ cfg_set_server_client_cert(const char *client_cert, const char **errstrp)
return (0); return (0);
} }
int
cfg_set_server_client_key(const char *client_key, const char **errstrp)
{
SET_STRLCPY(cfg.server.client_key, client_key, errstrp);
return (0);
}
int int
cfg_set_server_reconnect_attempts(const char *num_str, const char **errstrp) cfg_set_server_reconnect_attempts(const char *num_str, const char **errstrp)
{ {
@ -681,6 +704,20 @@ cfg_get_server_password(void)
return (cfg.server.password[0] ? cfg.server.password : NULL); return (cfg.server.password[0] ? cfg.server.password : NULL);
} }
enum cfg_server_tls
cfg_get_server_tls(void)
{
return (cfg.server.tls);
}
const char *
cfg_get_server_tls_cipher_suite(void)
{
return (cfg.server.tls_cipher_suite[0]
? cfg.server.tls_cipher_suite
: NULL);
}
const char * const char *
cfg_get_server_ca_dir(void) cfg_get_server_ca_dir(void)
{ {
@ -699,12 +736,6 @@ cfg_get_server_client_cert(void)
return (cfg.server.client_cert[0] ? cfg.server.client_cert : NULL); return (cfg.server.client_cert[0] ? cfg.server.client_cert : NULL);
} }
const char *
cfg_get_server_client_key(void)
{
return (cfg.server.client_key[0] ? cfg.server.client_key : NULL);
}
unsigned int unsigned int
cfg_get_server_reconnect_attempts(void) cfg_get_server_reconnect_attempts(void)
{ {

View File

@ -40,6 +40,14 @@ enum cfg_server_protocol {
CFG_PROTO_MAX = CFG_PROTO_HTTPS, CFG_PROTO_MAX = CFG_PROTO_HTTPS,
}; };
enum cfg_server_tls {
CFG_TLS_MAY = 0,
CFG_TLS_NONE,
CFG_TLS_REQUIRED,
CFG_TLS_MIN = CFG_TLS_MAY,
CFG_TLS_MAX = CFG_TLS_REQUIRED,
};
enum cfg_media_type { enum cfg_media_type {
CFG_MEDIA_AUTODETECT = 0, CFG_MEDIA_AUTODETECT = 0,
CFG_MEDIA_FILE, CFG_MEDIA_FILE,
@ -91,10 +99,11 @@ int cfg_set_server_hostname(const char *, const char **);
int cfg_set_server_port(const char *, const char **); int cfg_set_server_port(const char *, const char **);
int cfg_set_server_user(const char *, const char **); int cfg_set_server_user(const char *, const char **);
int cfg_set_server_password(const char *, const char **); int cfg_set_server_password(const char *, const char **);
int cfg_set_server_tls(const char *, const char **);
int cfg_set_server_tls_cipher_suite(const char *, const char **);
int cfg_set_server_ca_dir(const char *, const char **); int cfg_set_server_ca_dir(const char *, const char **);
int cfg_set_server_ca_file(const char *, const char **); int cfg_set_server_ca_file(const char *, const char **);
int cfg_set_server_client_cert(const char *, const char **); int cfg_set_server_client_cert(const char *, const char **);
int cfg_set_server_client_key(const char *, const char **);
int cfg_set_server_reconnect_attempts(const char *, const char **); int cfg_set_server_reconnect_attempts(const char *, const char **);
int cfg_set_stream_mountpoint(const char *, const char **); int cfg_set_stream_mountpoint(const char *, const char **);
@ -144,14 +153,16 @@ const char *
cfg_get_server_user(void); cfg_get_server_user(void);
const char * const char *
cfg_get_server_password(void); cfg_get_server_password(void);
enum cfg_server_tls
cfg_get_server_tls(void);
const char *
cfg_get_server_tls_cipher_suite(void);
const char * const char *
cfg_get_server_ca_dir(void); cfg_get_server_ca_dir(void);
const char * const char *
cfg_get_server_ca_file(void); cfg_get_server_ca_file(void);
const char * const char *
cfg_get_server_client_cert(void); cfg_get_server_client_cert(void);
const char *
cfg_get_server_client_key(void);
unsigned int unsigned int
cfg_get_server_reconnect_attempts(void); cfg_get_server_reconnect_attempts(void);

View File

@ -26,6 +26,7 @@
#define EXTENSIONS_MAX 16 #define EXTENSIONS_MAX 16
#define UCREDS_SIZE 256 #define UCREDS_SIZE 256
#define CSUITE_SIZE 2048
#define DEFAULT_PORT 8000 #define DEFAULT_PORT 8000
#define DEFAULT_USER "source" #define DEFAULT_USER "source"
@ -46,10 +47,11 @@ struct cfg {
unsigned int port; unsigned int port;
char user[UCREDS_SIZE]; char user[UCREDS_SIZE];
char password[UCREDS_SIZE]; char password[UCREDS_SIZE];
enum cfg_server_tls tls;
char tls_cipher_suite[CSUITE_SIZE];
char ca_dir[PATH_MAX]; char ca_dir[PATH_MAX];
char ca_file[PATH_MAX]; char ca_file[PATH_MAX];
char client_cert[PATH_MAX]; char client_cert[PATH_MAX];
char client_key[PATH_MAX];
unsigned int reconnect_attempts; unsigned int reconnect_attempts;
} server; } server;
struct stream { struct stream {

View File

@ -64,9 +64,11 @@ _cfg_xmlfile_parse_server(xmlDocPtr doc, xmlNodePtr cur)
XML_STRCONFIG("server", cfg_set_server_port, "port"); XML_STRCONFIG("server", cfg_set_server_port, "port");
XML_STRCONFIG("server", cfg_set_server_user, "user"); XML_STRCONFIG("server", cfg_set_server_user, "user");
XML_STRCONFIG("server", cfg_set_server_password, "password"); XML_STRCONFIG("server", cfg_set_server_password, "password");
XML_STRCONFIG("server", cfg_set_server_tls, "tls");
XML_STRCONFIG("server", cfg_set_server_tls_cipher_suite,
"tls_cipher_suite");
XML_STRCONFIG("server", cfg_set_server_ca_dir, "ca_dir"); XML_STRCONFIG("server", cfg_set_server_ca_dir, "ca_dir");
XML_STRCONFIG("server", cfg_set_server_ca_file, "ca_file"); XML_STRCONFIG("server", cfg_set_server_ca_file, "ca_file");
XML_STRCONFIG("server", cfg_set_server_client_key, "client_key");
XML_STRCONFIG("server", cfg_set_server_client_cert, "client_cert"); XML_STRCONFIG("server", cfg_set_server_client_cert, "client_cert");
XML_STRCONFIG("server", cfg_set_server_reconnect_attempts, XML_STRCONFIG("server", cfg_set_server_reconnect_attempts,
"reconnect_attempts"); "reconnect_attempts");
@ -267,10 +269,11 @@ _cfg_xmlfile_parse_encoders(xmlDocPtr doc, xmlNodePtr cur)
* port * port
* user * user
* password * password
* tls
* tls_cipher_suite
* ca_dir * ca_dir
* ca_file * ca_file
* client_cert * client_cert
* client_key
* reconnect_attempts * reconnect_attempts
* stream * stream
* mountpoint * mountpoint

View File

@ -295,6 +295,31 @@ START_TEST(test_server_ca_dir)
} }
END_TEST END_TEST
START_TEST(test_server_tls)
{
const char *errstr = NULL;
ck_assert_int_eq(cfg_set_server_tls("", &errstr), -1);
ck_assert_str_eq(errstr, "empty");
ck_assert_int_eq(cfg_set_server_tls("test", &errstr), -1);
ck_assert_str_eq(errstr, "invalid");
ck_assert_int_eq(cfg_get_server_tls(), CFG_TLS_MAY);
ck_assert_int_eq(cfg_set_server_tls("None", NULL), 0);
ck_assert_int_eq(cfg_get_server_tls(), CFG_TLS_NONE);
ck_assert_int_eq(cfg_set_server_tls("Required", NULL), 0);
ck_assert_int_eq(cfg_get_server_tls(), CFG_TLS_REQUIRED);
ck_assert_int_eq(cfg_set_server_tls("May", NULL), 0);
ck_assert_int_eq(cfg_get_server_tls(), CFG_TLS_MAY);
}
END_TEST
START_TEST(test_server_tls_cipher_suite)
{
TEST_STRLCPY(cfg_set_server_tls_cipher_suite,
cfg_get_server_tls_cipher_suite, CSUITE_SIZE);
}
END_TEST
START_TEST(test_server_ca_file) START_TEST(test_server_ca_file)
{ {
TEST_STRLCPY(cfg_set_server_ca_file, cfg_get_server_ca_file, PATH_MAX); TEST_STRLCPY(cfg_set_server_ca_file, cfg_get_server_ca_file, PATH_MAX);
@ -308,13 +333,6 @@ START_TEST(test_server_client_cert)
} }
END_TEST END_TEST
START_TEST(test_server_client_key)
{
TEST_STRLCPY(cfg_set_server_client_key, cfg_get_server_client_key,
PATH_MAX);
}
END_TEST
START_TEST(test_server_reconnect_attempts) START_TEST(test_server_reconnect_attempts)
{ {
TEST_UINTNUM(cfg_set_server_reconnect_attempts, TEST_UINTNUM(cfg_set_server_reconnect_attempts,
@ -802,10 +820,11 @@ cfg_suite(void)
tcase_add_test(tc_server, test_server_port); tcase_add_test(tc_server, test_server_port);
tcase_add_test(tc_server, test_server_user); tcase_add_test(tc_server, test_server_user);
tcase_add_test(tc_server, test_server_password); tcase_add_test(tc_server, test_server_password);
tcase_add_test(tc_server, test_server_tls);
tcase_add_test(tc_server, test_server_tls_cipher_suite);
tcase_add_test(tc_server, test_server_ca_dir); tcase_add_test(tc_server, test_server_ca_dir);
tcase_add_test(tc_server, test_server_ca_file); tcase_add_test(tc_server, test_server_ca_file);
tcase_add_test(tc_server, test_server_client_cert); tcase_add_test(tc_server, test_server_client_cert);
tcase_add_test(tc_server, test_server_client_key);
tcase_add_test(tc_server, test_server_reconnect_attempts); tcase_add_test(tc_server, test_server_reconnect_attempts);
suite_add_tcase(s, tc_server); suite_add_tcase(s, tc_server);

View File

@ -8,10 +8,11 @@
<port></port> <port></port>
<user></user> <user></user>
<password></password> <password></password>
<tls></tls>
<tls_cipher_suite></tls_cipher_suite>
<ca_dir></ca_dir> <ca_dir></ca_dir>
<ca_file></ca_file> <ca_file></ca_file>
<client_cert></client_cert> <client_cert></client_cert>
<client_key></client_key>
<reconnect_attempts></reconnect_attempts> <reconnect_attempts></reconnect_attempts>
</server> </server>