[IOMultiplexerV2] added SSL Backend
authorpk910 <pk910@pk910-laptop.(none)>
Tue, 4 Mar 2014 17:19:02 +0000 (18:19 +0100)
committerpk910 <pk910@pk910-laptop.(none)>
Tue, 4 Mar 2014 17:19:02 +0000 (18:19 +0100)
src/IOHandler/IOSSLBackend.c [new file with mode: 0644]
src/IOHandler/IOSSLBackend.h [new file with mode: 0644]
src/IOHandler/IOSockets.c
src/IOHandler/IOSockets.h
src/IOHandler/Makefile.am
src/IOHandler_test/socket/iotest.c

diff --git a/src/IOHandler/IOSSLBackend.c b/src/IOHandler/IOSSLBackend.c
new file mode 100644 (file)
index 0000000..5fe568e
--- /dev/null
@@ -0,0 +1,258 @@
+/* IOSSLBackend.c - IOMultiplexer
+ * Copyright (C) 2014  Philipp Kreil (pk910)
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License 
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. 
+ */
+#define _IOHandler_internals
+#include "IOInternal.h"
+#include "IOHandler.h"
+#include "IOLog.h"
+#include "IOSockets.h"
+#include "IOSSLBackend.h"
+
+#ifdef HAVE_OPENSSL_SSL_H
+/* OpenSSL Backend */
+
+
+void iossl_init() {
+    SSL_library_init();
+    OpenSSL_add_all_algorithms(); /* load & register all cryptos, etc. */
+    SSL_load_error_strings();
+}
+
+static void iossl_error() {
+    unsigned long e;
+    while((e = ERR_get_error())) {
+        iolog_trigger(IOLOG_ERROR, "SSLv23 ERROR %lu: %s", e, ERR_error_string(e, NULL));
+    }
+}
+
+// Client
+void iossl_connect(struct _IOSocket *iosock) {
+    struct IOSSLDescriptor *sslnode = malloc(sizeof(*sslnode));
+    sslnode->sslContext = SSL_CTX_new(SSLv23_client_method());
+    if(!sslnode->sslContext) {
+        iossl_error();
+        iolog_trigger(IOLOG_ERROR, "SSL: could not create client SSL CTX");
+        goto ssl_connect_err;
+    }
+    sslnode->sslHandle = SSL_new(sslnode->sslContext);
+    if(!sslnode->sslHandle) {
+        iossl_error();
+        iolog_trigger(IOLOG_ERROR, "SSL: could not create client SSL Handle");
+        goto ssl_connect_err;
+    }
+    if(!SSL_set_fd(sslnode->sslHandle, iosock->fd)) {
+        iossl_error();
+        iolog_trigger(IOLOG_ERROR, "SSL: could not set client fd in SSL Handle");
+        goto ssl_connect_err;
+    }
+    SSL_set_connect_state(sslnode->sslHandle);
+    iosock->sslnode = sslnode;
+       iosock->socket_flags |= IOSOCKETFLAG_SSL_HANDSHAKE;
+    iossl_client_handshake(iosock);
+    return;
+ssl_connect_err:
+    free(sslnode);
+    iosocket_events_callback(iosock, 0, 0);
+}
+
+void iossl_client_handshake(struct _IOSocket *iosock) {
+    // Perform an SSL handshake.
+    int ret = SSL_do_handshake(iosock->sslnode->sslHandle);
+    iosock->socket_flags &= ~IOSOCKETFLAG_SSL_WANTWRITE;
+    switch(SSL_get_error(iosock->sslnode->sslHandle, ret)) {
+        case SSL_ERROR_NONE:
+            iolog_trigger(IOLOG_DEBUG, "SSL handshake for fd %d successful", iosock->fd);
+                       iosock->socket_flags |= IOSOCKETFLAG_SSL_ESTABLISHED;
+            iosocket_events_callback(iosock, 0, 0); //perform IOEVENT_CONNECTED event
+            break;
+        case SSL_ERROR_WANT_READ:
+            iolog_trigger(IOLOG_DEBUG, "SSL_do_handshake for fd %d returned SSL_ERROR_WANT_READ", iosock->fd);
+            break;
+        case SSL_ERROR_WANT_WRITE:
+            iosock->socket_flags |= IOSOCKETFLAG_SSL_WANTWRITE;
+            iolog_trigger(IOLOG_DEBUG, "SSL_do_handshake for fd %d returned SSL_ERROR_WANT_WRITE", iosock->fd);
+            break;
+        default:
+            iolog_trigger(IOLOG_ERROR, "SSL_do_handshake for fd %d failed with ", iosock->fd);
+            iosocket_events_callback(iosock, 0, 0);
+            break;
+    }
+}
+
+
+// Server
+void iossl_listen(struct _IOSocket *iosock, const char *certfile, const char *keyfile) {
+    struct IOSSLDescriptor *sslnode = malloc(sizeof(*sslnode));
+    sslnode->sslContext = SSL_CTX_new(SSLv23_server_method());
+    if(!sslnode->sslContext) {
+        iossl_error();
+        iolog_trigger(IOLOG_ERROR, "SSL: could not create server SSL CTX");
+        goto ssl_listen_err;
+    }
+    /* load certificate */
+    if(SSL_CTX_use_certificate_file(sslnode->sslContext, certfile, SSL_FILETYPE_PEM) <= 0) {
+        iossl_error();
+        iolog_trigger(IOLOG_ERROR, "SSL: could not load server certificate (%s)", certfile);
+        goto ssl_listen_err;
+    }
+    /* load keyfile */
+    if(SSL_CTX_use_PrivateKey_file(sslnode->sslContext, keyfile, SSL_FILETYPE_PEM) <= 0) {
+        iossl_error();
+        iolog_trigger(IOLOG_ERROR, "SSL: could not load server keyfile (%s)", keyfile);
+        goto ssl_listen_err;
+    }
+    /* check certificate and keyfile */
+    if(!SSL_CTX_check_private_key(sslnode->sslContext)) {
+        iossl_error();
+        iolog_trigger(IOLOG_ERROR, "SSL: server certificate (%s) and keyfile (%s) doesn't match!", certfile, keyfile);
+        goto ssl_listen_err;
+    }
+    iosock->sslnode = sslnode;\r
+    iosock->socket_flags |= IOSOCKETFLAG_SSL_ESTABLISHED;
+    return;
+ssl_listen_err:
+    free(sslnode);
+    iosock->sslnode = NULL;
+    iosocket_events_callback(iosock, 0, 0);
+}
+
+void iossl_client_accepted(struct _IOSocket *iosock, struct _IOSocket *new_iosock) {
+    struct IOSSLDescriptor *sslnode = malloc(sizeof(*sslnode));
+    sslnode->sslHandle = SSL_new(sslnode->sslContext);
+    if(!sslnode->sslHandle) {
+        iossl_error();
+        iolog_trigger(IOLOG_ERROR, "SSL: could not create client SSL Handle");
+        goto ssl_accept_err;
+    }
+    if(!SSL_set_fd(sslnode->sslHandle, new_iosock->fd)) {
+        iossl_error();
+        iolog_trigger(IOLOG_ERROR, "SSL: could not set client fd in SSL Handle");
+        goto ssl_accept_err;
+    }
+    new_iosock->sslnode = sslnode;\r
+    new_iosock->socket_flags |= IOSOCKETFLAG_SSL_HANDSHAKE;
+    return;
+ssl_accept_err:
+    free(sslnode);\r
+    iosock->sslnode = NULL;\r
+    iosocket_events_callback(new_iosock, 0, 0);
+}
+
+void iossl_server_handshake(struct _IOSocket *iosock) {
+    // Perform an SSL handshake.
+    int ret = SSL_accept(iosock->sslnode->sslHandle);
+    iosock->socket_flags &= ~IOSOCKETFLAG_SSL_WANTWRITE;
+    switch(SSL_get_error(iosock->sslnode->sslHandle, ret)) {
+        case SSL_ERROR_NONE:
+            iolog_trigger(IOLOG_DEBUG, "SSL handshake for fd %d successful", iosock->fd);
+                       iosock->socket_flags |= IOSOCKETFLAG_SSL_ESTABLISHED;
+            iosocket_events_callback(iosock, 0, 0); //perform IOEVENT_CONNECTED event
+            break;
+        case SSL_ERROR_WANT_READ:
+            iolog_trigger(IOLOG_DEBUG, "SSL_do_handshake for fd %d returned SSL_ERROR_WANT_READ", iosock->fd);
+            break;
+        case SSL_ERROR_WANT_WRITE:
+            iosock->socket_flags |= IOSOCKETFLAG_SSL_WANTWRITE;
+            iolog_trigger(IOLOG_DEBUG, "SSL_do_handshake for fd %d returned SSL_ERROR_WANT_WRITE", iosock->fd);
+            break;
+        default:
+            iolog_trigger(IOLOG_ERROR, "SSL_do_handshake for fd %d failed with ", iosock->fd);
+            iosocket_events_callback(iosock, 0, 0);
+            break;
+    }
+}
+
+void iossl_disconnect(struct _IOSocket *iosock) {
+    if(!iosock->sslnode) return;
+    SSL_shutdown(iosock->sslnode->sslHandle);
+    SSL_free(iosock->sslnode->sslHandle);
+    SSL_CTX_free(iosock->sslnode->sslContext);
+    free(iosock->sslnode);
+    iosock->sslnode = NULL;
+    iosock->socket_flags &= ~IOSOCKETFLAG_SSLSOCKET;
+}
+
+int iossl_read(struct _IOSocket *iosock, char *buffer, int len) {
+    if((iosock->socket_flags & (IOSOCKETFLAG_SSLSOCKET | IOSOCKETFLAG_SSL_ESTABLISHED)) != (IOSOCKETFLAG_SSLSOCKET | IOSOCKETFLAG_SSL_ESTABLISHED))\r
+               return 0;
+    int ret = SSL_read(iosock->sslnode->sslHandle, buffer, len);
+    iosock->socket_flags &= ~(IOSOCKETFLAG_SSL_WANTWRITE | IOSOCKETFLAG_SSL_READHS);
+    switch(SSL_get_error(iosock->sslnode->sslHandle, ret)) {
+        case SSL_ERROR_NONE:
+        case SSL_ERROR_ZERO_RETURN:
+            break;
+        case SSL_ERROR_WANT_READ:\r
+                       iosock->socket_flags |= IOSOCKETFLAG_SSL_READHS;
+            iolog_trigger(IOLOG_DEBUG, "SSL_read for fd %d returned SSL_ERROR_WANT_READ", iosock->fd);
+            errno = EAGAIN;
+            ret = -1;
+            break;
+        case SSL_ERROR_WANT_WRITE:
+            iosock->socket_flags |= IOSOCKETFLAG_SSL_WANTWRITE | IOSOCKETFLAG_SSL_READHS;
+            iolog_trigger(IOLOG_DEBUG, "SSL_read for fd %d returned SSL_ERROR_WANT_WRITE", iosock->fd);
+            errno = EAGAIN;
+            ret = -1;
+            break;
+        default:
+            iolog_trigger(IOLOG_ERROR, "SSL_read for fd %d failed with ", iosock->fd);
+            ret = -1;
+            break;
+    }\r
+    return ret;
+}
+
+int iossl_write(struct _IOSocket *iosock, char *buffer, int len) {
+    if((iosock->socket_flags & (IOSOCKETFLAG_SSLSOCKET | IOSOCKETFLAG_SSL_ESTABLISHED)) != (IOSOCKETFLAG_SSLSOCKET | IOSOCKETFLAG_SSL_ESTABLISHED))\r
+               return 0;
+    int ret = SSL_write(iosock->sslnode->sslHandle, buffer, len);
+    iosock->socket_flags &= ~(IOSOCKETFLAG_SSL_WANTWRITE | IOSOCKETFLAG_SSL_WRITEHS);
+    switch(SSL_get_error(iosock->sslnode->sslHandle, ret)) {
+        case SSL_ERROR_NONE:
+        case SSL_ERROR_ZERO_RETURN:
+            break;
+        case SSL_ERROR_WANT_READ:
+            iosock->socket_flags |= IOSOCKETFLAG_SSL_WRITEHS;
+            iolog_trigger(IOLOG_DEBUG, "SSL_write for fd %d returned SSL_ERROR_WANT_READ", iosock->fd);
+            errno = EAGAIN;
+            ret = -1;
+            break;
+        case SSL_ERROR_WANT_WRITE:
+            iosock->socket_flags |= IOSOCKETFLAG_SSL_WANTWRITE | IOSOCKETFLAG_SSL_WRITEHS;
+            iolog_trigger(IOLOG_DEBUG, "SSL_write for fd %d returned SSL_ERROR_WANT_WRITE", iosock->fd);
+            errno = EAGAIN;
+            ret = -1;
+            break;
+        default:
+            iolog_trigger(IOLOG_ERROR, "SSL_write for fd %d failed with ", iosock->fd);
+            ret = -1;
+            break;
+    }\r
+    return ret;
+}
+
+#else
+// NULL-backend
+
+void iossl_init() {};
+void iossl_connect(struct _IOSocket *iosock) {};
+void iossl_listen(struct _IOSocket *iosock, const char *certfile, const char *keyfile) {};
+void iossl_client_handshake(struct _IOSocket *iosock) {};
+void iossl_client_accepted(struct _IOSocket *iosock, struct IODescriptor *client_iofd) {};
+void iossl_server_handshake(struct _IOSocket *iosock) {};
+void iossl_disconnect(struct _IOSocket *iosock) {};
+int iossl_read(struct _IOSocket *iosock, char *buffer, int len) { return 0; };
+int iossl_write(struct _IOSocket *iosock, char *buffer, int len) { return 0; };
+#endif
diff --git a/src/IOHandler/IOSSLBackend.h b/src/IOHandler/IOSSLBackend.h
new file mode 100644 (file)
index 0000000..879537e
--- /dev/null
@@ -0,0 +1,48 @@
+/* IOHandler_SSL.h - IOMultiplexer
+ * Copyright (C) 2014  Philipp Kreil (pk910)
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License 
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. 
+ */
+#ifndef _IOSSLBackend_h
+#define _IOSSLBackend_h
+
+struct _IOSocket;
+
+#ifdef HAVE_OPENSSL_SSL_H
+#include <openssl/rand.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+
+struct IOSSLDescriptor {
+       unsigned int flags : 8;
+    SSL *sslHandle;
+    SSL_CTX *sslContext;
+};
+#else
+struct IOSSLDescriptor {
+    //just unused
+};
+#endif
+
+void iossl_init();
+void iossl_connect(struct _IOSocket *iosock);
+void iossl_listen(struct _IOSocket *iosock, const char *certfile, const char *keyfile);
+void iossl_client_handshake(struct _IOSocket *iosock);
+void iossl_client_accepted(struct _IOSocket *iosock, struct _IOSocket *new_iosock);
+void iossl_server_handshake(struct _IOSocket *iosock);
+void iossl_disconnect(struct _IOSocket *iosock);
+int iossl_read(struct _IOSocket *iosock, char *buffer, int len);
+int iossl_write(struct _IOSocket *iosock, char *buffer, int len);
+
+#endif
index 480d1ba39ae9bfecd10c2e79707eadd35137b31e..4a7da99c6b8618c6df169a7ff65ce3775e3e0034 100644 (file)
@@ -100,7 +100,8 @@ void _init_sockets() {
     }
        #endif
        
