From 227995b5d1d8e8d226e987e6dfcb00c1136862b7 Mon Sep 17 00:00:00 2001 From: Marcel Poul Date: Wed, 14 Mar 2012 22:14:24 +0000 Subject: [PATCH] store proxy certificate + chain of approp. certs into context. --- emi.canl.canl-c/examples/canl_sample_client.c | 4 +- emi.canl.canl-c/examples/canl_sample_server.c | 10 +++-- emi.canl.canl-c/src/canl_cert.c | 9 +++- emi.canl.canl-c/src/canl_mech_ssl.h | 2 +- emi.canl.canl-c/src/canl_ssl.c | 63 +++++++++++++++++++-------- 5 files changed, 63 insertions(+), 25 deletions(-) diff --git a/emi.canl.canl-c/examples/canl_sample_client.c b/emi.canl.canl-c/examples/canl_sample_client.c index d3ae858..04c65fc 100644 --- a/emi.canl.canl-c/examples/canl_sample_client.c +++ b/emi.canl.canl-c/examples/canl_sample_client.c @@ -26,7 +26,7 @@ int main(int argc, char *argv[]) switch (opt) { case 'h': fprintf(stderr, "Usage: %s [-p port] [-c certificate]" - " [-k private key] [-s server] [-h] \n", argv[0]); + " [-k private key] [-d ca_dir] [-h] \n", argv[0]); exit(0); case 'p': port = atoi(optarg); @@ -42,7 +42,7 @@ int main(int argc, char *argv[]) break; default: /* '?' */ fprintf(stderr, "Usage: %s [-p port] [-c certificate]" - " [-k private key] [-s server] [-h] \n", argv[0]); + " [-k private key] [-d ca_dir] [-h] \n", argv[0]); exit(-1); } } diff --git a/emi.canl.canl-c/examples/canl_sample_server.c b/emi.canl.canl-c/examples/canl_sample_server.c index 04bbcf3..67e9068 100644 --- a/emi.canl.canl-c/examples/canl_sample_server.c +++ b/emi.canl.canl-c/examples/canl_sample_server.c @@ -19,17 +19,18 @@ int main(int argc, char *argv[]) int opt, port = 4321; char *serv_cert = NULL; char *serv_key = NULL; + char *ca_dir = NULL; char buf[BUF_LEN]; int buf_len = 0; struct timeval timeout; canl_principal princ = NULL; char *name = NULL; - while ((opt = getopt(argc, argv, "hp:c:k:")) != -1) { + while ((opt = getopt(argc, argv, "hp:c:k:d:")) != -1) { switch (opt) { case 'h': fprintf(stderr, "Usage: %s [-p port] [-c certificate]" - " [-k private key] [-h] \n", argv[0]); + " [-k private key] [-d ca_dir] [-h] \n", argv[0]); exit(0); case 'p': port = atoi(optarg); @@ -40,9 +41,12 @@ int main(int argc, char *argv[]) case 'k': serv_key = optarg; break; + case 'd': + ca_dir = optarg; + break; default: /* '?' */ fprintf(stderr, "Usage: %s [-p port] [-c certificate]" - " [-k private key] [-h] \n", argv[0]); + " [-k private key] [-d ca_dir] [-h] \n", argv[0]); exit(-1); } } diff --git a/emi.canl.canl-c/src/canl_cert.c b/emi.canl.canl-c/src/canl_cert.c index 4ff6f1a..867f096 100644 --- a/emi.canl.canl-c/src/canl_cert.c +++ b/emi.canl.canl-c/src/canl_cert.c @@ -58,7 +58,7 @@ end: //TODO cert int do_set_ctx_own_cert_file(glb_ctx *cc, mech_glb_ctx *m_ctx, - char *cert, char *key) + char *cert, char *key, char *proxy) { int err = 0; @@ -82,6 +82,13 @@ int do_set_ctx_own_cert_file(glb_ctx *cc, mech_glb_ctx *m_ctx, if (err) return err; } + + if (proxy) { + err = load_credentials(proxy, proxy, &m_ctx->cert_key->cert, + &m_ctx->cert_key->chain, &m_ctx->cert_key->key, NULL); + if (!err) + return err; + } return 0; } diff --git a/emi.canl.canl-c/src/canl_mech_ssl.h b/emi.canl.canl-c/src/canl_mech_ssl.h index e55e31b..f9010f3 100644 --- a/emi.canl.canl-c/src/canl_mech_ssl.h +++ b/emi.canl.canl-c/src/canl_mech_ssl.h @@ -24,7 +24,7 @@ typedef struct _mech_glb_ctx } mech_glb_ctx; int do_set_ctx_own_cert_file(glb_ctx *cc, mech_glb_ctx *m_ctx, - char *cert, char *key); + char *cert, char *key, char * proxy); int set_key_file(glb_ctx *cc, EVP_PKEY **to, const char *key); int set_cert_file(glb_ctx *cc, X509 **to, const char *cert); int set_cert_chain_file(glb_ctx *cc, STACK_OF(X509) **to, const char *cert); diff --git a/emi.canl.canl-c/src/canl_ssl.c b/emi.canl.canl-c/src/canl_ssl.c index b20a8e1..cab9b4b 100644 --- a/emi.canl.canl-c/src/canl_ssl.c +++ b/emi.canl.canl-c/src/canl_ssl.c @@ -133,7 +133,7 @@ ssl_server_init(glb_ctx *cc, void *v_ctx, void **ctx) if (!err && (!m_ctx->cert_key || !m_ctx->cert_key->cert || !m_ctx->cert_key->key)) { if (user_cert_fn && user_key_fn && !access(user_cert_fn, R_OK) && !access(user_key_fn, R_OK)) { - err = do_set_ctx_own_cert_file(cc, m_ctx, user_cert_fn, user_key_fn); + err = do_set_ctx_own_cert_file(cc, m_ctx, user_cert_fn, user_key_fn, NULL); if (err) return err; } @@ -206,7 +206,7 @@ ssl_client_init(glb_ctx *cc, void *v_ctx, void **ctx) mech_glb_ctx *m_ctx = (mech_glb_ctx *)v_ctx; SSL_CTX *ssl_ctx = (SSL_CTX *) m_ctx->mech_ctx; SSL *ssl = NULL; - int err = 0; + int err = 0, i = 0; char *user_cert_fn, *user_key_fn, *user_proxy_fn; user_cert_fn = user_key_fn = user_proxy_fn = NULL; @@ -216,32 +216,24 @@ ssl_client_init(glb_ctx *cc, void *v_ctx, void **ctx) if (ssl_ctx == NULL) return set_error(cc, EINVAL, POSIX_ERROR, "SSL not initialized"); - ssl = SSL_new(ssl_ctx); - if (ssl == NULL) - return set_error(cc, ERR_get_error(), SSL_ERROR, - "Failed to create SSL connection context"); - - SSL_set_connect_state(ssl); - err = proxy_get_filenames(0, NULL, NULL, &user_proxy_fn, &user_cert_fn, &user_key_fn); if (!err && (!m_ctx->cert_key || !m_ctx->cert_key->cert || !m_ctx->cert_key->key)) { if (user_proxy_fn && !access(user_proxy_fn, R_OK)) { - err = do_set_ctx_own_cert_file(cc, m_ctx, user_proxy_fn, - user_proxy_fn); + err = do_set_ctx_own_cert_file(cc, m_ctx, NULL, NULL, user_proxy_fn); if (err) return err; } else { if (user_cert_fn && !access(user_cert_fn, R_OK)) { err = do_set_ctx_own_cert_file(cc, m_ctx, - user_cert_fn, NULL); + user_cert_fn, NULL, NULL); if (err) return err; } if (user_key_fn && !access(user_key_fn, R_OK)) { err = do_set_ctx_own_cert_file(cc, m_ctx, - NULL, user_key_fn); + NULL, user_key_fn, NULL); if (err) return err; } @@ -255,6 +247,41 @@ ssl_client_init(glb_ctx *cc, void *v_ctx, void **ctx) free(user_proxy_fn); user_proxy_fn = NULL; + if (m_ctx->cert_key && m_ctx->cert_key->chain) { + /* + * Certificate was a proxy with a cert. chain. + * Add the certificates one by one to the chain. + */ + X509_STORE_add_cert(ssl_ctx->cert_store, m_ctx->cert_key->cert); + for (i = 0; i < sk_X509_num(m_ctx->cert_key->chain); ++i) { + X509 *cert = (sk_X509_value(m_ctx->cert_key->chain, i)); + + if (!X509_STORE_add_cert(ssl_ctx->cert_store, cert)) { + if (ERR_GET_REASON(ERR_peek_error()) == + X509_R_CERT_ALREADY_IN_HASH_TABLE) { + ERR_clear_error(); + continue; + } + else { + set_error(cc, 1, CANL_ERROR, "Cannot add certificate " + "to the SSL context's certificate store"); + } + } + } +#if OPENSSL_VERSION_NUMBER >= 0x10000000L + X509_STORE_set_verify_cb(ssl_ctx->cert_store, proxy_verify_callback); +#endif + } + + ssl = SSL_new(ssl_ctx); + if (ssl == NULL) + return set_error(cc, ERR_get_error(), SSL_ERROR, + "Failed to create SSL connection context"); + + SSL_set_connect_state(ssl); + + + 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); @@ -271,10 +298,10 @@ ssl_client_init(glb_ctx *cc, void *v_ctx, void **ctx) err = SSL_use_certificate(ssl, m_ctx->cert_key->cert); if (err != 1) { return set_error(cc, ERR_get_error(), SSL_ERROR, "Cannot" - "use certificate"); - } - } - /*Make sure the key and certificate file match + "use certificate"); + } + } + /*Make sure the key and certificate file match * not mandatory on client side*/ if (m_ctx->cert_key->cert && m_ctx->cert_key->key) if ( (err = SSL_check_private_key(ssl)) != 1) @@ -877,7 +904,7 @@ canl_ctx_set_ssl_cred(canl_ctx cc, char *cert, char *key, return EINVAL; } - err = do_set_ctx_own_cert_file(glb_cc, m_ctx, cert, key); + err = do_set_ctx_own_cert_file(glb_cc, m_ctx, cert, key, NULL); if(err) { // update_error(glb_cc, "can't set cert or key to context"); } -- 1.8.2.3