changes in structures with context handlers
authorMarcel Poul <marcel.poul@cern.ch>
Wed, 1 Feb 2012 14:44:46 +0000 (14:44 +0000)
committerMarcel Poul <marcel.poul@cern.ch>
Wed, 1 Feb 2012 14:44:46 +0000 (14:44 +0000)
emi.canl.canl-c/src/canl.c
emi.canl.canl-c/src/canl_cert.c
emi.canl.canl-c/src/canl_locl.h
emi.canl.canl-c/src/canl_ssl.c

index 6be2d02..39504b8 100644 (file)
@@ -20,7 +20,7 @@ canl_ctx canl_create_ctx()
         return NULL;
 
     for (i = 0; i < sizeof(mechs)/sizeof(mechs[0]); i++)
-       mechs[i]->initialize(ctx, &mechs[i]->global_context);
+       mechs[i]->initialize(ctx, &mechs[i]->glb_ctx);
 
     return ctx;
 }
@@ -69,8 +69,7 @@ canl_create_io_handler(canl_ctx cc, canl_io_handler *io)
 
 static int init_io_content(glb_ctx *cc, io_handler *io)
 {
-    io->authn_mech.type = AUTH_UNDEF;
-    io->authn_mech.oid = GSS_C_NO_OID;
+    io->oid = GSS_C_NO_OID;
     io->sock = -1;
     return 0;
 }
