mirror of
https://gitlab.xiph.org/xiph/icecast-server.git
synced 2024-09-29 04:25:55 -04:00
initial ssl port handling work
svn path=/icecast/branches/kh/icecast/; revision=9656
This commit is contained in:
parent
29f3d6639b
commit
eadfcbe19f
@ -53,6 +53,7 @@
|
|||||||
<!--
|
<!--
|
||||||
<listen-socket>
|
<listen-socket>
|
||||||
<port>8001</port>
|
<port>8001</port>
|
||||||
|
<ssl>1</ssl>
|
||||||
</listen-socket>
|
</listen-socket>
|
||||||
-->
|
-->
|
||||||
|
|
||||||
@ -158,6 +159,7 @@
|
|||||||
<webroot>@pkgdatadir@/web</webroot>
|
<webroot>@pkgdatadir@/web</webroot>
|
||||||
<adminroot>@pkgdatadir@/admin</adminroot>
|
<adminroot>@pkgdatadir@/admin</adminroot>
|
||||||
<!-- <pidfile>@pkgdatadir@/icecast.pid</pidfile> -->
|
<!-- <pidfile>@pkgdatadir@/icecast.pid</pidfile> -->
|
||||||
|
<!-- <ssl_certificate>@pkgdatadir@/icecast.pem</ssl_certificate> -->
|
||||||
|
|
||||||
<!-- Aliases: treat requests for 'source' path as being for 'dest' path
|
<!-- Aliases: treat requests for 'source' path as being for 'dest' path
|
||||||
May be made specific to a port or bound address using the "port"
|
May be made specific to a port or bound address using the "port"
|
||||||
|
@ -130,6 +130,14 @@ then
|
|||||||
else
|
else
|
||||||
AC_MSG_NOTICE([YP support disabled])
|
AC_MSG_NOTICE([YP support disabled])
|
||||||
fi
|
fi
|
||||||
|
XIPH_PATH_OPENSSL([
|
||||||
|
XIPH_VAR_APPEND([XIPH_CPPFLAGS],[$OPENSSL_CFLAGS])
|
||||||
|
XIPH_VAR_APPEND([XIPH_LDFLAGS],[$OPENSSL_LDFLAGS])
|
||||||
|
XIPH_VAR_PREPEND([XIPH_LIBS],[$OPENSSL_LIBS])
|
||||||
|
],
|
||||||
|
[ AC_MSG_NOTICE([SSL disabled!])
|
||||||
|
])
|
||||||
|
|
||||||
# don't log ip's in the access log
|
# don't log ip's in the access log
|
||||||
AC_ARG_ENABLE([log-ip],
|
AC_ARG_ENABLE([log-ip],
|
||||||
AC_HELP_STRING([--disable-log-ip],[disable logging of IP's in access log]),
|
AC_HELP_STRING([--disable-log-ip],[disable logging of IP's in access log]),
|
||||||
|
@ -354,6 +354,9 @@ void add_client (const char *mount, client_t *client)
|
|||||||
mount_proxy *mountinfo;
|
mount_proxy *mountinfo;
|
||||||
ice_config_t *config = config_get_config();
|
ice_config_t *config = config_get_config();
|
||||||
|
|
||||||
|
/* we don't need any more data from the listener, just setup for writing */
|
||||||
|
client->refbuf->len = PER_CLIENT_REFBUF_SIZE;
|
||||||
|
|
||||||
mountinfo = config_find_mount (config, mount);
|
mountinfo = config_find_mount (config, mount);
|
||||||
if (mountinfo && mountinfo->auth)
|
if (mountinfo && mountinfo->auth)
|
||||||
{
|
{
|
||||||
|
@ -794,6 +794,11 @@ static void _parse_listen_socket(xmlDocPtr doc, xmlNodePtr node,
|
|||||||
listener->shoutcast_compat = atoi(tmp);
|
listener->shoutcast_compat = atoi(tmp);
|
||||||
if(tmp) xmlFree(tmp);
|
if(tmp) xmlFree(tmp);
|
||||||
}
|
}
|
||||||
|
else if (strcmp(node->name, "ssl") == 0) {
|
||||||
|
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
||||||
|
listener->ssl = atoi(tmp);
|
||||||
|
if(tmp) xmlFree(tmp);
|
||||||
|
}
|
||||||
else if (strcmp(node->name, "bind-address") == 0) {
|
else if (strcmp(node->name, "bind-address") == 0) {
|
||||||
listener->bind_address = (char *)xmlNodeListGetString(doc,
|
listener->bind_address = (char *)xmlNodeListGetString(doc,
|
||||||
node->xmlChildrenNode, 1);
|
node->xmlChildrenNode, 1);
|
||||||
@ -900,6 +905,9 @@ static void _parse_paths(xmlDocPtr doc, xmlNodePtr node,
|
|||||||
} else if (strcmp(node->name, "pidfile") == 0) {
|
} else if (strcmp(node->name, "pidfile") == 0) {
|
||||||
if (configuration->pidfile) xmlFree(configuration->pidfile);
|
if (configuration->pidfile) xmlFree(configuration->pidfile);
|
||||||
configuration->pidfile = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
configuration->pidfile = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
||||||
|
} else if (strcmp(node->name, "ssl_certificate") == 0) {
|
||||||
|
if (configuration->cert_file) xmlFree(configuration->cert_file);
|
||||||
|
configuration->cert_file = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
||||||
} else if (strcmp(node->name, "webroot") == 0) {
|
} else if (strcmp(node->name, "webroot") == 0) {
|
||||||
if (configuration->webroot_dir && configuration->webroot_dir != CONFIG_DEFAULT_WEBROOT_DIR) xmlFree(configuration->webroot_dir);
|
if (configuration->webroot_dir && configuration->webroot_dir != CONFIG_DEFAULT_WEBROOT_DIR) xmlFree(configuration->webroot_dir);
|
||||||
configuration->webroot_dir = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
configuration->webroot_dir = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
||||||
|
@ -97,6 +97,7 @@ typedef struct {
|
|||||||
int port;
|
int port;
|
||||||
char *bind_address;
|
char *bind_address;
|
||||||
int shoutcast_compat;
|
int shoutcast_compat;
|
||||||
|
int ssl;
|
||||||
} listener_t;
|
} listener_t;
|
||||||
|
|
||||||
typedef struct ice_config_tag
|
typedef struct ice_config_tag
|
||||||
@ -147,6 +148,7 @@ typedef struct ice_config_tag
|
|||||||
char *base_dir;
|
char *base_dir;
|
||||||
char *log_dir;
|
char *log_dir;
|
||||||
char *pidfile;
|
char *pidfile;
|
||||||
|
char *cert_file;
|
||||||
char *webroot_dir;
|
char *webroot_dir;
|
||||||
char *adminroot_dir;
|
char *adminroot_dir;
|
||||||
aliases *aliases;
|
aliases *aliases;
|
||||||
|
55
src/client.c
55
src/client.c
@ -148,15 +148,34 @@ int client_read_bytes (client_t *client, void *buf, unsigned len)
|
|||||||
client->refbuf->len -= len;
|
client->refbuf->len -= len;
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
bytes = sock_read_bytes (client->con->sock, buf, len);
|
#ifdef HAVE_OPENSSL
|
||||||
|
if (client->con->ssl)
|
||||||
|
bytes = SSL_read (client->con->ssl, buf, len);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
bytes = sock_read_bytes (client->con->sock, buf, len);
|
||||||
|
|
||||||
if (bytes > 0)
|
if (bytes > 0)
|
||||||
return bytes;
|
return bytes;
|
||||||
|
|
||||||
if (bytes < 0)
|
if (bytes < 0)
|
||||||
{
|
{
|
||||||
if (sock_recoverable (sock_error()))
|
#ifdef HAVE_OPENSSL
|
||||||
return -1;
|
if (client->con->ssl)
|
||||||
WARN0 ("source connection has died");
|
{
|
||||||
|
switch (SSL_get_error (client->con->ssl, bytes))
|
||||||
|
{
|
||||||
|
case SSL_ERROR_WANT_READ:
|
||||||
|
case SSL_ERROR_WANT_WRITE:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
bytes = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
if (sock_recoverable (sock_error()))
|
||||||
|
return -1;
|
||||||
|
WARN0 ("reading from connection has failed");
|
||||||
}
|
}
|
||||||
client->con->error = 1;
|
client->con->error = 1;
|
||||||
return bytes;
|
return bytes;
|
||||||
@ -241,16 +260,36 @@ int client_send_bytes (client_t *client, const void *buf, unsigned len)
|
|||||||
return -1;
|
return -1;
|
||||||
ret = aio_return (aiocbp);
|
ret = aio_return (aiocbp);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
sock_set_error (err); /* make sure errno gets set */
|
sock_set_error (err); /* make sure errno gets set */
|
||||||
|
|
||||||
client->pending_io = 0;
|
client->pending_io = 0;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
int ret = sock_write_bytes (client->con->sock, buf, len);
|
int ret;
|
||||||
|
#ifdef HAVE_OPENSSL
|
||||||
|
if (client->con->ssl)
|
||||||
|
ret = SSL_write (client->con->ssl, buf, len);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
ret = sock_write_bytes (client->con->sock, buf, len);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ret < 0 && !sock_recoverable (sock_error()))
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_OPENSSL
|
||||||
|
if (client->con->ssl)
|
||||||
|
{
|
||||||
|
switch (SSL_get_error (client->con->ssl, ret))
|
||||||
|
{
|
||||||
|
case SSL_ERROR_WANT_READ:
|
||||||
|
case SSL_ERROR_WANT_WRITE:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
if (sock_recoverable (sock_error()))
|
||||||
|
return -1;
|
||||||
DEBUG0 ("Client connection died");
|
DEBUG0 ("Client connection died");
|
||||||
client->con->error = 1;
|
client->con->error = 1;
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,9 @@
|
|||||||
#define strcasecmp stricmp
|
#define strcasecmp stricmp
|
||||||
#define strncasecmp strnicmp
|
#define strncasecmp strnicmp
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_OPENSSL
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
|
|
||||||
@ -102,6 +105,10 @@ static volatile client_queue_t *_req_queue = NULL, **_req_queue_tail = &_req_que
|
|||||||
static volatile client_queue_t *_con_queue = NULL, **_con_queue_tail = &_con_queue;
|
static volatile client_queue_t *_con_queue = NULL, **_con_queue_tail = &_con_queue;
|
||||||
static mutex_t _con_queue_mutex;
|
static mutex_t _con_queue_mutex;
|
||||||
static mutex_t _req_queue_mutex;
|
static mutex_t _req_queue_mutex;
|
||||||
|
#ifdef HAVE_OPENSSL
|
||||||
|
static SSL_CTX *ssl_ctx;
|
||||||
|
static int ssl_ok;
|
||||||
|
#endif
|
||||||
|
|
||||||
rwlock_t _source_shutdown_rwlock;
|
rwlock_t _source_shutdown_rwlock;
|
||||||
|
|
||||||
@ -121,10 +128,58 @@ void connection_initialize(void)
|
|||||||
_initialized = 1;
|
_initialized = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void get_ssl_certificate ()
|
||||||
|
{
|
||||||
|
#ifdef HAVE_OPENSSL
|
||||||
|
SSL_METHOD *method;
|
||||||
|
ice_config_t *config;
|
||||||
|
|
||||||
|
SSL_load_error_strings(); /* readable error messages */
|
||||||
|
SSL_library_init(); /* initialize library */
|
||||||
|
|
||||||
|
method = SSLv23_server_method();
|
||||||
|
ssl_ctx = SSL_CTX_new (method);
|
||||||
|
|
||||||
|
ssl_ok = 0;
|
||||||
|
config = config_get_config ();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (config->cert_file == NULL)
|
||||||
|
break;
|
||||||
|
if (SSL_CTX_use_certificate_file (ssl_ctx, config->cert_file, SSL_FILETYPE_PEM) <= 0)
|
||||||
|
{
|
||||||
|
WARN1 ("Invalid cert file %s", config->cert_file);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (SSL_CTX_use_PrivateKey_file (ssl_ctx, config->cert_file, SSL_FILETYPE_PEM) <= 0)
|
||||||
|
{
|
||||||
|
WARN1 ("Invalid private key file %s", config->cert_file);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!SSL_CTX_check_private_key (ssl_ctx))
|
||||||
|
{
|
||||||
|
ERROR0 ("Invalid icecast.pem - Private key doesn't"
|
||||||
|
" match cert public key");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ssl_ok = 1;
|
||||||
|
} while (0);
|
||||||
|
config_release_config ();
|
||||||
|
if (ssl_ok == 0)
|
||||||
|
#endif
|
||||||
|
INFO0 ("No SSL capability on the configured ports");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void connection_shutdown(void)
|
void connection_shutdown(void)
|
||||||
{
|
{
|
||||||
if (!_initialized) return;
|
if (!_initialized) return;
|
||||||
|
|
||||||
|
#ifdef HAVE_OPENSSL
|
||||||
|
SSL_CTX_free (ssl_ctx);
|
||||||
|
#endif
|
||||||
|
|
||||||
thread_cond_destroy(&global.shutdown_cond);
|
thread_cond_destroy(&global.shutdown_cond);
|
||||||
thread_rwlock_destroy(&_source_shutdown_rwlock);
|
thread_rwlock_destroy(&_source_shutdown_rwlock);
|
||||||
thread_mutex_destroy(&_con_queue_mutex);
|
thread_mutex_destroy(&_con_queue_mutex);
|
||||||
@ -324,7 +379,7 @@ static void process_request_queue ()
|
|||||||
{
|
{
|
||||||
client_queue_t *node = *node_ref;
|
client_queue_t *node = *node_ref;
|
||||||
client_t *client = node->client;
|
client_t *client = node->client;
|
||||||
int len = client->refbuf->len - node->offset;
|
int len = PER_CLIENT_REFBUF_SIZE - node->offset;
|
||||||
char *buf = client->refbuf->data + node->offset;
|
char *buf = client->refbuf->data + node->offset;
|
||||||
|
|
||||||
if (len > 0)
|
if (len > 0)
|
||||||
@ -332,7 +387,7 @@ static void process_request_queue ()
|
|||||||
if (client->con->con_time + timeout <= global.time)
|
if (client->con->con_time + timeout <= global.time)
|
||||||
len = 0;
|
len = 0;
|
||||||
else
|
else
|
||||||
len = sock_read_bytes (client->con->sock, buf, len);
|
len = client_read_bytes (client, buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len > 0)
|
if (len > 0)
|
||||||
@ -380,7 +435,7 @@ static void process_request_queue ()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (len == 0 || !sock_recoverable (sock_error()))
|
if (len == 0 || client->con->error)
|
||||||
{
|
{
|
||||||
if ((client_queue_t **)_req_queue_tail == &node->next)
|
if ((client_queue_t **)_req_queue_tail == &node->next)
|
||||||
_req_queue_tail = (volatile client_queue_t **)node_ref;
|
_req_queue_tail = (volatile client_queue_t **)node_ref;
|
||||||
@ -411,6 +466,7 @@ void connection_accept_loop(void)
|
|||||||
{
|
{
|
||||||
connection_t *con;
|
connection_t *con;
|
||||||
|
|
||||||
|
get_ssl_certificate ();
|
||||||
tid = thread_create ("connection thread", _handle_connection, NULL, THREAD_ATTACHED);
|
tid = thread_create ("connection thread", _handle_connection, NULL, THREAD_ATTACHED);
|
||||||
|
|
||||||
while (global.running == ICE_RUNNING)
|
while (global.running == ICE_RUNNING)
|
||||||
@ -436,7 +492,7 @@ void connection_accept_loop(void)
|
|||||||
/* setup client for reading incoming http */
|
/* setup client for reading incoming http */
|
||||||
client->refbuf = refbuf_new (PER_CLIENT_REFBUF_SIZE);
|
client->refbuf = refbuf_new (PER_CLIENT_REFBUF_SIZE);
|
||||||
client->refbuf->data [PER_CLIENT_REFBUF_SIZE-1] = '\000';
|
client->refbuf->data [PER_CLIENT_REFBUF_SIZE-1] = '\000';
|
||||||
client->refbuf->len--; /* make sure we are nul terminated */
|
client->refbuf->len = 0; /* force reader code to ignore buffer */
|
||||||
|
|
||||||
node = calloc (1, sizeof (client_queue_t));
|
node = calloc (1, sizeof (client_queue_t));
|
||||||
if (node == NULL)
|
if (node == NULL)
|
||||||
@ -451,11 +507,29 @@ void connection_accept_loop(void)
|
|||||||
for (i = 0; i < global.server_sockets; i++)
|
for (i = 0; i < global.server_sockets; i++)
|
||||||
{
|
{
|
||||||
if (global.serversock[i] == con->serversock)
|
if (global.serversock[i] == con->serversock)
|
||||||
|
{
|
||||||
if (config->listeners[i].shoutcast_compat)
|
if (config->listeners[i].shoutcast_compat)
|
||||||
node->shoutcast = 1;
|
node->shoutcast = 1;
|
||||||
|
#ifdef HAVE_OPENSSL
|
||||||
|
if (config->listeners[i].ssl && ssl_ok)
|
||||||
|
{
|
||||||
|
client->con->ssl = SSL_new (ssl_ctx);
|
||||||
|
SSL_set_accept_state (client->con->ssl);
|
||||||
|
SSL_set_fd (client->con->ssl, client->con->sock);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
config_release_config();
|
config_release_config();
|
||||||
|
|
||||||
|
#ifdef HAVE_OPENSSL
|
||||||
|
if (node->shoutcast && client->con->ssl)
|
||||||
|
{
|
||||||
|
client_destroy (client);
|
||||||
|
free (node);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
sock_set_blocking (client->con->sock, SOCK_NONBLOCK);
|
sock_set_blocking (client->con->sock, SOCK_NONBLOCK);
|
||||||
sock_set_nodelay (client->con->sock);
|
sock_set_nodelay (client->con->sock);
|
||||||
|
|
||||||
@ -1045,5 +1119,8 @@ void connection_close(connection_t *con)
|
|||||||
sock_close(con->sock);
|
sock_close(con->sock);
|
||||||
if (con->ip) free(con->ip);
|
if (con->ip) free(con->ip);
|
||||||
if (con->host) free(con->host);
|
if (con->host) free(con->host);
|
||||||
|
#ifdef HAVE_OPENSSL
|
||||||
|
if (con->ssl) { SSL_shutdown (con->ssl); SSL_free (con->ssl); }
|
||||||
|
#endif
|
||||||
free(con);
|
free(con);
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,9 @@
|
|||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#ifdef HAVE_OPENSSL
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
#endif
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "httpp/httpp.h"
|
#include "httpp/httpp.h"
|
||||||
#include "thread/thread.h"
|
#include "thread/thread.h"
|
||||||
@ -35,6 +38,10 @@ typedef struct connection_tag
|
|||||||
int serversock;
|
int serversock;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
|
#ifdef HAVE_OPENSSL
|
||||||
|
/* SSL handler */
|
||||||
|
SSL *ssl;
|
||||||
|
#endif
|
||||||
char *ip;
|
char *ip;
|
||||||
char *host;
|
char *host;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user