summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--server/reds.c85
-rw-r--r--server/reds_stream.c50
-rw-r--r--server/reds_stream.h2
3 files changed, 82 insertions, 55 deletions
diff --git a/server/reds.c b/server/reds.c
index 3f625fa7..2e56758a 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
@@ -2677,24 +2673,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)
@@ -2756,52 +2750,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 093621fb..5ec0efa8 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 c7254142..a0a3651f 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