canl_io_accept with ssl support, sample server modified accordingly
authorMarcel Poul <marcel.poul@cern.ch>
Mon, 28 Nov 2011 20:03:09 +0000 (20:03 +0000)
committerMarcel Poul <marcel.poul@cern.ch>
Mon, 28 Nov 2011 20:03:09 +0000 (20:03 +0000)
emi.canl.canl-c/src/canl.c
emi.canl.canl-c/src/canl_locl.h
emi.canl.canl-c/src/canl_sample_server.c
emi.canl.canl-c/src/canl_ssl.c

index deb9c99..5ad9ee2 100644 (file)
@@ -289,15 +289,13 @@ int canl_io_accept(canl_ctx cc, canl_io_handler io, int port,
         if ((err = bind(sockfd, p->ai_addr, p->ai_addrlen))) {
             close(sockfd);
             err = errno;
-            // set err - perror("server: bind");
             continue;
         }
         break;
     }
 
     if (p == NULL) {
-        // set err - fprintf(stderr, "server: failed to bind\n");
-        update_error(glb_cc, err, "failed to bind"); //TODO is it there?????
+        update_error(glb_cc, err, "failed to bind (canl_io_accept)"); //TODO is it there?????
         freeaddrinfo(servinfo); // all done with this structure
         goto end;
     }
@@ -317,10 +315,16 @@ int canl_io_accept(canl_ctx cc, canl_io_handler io, int port,
         err = errno;
         goto end;
     }
+    else
+        (*io_new_cc)->sock = new_fd;
     /* TODO everything fine - set new_io_cc according to their_addr*/
 
 
-    /*call openssl to make a secured connection, optional?*/
+    /*call openssl */
+    err = ssl_init(glb_cc, *io_new_cc);
+    if (err)
+        goto end;
+    err = ssl_accept(glb_cc, io_cc, (*io_new_cc), timeout); 
 
     /*write succes or failure to cc, io*/
     //if (err)
index e0a6572..ca5b821 100644 (file)
@@ -48,6 +48,8 @@ int asyn_getservbyname(int a_family, asyn_result *ares_result,char const *name,
         struct timeval *timeout);
 int ssl_init(glb_ctx *cc, io_handler *io);
 int ssl_connect(glb_ctx *cc, io_handler *io, struct timeval *timeout);
