From 423b2e851f7190a2d3b603ee4205ba7da2fb99e5 Mon Sep 17 00:00:00 2001 From: Marcel Poul Date: Wed, 11 Jul 2012 22:15:39 +0000 Subject: [PATCH] OCSP move no 2. Build the library again. --- emi.canl.canl-c/Makefile | 2 +- emi.canl.canl-c/src/canl_locl.h | 16 ++ emi.canl.canl-c/src/canl_ssl.c | 527 ---------------------------------------- 3 files changed, 17 insertions(+), 528 deletions(-) diff --git a/emi.canl.canl-c/Makefile b/emi.canl.canl-c/Makefile index 8ab88d8..3f6779c 100644 --- a/emi.canl.canl-c/Makefile +++ b/emi.canl.canl-c/Makefile @@ -93,7 +93,7 @@ doc: canl.pdf ${LIBCANL}:\ canl_err_desc.lo canl.lo canl_err.lo canl_dns.lo canl_ssl.lo \ - canl_cert.lo canl_cred.lo\ + canl_cert.lo canl_cred.lo canl_ocsp.lo\ doio.lo evaluate.lo list.lo normalize.lo proxycertinfo.lo\ scutils.lo sslutils.lo data.lo namespaces_parse.lo namespaces_lex.lo\ signing_policy_parse.lo signing_policy_lex.lo diff --git a/emi.canl.canl-c/src/canl_locl.h b/emi.canl.canl-c/src/canl_locl.h index d253efc..1a3aed1 100644 --- a/emi.canl.canl-c/src/canl_locl.h +++ b/emi.canl.canl-c/src/canl_locl.h @@ -116,6 +116,22 @@ typedef struct canl_mech { } canl_mech; +typedef struct { + char *ca_dir; + char *crl_dir; +} canl_x509store_t; + +typedef struct { + char *url; + X509 *cert; + X509 *issuer; + canl_x509store_t *store; + X509 *sign_cert; + EVP_PKEY *sign_key; + long skew; + long maxage; +} canl_ocsprequest_t; + /* Mechanism specific */ extern canl_mech canl_mech_ssl; diff --git a/emi.canl.canl-c/src/canl_ssl.c b/emi.canl.canl-c/src/canl_ssl.c index 8488069..b2c2983 100644 --- a/emi.canl.canl-c/src/canl_ssl.c +++ b/emi.canl.canl-c/src/canl_ssl.c @@ -6,43 +6,6 @@ #define SSL_SERVER_METH SSLv23_server_method() #define SSL_CLIENT_METH SSLv3_client_method() #define DESTROY_TIMEOUT 10 -#define USENONCE 0 - -typedef struct { - char *ca_dir; - char *crl_dir; -} canl_x509store_t; - -typedef struct { - char *url; - X509 *cert; - X509 *issuer; - canl_x509store_t *store; - X509 *sign_cert; - EVP_PKEY *sign_key; - long skew; - long maxage; -} canl_ocsprequest_t; - - - -typedef enum { - CANL_OCSPRESULT_ERROR_NOTCONFIGURED = -14, - CANL_OCSPRESULT_ERROR_NOAIAOCSPURI = -13, - CANL_OCSPRESULT_ERROR_INVALIDRESPONSE = -12, - CANL_OCSPRESULT_ERROR_CONNECTFAILURE = -11, - CANL_OCSPRESULT_ERROR_SIGNFAILURE = -10, - CANL_OCSPRESULT_ERROR_BADOCSPADDRESS = -9, - CANL_OCSPRESULT_ERROR_OUTOFMEMORY = -8, - CANL_OCSPRESULT_ERROR_UNKNOWN = -7, - CANL_OCSPRESULT_ERROR_UNAUTHORIZED = -6, - CANL_OCSPRESULT_ERROR_SIGREQUIRED = -5, - CANL_OCSPRESULT_ERROR_TRYLATER = -3, - CANL_OCSPRESULT_ERROR_INTERNALERROR = -2, - CANL_OCSPRESULT_ERROR_MALFORMEDREQUEST = -1, - CANL_OCSPRESULT_CERTIFICATE_VALID = 0, - CANL_OCSPRESULT_CERTIFICATE_REVOKED = 1 -} canl_ocspresult_t; static int do_ssl_connect( glb_ctx *cc, io_handler *io, SSL *ssl, struct timeval *timeout); @@ -50,17 +13,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 OCSP_RESPONSE *send_request(OCSP_REQUEST *req, char *host, char *path, - int port, int ssl, int req_timeout); -static int set_ocsp_sign_cert(X509 *sign_cert); -static int set_ocsp_sign_key(EVP_PKEY *sign_key); -static int set_ocsp_cert(X509 *cert); -static int set_ocsp_skew(int skew); -static int set_ocsp_maxage(int maxage); -static int set_ocsp_url(char *url); -static int set_ocsp_issuer(X509 *issuer); -static canl_x509store_t * store_dup(canl_x509store_t *store_from); -static X509_STORE * canl_create_x509store(canl_x509store_t *store); static canl_error map_verify_result(unsigned long ssl_err, const SSL *ssl); static canl_error map_proxy_error(int reason); @@ -73,187 +25,10 @@ extern void pvd_destroy_initializers(char *cadir); static void dbg_print_ssl_error(int errorcode); #endif -static canl_ocsprequest_t *ocspreq = NULL; /*static int set_ocsp_url(char *url, X509 *cert, X509 *issuer, canl_x509store_t *store, X509 *sign_cert, EVP_PKEY *sign_key, long skew, long maxage) { */ -static OCSP_RESPONSE * -query_responder(BIO *conn, char *path, OCSP_REQUEST *req, int req_timeout); - -static int -set_ocsp_cert(X509 *cert) -{ - - if (!ocspreq) - ocspreq = calloc(1, sizeof(*ocspreq)); - if (!ocspreq) - return 1; - - if (cert) { - if (!ocspreq->cert) { - X509_free(ocspreq->cert); - ocspreq->cert = NULL; - } - ocspreq->cert = X509_dup(cert); - if (!ocspreq->cert) - return 1; - } - return 0; -} - - static int -set_ocsp_url(char *url) -{ - - int len = 0; - if (!ocspreq) - ocspreq = calloc(1, sizeof(*ocspreq)); - if (!ocspreq) - return 1; - - if (url) { - if (!ocspreq->url) { - free (ocspreq->url); - ocspreq->url = NULL; - } - len = strlen(url); - ocspreq->url = (char *) malloc((len +1) * sizeof (char)); - if (!ocspreq->url) - return 1; - strncpy(ocspreq->url, url, len + 1); - } - return 0; -} - - static int -set_ocsp_issuer(X509 *issuer) -{ - - if (!ocspreq) - ocspreq = calloc(1, sizeof(*ocspreq)); - if (!ocspreq) - return 1; - if (issuer) { - if (!ocspreq->issuer) { - X509_free (ocspreq->issuer); - ocspreq->issuer = NULL; - } - ocspreq->issuer = X509_dup(issuer); - if (!ocspreq->issuer) - return 1; - } - return 0; -} - - static int -set_ocsp_sign_cert(X509 *sign_cert) -{ - - if (!ocspreq) - ocspreq = calloc(1, sizeof(*ocspreq)); - if (!ocspreq) - return 1; - if (sign_cert) { - if (!ocspreq->sign_cert) { - X509_free (ocspreq->sign_cert); - ocspreq->sign_cert = NULL; - } - ocspreq->sign_cert = X509_dup(sign_cert); - if (!ocspreq->sign_cert) - return 1; - } - return 0; -} - - static int -set_ocsp_sign_key(EVP_PKEY *sign_key) -{ - - if (!ocspreq) - ocspreq = calloc(1, sizeof(*ocspreq)); - if (!ocspreq) - return 1; - if (sign_key) { - if (!ocspreq->sign_key) { - EVP_PKEY_free (ocspreq->sign_key); - ocspreq->sign_key = NULL; - } - pkey_dup(&ocspreq->sign_key, sign_key); - if (!ocspreq->sign_key) - return 1; - } - return 0; -} - static int -set_ocsp_skew(int skew) -{ - - if (!ocspreq) - ocspreq = calloc(1, sizeof(*ocspreq)); - if (!ocspreq) - return 1; - if (skew) - ocspreq->skew = skew; - return 0; -} - static int -set_ocsp_maxage(int maxage) -{ - - if (!ocspreq) - ocspreq = calloc(1, sizeof(*ocspreq)); - if (!ocspreq) - return 1; - if (maxage) - ocspreq->maxage = maxage; - return 0; -} - -static canl_x509store_t * -store_dup(canl_x509store_t *store_from) -{ - canl_x509store_t *store_to = NULL; - if (!store_from) - return NULL; - - store_to = calloc(1, sizeof(*store_to)); - if (!store_to) - return NULL; - - if (store_from->ca_dir) { - int len = strlen(store_from->ca_dir); - store_to->ca_dir = (char *) malloc((len + 1) * sizeof (char)); - if (store_to->ca_dir) - return NULL; - strncpy (store_to->ca_dir, store_from->ca_dir, len + 1); - } - if (store_from->crl_dir) { - int len = strlen(store_from->crl_dir); - store_to->crl_dir = (char *) malloc((len + 1) * sizeof (char)); - if (store_to->crl_dir) - return NULL; - strncpy (store_to->crl_dir, store_from->crl_dir, len + 1); - } - return store_to; -} - - static int -set_ocsp_store(canl_x509store_t *store) -{ - - if (!ocspreq) - ocspreq = calloc(1, sizeof(*ocspreq)); - if (!ocspreq) - return 1; - if (store){ - ocspreq->store = store_dup(store); - if (!ocspreq->store) - return 1; - } - return 0; -} - static canl_err_code ssl_initialize(glb_ctx *cc) @@ -1403,308 +1178,6 @@ static void dbg_print_ssl_error(int errorcode) } #endif -static X509_STORE * -canl_create_x509store(canl_x509store_t *store) -{ - return NULL; -} - -/*TODO error codes in this function has to be passed to canl_ctx somehow*/ -/*Timeout shoult be in data structure*/ -int do_ocsp_verify (canl_ocsprequest_t *data) -{ - OCSP_REQUEST *req = NULL; - OCSP_RESPONSE *resp = NULL; - OCSP_BASICRESP *basic = NULL; - X509_STORE *store = 0; - int rc = 0, reason = 0, ssl = 0, status = 0; - char *host = NULL, *path = NULL, *port = NULL; - OCSP_CERTID *id = NULL; - char *chosenurl = NULL; - canl_ocspresult_t result = 0; - ASN1_GENERALIZEDTIME *producedAt, *thisUpdate, *nextUpdate; - int timeout = -1; // -1 means no timeout - use blocking I/O - - 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 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 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 - 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; - } - - - /* establish a connection to the OCSP responder */ - if (!(resp = send_request(req, host, path, atoi(port), ssl, timeout))) { - result = CANL_OCSPRESULT_ERROR_CONNECTFAILURE; - goto end; - } - - /* send the request and get a response */ - if ((rc = OCSP_response_status(resp)) != OCSP_RESPONSE_STATUS_SUCCESSFUL) { - switch (rc) { - case OCSP_RESPONSE_STATUS_MALFORMEDREQUEST: - result = CANL_OCSPRESULT_ERROR_MALFORMEDREQUEST; break; - case OCSP_RESPONSE_STATUS_INTERNALERROR: - result = CANL_OCSPRESULT_ERROR_INTERNALERROR; break; - case OCSP_RESPONSE_STATUS_TRYLATER: - result = CANL_OCSPRESULT_ERROR_TRYLATER; break; - case OCSP_RESPONSE_STATUS_SIGREQUIRED: - result = CANL_OCSPRESULT_ERROR_SIGREQUIRED; break; - case OCSP_RESPONSE_STATUS_UNAUTHORIZED: - result = CANL_OCSPRESULT_ERROR_UNAUTHORIZED; break; - } - goto end; - } - - /* verify the response */ - result = CANL_OCSPRESULT_ERROR_INVALIDRESPONSE; - if (!(basic = OCSP_response_get1_basic(resp))) - goto end; - if (USENONCE && OCSP_check_nonce(req, basic) <= 0) - goto end; - /*TODO make the store*/ - if (data->store && !(store = canl_create_x509store(data->store))) - goto end; - /*TODO check the second parametr (responder_cert) and the last one*/ - if ((rc = OCSP_basic_verify(basic, 0, store, 0)) <= 0) - if ((rc = OCSP_basic_verify(basic, NULL, store, 0)) <= 0) - goto end; - - if (!OCSP_resp_find_status(basic, id, &status, &reason, &producedAt, - &thisUpdate, &nextUpdate)) - goto end; - if (!OCSP_check_validity(thisUpdate, nextUpdate, data->skew, data->maxage)) - goto end; - - /* All done. Set the return code based on the status from the response. */ - if (status == V_OCSP_CERTSTATUS_REVOKED) { - result = CANL_OCSPRESULT_CERTIFICATE_REVOKED; - /*TODO myproxy_log("OCSP status revoked!"); */ - } else { - result = CANL_OCSPRESULT_CERTIFICATE_VALID; - /*TODO myproxy_log("OCSP status valid"); */ - } -end: - /*TODO check what's this - if (result < 0 && result != CANL_OCSPRESULT_ERROR_NOTCONFIGURED) { - ssl_error_to_verror(); - TODO myproxy_log("OCSP check failed"); - myproxy_log_verror(); - } */ - - if (host) OPENSSL_free(host); - if (port) OPENSSL_free(port); - if (path) OPENSSL_free(path); - if (req) OCSP_REQUEST_free(req); - if (resp) OCSP_RESPONSE_free(resp); - if (basic) OCSP_BASICRESP_free(basic); - - return result; -} - -static OCSP_RESPONSE * -send_request(OCSP_REQUEST *req, char *host, char *path, int port, int ssl, - int req_timeout) { - BIO *conn; - SSL_CTX *ctx_in = NULL; - OCSP_RESPONSE *resp = NULL; - - if (!(conn = BIO_new_connect(host))) - goto end; - 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 end; - } - //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); - - TODO figure out, how to check cert without canl_ctx - - if (!check_hostname_cert(SSL_get_peer_certificate(ssl_ptr), host)) - goto end; - - 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 end; - */ - } - - resp = query_responder(conn, path, req, req_timeout); - -end: - if (conn) - BIO_free_all(conn); - if (ctx_in) - SSL_CTX_free(ctx_in); - return resp; -} - -/*TODO the timeout variable should be modified if TO is reached. - Somehow retur error codes! */ - static OCSP_RESPONSE * -query_responder(BIO *conn, char *path, OCSP_REQUEST *req, int req_timeout) -{ - OCSP_RESPONSE *rsp = NULL; - -/*openssl does support non blocking BIO for OCSP_send_request*/ -#if SSLEAY_VERSION_NUMBER >= 0x0090808fL - int fd; - int rv; - OCSP_REQ_CTX *ctx = NULL; - fd_set confds; - struct timeval tv; - - /*If timeout is set, the nonblocking I/O flag is set*/ - if (req_timeout != -1) - BIO_set_nbio(conn, 1); - - rv = BIO_do_connect(conn); - if ((rv <= 0) && ((req_timeout == -1) || !BIO_should_retry(conn))) - { - /*connect failed*/ - return NULL; - } - - if (BIO_get_fd(conn, &fd) <= 0) - { - /*Cannot get the socket*/ - goto err; - } - - if (req_timeout != -1 && rv <= 0) - { - /*try connecting untill timeout is reached*/ - FD_ZERO(&confds); - FD_SET(fd, &confds); - tv.tv_usec = 0; - tv.tv_sec = req_timeout; - rv = select(fd + 1, NULL, (void *)&confds, NULL, &tv); - if (rv == 0) - { - /*Timeout reached*/ - return NULL; - } - } - - - /*Prepare OCSP_REQ_CTX*/ - ctx = OCSP_sendreq_new(conn, path, NULL, -1); - if (!ctx) - return NULL; - if (!OCSP_REQ_CTX_set1_req(ctx, req)) - goto err; - - /*send the OCSP request and wait for the response*/ - for (;;) - { - rv = OCSP_sendreq_nbio(&rsp, ctx); - if (rv != -1) - break; - - /* Blocking I/O flag set - TODO - might end in an infinite loop? - what about - SSL_MODE_AUTO_RETRY ?? */ - if (req_timeout == -1) - continue; - FD_ZERO(&confds); - openssl_fdset(fd, &confds); - tv.tv_usec = 0; - tv.tv_sec = req_timeout; - if (BIO_should_read(conn)) - rv = select(fd + 1, (void *)&confds, NULL, NULL, &tv); - else if (BIO_should_write(conn)) - rv = select(fd + 1, NULL, (void *)&confds, NULL, &tv); - else - { - /* Unexpected retry condition */ - goto err; - } - if (rv == 0) - { - /*Timeout on request */ - break; - } - if (rv == -1) - { - /*Select error*/ - break; - } - - } - -#else - /*openssl does not support non blocking BIO for OCSP_send_request*/ - - if (BIO_do_connect(conn) <= 0) - { - /*Error connecting BIO*/ - goto err; - } - - rsp = OCSP_sendreq_bio(conn, path, req); - if (!rsp) { - /*no response from the server*/ - goto err; - } - -#endif - -err: -#if SSLEAY_VERSION_NUMBER >= 0x0090808fL - if (ctx) - OCSP_REQ_CTX_free(ctx); -#endif - return rsp; -} canl_mech canl_mech_ssl = { TLS, -- 1.8.2.3