-       iosockets_init_engine();
+       iosockets_init_engine();\r
+       iossl_init();
 }
 
 
@@ -140,6 +141,8 @@ void _free_socket(struct _IOSocket *iosock) {
                free(iosock->readbuf.buffer);
        if(iosock->writebuf.buffer)
                free(iosock->writebuf.buffer);
+       if((iosock->socket_flags & IOSOCKETFLAG_SSLSOCKET))\r
+               iossl_disconnect(iosock);\r
        
        free(iosock);
 }
@@ -622,7 +625,8 @@ struct _IOSocket *iosocket_accept_client(struct _IOSocket *iosock) {
        if((iosock->socket_flags & IOSOCKETFLAG_SSLSOCKET)) {
                new_iosocket->ssl = 1;
                new_iosock->socket_flags |= IOSOCKETFLAG_SSLSOCKET;
-               //TODO: SSL Handshake
+               \r
+               iossl_client_accepted(iosock, new_iosock);
        }
        
        iosocket_activate(new_iosock);
@@ -717,12 +721,6 @@ struct IOSocket *iosocket_listen_flags(const char *hostname, unsigned int port,
        iosock->parent = iodescriptor;
        iosock->socket_flags |= IOSOCKETFLAG_PARENT_PUBLIC | IOSOCKETFLAG_LISTENING;
        iosock->port = port;
-       /*
-       if(ssl) {
-               iodescriptor->ssl = 1;
-               iosock->socket_flags |= IOSOCKETFLAG_SSLSOCKET;
-       }
-       */
        
        switch(iosocket_parse_address(hostname, &iosock->bind.addr, flags)) {
        case -1:
@@ -748,8 +746,11 @@ struct IOSocket *iosocket_listen_ssl(const char *hostname, unsigned int port, co
 }
 
 struct IOSocket *iosocket_listen_ssl_flags(const char *hostname, unsigned int port, const char *certfile, const char *keyfile, iosocket_callback *callback, int flags) {
-       //TODO: SSL
-       return NULL;
+       struct IOSocket *iosocket = iosocket_listen_flags(hostname, port, callback, flags);\r
+       struct _IOSocket *iosock = iosocket->iosocket;\r
+       iosock->socket_flags |= IOSOCKETFLAG_SSLSOCKET | IOSOCKETFLAG_SSL_HANDSHAKE;\r
+       iossl_listen(iosock, certfile, keyfile);
+       return iosocket;
 }
 
 void iosocket_close(struct IOSocket *iosocket) {
@@ -777,9 +778,8 @@ void iosocket_close(struct IOSocket *iosocket) {
                iosocket_try_write(iosock);
        }
        //close IOSocket
-       if(iosock->sslnode) {
-               //TODO: SSL
-       }
+       if((iosock->socket_flags & IOSOCKETFLAG_SSLSOCKET))
+               iossl_disconnect(iosock);
        if(iosock->fd)
                close(iosock->fd);
        _free_socket(iosock);
@@ -789,13 +789,13 @@ void iosocket_close(struct IOSocket *iosocket) {
 }
 
 static int iosocket_try_write(struct _IOSocket *iosock) {
-       if(!iosock->writebuf.bufpos) return 0;
+       if(!iosock->writebuf.bufpos && !(iosock->socket_flags & IOSOCKETFLAG_SSL_WRITEHS)) \r
+               return 0;
        iolog_trigger(IOLOG_DEBUG, "write writebuf (%d bytes) to socket (fd: %d)", iosock->writebuf.bufpos, iosock->fd);
        int res;
-       if(iosock->sslnode) {
-               /* res = iohandler_ssl_write(iofd, iofd->writebuf.buffer, iofd->writebuf.bufpos); */
-               // TODO
-       } else
+       if((iosock->socket_flags & IOSOCKETFLAG_SSLSOCKET))
+               res = iossl_write(iosock, iosock->writebuf.buffer, iosock->writebuf.bufpos);
+       else
                res = send(iosock->fd, iosock->writebuf.buffer, iosock->writebuf.bufpos, 0);
        if(res < 0) {
                if (errno != EAGAIN && errno != EWOULDBLOCK)
@@ -846,12 +846,11 @@ void iosocket_printf(struct IOSocket *iosocket, const char *text, ...) {
        int pos;
        sendBuf[0] = '\0';
        va_start(arg_list, text);
-       pos = vsnprintf(sendBuf, IOSOCKET_PRINTF_LINE_LEN - 2, text, arg_list);
+       pos = vsnprintf(sendBuf, IOSOCKET_PRINTF_LINE_LEN - 1, text, arg_list);
        va_end(arg_list);
-       if (pos < 0 || pos > (IOSOCKET_PRINTF_LINE_LEN - 2)) pos = IOSOCKET_PRINTF_LINE_LEN - 2;
-       sendBuf[pos] = '\n';
-       sendBuf[pos+1] = '\0';
-       iosocket_send(iosocket, sendBuf, pos+1);
+       if (pos < 0 || pos > (IOSOCKET_PRINTF_LINE_LEN - 1)) pos = IOSOCKET_PRINTF_LINE_LEN - 1;
+       sendBuf[pos] = '\0';
+       iosocket_send(iosocket, sendBuf, pos);
 }
 
 
@@ -871,7 +870,40 @@ void iosocket_events_callback(struct _IOSocket *iosock, int readable, int writea
                callback_event.socket = iosocket;
                
                if((iosock->socket_flags & IOSOCKETFLAG_SSL_HANDSHAKE)) {
-                       //TODO: SSL
+                       if(readable || writeable) {
+                               if((iosock->socket_flags & IOSOCKETFLAG_INCOMING)) 
+                                       iossl_server_handshake(iosock);
+                               else
+                                       iossl_client_handshake(iosock);
+                               engine->update(iosock);\r
+                       } else if((iosock->socket_flags & IOSOCKETFLAG_LISTENING)) {\r
+                               //TODO: SSL init error\r
+                       } else if((iosock->socket_flags & IOSOCKETFLAG_INCOMING)) {\r
+                               if((iosock->socket_flags & IOSOCKETFLAG_SSL_ESTABLISHED)) {\r
+                                       //incoming SSL connection accepted\r
+                                       iosock->socket_flags &= ~IOSOCKETFLAG_SSL_HANDSHAKE;\r
+                                       callback_event.type = IOSOCKETEVENT_ACCEPT;\r
+                                       callback_event.data.accept_socket = iosock->parent;\r
+                               } else {\r
+                                       //incoming SSL connection failed, simply drop\r
+                                       iosock->socket_flags |= IOSOCKETFLAG_DEAD;\r
+                                       iolog_trigger(IOLOG_ERROR, "SSL Handshake failed for incoming connection. Dropping fd %d", iosock->fd);\r
+                               }
+                       } else {
+                               // SSL Backend finished
+                               if((iosock->socket_flags & IOSOCKETFLAG_SSL_ESTABLISHED)) {\r
+                                       iosocket->status = IOSOCKET_CONNECTED;\r
+                                       iosock->socket_flags &= ~IOSOCKETFLAG_SSL_HANDSHAKE;\r
+                                       callback_event.type = IOSOCKETEVENT_CONNECTED;\r
+                                       engine->update(iosock);\r
+                                       \r
+                                       //initialize readbuf\r
+                                       iosocket_increase_buffer(&iosock->readbuf, 1024);
+                               } else {
+                                       callback_event.type = IOSOCKETEVENT_NOTCONNECTED;\r
+                                       iosock->socket_flags |= IOSOCKETFLAG_DEAD;
+                               }
+                       }
                } else if((iosock->socket_flags & IOSOCKETFLAG_LISTENING)) {
                        if(readable) {
                                //new client connected
@@ -904,32 +936,43 @@ void iosocket_events_callback(struct _IOSocket *iosock, int readable, int writea
                                        iosock->socket_flags |= IOSOCKETFLAG_DEAD;
                                }
                        } else if(writeable) { //connection established
-                               iosocket->status = IOSOCKET_CONNECTED;
-                               if((iosock->socket_flags & IOSOCKETFLAG_SSLSOCKET)) {
-                                       //TODO: SSL Handshake
+                               iosock->socket_flags &= ~IOSOCKETFLAG_CONNECTING;
+                               socket_lookup_clear(iosock);
+                               if((iosock->socket_flags & IOSOCKETFLAG_SSLSOCKET)) {\r
+                                       iolog_trigger(IOLOG_DEBUG, "SSL client socket connected. Stating SSL handshake...");
+                                       iossl_connect(iosock);
+                                       engine->update(iosock);
                                        return;
                                }
+                               iosocket->status = IOSOCKET_CONNECTED;
                                
                                callback_event.type = IOSOCKETEVENT_CONNECTED;
-                               iosock->socket_flags &= ~IOSOCKETFLAG_CONNECTING;
-                               socket_lookup_clear(iosock);
                                engine->update(iosock);
                                
                                //initialize readbuf
                                iosocket_increase_buffer(&iosock->readbuf, 1024);
                        }
-               } else {
-                       if(readable) {
+               } else {\r
+                       int ssl_rehandshake = 0;\r
+                       if((iosock->socket_flags & IOSOCKETFLAG_SSLSOCKET)) {\r
+                               if((iosock->socket_flags & IOSOCKETFLAG_SSL_READHS))\r
+                                       ssl_rehandshake = 1;\r
+                               else if((iosock->socket_flags & IOSOCKETFLAG_SSL_WRITEHS))\r
+                                       ssl_rehandshake = 2;\r
+                       }
+                       if((readable && ssl_rehandshake == 0) || ssl_rehandshake == 1) {
                                int bytes;
                                if(iosock->readbuf.buflen - iosock->readbuf.bufpos >= 128)
                                        iosocket_increase_buffer(&iosock->readbuf, iosock->readbuf.buflen + 1024);
-                               if((iosock->socket_flags & IOSOCKETFLAG_SSLSOCKET)) {
-                                       //TODO: SSL read
-                               else 
+                               if((iosock->socket_flags & IOSOCKETFLAG_SSLSOCKET))
+                                       bytes = iossl_read(iosock, iosock->readbuf.buffer + iosock->readbuf.bufpos, iosock->readbuf.buflen - iosock->readbuf.bufpos);
+                               else 
                                        bytes = recv(iosock->fd, iosock->readbuf.buffer + iosock->readbuf.bufpos, iosock->readbuf.buflen - iosock->readbuf.bufpos, 0);
                                        
-                               if(bytes <= 0) {
-                                       if (errno != EAGAIN || errno != EWOULDBLOCK) {
+                               if(bytes <= 0) {\r
+                                       if((iosock->socket_flags & (IOSOCKETFLAG_SSLSOCKET | IOSOCKETFLAG_SSL_READHS)) == (IOSOCKETFLAG_SSLSOCKET | IOSOCKETFLAG_SSL_READHS)) {\r
+                                               ssl_rehandshake = 1;\r
+                                       } else if (errno != EAGAIN || errno != EWOULDBLOCK) {
                                                iosock->socket_flags |= IOSOCKETFLAG_DEAD;
                                                
                                                callback_event.type = IOSOCKETEVENT_CLOSED;
@@ -989,17 +1032,23 @@ void iosocket_events_callback(struct _IOSocket *iosock, int readable, int writea
                                                callback_event.data.recv_buf = &iosock->readbuf;
                                }
                        }
-                       if(writeable) {
+                       if((writeable && ssl_rehandshake == 0) || ssl_rehandshake == 2) {
                                int bytes;
                                bytes = iosocket_try_write(iosock);
-                               if(bytes < 0) {
-                                       iosock->socket_flags |= IOSOCKETFLAG_DEAD;
-                                       
-                                       callback_event.type = IOSOCKETEVENT_CLOSED;
-                                       callback_event.data.errid = errno;
+                               if(bytes < 0) {\r
+                                       if((iosock->socket_flags & (IOSOCKETFLAG_SSLSOCKET | IOSOCKETFLAG_SSL_WRITEHS)) == (IOSOCKETFLAG_SSLSOCKET | IOSOCKETFLAG_SSL_WRITEHS)) {\r
+                                               ssl_rehandshake = 1;\r
+                                       } else {
+                                               iosock->socket_flags |= IOSOCKETFLAG_DEAD;
+                                               
+                                               callback_event.type = IOSOCKETEVENT_CLOSED;
+                                               callback_event.data.errid = errno;\r
+                                       }
                                }
+                       }\r
+                       if(ssl_rehandshake) {
+                               engine->update(iosock);\r
                        }
-                       
                }
                if(callback_event.type != IOSOCKETEVENT_IGNORE)
                        iosocket_trigger_event(&callback_event);
index 6f0716059ddadee6b923a1d629ddf35ffc3ef100..2d8dd7738fac1acd0dc6beeff97f90d911a323a9 100644 (file)
@@ -70,12 +70,15 @@ extern struct _IOSocket *iosocket_last;
 #define IOSOCKETFLAG_PARENT_DNSENGINE 0x0200
 #define IOSOCKETFLAG_SSLSOCKET        0x0400 /* use ssl after connecting */
 #define IOSOCKETFLAG_SSL_HANDSHAKE    0x0800 /* SSL Handshake in progress */
-#define IOSOCKETFLAG_SSL_WANTWRITE    0x1000
-#define IOSOCKETFLAG_SHUTDOWN         0x2000 /* disconnect pending */
-#define IOSOCKETFLAG_CONNECTING       0x4000
-#define IOSOCKETFLAG_INCOMING         0x8000 /* incoming (accepted) connection */
-#define IOSOCKETFLAG_DEAD            0x10000
-#define IOSOCKETFLAG_RECONNECT_IPV4  0x20000 /* possible fallback to ipv4 connect if ipv6 fails */
+#define IOSOCKETFLAG_SSL_WANTWRITE    0x1000\r
+#define IOSOCKETFLAG_SSL_READHS       0x2000 /* ssl read rehandshake */\r
+#define IOSOCKETFLAG_SSL_WRITEHS      0x4000 /* ssl write rehandshake */
+#define IOSOCKETFLAG_SSL_ESTABLISHED  0x8000
+#define IOSOCKETFLAG_SHUTDOWN        0x10000 /* disconnect pending */
+#define IOSOCKETFLAG_CONNECTING      0x20000
+#define IOSOCKETFLAG_INCOMING        0x40000 /* incoming (accepted) connection */
+#define IOSOCKETFLAG_DEAD            0x80000
+#define IOSOCKETFLAG_RECONNECT_IPV4 0x100000 /* possible fallback to ipv4 connect if ipv6 fails */
 
 struct IOSocketDNSLookup {
        unsigned int bindlookup : 1;
@@ -115,8 +118,8 @@ void _init_sockets();
 void iosocket_loop(int usec);
 void iosocket_lookup_callback(struct IOSocketDNSLookup *lookup, struct IODNSEvent *event);
 void iosocket_events_callback(struct _IOSocket *iosock, int readable, int writeable);
-
-#define iosocket_wants_writes(IOSOCK) (IOSOCK->writebuf.bufpos || (IOSOCK->socket_flags & (IOSOCKETFLAG_CONNECTING | IOSOCKETFLAG_SSL_WANTWRITE)))
+\r
+#define iosocket_wants_writes(IOSOCK) ((IOSOCK->writebuf.bufpos && !(IOSOCK->socket_flags & (IOSOCKETFLAG_SSL_READHS | IOSOCKETFLAG_SSL_WRITEHS))) || (IOSOCK->socket_flags & (IOSOCKETFLAG_CONNECTING | IOSOCKETFLAG_SSL_WANTWRITE)))
 
 #endif
 
@@ -129,7 +132,8 @@ enum IOSocketStatus {
     IOSOCKET_CLOSED, /* descriptor is dead (socket waiting for removal or timer) */
     IOSOCKET_LISTENING, /* descriptor is waiting for connections (server socket) */
     IOSOCKET_CONNECTING, /* descriptor is waiting for connection approval (connecting client socket) */
-    IOSOCKET_CONNECTED /* descriptor is connected (connected client socket) */
+    IOSOCKET_CONNECTED, /* descriptor is connected (connected client socket) */
+       IOSOCKET_SSLHANDSHAKE /* descriptor is waiting for ssl (handshake) */
 };
 
 enum IOSocketEventType {
@@ -139,7 +143,6 @@ enum IOSocketEventType {
     IOSOCKETEVENT_NOTCONNECTED, /* client socket could not connect (errid valid) */
     IOSOCKETEVENT_CLOSED, /* client socket lost connection (errid valid) */
     IOSOCKETEVENT_ACCEPT, /* server socket accepted new connection (accept_socket valid) */
-    IOSOCKETEVENT_SSLFAILED, /* failed to initialize SSL session */
        IOSOCKETEVENT_DNSFAILED /* failed to lookup DNS information (recv_str contains error message) */
 };
 
index 7cbb02cdffe7f8c1630086536277f9d4df785978..ab0142fcb215a687361e70b9280f34664e0f7613 100644 (file)
@@ -14,6 +14,7 @@ libiohandler_a_SOURCES = compat/utime.c \
     IOGarbageCollector.c \
     IOLog.c \
     IOSockets.c \
+    IOSSLBackend.c \
     IOTimer.c
 
 noinst_LIBRARIES = libiohandler.a
index d534ccbefc15f046e2634312a33fbcaa26bddf56..9da8b2be5a721bbee6f72529b400cdca231fa0c6 100644 (file)
@@ -30,10 +30,7 @@ int main(int argc, char *argv[]) {
        
     iolog_register_callback(io_log);
     
-    irc_iofd = iosocket_connect("irc.nextirc.net", 6667, 0, NULL, io_callback);
-    irc_iofd->parse_delimiter = 1;
-       irc_iofd->delimiters[0] = '\n';
-       irc_iofd->delimiters[1] = '\r';
+    irc_iofd = iosocket_connect("test.pk910.de", 443, 1, NULL, io_callback);
        
        iohandler_run();
        
@@ -44,12 +41,20 @@ static IOSOCKET_CALLBACK(io_callback) {
     switch(event->type) {
         case IOSOCKETEVENT_CONNECTED:
             printf("[connect]\n");
+            iosocket_printf(event->socket, "GET / HTTP/1.1\r\n");
+            iosocket_printf(event->socket, "Host: test.pk910.de\r\n");
+            iosocket_printf(event->socket, "\r\n");
             break;
         case IOSOCKETEVENT_CLOSED:
             printf("[disconnect]\n");
             break;
         case IOSOCKETEVENT_RECV:
-            printf("[in] %s\n", event->data.recv_str);
+                       {
+                               struct IOSocketBuffer *recv_buf = event->data.recv_buf;
+                               write(1, recv_buf->buffer, recv_buf->bufpos);
+                               recv_buf->bufpos = 0;
+                               printf("\n");
+            }
             break;
         
         default: