[Spice-devel] [PATCH 04/17] reds: Move SSL-related code to RedsStream

Christophe Fergeau cfergeau at redhat.com
Tue Jan 7 03:14:30 PST 2014


Code to initiate a SSL stream belongs there
---
 server/reds.c        | 85 +++++++++++++++++++---------------------------------
 server/reds_stream.c | 50 +++++++++++++++++++++++++++++++
 server/reds_stream.h |  2 ++
 3 files changed, 82 insertions(+), 55 deletions(-)

diff --git a/server/reds.c b/server/reds.c
index ce8bb97..cf1dca3 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -37,12 +37,8 @@
 #include <ctype.h>
 #include <stdbool.h>
 
-#include <openssl/bio.h>
-#include <openssl/pem.h>
-#include <openssl/bn.h>
-#include <openssl/rsa.h>
-#include <openssl/ssl.h>
 #include <openssl/err.h>
+
 #if HAVE_SASL
 #include <sasl/sasl.h>
 #endif
@@ -2676,24 +2672,22 @@ static void reds_handle_new_link(RedLinkInfo *link)
 static void reds_handle_ssl_accept(int fd, int event, void *data)
 {
     RedLinkInfo *link = (RedLinkInfo *)data;
-    int return_code;
+    int return_code = reds_stream_ssl_accept(link->stream);
 
-    if ((return_code = SSL_accept(link->stream->ssl)) != 1) {
-        int ssl_error = SSL_get_error(link->stream->ssl, return_code);
-        if (ssl_error != SSL_ERROR_WANT_READ && ssl_error != SSL_ERROR_WANT_WRITE) {
-            spice_warning("SSL_accept failed, error=%d", ssl_error);
+    switch (return_code) {
+        case REDS_STREAM_SSL_STATUS_ERROR:
             reds_link_free(link);
-        } else {
-            if (ssl_error == SSL_ERROR_WANT_READ) {
-                core->watch_update_mask(link->stream->watch, SPICE_WATCH_EVENT_READ);
-            } else {
-                core->watch_update_mask(link->stream->watch, SPICE_WATCH_EVENT_WRITE);
-            }
-        }
-        return;
+            return;
+        case REDS_STREAM_SSL_STATUS_WAIT_FOR_READ:
+            core->watch_update_mask(link->stream->watch, SPICE_WATCH_EVENT_READ);
+            return;
+        case REDS_STREAM_SSL_STATUS_WAIT_FOR_WRITE:
+            core->watch_update_mask(link->stream->watch, SPICE_WATCH_EVENT_WRITE);
+            return;
+        case REDS_STREAM_SSL_STATUS_OK:
+            reds_stream_remove_watch(link->stream);
+            reds_handle_new_link(link);
     }
-    reds_stream_remove_watch(link->stream);
-    reds_handle_new_link(link);
 }
 
 static RedLinkInfo *reds_init_client_connection(int socket)
@@ -2755,52 +2749,33 @@ error:
 static RedLinkInfo *reds_init_client_ssl_connection(int socket)
 {
     RedLinkInfo *link;
-    int return_code;
-    int ssl_error;
-    BIO *sbio;
+    int ssl_status;
 
     link = reds_init_client_connection(socket);
     if (link == NULL)
         goto error;
 
-    // Handle SSL handshaking
-    if (!(sbio = BIO_new_socket(link->stream->socket, BIO_NOCLOSE))) {
-        spice_warning("could not allocate ssl bio socket");
-        goto error;
-    }
-
-    link->stream->ssl = SSL_new(reds->ctx);
-    if (!link->stream->ssl) {
-        spice_warning("could not allocate ssl context");
-        BIO_free(sbio);
-        goto error;
-    }
-
-    SSL_set_bio(link->stream->ssl, sbio, sbio);
-
     link->stream->write = stream_ssl_write_cb;
     link->stream->read = stream_ssl_read_cb;
     link->stream->writev = NULL;
 
-    return_code = SSL_accept(link->stream->ssl);
-    if (return_code == 1) {
-        reds_handle_new_link(link);
-        return link;
-    }
-
-    ssl_error = SSL_get_error(link->stream->ssl, return_code);
-    if (return_code == -1 && (ssl_error == SSL_ERROR_WANT_READ ||
-                              ssl_error == SSL_ERROR_WANT_WRITE)) {
-        int eventmask = ssl_error == SSL_ERROR_WANT_READ ?
-            SPICE_WATCH_EVENT_READ : SPICE_WATCH_EVENT_WRITE;
-        link->stream->watch = core->watch_add(link->stream->socket, eventmask,
+    ssl_status = reds_stream_enable_ssl(link->stream, reds->ctx);
+    switch (ssl_status) {
+        case REDS_STREAM_SSL_STATUS_OK:
+            reds_handle_new_link(link);
+            return link;
+        case REDS_STREAM_SSL_STATUS_ERROR:
+            goto error;
+        case REDS_STREAM_SSL_STATUS_WAIT_FOR_READ:
+            link->stream->watch = core->watch_add(link->stream->socket, SPICE_WATCH_EVENT_READ,
                                             reds_handle_ssl_accept, link);
-        return link;
+            break;
+        case REDS_STREAM_SSL_STATUS_WAIT_FOR_WRITE:
+            link->stream->watch = core->watch_add(link->stream->socket, SPICE_WATCH_EVENT_WRITE,
+                                                  reds_handle_ssl_accept, link);
+            break;
     }
-
-    ERR_print_errors_fp(stderr);
-    spice_warning("SSL_accept failed, error=%d", ssl_error);
-    SSL_free(link->stream->ssl);
+    return link;
 
 error:
     free(link->stream);
diff --git a/server/reds_stream.c b/server/reds_stream.c
index 093621f..5ec0efa 100644
--- a/server/reds_stream.c
+++ b/server/reds_stream.c
@@ -149,6 +149,56 @@ void reds_stream_push_channel_event(RedsStream *s, int event)
     main_dispatcher_channel_event(event, s->info);
 }
 
+RedsStreamSslStatus reds_stream_ssl_accept(RedsStream *stream)
+{
+    int ssl_error;
+    int return_code;
+
+    return_code = SSL_accept(stream->ssl);
+    if (return_code == 1) {
+        return REDS_STREAM_SSL_STATUS_OK;
+    }
+
+    ssl_error = SSL_get_error(stream->ssl, return_code);
+    if (return_code == -1 && (ssl_error == SSL_ERROR_WANT_READ ||
+                              ssl_error == SSL_ERROR_WANT_WRITE)) {
+        if (ssl_error == SSL_ERROR_WANT_READ) {
+            return REDS_STREAM_SSL_STATUS_WAIT_FOR_READ;
+        } else {
+            return REDS_STREAM_SSL_STATUS_WAIT_FOR_WRITE;
+        }
+    }
+
+    ERR_print_errors_fp(stderr);
+    spice_warning("SSL_accept failed, error=%d", ssl_error);
+    SSL_free(stream->ssl);
+    stream->ssl = NULL;
+
+    return REDS_STREAM_SSL_STATUS_ERROR;
+}
+
+int reds_stream_enable_ssl(RedsStream *stream, SSL_CTX *ctx)
+{
+    BIO *sbio;
+
+    // Handle SSL handshaking
+    if (!(sbio = BIO_new_socket(stream->socket, BIO_NOCLOSE))) {
+        spice_warning("could not allocate ssl bio socket");
+        return REDS_STREAM_SSL_STATUS_ERROR;
+    }
+
+    stream->ssl = SSL_new(ctx);
+    if (!stream->ssl) {
+        spice_warning("could not allocate ssl context");
+        BIO_free(sbio);
+        return REDS_STREAM_SSL_STATUS_ERROR;
+    }
+
+    SSL_set_bio(stream->ssl, sbio, sbio);
+
+    return reds_stream_ssl_accept(stream);
+}
+
 #if HAVE_SASL
 bool reds_stream_write_u8(RedsStream *s, uint8_t n)
 {
diff --git a/server/reds_stream.h b/server/reds_stream.h
index c725414..a0a3651 100644
--- a/server/reds_stream.h
+++ b/server/reds_stream.h
@@ -101,5 +101,7 @@ void reds_stream_free(RedsStream *s);
 
 void reds_stream_push_channel_event(RedsStream *s, int event);
 void reds_stream_remove_watch(RedsStream* s);
+RedsStreamSslStatus reds_stream_ssl_accept(RedsStream *stream);
+int reds_stream_enable_ssl(RedsStream *stream, SSL_CTX *ctx);
 
 #endif
-- 
1.8.4.2



More information about the Spice-devel mailing list