[xiph-commits] r13650 - in icecast/trunk/icecast: . src
karl at svn.xiph.org
karl at svn.xiph.org
Tue Aug 28 20:51:22 PDT 2007
Author: karl
Date: 2007-08-28 20:51:22 -0700 (Tue, 28 Aug 2007)
New Revision: 13650
Modified:
icecast/trunk/icecast/configure.in
icecast/trunk/icecast/src/cfgfile.c
icecast/trunk/icecast/src/cfgfile.h
icecast/trunk/icecast/src/client.c
icecast/trunk/icecast/src/connection.c
icecast/trunk/icecast/src/connection.h
Log:
merge work. allow sockets to be marked as ssl capable. This is mainly for /admin
requests but can be used for sources and listeners
Modified: icecast/trunk/icecast/configure.in
===================================================================
--- icecast/trunk/icecast/configure.in 2007-08-29 02:01:28 UTC (rev 13649)
+++ icecast/trunk/icecast/configure.in 2007-08-29 03:51:22 UTC (rev 13650)
@@ -129,6 +129,13 @@
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
Modified: icecast/trunk/icecast/src/cfgfile.c
===================================================================
--- icecast/trunk/icecast/src/cfgfile.c 2007-08-29 02:01:28 UTC (rev 13649)
+++ icecast/trunk/icecast/src/cfgfile.c 2007-08-29 03:51:22 UTC (rev 13650)
@@ -787,6 +787,11 @@
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 @@
} 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);
Modified: icecast/trunk/icecast/src/cfgfile.h
===================================================================
--- icecast/trunk/icecast/src/cfgfile.h 2007-08-29 02:01:28 UTC (rev 13649)
+++ icecast/trunk/icecast/src/cfgfile.h 2007-08-29 03:51:22 UTC (rev 13650)
@@ -99,6 +99,7 @@
int port;
char *bind_address;
int shoutcast_compat;
+ int ssl;
} listener_t;
typedef struct ice_config_tag
@@ -149,6 +150,7 @@
char *base_dir;
char *log_dir;
char *pidfile;
+ char *cert_file;
char *webroot_dir;
char *adminroot_dir;
aliases *aliases;
Modified: icecast/trunk/icecast/src/client.c
===================================================================
--- icecast/trunk/icecast/src/client.c 2007-08-29 02:01:28 UTC (rev 13649)
+++ icecast/trunk/icecast/src/client.c 2007-08-29 03:51:22 UTC (rev 13650)
@@ -101,7 +101,7 @@
*/
if (client->respcode && client->parser)
logging_access(client);
-
+
if (client->con)
connection_close(client->con);
if (client->parser)
@@ -127,7 +127,7 @@
int client_read_bytes (client_t *client, void *buf, unsigned len)
{
int bytes;
-
+
if (client->refbuf && client->refbuf->len)
{
/* we have data to read from a refbuf first */
@@ -142,18 +142,12 @@
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 @@
/* 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;
}
Modified: icecast/trunk/icecast/src/connection.c
===================================================================
--- icecast/trunk/icecast/src/connection.c 2007-08-29 02:01:28 UTC (rev 13649)
+++ icecast/trunk/icecast/src/connection.c 2007-08-29 03:51:22 UTC (rev 13650)
@@ -103,6 +103,11 @@
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 @@
{
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 @@
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 @@
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 @@
{
connection_t *con;
+ get_ssl_certificate ();
tid = thread_create ("connection thread", _handle_connection, NULL, THREAD_ATTACHED);
while (global.running == ICE_RUNNING)
@@ -478,9 +623,11 @@
{
if (config->listeners[i].shoutcast_compat)
node->shoutcast = 1;
+ if (config->listeners[i].ssl && ssl_ok)
+ connection_uses_ssl (client->con);
}
}
- config_release_config();
+ config_release_config();
sock_set_blocking (client->con->sock, SOCK_NONBLOCK);
sock_set_nodelay (client->con->sock);
@@ -1069,5 +1216,8 @@
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);
}
Modified: icecast/trunk/icecast/src/connection.h
===================================================================
--- icecast/trunk/icecast/src/connection.h 2007-08-29 02:01:28 UTC (rev 13649)
+++ icecast/trunk/icecast/src/connection.h 2007-08-29 03:51:22 UTC (rev 13650)
@@ -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 @@
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;
More information about the commits
mailing list