From 919995ec1acb371798d7dde09349504eb9a0f9b6 Mon Sep 17 00:00:00 2001 From: Marcel Poul Date: Wed, 1 Feb 2012 14:44:46 +0000 Subject: [PATCH] changes in structures with context handlers --- emi.canl.canl-c/src/canl.c | 46 +++++++++++++-------------- emi.canl.canl-c/src/canl_cert.c | 1 - emi.canl.canl-c/src/canl_locl.h | 30 ++++++++++++------ emi.canl.canl-c/src/canl_ssl.c | 69 ++++++++++++++++++++++++++++++++--------- 4 files changed, 96 insertions(+), 50 deletions(-) diff --git a/emi.canl.canl-c/src/canl.c b/emi.canl.canl-c/src/canl.c index 6be2d02..39504b8 100644 --- a/emi.canl.canl-c/src/canl.c +++ b/emi.canl.canl-c/src/canl.c @@ -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; diff --git a/emi.canl.canl-c/src/canl_cert.c b/emi.canl.canl-c/src/canl_cert.c index 057311f..8dae50e 100644 --- a/emi.canl.canl-c/src/canl_cert.c +++ b/emi.canl.canl-c/src/canl_cert.c @@ -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) diff --git a/emi.canl.canl-c/src/canl_locl.h b/emi.canl.canl-c/src/canl_locl.h index 32c7e79..f569255 100644 --- a/emi.canl.canl-c/src/canl_locl.h +++ b/emi.canl.canl-c/src/canl_locl.h @@ -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 *); diff --git a/emi.canl.canl-c/src/canl_ssl.c b/emi.canl.canl-c/src/canl_ssl.c index c239df6..a8226b2 100644 --- a/emi.canl.canl-c/src/canl_ssl.c +++ b/emi.canl.canl-c/src/canl_ssl.c @@ -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, -- 1.8.2.3