@@ -148,7 +147,7 @@ canl_io_connect(canl_ctx cc, canl_io_handler io, const char *host, const char *s
                if (err)
                    continue;
 
-               err = mech->client_init(glb_cc, mech->global_context, &ctx);
+               err = mech->client_init(glb_cc, mech->glb_ctx, &ctx);
                if (err) {
                    canl_io_close(glb_cc, io_cc);
                    continue;
@@ -161,8 +160,7 @@ canl_io_connect(canl_ctx cc, canl_io_handler io, const char *host, const char *s
                    ctx = NULL;
                    continue;
                }
-               io_cc->authn_mech.ctx = ctx;
-               io_cc->authn_mech.type = mech->mech;
+               io_cc->conn_ctx = ctx;
                done = 1;
                break;
            }
@@ -264,7 +262,7 @@ canl_io_accept(canl_ctx cc, canl_io_handler io, int new_fd,
 
     io_cc->sock = new_fd;
 
-    err = mech->server_init(glb_cc, mech->global_context, &conn_ctx);
+    err = mech->server_init(glb_cc, mech->glb_ctx, &conn_ctx);
     if (err)
         goto end;
 
@@ -279,9 +277,8 @@ canl_io_accept(canl_ctx cc, canl_io_handler io, int new_fd,
            goto end;
     }
 */
-    io_cc->authn_mech.ctx = conn_ctx;
-    io_cc->authn_mech.type = mech->mech;
-    io_cc->authn_mech.oid = GSS_C_NO_OID;
+    io_cc->conn_ctx = conn_ctx;
+    io_cc->oid = GSS_C_NO_OID;
 
     err = 0;
 
@@ -311,9 +308,9 @@ canl_io_close(canl_ctx cc, canl_io_handler io)
     if (!io)
        return set_error(cc, EINVAL, POSIX_ERROR, "IO handler not initialized");
 
-    if (io_cc->authn_mech.ctx) {
-       mech = find_mech(io_cc->authn_mech.oid);
-       mech->close(glb_cc, io, io_cc->authn_mech.ctx);
+    if (io_cc->conn_ctx) {
+       mech = find_mech(io_cc->oid);
+       mech->close(glb_cc, io, io_cc->conn_ctx);
        /* XXX can it be safely reopened ?*/
     }
 
@@ -333,12 +330,11 @@ static void io_destroy(glb_ctx *cc, io_handler *io)
     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;
+    if (io_cc->conn_ctx) {
+       mech = find_mech(io->oid);
+       mech->free_ctx(cc, io_cc->conn_ctx);
+       io_cc->conn_ctx = NULL;
+       io_cc->oid = GSS_C_NO_OID;
     }
 
     return;
@@ -384,7 +380,7 @@ size_t canl_io_read(canl_ctx cc, canl_io_handler io, void *buffer, size_t size,
         return -1;
     }
 
-    if (io_cc->authn_mech.ctx == NULL)
+    if (io_cc->conn_ctx == NULL)
        return set_error(cc, EINVAL, POSIX_ERROR, "Connection not secured");
     
     if (!buffer || !size) {
@@ -392,9 +388,9 @@ size_t canl_io_read(canl_ctx cc, canl_io_handler io, void *buffer, size_t size,
        return -1;
     }
 
-    mech = find_mech(io_cc->authn_mech.oid);
+    mech = find_mech(io_cc->oid);
 
-    b_recvd = mech->read(glb_cc, io_cc, io_cc->authn_mech.ctx,
+    b_recvd = mech->read(glb_cc, io_cc, io_cc->conn_ctx,
                         buffer, size, timeout);
 
     return b_recvd;
@@ -415,7 +411,7 @@ 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)
+    if (io_cc->conn_ctx == NULL)
        return set_error(cc, EINVAL, POSIX_ERROR, "Connection not secured");
 
     if (!buffer || !size) {
@@ -423,9 +419,9 @@ size_t canl_io_write(canl_ctx cc, canl_io_handler io, void *buffer, size_t size,
        return -1;
     }
 
-    mech = find_mech(io_cc->authn_mech.oid);
+    mech = find_mech(io_cc->oid);
 
-    b_written = mech->write(glb_cc, io_cc, io_cc->authn_mech.ctx,
+    b_written = mech->write(glb_cc, io_cc, io_cc->conn_ctx,
                            buffer, size, timeout);
 
     return b_written;
index 057311f..8dae50e 100644 (file)
@@ -67,7 +67,6 @@ int do_set_ctx_own_cert_file(glb_ctx *cc, char *cert, char *key)
         }
     }
 
-    /* otherwise the private key is in cert file*/
     if (key) {
         err = set_key_file(cc, &cc->cert_key->key, key);
         if (err)
index 32c7e79..f569255 100644 (file)
@@ -82,28 +82,40 @@ typedef struct _io_handler
 {
     int sock;
     principal_int *princ_int;
-    struct authn_mech {
-       CANL_AUTH_MECHANISM type;
-       gss_OID oid;
-       void *ctx;
-    } authn_mech;
+    void *conn_ctx; //like SSL *
+    gss_OID oid;
 } io_handler;
 
+typedef struct _mech_glb_ctx
+{
+    void *mech_ctx; //like SSL_CTX *
+    unsigned int flags;
+} mech_glb_ctx;
+
 typedef struct canl_mech {
     CANL_AUTH_MECHANISM mech;
-    void *global_context;
+    mech_glb_ctx *glb_ctx;
 
     canl_err_code (*initialize)
-        (glb_ctx *, void **);
+        (glb_ctx *, mech_glb_ctx **);
+
+    canl_err_code (*set_flags)
+        (glb_ctx *cc, unsigned int *mech_flags,  unsigned int flags);
+
+    canl_err_code (*set_ca_dir)
+        (glb_ctx *, const char *);
+    
+    canl_err_code (*set_crl_dir)
+        (glb_ctx *, const char *);
 
     canl_err_code (*finish)
        (glb_ctx *, void *);
 
     canl_err_code (*client_init)
-        (glb_ctx *, void *, void **);
+        (glb_ctx *, mech_glb_ctx *, void **);
 
     canl_err_code (*server_init)
-        (glb_ctx *, void *, void **);
+        (glb_ctx *, mech_glb_ctx *, void **);
 
     canl_err_code (*free_ctx)
        (glb_ctx *, void *);
index c239df6..a8226b2 100644 (file)
@@ -13,7 +13,7 @@ static void dbg_print_ssl_error(int errorcode);
 #endif
 
 static canl_err_code
-ssl_initialize(glb_ctx *cc, void **ctx)
+ssl_initialize(glb_ctx *cc, mech_glb_ctx **m_glb_ctx)
 {
     int err = 0;
     char *ca_cert_fn, *user_cert_fn, *user_key_fn, *user_proxy_fn;
@@ -30,9 +30,14 @@ ssl_initialize(glb_ctx *cc, void **ctx)
 
     ssl_ctx = SSL_CTX_new(SSLv23_method());
     if (!ssl_ctx)
-       return set_error(cc, ERR_get_error(), SSL_ERROR,
+        return set_error(cc, ERR_get_error(), SSL_ERROR,
                 "Cannot initialize SSL context");
 
+    if (!*m_glb_ctx)
+        *m_glb_ctx = (mech_glb_ctx *) calloc(1, sizeof(**m_glb_ctx));
+    if (!*m_glb_ctx)
+        return set_error(cc, ENOMEM, POSIX_ERROR, "Not enough memory");
+
     /* TODO what is this? */
     SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_SSLv2);
 
@@ -60,7 +65,7 @@ ssl_initialize(glb_ctx *cc, void **ctx)
     // TODO proxy_verify_callback, verify_none only for testing !!!!!!!
     //SSL_CTX_set_verify_depth(ctx, 100);
 
-    *ctx = ssl_ctx;
+    (*m_glb_ctx)->mech_ctx = ssl_ctx;
     ssl_ctx = NULL;
     err = 0;
 
@@ -71,10 +76,33 @@ end:
     return err;
 }
 
+static canl_err_code 
+ssl_set_flags(glb_ctx *cc, unsigned int *mech_flags,  unsigned int flags)
+{
+    if (cc == NULL)
+        return EINVAL;
+
+
+    *mech_flags = (flags | *mech_flags);
+
+    return 0;
+}
+
 static canl_err_code
-ssl_server_init(glb_ctx *cc, void *mech_ctx, void **ctx)
+ssl_set_ca_dir(glb_ctx *cc, const char *ca_dir)
 {
-    SSL_CTX *ssl_ctx = (SSL_CTX *) mech_ctx;
+    return ENOSYS;
+}
+static canl_err_code
+ssl_set_crl_dir(glb_ctx *cc, const char *crl_dir)
+{
+    return ENOSYS;
+}
+
+static canl_err_code
+ssl_server_init(glb_ctx *cc, mech_glb_ctx *m_ctx, void **ctx)
+{
+    SSL_CTX *ssl_ctx = (SSL_CTX *) m_ctx->mech_ctx;
     SSL *ssl = NULL;
     char *user_cert_fn, *user_key_fn, *user_proxy_fn;
     int err = 0;
@@ -114,6 +142,10 @@ ssl_server_init(glb_ctx *cc, void *mech_ctx, void **ctx)
      *  if SSL_VERIFY_NONE, then we cannot extract peer cert. of ssl
      *  if SSL_VERIFY_PEER, then client cert verification is mandatory!!!*/
     SSL_set_verify(ssl, SSL_VERIFY_PEER, proxy_verify_callback);
+    
+    if (!(CANL_ACCEPT_SSLv2 & m_ctx->flags))
+        SSL_set_options(ssl, SSL_OP_NO_SSLv2);
+
 
 //    SSL_use_certificate_file(ssl, "/etc/grid-security/hostcert.pem", SSL_FILETYPE_PEM);
 //    SSL_use_PrivateKey_file(ssl, "/etc/grid-security/hostkey.pem", SSL_FILETYPE_PEM);
@@ -155,9 +187,9 @@ ssl_server_init(glb_ctx *cc, void *mech_ctx, void **ctx)
 }
 
 static canl_err_code
-ssl_client_init(glb_ctx *cc, void *mech_ctx, void **ctx)
+ssl_client_init(glb_ctx *cc, mech_glb_ctx *m_ctx, void **ctx)
 {
-    SSL_CTX *ssl_ctx = (SSL_CTX *) mech_ctx;
+    SSL_CTX *ssl_ctx = (SSL_CTX *) m_ctx->mech_ctx;
     SSL *ssl = NULL;
     int err = 0;
     char *user_cert_fn, *user_key_fn, *user_proxy_fn;
@@ -206,6 +238,8 @@ ssl_client_init(glb_ctx *cc, void *mech_ctx, void **ctx)
     user_proxy_fn = NULL;
 
     SSL_set_verify(ssl, SSL_VERIFY_PEER, proxy_verify_callback);
+    if (!(CANL_ACCEPT_SSLv2 & m_ctx->flags))
+        SSL_set_options(ssl, SSL_OP_NO_SSLv2);
 
     if (cc->cert_key) {
         if (cc->cert_key->key) {
@@ -222,13 +256,13 @@ ssl_client_init(glb_ctx *cc, void *mech_ctx, void **ctx)
                         "use certificate");
             }
         }
+        /*Make sure the key and certificate file match
+         * not mandatory on client side*/
+        if (cc->cert_key->cert && cc->cert_key->key)
+            if ( (err = SSL_check_private_key(ssl)) != 1)
+                return set_error(cc, ERR_get_error(), SSL_ERROR, "Private key"
+                        " does not match the certificate public key"); 
     }
-    /*Make sure the key and certificate file match
-     * not mandatory on client side*/
-    if (cc->cert_key->cert && cc->cert_key->key)
-    if ( (err = SSL_check_private_key(ssl)) != 1)
-        return set_error(cc, ERR_get_error(), SSL_ERROR, "Private key"
-                " does not match the certificate public key"); 
 
     *ctx = ssl;
     return 0;
@@ -285,6 +319,8 @@ static int check_hostname_cert(glb_ctx *cc, io_handler *io,
     /*if extensions are present, hostname has to correspond
      *  to subj. alt. name*/
     serv_cert = SSL_get_peer_certificate(ssl);
+    if (!serv_cert)
+        return 0; //TODO is missing certificate 
     i = X509_get_ext_by_NID(serv_cert, NID_subject_alt_name, -1);
     if (i != -1) {
         /* subj. alt. name extention present */
@@ -484,7 +520,7 @@ static int do_ssl_connect(glb_ctx *cc, io_handler *io,
             update_error (cc, err, POSIX_ERROR, "Connection stuck during"
                   " handshake: timeout reached");
         }
-        else if (ret2 < 0)
+        else if (ret2 < 0 && ssl_err)
             return update_error(cc, ssl_err, e_orig, "Error during SSL handshake");
         else if (ret2 == 0)//TODO is 0 (conn closed by the other side) error?
             update_error (cc, ECONNREFUSED, POSIX_ERROR, "Connection closed"
@@ -548,7 +584,7 @@ static int do_ssl_accept(glb_ctx *cc, io_handler *io,
         else if (ret2 == 0)
             set_error (cc, ECONNREFUSED, POSIX_ERROR, "Connection closed by"
                    " the other side");
-        else if (ret2 < 0)
+        else if (ret2 < 0 && ssl_err)
             set_error (cc, ssl_err, SSL_ERROR, "Error during SSL handshake");
        else
            set_error (cc, 0, UNKNOWN_ERROR, "Error during SSL handshake");
@@ -908,6 +944,9 @@ struct canl_mech canl_mech_ssl = {
     TLS,
     NULL,
     ssl_initialize,
+    ssl_set_flags,
+    ssl_set_ca_dir,
+    ssl_set_crl_dir,
     ssl_finish,
     ssl_client_init,
     ssl_server_init,