mirror of
https://gitlab.xiph.org/xiph/icecast-server.git
synced 2024-12-04 14:46:30 -05:00
merge work. allow sockets to be marked as ssl capable. This is mainly for /admin
requests but can be used for sources and listeners svn path=/icecast/trunk/icecast/; revision=13650
This commit is contained in:
parent
31ce005ef3
commit
7e5604b993
@ -129,6 +129,13 @@ 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!])
|
||||
])
|
||||
|
||||
dnl Make substitutions
|
||||
|
||||
|
@ -787,6 +787,11 @@ static void _parse_listen_socket(xmlDocPtr doc, xmlNodePtr node,
|
||||
listener->port = 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, "shoutcast-compat") == 0) {
|
||||
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
||||
listener->shoutcast_compat = atoi(tmp);
|
||||
@ -898,6 +903,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);
|
||||
|
@ -99,6 +99,7 @@ typedef struct {
|
||||
int port;
|
||||
char *bind_address;
|
||||
int shoutcast_compat;
|
||||
int ssl;
|
||||
} listener_t;
|
||||
|
||||
typedef struct ice_config_tag
|
||||
@ -149,6 +150,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;
|
||||
|
27
src/client.c
27
src/client.c
@ -142,18 +142,12 @@ 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);
|
||||
if (bytes > 0)
|
||||
return bytes;
|
||||
bytes = client->con->read (client->con, buf, len);
|
||||
|
||||
if (bytes < 0)
|
||||
{
|
||||
if (sock_recoverable (sock_error()))
|
||||
return -1;
|
||||
WARN0 ("source connection has died");
|
||||
}
|
||||
client->con->error = 1;
|
||||
return -1;
|
||||
if (bytes == -1 && client->con->error)
|
||||
DEBUG0 ("reading from connection has failed");
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
@ -205,14 +199,11 @@ void client_send_403(client_t *client, const char *reason)
|
||||
/* helper function for sending the data to a client */
|
||||
int client_send_bytes (client_t *client, const void *buf, unsigned len)
|
||||
{
|
||||
int ret = sock_write_bytes (client->con->sock, buf, len);
|
||||
if (ret < 0 && !sock_recoverable (sock_error()))
|
||||
{
|
||||
int ret = client->con->send (client->con, buf, len);
|
||||
|
||||
if (client->con->error)
|
||||
DEBUG0 ("Client connection died");
|
||||
client->con->error = 1;
|
||||
}
|
||||
if (ret > 0)
|
||||
client->con->sent_bytes += ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
150
src/connection.c
150
src/connection.c
@ -103,6 +103,11 @@ static volatile client_queue_t *_con_queue = NULL, **_con_queue_tail = &_con_que
|
||||
static mutex_t _con_queue_mutex;
|
||||
static mutex_t _req_queue_mutex;
|
||||
|
||||
static int ssl_ok;
|
||||
#ifdef HAVE_OPENSSL
|
||||
static SSL_CTX *ssl_ctx;
|
||||
#endif
|
||||
|
||||
rwlock_t _source_shutdown_rwlock;
|
||||
|
||||
static void *_handle_connection(void *arg);
|
||||
@ -129,6 +134,10 @@ 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);
|
||||
@ -150,6 +159,126 @@ static unsigned long _next_connection_id(void)
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
static void get_ssl_certificate ()
|
||||
{
|
||||
SSL_METHOD *method;
|
||||
ice_config_t *config;
|
||||
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);
|
||||
|
||||
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;
|
||||
INFO1 ("SSL certificate found at %s", config->cert_file);
|
||||
} while (0);
|
||||
config_release_config ();
|
||||
if (ssl_ok == 0)
|
||||
INFO0 ("No SSL capability on any configured ports");
|
||||
}
|
||||
|
||||
|
||||
/* handlers for reading and writing a connection_t when there is ssl
|
||||
* configured on the listening port
|
||||
*/
|
||||
static int connection_read_ssl (connection_t *con, void *buf, size_t len)
|
||||
{
|
||||
int bytes = SSL_read (con->ssl, buf, len);
|
||||
|
||||
if (bytes < 0)
|
||||
{
|
||||
switch (SSL_get_error (con->ssl, bytes))
|
||||
{
|
||||
case SSL_ERROR_WANT_READ:
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
return -1;
|
||||
}
|
||||
con->error = 1;
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
static int connection_send_ssl (connection_t *con, const void *buf, size_t len)
|
||||
{
|
||||
int bytes = SSL_write (con->ssl, buf, len);
|
||||
|
||||
if (bytes < 0)
|
||||
{
|
||||
switch (SSL_get_error (con->ssl, bytes))
|
||||
{
|
||||
case SSL_ERROR_WANT_READ:
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
return -1;
|
||||
}
|
||||
con->error = 1;
|
||||
}
|
||||
else
|
||||
con->sent_bytes += bytes;
|
||||
return bytes;
|
||||
}
|
||||
#else
|
||||
|
||||
/* SSL not compiled in, so at least log it */
|
||||
static void get_ssl_certificate ()
|
||||
{
|
||||
ssl_ok = 0;
|
||||
INFO0 ("No SSL capability");
|
||||
}
|
||||
#endif /* HAVE_OPENSSL */
|
||||
|
||||
|
||||
/* handlers (default) for reading and writing a connection_t, no encrpytion
|
||||
* used just straight access to the socket
|
||||
*/
|
||||
static int connection_read (connection_t *con, void *buf, size_t len)
|
||||
{
|
||||
int bytes = sock_read_bytes (con->sock, buf, len);
|
||||
if (bytes == 0)
|
||||
con->error = 1;
|
||||
if (bytes == -1 && !sock_recoverable (sock_error()))
|
||||
con->error = 1;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
static int connection_send (connection_t *con, const void *buf, size_t len)
|
||||
{
|
||||
int bytes = sock_write_bytes (con->sock, buf, len);
|
||||
if (bytes < 0)
|
||||
{
|
||||
if (!sock_recoverable (sock_error()))
|
||||
con->error = 1;
|
||||
}
|
||||
else
|
||||
con->sent_bytes += bytes;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
connection_t *connection_create (sock_t sock, sock_t serversock, char *ip)
|
||||
{
|
||||
connection_t *con;
|
||||
@ -161,11 +290,26 @@ 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->read = connection_read;
|
||||
con->send = connection_send;
|
||||
}
|
||||
|
||||
return con;
|
||||
}
|
||||
|
||||
/* prepare connection for interacting over a SSL connection
|
||||
*/
|
||||
void connection_uses_ssl (connection_t *con)
|
||||
{
|
||||
#ifdef HAVE_OPENSSL
|
||||
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);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int wait_for_serversock(int timeout)
|
||||
{
|
||||
#ifdef HAVE_POLL
|
||||
@ -437,6 +581,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)
|
||||
@ -478,6 +623,8 @@ void connection_accept_loop(void)
|
||||
{
|
||||
if (config->listeners[i].shoutcast_compat)
|
||||
node->shoutcast = 1;
|
||||
if (config->listeners[i].ssl && ssl_ok)
|
||||
connection_uses_ssl (client->con);
|
||||
}
|
||||
}
|
||||
config_release_config();
|
||||
@ -1069,5 +1216,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,11 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#ifdef HAVE_OPENSSL
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
#endif
|
||||
|
||||
#include "compat.h"
|
||||
#include "httpp/httpp.h"
|
||||
#include "thread/thread.h"
|
||||
@ -35,6 +40,12 @@ typedef struct connection_tag
|
||||
int serversock;
|
||||
int error;
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
SSL *ssl; /* SSL handler */
|
||||
#endif
|
||||
int (*send)(struct connection_tag *handle, const void *buf, size_t len);
|
||||
int (*read)(struct connection_tag *handle, void *buf, size_t len);
|
||||
|
||||
char *ip;
|
||||
char *host;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user