Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Xiph.Org
Icecast-Server
Commits
fa86f2de
Commit
fa86f2de
authored
Jul 23, 2017
by
Philipp Schafft
🦁
Browse files
Merge branch 'ph3-update-TLS'
parents
b7087c38
cd9c8420
Changes
12
Hide whitespace changes
Inline
Side-by-side
src/Makefile.am
View file @
fa86f2de
...
...
@@ -16,7 +16,7 @@ noinst_HEADERS = admin.h cfgfile.h logging.h sighandler.h connection.h \
format_kate.h format_skeleton.h format_opus.h
icecast_SOURCES
=
cfgfile.c main.c logging.c sighandler.c connection.c global.c
\
util.c slave.c source.c stats.c refbuf.c client.c playlist.c
\
xslt.c fserve.c admin.c md5.c matchfile.c
\
xslt.c fserve.c admin.c md5.c matchfile.c
tls.c
\
format.c format_ogg.c format_mp3.c format_midi.c format_flac.c format_ebml.c
\
format_kate.c format_skeleton.c format_opus.c
\
event.c event_log.c event_exec.c
\
...
...
src/admin.c
View file @
fa86f2de
...
...
@@ -695,11 +695,7 @@ static inline xmlNodePtr __add_listener(client_t *client,
if
(
client
->
role
)
xmlNewTextChild
(
node
,
NULL
,
XMLSTR
(
"role"
),
XMLSTR
(
client
->
role
));
#ifdef HAVE_OPENSSL
xmlNewTextChild
(
node
,
NULL
,
XMLSTR
(
"tls"
),
XMLSTR
(
client
->
con
->
ssl
?
"true"
:
"false"
));
#else
xmlNewTextChild
(
node
,
NULL
,
XMLSTR
(
"tls"
),
XMLSTR
(
"false"
));
#endif
xmlNewTextChild
(
node
,
NULL
,
XMLSTR
(
"tls"
),
XMLSTR
(
client
->
con
->
tls
?
"true"
:
"false"
));
return
node
;
}
...
...
src/cfgfile.c
View file @
fa86f2de
...
...
@@ -34,11 +34,13 @@
#include "util.h"
#include "auth.h"
#include "event.h"
#include "tls.h"
/* for config_reread_config() */
#include "yp.h"
#include "fserve.h"
#include "stats.h"
#include "connection.h"
#define CATMODULE "CONFIG"
#define CONFIG_DEFAULT_LOCATION "Earth"
...
...
@@ -233,6 +235,60 @@ 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
;
}
/* This checks for the TLS implementation of a node */
static
int
__check_node_impl
(
xmlNodePtr
node
,
const
char
*
def
)
{
char
*
impl
;
int
res
;
impl
=
(
char
*
)
xmlGetProp
(
node
,
XMLSTR
(
"implementation"
));
if
(
!
impl
)
impl
=
(
char
*
)
xmlGetProp
(
node
,
XMLSTR
(
"impl"
));
if
(
!
impl
)
impl
=
(
char
*
)
xmlStrdup
(
XMLSTR
(
def
));
res
=
tls_check_impl
(
impl
);
xmlFree
(
impl
);
return
res
;
}
static
void
__append_old_style_auth
(
auth_stack_t
**
stack
,
const
char
*
name
,
const
char
*
type
,
...
...
@@ -532,8 +588,6 @@ void config_clear(ice_config_t *c)
if
(
c
->
webroot_dir
)
xmlFree
(
c
->
webroot_dir
);
if
(
c
->
adminroot_dir
)
xmlFree
(
c
->
adminroot_dir
);
if
(
c
->
null_device
)
xmlFree
(
c
->
null_device
);
if
(
c
->
cert_file
)
xmlFree
(
c
->
cert_file
);
if
(
c
->
cipher_list
)
xmlFree
(
c
->
cipher_list
);
if
(
c
->
pidfile
)
xmlFree
(
c
->
pidfile
);
if
(
c
->
banfile
)
xmlFree
(
c
->
banfile
);
if
(
c
->
allowfile
)
xmlFree
(
c
->
allowfile
);
...
...
@@ -549,6 +603,10 @@ void config_clear(ice_config_t *c)
if
(
c
->
group
)
xmlFree
(
c
->
group
);
if
(
c
->
mimetypes_fn
)
xmlFree
(
c
->
mimetypes_fn
);
if
(
c
->
tls_context
.
cert_file
)
xmlFree
(
c
->
tls_context
.
cert_file
);
if
(
c
->
tls_context
.
key_file
)
xmlFree
(
c
->
tls_context
.
key_file
);
if
(
c
->
tls_context
.
cipher_list
)
xmlFree
(
c
->
tls_context
.
cipher_list
);
event_registration_release
(
c
->
event
);
while
((
c
->
listen_sock
=
config_clear_listener
(
c
->
listen_sock
)));
...
...
@@ -636,6 +694,7 @@ void config_reread_config(void)
config_set_config
(
&
new_config
);
config
=
config_get_config_unlocked
();
restart_logging
(
config
);
connection_reread_config
(
config
);
yp_recheck_config
(
config
);
fserve_recheck_mime_types
(
config
);
stats_global
(
config
);
...
...
@@ -766,8 +825,6 @@ static void _set_defaults(ice_config_t *configuration)
->
base_dir
=
(
char
*
)
xmlCharStrdup
(
CONFIG_DEFAULT_BASE_DIR
);
configuration
->
log_dir
=
(
char
*
)
xmlCharStrdup
(
CONFIG_DEFAULT_LOG_DIR
);
configuration
->
cipher_list
=
(
char
*
)
xmlCharStrdup
(
CONFIG_DEFAULT_CIPHER_LIST
);
configuration
->
null_device
=
(
char
*
)
xmlCharStrdup
(
CONFIG_DEFAULT_NULL_FILE
);
configuration
...
...
@@ -795,6 +852,8 @@ static void _set_defaults(ice_config_t *configuration)
/* default to a typical prebuffer size used by clients */
configuration
->
burst_size
=
CONFIG_DEFAULT_BURST_SIZE
;
configuration
->
tls_context
.
cipher_list
=
(
char
*
)
xmlCharStrdup
(
CONFIG_DEFAULT_CIPHER_LIST
);
}
static
inline
void
__check_hostname
(
ice_config_t
*
configuration
)
...
...
@@ -1676,7 +1735,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
->
ssl
=
util_str_to_bool
(
tmp
);
listener
->
tls
=
str_to_tlsmode
(
tmp
);
if
(
tmp
)
xmlFree
(
tmp
);
}
else
if
(
xmlStrcmp
(
node
->
name
,
XMLSTR
(
"shoutcast-compat"
))
==
0
)
{
...
...
@@ -1882,14 +1941,24 @@ static void _parse_paths(xmlDocPtr doc,
configuration
->
allowfile
=
(
char
*
)
xmlNodeListGetString
(
doc
,
node
->
xmlChildrenNode
,
1
);
}
else
if
(
xmlStrcmp
(
node
->
name
,
XMLSTR
(
"tls-certificate"
))
==
0
||
xmlStrcmp
(
node
->
name
,
XMLSTR
(
"ssl-certificate"
))
==
0
)
{
if
(
configuration
->
cert_file
)
xmlFree
(
configuration
->
cert_file
);
configuration
->
cert_file
=
(
char
*
)
xmlNodeListGetString
(
doc
,
node
->
xmlChildrenNode
,
1
);
if
(
__check_node_impl
(
node
,
"generic"
)
!=
0
)
{
ICECAST_LOG_WARN
(
"Node %s uses unsupported implementation."
,
node
->
name
);
continue
;
}
if
(
configuration
->
tls_context
.
cert_file
)
xmlFree
(
configuration
->
tls_context
.
cert_file
);
configuration
->
tls_context
.
cert_file
=
(
char
*
)
xmlNodeListGetString
(
doc
,
node
->
xmlChildrenNode
,
1
);
}
else
if
(
xmlStrcmp
(
node
->
name
,
XMLSTR
(
"tls-allowed-ciphers"
))
==
0
||
xmlStrcmp
(
node
->
name
,
XMLSTR
(
"ssl-allowed-ciphers"
))
==
0
)
{
if
(
configuration
->
cipher_list
)
xmlFree
(
configuration
->
cipher_list
);
configuration
->
cipher_list
=
(
char
*
)
xmlNodeListGetString
(
doc
,
node
->
xmlChildrenNode
,
1
);
if
(
__check_node_impl
(
node
,
"openssl"
)
!=
0
)
{
ICECAST_LOG_WARN
(
"Node %s uses unsupported implementation."
,
node
->
name
);
continue
;
}
if
(
configuration
->
tls_context
.
cipher_list
)
xmlFree
(
configuration
->
tls_context
.
cipher_list
);
configuration
->
tls_context
.
cipher_list
=
(
char
*
)
xmlNodeListGetString
(
doc
,
node
->
xmlChildrenNode
,
1
);
}
else
if
(
xmlStrcmp
(
node
->
name
,
XMLSTR
(
"webroot"
))
==
0
)
{
if
(
!
(
temp
=
(
char
*
)
xmlNodeListGetString
(
doc
,
node
->
xmlChildrenNode
,
1
)))
{
ICECAST_LOG_WARN
(
"<webroot> setting must not be empty."
);
...
...
@@ -2002,6 +2071,54 @@ static void _parse_logging(xmlDocPtr doc,
}
while
((
node
=
node
->
next
));
}
static
void
_parse_tls_context
(
xmlDocPtr
doc
,
xmlNodePtr
node
,
ice_config_t
*
configuration
)
{
config_tls_context_t
*
context
=
&
configuration
->
tls_context
;
node
=
node
->
xmlChildrenNode
;
do
{
if
(
node
==
NULL
)
break
;
if
(
xmlIsBlankNode
(
node
))
continue
;
if
(
xmlStrcmp
(
node
->
name
,
XMLSTR
(
"tls-certificate"
))
==
0
)
{
if
(
__check_node_impl
(
node
,
"generic"
)
!=
0
)
{
ICECAST_LOG_WARN
(
"Node %s uses unsupported implementation."
,
node
->
name
);
continue
;
}
if
(
context
->
cert_file
)
xmlFree
(
context
->
cert_file
);
context
->
cert_file
=
(
char
*
)
xmlNodeListGetString
(
doc
,
node
->
xmlChildrenNode
,
1
);
}
else
if
(
xmlStrcmp
(
node
->
name
,
XMLSTR
(
"tls-key"
))
==
0
)
{
if
(
__check_node_impl
(
node
,
"generic"
)
!=
0
)
{
ICECAST_LOG_WARN
(
"Node %s uses unsupported implementation."
,
node
->
name
);
continue
;
}
if
(
context
->
key_file
)
xmlFree
(
context
->
key_file
);
context
->
key_file
=
(
char
*
)
xmlNodeListGetString
(
doc
,
node
->
xmlChildrenNode
,
1
);
}
else
if
(
xmlStrcmp
(
node
->
name
,
XMLSTR
(
"tls-allowed-ciphers"
))
==
0
)
{
if
(
__check_node_impl
(
node
,
"openssl"
)
!=
0
)
{
ICECAST_LOG_WARN
(
"Node %s uses unsupported implementation."
,
node
->
name
);
continue
;
}
if
(
context
->
cipher_list
)
xmlFree
(
context
->
cipher_list
);
context
->
cipher_list
=
(
char
*
)
xmlNodeListGetString
(
doc
,
node
->
xmlChildrenNode
,
1
);
}
else
{
ICECAST_LOG_ERROR
(
"Unknown config tag: %s"
,
node
->
name
);
}
}
while
((
node
=
node
->
next
));
}
static
void
_parse_security
(
xmlDocPtr
doc
,
xmlNodePtr
node
,
ice_config_t
*
configuration
)
...
...
@@ -2020,6 +2137,8 @@ static void _parse_security(xmlDocPtr doc,
configuration
->
chroot
=
util_str_to_bool
(
tmp
);
if
(
tmp
)
xmlFree
(
tmp
);
}
else
if
(
xmlStrcmp
(
node
->
name
,
XMLSTR
(
"tls-context"
))
==
0
)
{
_parse_tls_context
(
doc
,
node
,
configuration
);
}
else
if
(
xmlStrcmp
(
node
->
name
,
XMLSTR
(
"changeowner"
))
==
0
)
{
configuration
->
chuid
=
1
;
oldnode
=
node
;
...
...
src/cfgfile.h
View file @
fa86f2de
...
...
@@ -172,9 +172,15 @@ typedef struct _listener_t {
char
*
bind_address
;
int
shoutcast_compat
;
char
*
shoutcast_mount
;
int
ssl
;
tlsmode_t
tls
;
}
listener_t
;
typedef
struct
_config_tls_context
{
char
*
cert_file
;
char
*
key_file
;
char
*
cipher_list
;
}
config_tls_context_t
;
typedef
struct
ice_config_tag
{
char
*
config_filename
;
...
...
@@ -229,8 +235,6 @@ typedef struct ice_config_tag {
char
*
null_device
;
char
*
banfile
;
char
*
allowfile
;
char
*
cert_file
;
char
*
cipher_list
;
char
*
webroot_dir
;
char
*
adminroot_dir
;
aliases
*
aliases
;
...
...
@@ -242,6 +246,8 @@ typedef struct ice_config_tag {
int
logsize
;
int
logarchive
;
config_tls_context_t
tls_context
;
int
chroot
;
int
chuid
;
char
*
user
;
...
...
src/client.c
View file @
fa86f2de
...
...
@@ -105,26 +105,24 @@ static inline void client_reuseconnection(client_t *client) {
client
->
con
->
sock
=
-
1
;
/* TODO: do not use magic */
/* handle to keep the TLS connection */
#ifdef HAVE_OPENSSL
if
(
client
->
con
->
ssl
)
{
if
(
client
->
con
->
tls
)
{
/* AHhhggrr.. That pain....
* stealing
SSL
state...
* stealing
TLS
state...
*/
con
->
ssl
=
client
->
con
->
ssl
;
con
->
tls
=
client
->
con
->
tls
;
con
->
read
=
client
->
con
->
read
;
con
->
send
=
client
->
con
->
send
;
client
->
con
->
ssl
=
NULL
;
client
->
con
->
tls
=
NULL
;
client
->
con
->
read
=
NULL
;
client
->
con
->
send
=
NULL
;
}
#endif
client
->
reuse
=
ICECAST_REUSE_CLOSE
;
client_destroy
(
client
);
if
(
reuse
==
ICECAST_REUSE_UPGRADETLS
)
connection_uses_
ssl
(
con
);
connection_uses_
tls
(
con
);
connection_queue
(
con
);
}
...
...
src/connection.c
View file @
fa86f2de
...
...
@@ -59,6 +59,7 @@
#include "admin.h"
#include "auth.h"
#include "matchfile.h"
#include "tls.h"
#define CATMODULE "connection"
...
...
@@ -97,10 +98,8 @@ static int _initialized = 0;
static
volatile
client_queue_t
*
_req_queue
=
NULL
,
**
_req_queue_tail
=
&
_req_queue
;
static
volatile
client_queue_t
*
_con_queue
=
NULL
,
**
_con_queue_tail
=
&
_con_queue
;
static
int
ssl_ok
;
#ifdef HAVE_OPENSSL
static
SSL_CTX
*
ssl_ctx
;
#endif
static
int
tls_ok
;
static
tls_ctx_t
*
tls_ctx
;
/* filtering client connection based on IP */
static
matchfile_t
*
banned_ip
,
*
allowed_ip
;
...
...
@@ -108,6 +107,7 @@ static matchfile_t *banned_ip, *allowed_ip;
rwlock_t
_source_shutdown_rwlock
;
static
void
_handle_connection
(
void
);
static
void
get_tls_certificate
(
ice_config_t
*
config
);
void
connection_initialize
(
void
)
{
...
...
@@ -131,9 +131,7 @@ void connection_shutdown(void)
if
(
!
_initialized
)
return
;
#ifdef HAVE_OPENSSL
SSL_CTX_free
(
ssl_ctx
);
#endif
tls_ctx_unref
(
tls_ctx
);
matchfile_release
(
banned_ip
);
matchfile_release
(
allowed_ip
);
...
...
@@ -145,6 +143,11 @@ void connection_shutdown(void)
_initialized
=
0
;
}
void
connection_reread_config
(
struct
ice_config_tag
*
config
)
{
get_tls_certificate
(
config
);
}
static
unsigned
long
_next_connection_id
(
void
)
{
unsigned
long
id
;
...
...
@@ -157,80 +160,50 @@ static unsigned long _next_connection_id(void)
}
#ifdef
HAVE_OPENSSL
static
void
get_
ssl
_certificate
(
ice_config_t
*
config
)
#ifdef
ICECAST_CAP_TLS
static
void
get_
tls
_certificate
(
ice_config_t
*
config
)
{
SSL_METHOD
*
method
;
long
ssl_opts
;
config
->
tls_ok
=
ssl_ok
=
0
;
SSL_load_error_strings
();
/* readable error messages */
SSL_library_init
();
/* initialize library */
method
=
SSLv23_server_method
();
ssl_ctx
=
SSL_CTX_new
(
method
);
ssl_opts
=
SSL_CTX_get_options
(
ssl_ctx
);
#ifdef SSL_OP_NO_COMPRESSION
SSL_CTX_set_options
(
ssl_ctx
,
ssl_opts
|
SSL_OP_NO_SSLv2
|
SSL_OP_NO_SSLv3
|
SSL_OP_NO_COMPRESSION
);
#else
SSL_CTX_set_options
(
ssl_ctx
,
ssl_opts
|
SSL_OP_NO_SSLv2
|
SSL_OP_NO_SSLv3
);
#endif
const
char
*
keyfile
;
do
{
if
(
config
->
cert_file
==
NULL
)
break
;
if
(
SSL_CTX_use_certificate_chain_file
(
ssl_ctx
,
config
->
cert_file
)
<=
0
)
{
ICECAST_LOG_WARN
(
"Invalid cert file %s"
,
config
->
cert_file
);
break
;
}
if
(
SSL_CTX_use_PrivateKey_file
(
ssl_ctx
,
config
->
cert_file
,
SSL_FILETYPE_PEM
)
<=
0
)
{
ICECAST_LOG_WARN
(
"Invalid private key file %s"
,
config
->
cert_file
);
break
;
}
if
(
!
SSL_CTX_check_private_key
(
ssl_ctx
))
{
ICECAST_LOG_ERROR
(
"Invalid %s - Private key does not match cert public key"
,
config
->
cert_file
);
break
;
}
if
(
SSL_CTX_set_cipher_list
(
ssl_ctx
,
config
->
cipher_list
)
<=
0
)
{
ICECAST_LOG_WARN
(
"Invalid cipher list: %s"
,
config
->
cipher_list
);
}
config
->
tls_ok
=
ssl_ok
=
1
;
ICECAST_LOG_INFO
(
"Certificate found at %s"
,
config
->
cert_file
);
ICECAST_LOG_INFO
(
"Using ciphers %s"
,
config
->
cipher_list
);
config
->
tls_ok
=
tls_ok
=
0
;
keyfile
=
config
->
tls_context
.
key_file
;
if
(
!
keyfile
)
keyfile
=
config
->
tls_context
.
cert_file
;
tls_ctx_unref
(
tls_ctx
);
tls_ctx
=
tls_ctx_new
(
config
->
tls_context
.
cert_file
,
keyfile
,
config
->
tls_context
.
cipher_list
);
if
(
!
tls_ctx
)
{
ICECAST_LOG_INFO
(
"No TLS capability on any configured ports"
);
return
;
}
while
(
0
);
ICECAST_LOG_INFO
(
"No TLS capability on any configured ports"
);
}
config
->
tls_ok
=
tls_ok
=
1
;
}
/* handlers for reading and writing a connection_t when there is
ssl
/* handlers for reading and writing a connection_t when there is
TLS
* configured on the listening port
*/
static
int
connection_read_
ssl
(
connection_t
*
con
,
void
*
buf
,
size_t
len
)
static
int
connection_read_
tls
(
connection_t
*
con
,
void
*
buf
,
size_t
len
)
{
in
t
bytes
=
SSL
_read
(
con
->
ssl
,
buf
,
len
);
ssize_
t
bytes
=
tls
_read
(
con
->
tls
,
buf
,
len
);
if
(
bytes
<
0
)
{
switch
(
SSL_get_error
(
con
->
ssl
,
bytes
))
{
case
SSL_ERROR_WANT_READ
:
case
SSL_ERROR_WANT_WRITE
:
if
(
tls_want_io
(
con
->
tls
)
>
0
)
return
-
1
;
}
con
->
error
=
1
;
}
return
bytes
;
}
static
int
connection_send_
ssl
(
connection_t
*
con
,
const
void
*
buf
,
size_t
len
)
static
int
connection_send_
tls
(
connection_t
*
con
,
const
void
*
buf
,
size_t
len
)
{
in
t
bytes
=
SSL
_write
(
con
->
ssl
,
buf
,
len
);
ssize_
t
bytes
=
tls
_write
(
con
->
tls
,
buf
,
len
);
if
(
bytes
<
0
)
{
switch
(
SSL_get_error
(
con
->
ssl
,
bytes
)){
case
SSL_ERROR_WANT_READ
:
case
SSL_ERROR_WANT_WRITE
:
return
-
1
;
}
if
(
tls_want_io
(
con
->
tls
)
>
0
)
return
-
1
;
con
->
error
=
1
;
}
else
{
con
->
sent_bytes
+=
bytes
;
...
...
@@ -239,14 +212,14 @@ static int connection_send_ssl(connection_t *con, const void *buf, size_t len)
}
#else
/*
SSL
not compiled in, so at least log it */
static
void
get_
ssl
_certificate
(
ice_config_t
*
config
)
/*
TLS
not compiled in, so at least log it */
static
void
get_
tls
_certificate
(
ice_config_t
*
config
)
{
ssl
_ok
=
0
;
tls
_ok
=
0
;
ICECAST_LOG_INFO
(
"No TLS capability. "
"Rebuild Icecast with
o
penSSL support to enable this."
);
"Rebuild Icecast with
O
penSSL support to enable this."
);
}
#endif
/*
HAVE_OPENSSL
*/
#endif
/*
ICECAST_CAP_TLS
*/
/* handlers (default) for reading and writing a connection_t, no encrpytion
...
...
@@ -284,6 +257,7 @@ connection_t *connection_create (sock_t sock, sock_t serversock, char *ip)
con
->
con_time
=
time
(
NULL
);
con
->
id
=
_next_connection_id
();
con
->
ip
=
ip
;
con
->
tlsmode
=
ICECAST_TLSMODE_AUTO
;
con
->
read
=
connection_read
;
con
->
send
=
connection_send
;
}
...
...
@@ -291,19 +265,20 @@ connection_t *connection_create (sock_t sock, sock_t serversock, char *ip)
return
con
;
}
/* prepare connection for interacting over a
SSL
connection
/* prepare connection for interacting over a
TLS
connection
*/
void
connection_uses_
ssl
(
connection_t
*
con
)
void
connection_uses_
tls
(
connection_t
*
con
)
{
#ifdef
HAVE_OPENSSL
if
(
con
->
ssl
)
#ifdef
ICECAST_CAP_TLS
if
(
con
->
tls
)
return
;
con
->
read
=
connection_read_ssl
;
con
->
send
=
connection_send_ssl
;
con
->
ssl
=
SSL_new
(
ssl_ctx
);
SSL_set_accept_state
(
con
->
ssl
);
SSL_set_fd
(
con
->
ssl
,
con
->
sock
);
con
->
tlsmode
=
ICECAST_TLSMODE_RFC2818
;
con
->
read
=
connection_read_tls
;
con
->
send
=
connection_send_tls
;
con
->
tls
=
tls_new
(
tls_ctx
);
tls_set_incoming
(
con
->
tls
);
tls_set_socket
(
con
->
tls
,
con
->
sock
);
#endif
}
...
...
@@ -462,8 +437,12 @@ static client_queue_t *_get_connection(void)
static
void
process_request_queue
(
void
)
{
client_queue_t
**
node_ref
=
(
client_queue_t
**
)
&
_req_queue
;
ice_config_t
*
config
=
config_get_config
();
int
timeout
=
config
->
header_timeout
;
ice_config_t
*
config
;
int
timeout
;
char
peak
;
config
=
config_get_config
();
timeout
=
config
->
header_timeout
;
config_release_config
();
while
(
*
node_ref
)
{
...
...
@@ -472,6 +451,14 @@ 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
||
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
);
}
}
}
if
(
len
>
0
)
{
if
(
client
->
con
->
con_time
+
timeout
<=
time
(
NULL
))
{
len
=
0
;
...
...
@@ -568,8 +555,9 @@ static client_queue_t *create_client_node(client_t *client)
if
(
listener
)
{
if
(
listener
->
shoutcast_compat
)
node
->
shoutcast
=
1
;
if
(
listener
->
ssl
&&
ssl_ok
)
connection_uses_ssl
(
client
->
con
);
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
);
}
...
...
@@ -621,7 +609,7 @@ void connection_accept_loop(void)
int
duration
=
300
;
config
=
config_get_config
();
get_
ssl
_certificate
(
config
);
get_
tls
_certificate
(
config
);
config_release_config
();
while
(
global
.
running
==
ICECAST_RUNNING
)
{
...
...
@@ -1358,8 +1346,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
;
}
...
...
@@ -1495,8 +1491,6 @@ void connection_close(connection_t *con)
sock_close
(
con
->
sock
);
if
(
con
->
ip
)
free
(
con
->
ip
);
#ifdef HAVE_OPENSSL
if
(
con
->
ssl
)
{
SSL_shutdown
(
con
->
ssl
);
SSL_free
(
con
->
ssl
);
}
#endif
tls_unref
(
con
->
tls
);
free
(
con
);
}
src/connection.h
View file @
fa86f2de
...
...
@@ -16,10 +16,8 @@
#include <sys/types.h>
#include <time.h>
#ifdef HAVE_OPENSSL
#include <openssl/ssl.h>
#include <openssl/err.h>
#endif
#include "tls.h"
#include "compat.h"
#include "common/httpp/httpp.h"
...
...
@@ -30,6 +28,19 @@ struct _client_tag;
struct
source_tag
;
struct
ice_config_tag
;
typedef
enum
_tlsmode_tag
{
/* no TLS is used at all */
ICECAST_TLSMODE_DISABLED
=
0
,