[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