per-connection SSL context remove from the contexts
authorDaniel Kouřil <kouril@ics.muni.cz>
Tue, 17 Jan 2012 20:13:38 +0000 (20:13 +0000)
committerDaniel Kouřil <kouril@ics.muni.cz>
Tue, 17 Jan 2012 20:13:38 +0000 (20:13 +0000)
emi.canl.canl-c/src/canl.c
emi.canl.canl-c/src/canl_locl.h
emi.canl.canl-c/src/canl_ssl.c

index 5a8e2fd..bfa242e 100644 (file)
@@ -68,11 +68,8 @@ canl_create_io_handler(canl_ctx cc, canl_io_handler *io)
 
 static int init_io_content(glb_ctx *cc, io_handler *io)
 {
-    io->s_ctx = (ossl_ctx *) calloc(1, sizeof(*(io->s_ctx)));
-    if (!io->s_ctx)
-        return set_error(cc, ENOMEM, posix_error, "Not enough memory");
-
     io->authn_mech.type = AUTH_UNDEF;
+    io->authn_mech.oid = GSS_C_NO_OID;
     io->sock = -1;
     return 0;
 }
@@ -267,6 +264,7 @@ canl_io_accept(canl_ctx cc, canl_io_handler io, int new_fd,
 
     io_cc->authn_mech.ctx = conn_ctx;
     io_cc->authn_mech.type = mech->mech;
+    io_cc->authn_mech.oid = GSS_C_NO_OID;
 
     err = 0;
 
@@ -286,6 +284,8 @@ canl_io_close(canl_ctx cc, canl_io_handler io)
     io_handler *io_cc = (io_handler*) io;
     glb_ctx *glb_cc = (glb_ctx*) cc;
     int err = 0;
+    canl_mech *mech;
+
     /*check cc and io*/
     if (!cc) {
         return EINVAL; /* XXX Should rather be a CANL error */
@@ -294,9 +294,11 @@ canl_io_close(canl_ctx cc, canl_io_handler io)
     if (!io)
        return set_error(cc, EINVAL, posix_error, "IO handler not initialized");
 
-    err = ssl_close(glb_cc, io_cc);
-    if (err <= 0)
-        return err;
+    if (io_cc->authn_mech.ctx) {
+       mech = find_mech(io_cc->authn_mech.oid);
+       mech->close(glb_cc, io, io_cc->authn_mech.ctx);
+       /* XXX can it be safely reopened ?*/
+    }
 
     if (io_cc->sock != -1) {
         close (io_cc->sock);
@@ -309,13 +311,17 @@ canl_io_close(canl_ctx cc, canl_io_handler io)
 static void io_destroy(glb_ctx *cc, io_handler *io)
 {
     io_handler *io_cc = (io_handler*) io;
-
-    if (io_cc->s_ctx) {
-       if (io_cc->s_ctx->ssl_io)
-           ssl_free(cc, io_cc->s_ctx->ssl_io);
-
-       free (io_cc->s_ctx);
-       io_cc->s_ctx = NULL;
+    canl_mech *mech;
+    
+    if (io == NULL)
+       return;
+
+    if (io_cc->authn_mech.ctx) {
+       mech = find_mech(io->authn_mech.oid);
+       mech->free_ctx(cc, io_cc->authn_mech.ctx);
+       io_cc->authn_mech.ctx = NULL;
+       io_cc->authn_mech.type = AUTH_UNDEF;
+       io_cc->authn_mech.oid = GSS_C_NO_OID;
     }
 
     return;
@@ -359,13 +365,18 @@ size_t canl_io_read(canl_ctx cc, canl_io_handler io, void *buffer, size_t size,
         set_error(cc, EINVAL, posix_error, "IO handler not initialized");
         return -1;
     }
+
+    if (io_cc->authn_mech.ctx == NULL)
+       return set_error(cc, EINVAL, posix_error, "Connection not secured");
+
     
     if (!buffer || !size) {
        set_error(cc, EINVAL, posix_error, "No memory to write into");
        return -1;
     }
 
-    b_recvd = ssl_read(glb_cc, io_cc, buffer, size, timeout);
+    b_recvd = ssl_read(glb_cc, io_cc, io_cc->authn_mech.ctx,
+                      buffer, size, timeout);
 
     return b_recvd;
 }
@@ -384,12 +395,16 @@ size_t canl_io_write(canl_ctx cc, canl_io_handler io, void *buffer, size_t size,
        return -1;
     }
 
+    if (io_cc->authn_mech.ctx == NULL)
+       return set_error(cc, EINVAL, posix_error, "Connection not secured");
+
     if (!buffer || !size) {
        set_error(cc, EINVAL, posix_error, "No memory to read from");
        return -1;
     }
 
-    b_written = ssl_write(glb_cc, io_cc, buffer, size, timeout);
+    b_written = ssl_write(glb_cc, io_cc, io_cc->authn_mech.ctx,
+                         buffer, size, timeout);
 
     return b_written;
 }
index 51233a6..08b7a83 100644 (file)
@@ -69,11 +69,6 @@ typedef struct _glb_ctx
     cert_key_store *cert_key;
 } glb_ctx;
 
-typedef struct _ossl_ctx
-{
-    SSL *ssl_io;
-} ossl_ctx;
-
 typedef struct _asyn_result {
     struct hostent *ent;
     int err;
@@ -88,10 +83,10 @@ typedef struct _principal_int {
 typedef struct _io_handler
 {
     int sock;
-    ossl_ctx *s_ctx;
     principal_int *princ_int;
     struct authn_mech {
        CANL_AUTH_MECHANISM type;
+       gss_OID oid;
        void *ctx;
     } authn_mech;
 } io_handler;
@@ -150,11 +145,11 @@ int ssl_free(glb_ctx *cc, void *ctx);
 int ssl_connect(glb_ctx *cc, io_handler *io, void *conn_ctx, struct timeval *timeout, const char * host);
 int ssl_accept(glb_ctx *cc, io_handler *io, void *conn_ctx,
         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, 
-        struct timeval *tout);
-int ssl_close(glb_ctx *cc, io_handler *io);
+int ssl_read(glb_ctx *cc, io_handler *io, void *auth_ctx,
+       void *buffer, size_t size, struct timeval *tout);
+int ssl_write(glb_ctx *cc, io_handler *io, void *auth_ctx,
+       void *buffer, size_t size, struct timeval *tout);
+int ssl_close(glb_ctx *cc, io_handler *io, void *auth_ctx);
 int ssl_initialize();
 
 #endif
index 7f855f6..3793eb4 100644 (file)
@@ -4,9 +4,9 @@
 #define SSL_CLIENT_METH SSLv3_client_method()
 #define DESTROY_TIMEOUT 10
 
-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);
-static int check_hostname_cert(glb_ctx *cc, io_handler *io, const char *host);
+static int do_ssl_connect( glb_ctx *cc, io_handler *io, SSL *ssl, struct timeval *timeout);
+static int do_ssl_accept( glb_ctx *cc, io_handler *io, SSL *ssl, struct timeval *timeout);
+static int check_hostname_cert(glb_ctx *cc, io_handler *io, SSL *ssl, const char *host);
 #ifdef DEBUG
 static void dbg_print_ssl_error(int errorcode);
 #endif
@@ -210,11 +210,11 @@ int ssl_client_init(glb_ctx *cc, void *mech_ctx, void **ctx)
     return 0;
 }
 
-int ssl_connect(glb_ctx *cc, io_handler *io, void *conn_ctx,
+int ssl_connect(glb_ctx *cc, io_handler *io, void *auth_ctx,
                struct timeval *timeout, const char * host)
 {
     SSL_CTX *ctx;
-    SSL *ssl = (SSL *) conn_ctx;
+    SSL *ssl = (SSL *) auth_ctx;
     int err = 0, flags;
 
     if (!cc) {
@@ -224,7 +224,7 @@ int ssl_connect(glb_ctx *cc, io_handler *io, void *conn_ctx,
         err = EINVAL;
         goto end;
     }
-    if (conn_ctx == NULL)
+    if (ssl == NULL)
        return set_error(cc, EINVAL, posix_error, "SSL not initialized");
 
     ctx = SSL_get_SSL_CTX(ssl);
@@ -235,18 +235,19 @@ int ssl_connect(glb_ctx *cc, io_handler *io, void *conn_ctx,
     //setup_SSL_proxy_handler(cc->ssl_ctx, cacertdir);
     SSL_set_fd(ssl, io->sock);
 
-    err = do_ssl_connect(cc, io, timeout); 
+    err = do_ssl_connect(cc, io, ssl, timeout); 
     if (err) {
         goto end;
     }
     /*check server hostname on the certificate*/
-    err = check_hostname_cert(cc, io, host);
+    err = check_hostname_cert(cc, io, ssl, host);
 
 end:
     return err;
 }
 
-static int check_hostname_cert(glb_ctx *cc, io_handler *io, const char *host)
+static int check_hostname_cert(glb_ctx *cc, io_handler *io,
+                              SSL *ssl, const char *host)
 {
     X509 * serv_cert = NULL;
     X509_EXTENSION *ext = NULL;
@@ -260,7 +261,7 @@ static int check_hostname_cert(glb_ctx *cc, io_handler *io, const char *host)
 
     /*if extensions are present, hostname has to correspond
      *  to subj. alt. name*/
-    serv_cert = SSL_get_peer_certificate(io->s_ctx->ssl_io);
+    serv_cert = SSL_get_peer_certificate(ssl);
     i = X509_get_ext_by_NID(serv_cert, NID_subject_alt_name, -1);
     if (i != -1) {
         /* subj. alt. name extention present */
@@ -348,9 +349,9 @@ int ssl_accept(glb_ctx *cc, io_handler *io, void *auth_ctx,
     (void)fcntl(io->sock, F_SETFL, flags | O_NONBLOCK);
 
     //setup_SSL_proxy_handler(cc->ssl_ctx, cacertdir);
-    SSL_set_fd(io->s_ctx->ssl_io, io->sock);
+    SSL_set_fd(ssl, io->sock);
 
-    err = do_ssl_accept(cc, io, timeout);
+    err = do_ssl_accept(cc, io, ssl, timeout);
     if (err) {
         goto end;
     }
@@ -418,7 +419,8 @@ int do_select(int fd, time_t starttime, int timeout, int wanted)
         ((errorcode) == SSL_ERROR_WANT_READ ||                 \
          (errorcode) == SSL_ERROR_WANT_WRITE)))
 
-static int do_ssl_connect( glb_ctx *cc, io_handler *io, struct timeval *timeout)
+static int do_ssl_connect(glb_ctx *cc, io_handler *io,
+                         SSL *ssl, struct timeval *timeout)
 {
     time_t starttime, curtime;
     int ret = -1, ret2 = -1;
@@ -440,12 +442,12 @@ static int do_ssl_connect( glb_ctx *cc, io_handler *io, struct timeval *timeout)
     do {
         ret = do_select(io->sock, starttime, locl_timeout, expected);
         if (ret > 0) {
-            ret2 = SSL_connect(io->s_ctx->ssl_io);
+            ret2 = SSL_connect(ssl);
             if (ret2 < 0) {
                 ssl_err = ERR_get_error();
                 e_orig = ssl_error;
             }
-            expected = errorcode = SSL_get_error(io->s_ctx->ssl_io, ret2);
+            expected = errorcode = SSL_get_error(ssl, ret2);
         }
         curtime = time(NULL);
     } while (TEST_SELECT(ret, ret2, locl_timeout, curtime, starttime, errorcode));
@@ -471,7 +473,8 @@ 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)
+static int do_ssl_accept(glb_ctx *cc, io_handler *io,
+                        SSL *ssl, struct timeval *timeout)
 {
     time_t starttime, curtime;
     int ret = -1, ret2 = -1;
@@ -493,12 +496,12 @@ static int do_ssl_accept( glb_ctx *cc, io_handler *io, struct timeval *timeout)
     do {
         ret = do_select(io->sock, starttime, locl_timeout, expected);
         if (ret > 0) {
-            ret2 = SSL_accept(io->s_ctx->ssl_io);
+            ret2 = SSL_accept(ssl);
             if (ret2 < 0) {
                 ssl_err = ERR_peek_error();
                 e_orig = ssl_error;
             }
-            expected = errorcode = SSL_get_error(io->s_ctx->ssl_io, ret2);
+            expected = errorcode = SSL_get_error(ssl, ret2);
         }
         curtime = time(NULL);
 #ifdef DEBUG
@@ -530,7 +533,8 @@ static int do_ssl_accept( glb_ctx *cc, io_handler *io, struct timeval *timeout)
 }
 
 /* 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)
+int ssl_write(glb_ctx *cc, io_handler *io, void *auth_ctx,
+             void *buffer, size_t size, struct timeval *timeout)
 {
     int err = 0;
     int ret = 0, nwritten=0;
@@ -542,13 +546,19 @@ int ssl_write(glb_ctx *cc, io_handler *io, void *buffer, size_t size, struct tim
     int locl_timeout;
     int touted = 0;
     int to = 0; // bool
+    SSL *ssl = (SSL *) auth_ctx;
 
-    if (!io->s_ctx || !io->s_ctx->ssl_io) {
-        set_error(cc, EINVAL, posix_error, "SSL not initialized");
-        return -1;
-    }
-    
-    fd = BIO_get_fd(SSL_get_rbio(io->s_ctx->ssl_io), NULL);
+    if (cc == NULL)
+       return EINVAL;
+
+    if (io == NULL)
+       return set_error(cc, EINVAL, posix_error,
+                        "Connection not established");
+
+    if (ssl == NULL)
+       return set_error(cc, EINVAL, posix_error, "SSL not initialized");
+
+    fd = BIO_get_fd(SSL_get_rbio(ssl), NULL);
     str = buffer;//TODO !!!!!! text.c_str();
 
     curtime = starttime = time(NULL);
@@ -569,9 +579,9 @@ int ssl_write(glb_ctx *cc, io_handler *io, void *buffer, size_t size, struct tim
         if (ret > 0) {
             int v;
             errno = 0;
-            ret = SSL_write(io->s_ctx->ssl_io, str + nwritten,
+            ret = SSL_write(ssl, str + nwritten,
                     strlen(str) - nwritten);
-            v = SSL_get_error(io->s_ctx->ssl_io, ret);
+            v = SSL_get_error(ssl, ret);
 
             switch (v) {
                 case SSL_ERROR_NONE:
@@ -621,7 +631,8 @@ end:
     return ret;
 }
 
-int ssl_read(glb_ctx *cc, io_handler *io, void *buffer, size_t size, struct timeval *tout)
+int ssl_read(glb_ctx *cc, io_handler *io, void *auth_ctx,
+            void *buffer, size_t size, struct timeval *tout)
 {
     int err = 0;
     int ret = 0, nwritten=0, ret2 = 0;
@@ -630,14 +641,19 @@ int ssl_read(glb_ctx *cc, io_handler *io, void *buffer, size_t size, struct time
     time_t starttime, curtime;
     int expected = 0, error = 0;
     int timeout;
+    SSL *ssl = (SSL *) auth_ctx;
 
-    if (!io->s_ctx || !io->s_ctx->ssl_io) {
-        err = EINVAL;
-        set_error(cc, err, posix_error, "wrong ssl handler"); 
-        return -1;
-    }
+    if (cc == NULL)
+       return EINVAL;
+
+    if (io == NULL)
+       return set_error(cc, EINVAL, posix_error,
+                        "Connection not established");
 
-    fd = BIO_get_fd(SSL_get_rbio(io->s_ctx->ssl_io), NULL);
+    if (ssl == NULL)
+       return set_error(cc, EINVAL, posix_error, "SSL not initialized");
+
+    fd = BIO_get_fd(SSL_get_rbio(ssl), NULL);
     str = buffer;//TODO !!!!!! text.c_str();
 
     curtime = starttime = time(NULL);
@@ -653,11 +669,11 @@ int ssl_read(glb_ctx *cc, io_handler *io, void *buffer, size_t size, struct time
         curtime = time(NULL);
 
         if (ret > 0) {
-            ret2 = SSL_read(io->s_ctx->ssl_io, str + nwritten,
+            ret2 = SSL_read(ssl, str + nwritten,
                     strlen(str) - nwritten);
 
             if (ret2 <= 0) {
-                expected = error = SSL_get_error(io->s_ctx->ssl_io, ret2);
+                expected = error = SSL_get_error(ssl, ret2);
             }
         }
     } while (TEST_SELECT(ret, ret2, timeout, curtime, starttime, error));
@@ -680,33 +696,31 @@ int ssl_read(glb_ctx *cc, io_handler *io, void *buffer, size_t size, struct time
  * ret = 0 connection closed successfully (one direction)
  * ret = 1 connection closed successfully (both directions)
  * ret < 0 error occured (e.g. timeout reached) */
-int ssl_close(glb_ctx *cc, io_handler *io)
+int ssl_close(glb_ctx *cc, io_handler *io, void *auth_ctx)
 {
     SSL_CTX *ctx;
-    SSL *ssl = NULL;
     int timeout = DESTROY_TIMEOUT;
     time_t starttime, curtime;
     int expected = 0, error = 0, ret = 0, ret2 = 0;
     int fd;
     unsigned long ssl_err = 0;
+    SSL *ssl = (SSL *) auth_ctx;
 
     if (!cc)
         return EINVAL;
     if (!io)
         return set_error(cc, EINVAL, posix_error,
                         "Connection not initialized");
-
-    ssl = io->s_ctx->ssl_io;
-    if (!ssl)
+    if (ssl == NULL)
        return set_error(cc, EINVAL, posix_error, "SSL not initialized");
 
     ctx = SSL_get_SSL_CTX(ssl);
 
-    fd = BIO_get_fd(SSL_get_rbio(io->s_ctx->ssl_io), NULL);
+    fd = BIO_get_fd(SSL_get_rbio(ssl), NULL);
     curtime = starttime = time(NULL);
     
     /* check the shutdown state*/
-    ret = SSL_get_shutdown(io->s_ctx->ssl_io);
+    ret = SSL_get_shutdown(ssl);
     if (ret & SSL_SENT_SHUTDOWN)
         if (ret & SSL_RECEIVED_SHUTDOWN)
             return 1;
@@ -722,10 +736,10 @@ int ssl_close(glb_ctx *cc, io_handler *io)
        curtime = time(NULL);
 
        if (ret > 0) {
-           ret2 = SSL_shutdown(io->s_ctx->ssl_io);
+           ret2 = SSL_shutdown(ssl);
            if (ret2 < 0) {
                 ssl_err = ERR_peek_error();
-               expected = error = SSL_get_error(io->s_ctx->ssl_io, ret2);
+               expected = error = SSL_get_error(ssl, ret2);
             }
         }
     } while (TEST_SELECT(ret, ret2, timeout, curtime, starttime, error));