From 18985a2b4b94796e8ebe63e088d245f82ab40620 Mon Sep 17 00:00:00 2001 From: Marcel Poul Date: Wed, 4 Jul 2012 11:28:42 +0000 Subject: [PATCH] OCSP routines changes - we do not need my_connect_ssl anymore (all needed is in my_connect) - ssl connection not mandatory - inpired by openssl ocsp tool (apps/ocsp.c) --- emi.canl.canl-c/src/canl_ssl.c | 121 ++++++++++++++++++++++++----------------- 1 file changed, 72 insertions(+), 49 deletions(-) diff --git a/emi.canl.canl-c/src/canl_ssl.c b/emi.canl.canl-c/src/canl_ssl.c index 3f594b9..41d3903 100644 --- a/emi.canl.canl-c/src/canl_ssl.c +++ b/emi.canl.canl-c/src/canl_ssl.c @@ -50,7 +50,6 @@ 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); -static BIO *my_connect_ssl(char *host, int port, SSL_CTX **ctx); static BIO *my_connect(char *host, int port, int ssl, SSL_CTX **ctx); static int set_ocsp_sign_cert(X509 *sign_cert); static int set_ocsp_sign_key(EVP_PKEY *sign_key); @@ -1351,6 +1350,7 @@ canl_create_x509store(canl_x509store_t *store) return NULL; } +/*TODO error codes in this function has to be passed to canl_ctx somehow*/ int do_ocsp_verify (canl_ocsprequest_t *data) { OCSP_REQUEST *req = NULL; @@ -1361,54 +1361,61 @@ int do_ocsp_verify (canl_ocsprequest_t *data) char *host = NULL, *path = NULL, *port = NULL; OCSP_CERTID *id = NULL; char *chosenurl = NULL; - BIO *bio = NULL; + BIO *conn_bio = NULL; SSL_CTX *ctx = NULL; canl_ocspresult_t result = 0; ASN1_GENERALIZEDTIME *producedAt, *thisUpdate, *nextUpdate; + + if (!data || !data->cert) { // TODO || !data->issuer ? + result = EINVAL; //TODO error code + return result; + } + /*get url from cert or use some implicit value*/ - /*get connection parameters out of url*/ + /*get connection parameters out of the chosenurl. + Determine whether to use encrypted (ssl) connection (based on the url + format). Url is http[s]://host where host consists of + DN [:port] and [path]*/ if (!OCSP_parse_url(chosenurl, &host, &port, &path, &ssl)) { result = CANL_OCSPRESULT_ERROR_BADOCSPADDRESS; goto end; } + /*Make new OCSP_REQUEST*/ if (!(req = OCSP_REQUEST_new())) { result = CANL_OCSPRESULT_ERROR_OUTOFMEMORY; goto end; } + /*map a cert and its issuer to an ID*/ id = OCSP_cert_to_id(0, data->cert, data->issuer); - /* Add id and nonce*/ + /* Add an id and nonce to the request*/ if (!id || !OCSP_request_add0_id(req, id)) goto end; if (USENONCE) OCSP_request_add1_nonce(req, 0, -1); - /* sign the request */ - if (data->sign_cert && data->sign_key && - !OCSP_request_sign(req, data->sign_cert, data->sign_key, - EVP_sha1(), 0, 0)) { - result = CANL_OCSPRESULT_ERROR_SIGNFAILURE; - goto end; - } - - ctx = SSL_CTX_new(SSLv3_client_method()); - if (ctx == NULL) { - result = CANL_OCSPRESULT_ERROR_OUTOFMEMORY; + /* sign the request + Default hash algorithm is sha1(), might be changed. + Do not add additional certificates to request + Do not use flags (e.g. like -no_certs for command line ) now */ + if (data->sign_cert && data->sign_key && + !OCSP_request_sign(req, data->sign_cert, data->sign_key, + EVP_sha1(), 0, 0)) { + result = CANL_OCSPRESULT_ERROR_SIGNFAILURE; goto end; } - //SSL_CTX_set_cert_store(ctx, store); - SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER,NULL); + /* establish a connection to the OCSP responder */ - if (!(bio = my_connect(host, atoi(port), ssl, &ctx))) { + if (!(conn_bio = my_connect(host, atoi(port), ssl, &ctx))) { result = CANL_OCSPRESULT_ERROR_CONNECTFAILURE; goto end; } /* send the request and get a response */ - resp = OCSP_sendreq_bio(bio, path, req); + resp = OCSP_sendreq_bio(conn_bio, path, req); if ((rc = OCSP_response_status(resp)) != OCSP_RESPONSE_STATUS_SUCCESSFUL) { switch (rc) { case OCSP_RESPONSE_STATUS_MALFORMEDREQUEST: @@ -1424,6 +1431,8 @@ int do_ocsp_verify (canl_ocsprequest_t *data) } goto end; } + if (conn_bio) + BIO_free_all(conn_bio); /* verify the response */ result = CANL_OCSPRESULT_ERROR_INVALIDRESPONSE; @@ -1469,48 +1478,62 @@ end: if (basic) OCSP_BASICRESP_free(basic); if (ctx) SSL_CTX_free(ctx); /* this does X509_STORE_free(store) */ - return 0; + return result; } static BIO * -my_connect_ssl(char *host, int port, SSL_CTX **ctx) { - BIO *conn = 0; +my_connect(char *host, int port, int ssl, SSL_CTX **ctx) { + BIO *conn; + SSL_CTX *ctx_in = NULL; + + if (!(conn = BIO_new_connect(host))) + goto error_exit; + BIO_set_conn_int_port(conn, &port); + + if (ssl){ + BIO *sbio; + /*TODO what method to use? default is SSLv3 for now*/ + ctx_in = SSL_CTX_new(SSLv3_client_method()); + if (ctx_in == NULL) { + goto error_exit; + } + //SSL_CTX_set_cert_store(ctx_in, store); + /*TODO verify using OCSP? Infinite loop + SSL_CTX_set_mode(ctx_in, SSL_MODE_AUTO_RETRY); ? - return only after + the handshake and successful completion*/ + SSL_CTX_set_verify(ctx_in, SSL_VERIFY_PEER, NULL); + + sbio = BIO_new_ssl(ctx_in, 1); + conn = BIO_push(sbio, conn); + /* + BIO_get_ssl(conn, &ssl_ptr); - if (!(conn = BIO_new_ssl_connect(*ctx))) goto error_exit; - BIO_set_conn_hostname(conn, host); - BIO_set_conn_int_port(conn, &port); + TODO figure out, how to check cert without canl_ctx - if (BIO_do_connect(conn) <= 0) goto error_exit; - return conn; + if (!check_hostname_cert(SSL_get_peer_certificate(ssl_ptr), host)) + goto error_exit; -error_exit: - if (conn) BIO_free_all(conn); - return 0; -} + TODO verify certs in OCSP at this place? openssl CL tool does not do + that. + if (SSL_get_verify_result(ssl_ptr) != X509_V_OK) + goto error_exit; + */ -static BIO * -my_connect(char *host, int port, int ssl, SSL_CTX **ctx) { - BIO *conn; - SSL *ssl_ptr; - - if (ssl) { - if (!(conn = my_connect_ssl(host, port, ctx))) goto error_exit; - BIO_get_ssl(conn, &ssl_ptr); - /*TODO figure out, how to check cert without canl_ctx - if (!check_hostname_cert(SSL_get_peer_certificate(ssl_ptr), host)) - goto error_exit;*/ - if (SSL_get_verify_result(ssl_ptr) != X509_V_OK) goto error_exit; - return conn; + *ctx = ctx_in; } - if (!(conn = BIO_new_connect(host))) goto error_exit; - BIO_set_conn_int_port(conn, &port); - if (BIO_do_connect(conn) <= 0) goto error_exit; + if (BIO_do_connect(conn) <= 0) + goto error_exit; return conn; error_exit: - if (conn) BIO_free_all(conn); - return 0; + if (conn) + BIO_free_all(conn); + if (*ctx) { + SSL_CTX_free(*ctx); + *ctx = NULL; + } + return NULL; } canl_mech canl_mech_ssl = { -- 1.8.2.3