+int ssl_accept(glb_ctx *cc, io_handler *io, io_handler *new_io,
+        struct timeval *timeout);
 int ssl_read(glb_ctx *cc, io_handler *io, void *buffer, size_t size, 
         struct timeval *tout);
 int ssl_write(glb_ctx *cc, io_handler *io, void *buffer, size_t size, 
index 315cba6..777d80c 100644 (file)
@@ -1,6 +1,7 @@
 #include <stdio.h>
 #include <unistd.h>
 #include <stdlib.h>
+#include <string.h>
 #include "canl.h"
 
 #define BUF_LEN 1000
@@ -14,6 +15,8 @@ int main(int argc, char *argv[])
     char *err_msg = NULL;
     int opt, port = 4321;
     char buf[BUF_LEN];
+    int buf_len = 0;
+    struct timeval timeout;
 
     while ((opt = getopt(argc, argv, "hp:")) != -1) {
         switch (opt) {
@@ -47,16 +50,32 @@ int main(int argc, char *argv[])
         goto end;
     }
 
+    timeout.tv_sec = 15;
+    timeout.tv_usec = 0;
+
     /* canl_create_io_handler has to be called for my_new_io_h and my_io_h*/
-    err = canl_io_accept(my_ctx, my_io_h, port, 0, NULL, NULL, &my_new_io_h);
+    /* TODO timeout in this function?*/
+    err = canl_io_accept(my_ctx, my_io_h, port, 0, NULL, &timeout, &my_new_io_h);
     if (err) {
-        //set_error("cannot make a connection");
+        printf("connection cannot be established\n");
         goto end;
     }
+    else {
+        printf("connection established\n");
+    }
+
+    strcpy(buf, "This is the testing message to send");
+    buf_len = strlen(buf) + 1;
 
-    err = canl_io_write (my_ctx, my_new_io_h, NULL, 0, NULL);
+    printf("Trying to send sth to the client\n");
+    err = canl_io_write (my_ctx, my_new_io_h, buf, buf_len, &timeout);
     if (err) {
-        //set_error ("cannot write");
+        printf("cannot send message to the client\n");
+        goto end;
+    }
+    else {
+        buf[err] = '\0';
+        printf("message \"%s\" sent successfully\n", buf);
     }
 
     err = canl_io_read (my_ctx, my_io_h, buf, sizeof(buf)-1, NULL);
index 9cb8f4c..eb316d2 100644 (file)
@@ -1,6 +1,7 @@
 #include "canl_locl.h"
 
 static int do_ssl_connect( glb_ctx *cc, io_handler *io, struct timeval *timeout);
+static int do_ssl_accept( glb_ctx *cc, io_handler *io, struct timeval *timeout);
 
 int ssl_init(glb_ctx *cc, io_handler *io)
 {
@@ -17,7 +18,7 @@ int ssl_init(glb_ctx *cc, io_handler *io)
     SSL_load_error_strings();
     SSL_library_init();
 
-    io->s_ctx->ssl_meth = SSLv23_method();
+    io->s_ctx->ssl_meth = SSLv23_method();  //TODO dynamically
     io->s_ctx->ssl_ctx = SSL_CTX_new(io->s_ctx->ssl_meth);
     if (!io->s_ctx->ssl_ctx){
         err = 1; //TODO set appropriate
@@ -54,7 +55,7 @@ int ssl_connect(glb_ctx *cc, io_handler *io, struct timeval *timeout)
     //setup_SSL_proxy_handler(io->s_ctx->ssl_ctx, cacertdir);
     SSL_set_bio(io->s_ctx->ssl_io, io->s_ctx->bio_conn, io->s_ctx->bio_conn);
 
-    io->s_ctx->bio_conn = NULL; //TODO ???? 
+    io->s_ctx->bio_conn = NULL; //TODO WHAT THE HELL IS THIS???? 
 
     if ((err = do_ssl_connect(cc, io, timeout))) {
         goto end;
@@ -74,6 +75,48 @@ end:
     return err;
 }
 
+int ssl_accept(glb_ctx *cc, io_handler *io, io_handler *new_io, 
+        struct timeval *timeout)
+{
+    int err = 0, flags;
+
+    if (!cc) {
+        return EINVAL;
+    }
+    if (!io) {
+        err = EINVAL;
+        goto end;
+    }
+
+    flags = fcntl(new_io->sock, F_GETFL, 0);
+    (void)fcntl(new_io->sock, F_SETFL, flags | O_NONBLOCK);
+
+    new_io->s_ctx->bio_conn = BIO_new_socket(new_io->sock, BIO_NOCLOSE);
+    (void)BIO_set_nbio(new_io->s_ctx->bio_conn,1);
+
+    new_io->s_ctx->ssl_io = SSL_new(new_io->s_ctx->ssl_ctx);
+    //setup_SSL_proxy_handler(io->s_ctx->ssl_ctx, cacertdir);
+    SSL_set_bio(new_io->s_ctx->ssl_io, new_io->s_ctx->bio_conn, 
+            new_io->s_ctx->bio_conn);
+
+    if ((err = do_ssl_accept(cc, new_io, timeout))) {
+        goto end;
+    }
+
+    /*
+       if (post_connection_check(io->s_ctx->ssl_io)) {
+       opened = 1;
+       (void)Send("0");
+       return 1;
+       }
+     */
+
+end:
+    if (err)
+        update_error(cc, err, "(ssl_accept)"); //TODO update error
+    return err;
+}
+
 /*
  * Encapsulates select behaviour
  *
@@ -176,6 +219,48 @@ static int do_ssl_connect( glb_ctx *cc, io_handler *io, struct timeval *timeout)
     return 0;
 }
 
+static int do_ssl_accept( glb_ctx *cc, io_handler *io, struct timeval *timeout)
+{
+    time_t starttime, curtime;
+    int ret = -1, ret2 = -1, err = 0;
+    long errorcode = 0;
+    int expected = 0;
+    int locl_timeout = -1;
+
+    /* do not take tv_usec into account in this function*/
+    if (timeout)
+        locl_timeout = timeout->tv_sec;
+    else
+        locl_timeout = -1;
+    curtime = starttime = time(NULL);
+
+    do {
+        ret = do_select(io->sock, starttime, locl_timeout, expected);
+        if (ret > 0) {
+            ret2 = SSL_accept(io->s_ctx->ssl_io);
+            expected = errorcode = SSL_get_error(io->s_ctx->ssl_io, ret2);
+        }
+        curtime = time(NULL);
+    } while (TEST_SELECT(ret, ret2, locl_timeout, curtime, starttime, errorcode));
+
+    //TODO split ret2 and ret into 2 ifs to set approp. error message
+    if (ret2 <= 0 || ret <= 0) {
+        if (timeout && (curtime - starttime >= locl_timeout)){
+            timeout->tv_sec=0;
+            timeout->tv_usec=0;
+            err = ETIMEDOUT; 
+            update_error (cc, err, "Connection stuck during handshake: timeout reached (do_ssl_accept)");
+        }
+        else{
+            err = -1; //TODO set approp. error message
+            update_error (cc, err, "Error during SSL handshake (do_ssl_accept)");
+        }
+        return err;
+    }
+
+    return 0;
+}
+
 /* this function has to return # bytes written or ret < 0 when sth went wrong*/
 int ssl_write(glb_ctx *cc, io_handler *io, void *buffer, size_t size, struct timeval *timeout)
 {