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>
|
||||
<port>8001</port>
|
||||
<ssl>1</ssl>
|
||||
</listen-socket>
|
||||
-->
|
||||
|
||||
@ -158,6 +159,7 @@
|
||||
<webroot>@pkgdatadir@/web</webroot>
|
||||
<adminroot>@pkgdatadir@/admin</adminroot>
|
||||
<!-- <pidfile>@pkgdatadir@/icecast.pid</pidfile> -->
|
||||
<!-- <ssl_certificate>@pkgdatadir@/icecast.pem</ssl_certificate> -->
|
||||
|
||||
<!-- Aliases: treat requests for 'source' path as being for 'dest' path
|
||||
May be made specific to a port or bound address using the "port"
|
||||
|
@ -130,6 +130,14 @@ then
|
||||
else
|
||||
AC_MSG_NOTICE([YP support disabled])
|
||||
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
|
||||
AC_ARG_ENABLE([log-ip],
|
||||
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;
|
||||
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);
|
||||
if (mountinfo && mountinfo->auth)
|
||||
{
|
||||
|
@ -794,6 +794,11 @@ static void _parse_listen_socket(xmlDocPtr doc, xmlNodePtr node,
|
||||
listener->shoutcast_compat = atoi(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) {
|
||||
listener->bind_address = (char *)xmlNodeListGetString(doc,
|
||||
node->xmlChildrenNode, 1);
|
||||
@ -900,6 +905,9 @@ static void _parse_paths(xmlDocPtr doc, xmlNodePtr node,
|
||||
} else if (strcmp(node->name, "pidfile") == 0) {
|
||||
if (configuration->pidfile) xmlFree(configuration->pidfile);
|
||||
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) {
|
||||
if (configuration->webroot_dir && configuration->webroot_dir != CONFIG_DEFAULT_WEBROOT_DIR) xmlFree(configuration->webroot_dir);
|
||||
configuration->webroot_dir = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
||||
|
@ -97,6 +97,7 @@ typedef struct {
|
||||
int port;
|
||||
char *bind_address;
|
||||
int shoutcast_compat;
|
||||
int ssl;
|
||||
} listener_t;
|
||||
|
||||
typedef struct ice_config_tag
|
||||
@ -147,6 +148,7 @@ typedef struct ice_config_tag
|
||||
char *base_dir;
|
||||
char *log_dir;
|
||||
char *pidfile;
|
||||
char *cert_file;
|
||||
char *webroot_dir;
|
||||
char *adminroot_dir;
|
||||
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;
|
||||
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)
|
||||
return bytes;
|
||||
|
||||
if (bytes < 0)
|
||||
{
|
||||
if (sock_recoverable (sock_error()))
|
||||
return -1;
|
||||
WARN0 ("source connection has died");
|
||||
#ifdef HAVE_OPENSSL
|
||||
if (client->con->ssl)
|
||||
{
|
||||
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;
|
||||
return bytes;
|
||||
@ -241,16 +260,36 @@ int client_send_bytes (client_t *client, const void *buf, unsigned len)
|
||||
return -1;
|
||||
ret = aio_return (aiocbp);
|
||||
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;
|
||||
|
||||
#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
|
||||
|
||||
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");
|
||||
client->con->error = 1;
|
||||
}
|
||||
|
@ -33,6 +33,9 @@
|
||||
#define strcasecmp stricmp
|
||||
#define strncasecmp strnicmp
|
||||
#endif
|
||||
#ifdef HAVE_OPENSSL
|
||||
#include <openssl/ssl.h>
|
||||
#endif
|
||||
|
||||
#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 mutex_t _con_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;
|
||||
|
||||
@ -121,10 +128,58 @@ void connection_initialize(void)
|
||||
_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)
|
||||
{
|
||||
if (!_initialized) return;
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
SSL_CTX_free (ssl_ctx);
|
||||
#endif
|
||||
|
||||
thread_cond_destroy(&global.shutdown_cond);
|
||||
thread_rwlock_destroy(&_source_shutdown_rwlock);
|
||||
thread_mutex_destroy(&_con_queue_mutex);
|
||||
@ -324,7 +379,7 @@ static void process_request_queue ()
|
||||
{
|
||||
client_queue_t *node = *node_ref;
|
||||
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;
|
||||
|
||||
if (len > 0)
|
||||
@ -332,7 +387,7 @@ static void process_request_queue ()
|
||||
if (client->con->con_time + timeout <= global.time)
|
||||
len = 0;
|
||||
else
|
||||
len = sock_read_bytes (client->con->sock, buf, len);
|
||||
len = client_read_bytes (client, buf, len);
|
||||
}
|
||||
|
||||
if (len > 0)
|
||||
@ -380,7 +435,7 @@ static void process_request_queue ()
|
||||
}
|
||||
else
|
||||
{
|
||||
if (len == 0 || !sock_recoverable (sock_error()))
|
||||
if (len == 0 || client->con->error)
|
||||
{
|
||||
if ((client_queue_t **)_req_queue_tail == &node->next)
|
||||
_req_queue_tail = (volatile client_queue_t **)node_ref;
|
||||
@ -411,6 +466,7 @@ void connection_accept_loop(void)
|
||||
{
|
||||
connection_t *con;
|
||||
|
||||
get_ssl_certificate ();
|
||||
tid = thread_create ("connection thread", _handle_connection, NULL, THREAD_ATTACHED);
|
||||
|
||||
while (global.running == ICE_RUNNING)
|
||||
@ -436,7 +492,7 @@ void connection_accept_loop(void)
|
||||
/* setup client for reading incoming http */
|
||||
client->refbuf = refbuf_new (PER_CLIENT_REFBUF_SIZE);
|
||||
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));
|
||||
if (node == NULL)
|
||||
@ -451,11 +507,29 @@ void connection_accept_loop(void)
|
||||
for (i = 0; i < global.server_sockets; i++)
|
||||
{
|
||||
if (global.serversock[i] == con->serversock)
|
||||
{
|
||||
if (config->listeners[i].shoutcast_compat)
|
||||
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();
|
||||
|
||||
#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_nodelay (client->con->sock);
|
||||
|
||||
@ -1045,5 +1119,8 @@ void connection_close(connection_t *con)
|
||||
sock_close(con->sock);
|
||||
if (con->ip) free(con->ip);
|
||||
if (con->host) free(con->host);
|
||||
#ifdef HAVE_OPENSSL
|
||||
if (con->ssl) { SSL_shutdown (con->ssl); SSL_free (con->ssl); }
|
||||
#endif
|
||||
free(con);
|
||||
}
|
||||
|
@ -15,6 +15,9 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#ifdef HAVE_OPENSSL
|
||||
#include <openssl/ssl.h>
|
||||
#endif
|
||||
#include "compat.h"
|
||||
#include "httpp/httpp.h"
|
||||
#include "thread/thread.h"
|
||||
@ -35,6 +38,10 @@ typedef struct connection_tag
|
||||
int serversock;
|
||||
int error;
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
/* SSL handler */
|
||||
SSL *ssl;
|
||||
#endif
|
||||
char *ip;
|
||||
char *host;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user