Hi! I made some changes reflecting Erwann comments.

Here they are:

1) OCSP URL processing logic now fully conforms to RFC2560 with
following additional settings:

 - User can disable OCSP for the particular CA making OCSP verification
succeed for all certificates, issued by that CA;
 - User can force OCSP url for the CA. This way all certs issued by that
CA will be validated against OCSP using the forced url, totally ignoring
certificate-provided OCSP url (good thing is that this will work for
certificates without AuthorityInfoAccess extension).

2) X509_V_FLAG_OCSP_NO_NONCE flag is introduced. Setting it with
X509_STORE_set_flags() will disable nonce usage in OCSP verification and
increase protocol efficiency, making it insecure(!!!).

3) Issuer certificates are now taken from the certificate chain built by
OpenSSL, thus eliminating additional overhead and potential problems
with identical CA names on this level.

4) OCSP verification now reports meaningful errors to the client's
callback instead of ambiguous X509_V_ERR_APPLICATION_VERIFICATION.


Patch is attached.

P.S> I tested this patch with OpenLDAP and it seems to work pretty fine
with OpenSSL ocsp server.

On Fri, 2012-06-08 at 16:54 +0200, Erwann Abalea wrote:
> Bonjour,
> 
> If the OCSP URL isn't found in the supplied certificate, you're trying 
> to find it in its issuer? That's not standard, even if it can work.
> 
> It seems you're looking for the issuer by its subject name. When you 
> have several CA certificates with the same name in your store (that's 
> permitted), you may not get the real issuer certificate, and the 
> calculated issuerKeyHash will be wrong.
> 
> Please don't add a nonce, at least not by default. Looking at our busy 
> OCSP responders, *nobody* asks for a nonce, and it's perfect like this. 
> Having a nonce may provide you a benefit, but it defeats CA 
> optimizations (cached responses, mainly).
> 
> It seems the supplied code doesn't check for a dedicated OCSP 
> responder's certificate validity (not necessary if this certificate has 
> an OCSPNoCheck extension, but some don't have this extension).
> 
> Le 08/06/2012 13:07, Alexander Komyagin a écrit :
> > [...]
> > How it works:
> >
> > 1) OCSP revocation check is done right before CRL check
> > 2) first, OpenSSL tries to get the OCSP url for the certificate being
> > checked - it's either forced url or embedded into the certificate.
> > 3) if it fails, issuer shall be found
> > 4) if OCSP validation for issuer is disabled, we completely trust him
> > and the check is successful.
> > 5) otherwise, we extract issuer OCSP url the same way as in (2) and use
> > it to check.
> >
> > =========================
> > Possible errors:
> >   - X509_V_ERR_CERT_UNKNOWN [OCSP responder never heard about this
> > certificate]
> >   - X509_V_ERR_CERT_REVOKED [Certificate had been revoked]
> >   - X509_V_ERR_APPLICATION_VERIFICATION [for everything else]
> >
> >
> > ========================
> >
> > P.S>  OCSP querying code was taken from OpenSSL ocsp app. Also I still
> > want to add additional error codes for reporting OCSP-related failures
> > during verification (obviously, APPLICATION_VERIFICATION_FAILURE doesn't
> > tell you much).
> >
> 
> 

-- 
Best wishes,
Alexander Komyagin
diff --git a/apps/apps.c b/apps/apps.c
index 4e11915..47f8c2f 100644
--- a/apps/apps.c
+++ b/apps/apps.c
@@ -2338,8 +2338,12 @@ int args_verify(char ***pargs, int *pargc,
 		flags |= X509_V_FLAG_CB_ISSUER_CHECK;
 	else if (!strcmp(arg, "-crl_check"))
 		flags |=  X509_V_FLAG_CRL_CHECK;
+	else if (!strcmp(arg, "-ocsp_check"))
+		flags |=  X509_V_FLAG_OCSP_CHECK;
 	else if (!strcmp(arg, "-crl_check_all"))
 		flags |= X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL;
+	else if (!strcmp(arg, "-ocsp_check_all"))
+		flags |= X509_V_FLAG_OCSP_CHECK|X509_V_FLAG_OCSP_CHECK_ALL;	
 	else if (!strcmp(arg, "-policy_check"))
 		flags |= X509_V_FLAG_POLICY_CHECK;
 	else if (!strcmp(arg, "-explicit_policy"))
diff --git a/apps/verify.c b/apps/verify.c
index b9749dc..8eeaf7b 100644
--- a/apps/verify.c
+++ b/apps/verify.c
@@ -65,6 +65,8 @@
 #include <openssl/x509.h>
 #include <openssl/x509v3.h>
 #include <openssl/pem.h>
+#include <openssl/x509_vfy_ocsp.h>
+#include <openssl/ocsp_clnt.h>
 
 #undef PROG
 #define PROG	verify_main
@@ -88,6 +90,8 @@ int MAIN(int argc, char **argv)
 	X509_STORE *cert_ctx=NULL;
 	X509_LOOKUP *lookup=NULL;
 	X509_VERIFY_PARAM *vpm = NULL;
+	char *ocsp_url = NULL;
+	int ocsp_validate = X509_OCSP_VALIDATE_ENABLED;
 #ifndef OPENSSL_NO_ENGINE
 	char *engine=NULL;
 #endif
@@ -95,6 +99,7 @@ int MAIN(int argc, char **argv)
 	cert_ctx=X509_STORE_new();
 	if (cert_ctx == NULL) goto end;
 	X509_STORE_set_verify_cb(cert_ctx,cb);
+	X509_STORE_set_ocsp_process_resp(cert_ctx, &ocsp_process_responder);
 
 	ERR_load_crypto_strings();
 
@@ -123,6 +128,16 @@ int MAIN(int argc, char **argv)
 				if (argc-- < 1) goto end;
 				CAfile= *(++argv);
 				}
+			else if (strcmp(*argv,"-ocsp_url") == 0)
+				{
+				if (argc-- < 1) goto end;
+				ocsp_url= *(++argv);
+				}
+			else if (strcmp(*argv,"-ocsp_validate") == 0)
+				{
+				if (argc-- < 1) goto end;
+				ocsp_validate = atoi(*(++argv));
+				}
 			else if (args_verify(&argv, &argc, &badarg, bio_err,
 									&vpm))
 				{
@@ -222,6 +237,18 @@ int MAIN(int argc, char **argv)
 			goto end;
 		}
 
+	if (ocsp_url && CAfile)
+	{
+		BIO_printf(bio_err, "Setting OCSP params for %s (%s,%d)... ", CAfile, ocsp_url, ocsp_validate);
+		i = X509_set_cert_ocsp_opt(cert_ctx, CAfile, ocsp_url, ocsp_validate);
+		if(!i) {
+			BIO_printf(bio_err, "Error setting OCSP params for %s\n", CAfile);
+			ERR_print_errors(bio_err);
+			goto end;
+		}
+		BIO_printf(bio_err, "Done.\n");
+	}
+
 	if (argc < 1) check(cert_ctx, NULL, untrusted, trusted, crls, e);
 	else
 		for (i=0; i<argc; i++)
diff --git a/crypto/asn1/x_x509.c b/crypto/asn1/x_x509.c
index de3df9e..2074a84 100644
--- a/crypto/asn1/x_x509.c
+++ b/crypto/asn1/x_x509.c
@@ -81,6 +81,10 @@ IMPLEMENT_ASN1_FUNCTIONS(X509_CINF)
 
 extern void policy_cache_free(X509_POLICY_CACHE *cache);
 
+#ifndef OPENSSL_NO_OCSP
+extern void X509_CERT_OCSP_free(X509_CERT_OCSP *ocsp);
+#endif
+
 static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
 								void *exarg)
 {
@@ -102,6 +106,9 @@ static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
 		ret->aux = NULL;
 		ret->crldp = NULL;
 		CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509, ret, &ret->ex_data);
+#ifndef OPENSSL_NO_OCSP
+		ret->ocsp = NULL;
+#endif
 		break;
 
 		case ASN1_OP_D2I_POST:
@@ -122,7 +129,9 @@ static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
 		sk_IPAddressFamily_pop_free(ret->rfc3779_addr, IPAddressFamily_free);
 		ASIdentifiers_free(ret->rfc3779_asid);
 #endif
-
+#ifndef OPENSSL_NO_OCSP
+		if (ret->ocsp != NULL) X509_CERT_OCSP_free(ret->ocsp);
+#endif
 		if (ret->name != NULL) OPENSSL_free(ret->name);
 		break;
 
diff --git a/crypto/x509/Makefile b/crypto/x509/Makefile
index 72c8227..5a56e42 100644
--- a/crypto/x509/Makefile
+++ b/crypto/x509/Makefile
@@ -18,13 +18,13 @@ APPS=
 
 LIB=$(TOP)/libcrypto.a
 LIBSRC=	x509_def.c x509_d2.c x509_r2x.c x509_cmp.c \
-	x509_obj.c x509_req.c x509spki.c x509_vfy.c \
+	x509_obj.c x509_req.c x509spki.c x509_vfy.c x509_vfy_ocsp.c \
 	x509_set.c x509cset.c x509rset.c x509_err.c \
 	x509name.c x509_v3.c x509_ext.c x509_att.c \
 	x509type.c x509_lu.c x_all.c x509_txt.c \
 	x509_trs.c by_file.c by_dir.c x509_vpm.c
 LIBOBJ= x509_def.o x509_d2.o x509_r2x.o x509_cmp.o \
-	x509_obj.o x509_req.o x509spki.o x509_vfy.o \
+	x509_obj.o x509_req.o x509spki.o x509_vfy.o x509_vfy_ocsp.o\
 	x509_set.o x509cset.o x509rset.o x509_err.o \
 	x509name.o x509_v3.o x509_ext.o x509_att.o \
 	x509type.o x509_lu.o x_all.o x509_txt.o \
@@ -32,7 +32,7 @@ LIBOBJ= x509_def.o x509_d2.o x509_r2x.o x509_cmp.o \
 
 SRC= $(LIBSRC)
 
-EXHEADER= x509.h x509_vfy.h
+EXHEADER= x509.h x509_vfy.h x509_vfy_ocsp.h
 HEADER=	$(EXHEADER)
 
 ALL=    $(GENERAL) $(SRC) $(HEADER)
@@ -95,7 +95,7 @@ by_dir.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
 by_dir.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h
 by_dir.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
 by_dir.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
-by_dir.o: ../../include/openssl/x509_vfy.h ../cryptlib.h by_dir.c
+by_dir.o: ../../include/openssl/x509_vfy.h ../../include/openssl/x509_vfy_ocsp.h ../cryptlib.h by_dir.c
 by_file.o: ../../e_os.h ../../include/openssl/asn1.h
 by_file.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
 by_file.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
@@ -109,7 +109,7 @@ by_file.o: ../../include/openssl/pem2.h ../../include/openssl/pkcs7.h
 by_file.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h
 by_file.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
 by_file.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h
-by_file.o: ../cryptlib.h by_file.c
+by_file.o: ../cryptlib.h ../../include/openssl/x509_vfy_ocsp.h by_file.c
 x509_att.o: ../../e_os.h ../../include/openssl/asn1.h
 x509_att.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
 x509_att.o: ../../include/openssl/conf.h ../../include/openssl/crypto.h
@@ -311,8 +311,22 @@ x509_vfy.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
 x509_vfy.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h
 x509_vfy.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
 x509_vfy.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
-x509_vfy.o: ../../include/openssl/x509_vfy.h ../../include/openssl/x509v3.h
+x509_vfy.o: ../../include/openssl/x509_vfy.h ../../include/openssl/x509_vfy_ocsp.h ../../include/openssl/x509v3.h
 x509_vfy.o: ../cryptlib.h x509_vfy.c
+x509_vfy_ocsp.o: ../../e_os.h ../../include/openssl/asn1.h
+x509_vfy_ocsp.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
+x509_vfy_ocsp.o: ../../include/openssl/conf.h ../../include/openssl/crypto.h
+x509_vfy_ocsp.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h
+x509_vfy_ocsp.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h
+x509_vfy_ocsp.o: ../../include/openssl/err.h ../../include/openssl/evp.h
+x509_vfy_ocsp.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
+x509_vfy_ocsp.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h
+x509_vfy_ocsp.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
+x509_vfy_ocsp.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h
+x509_vfy_ocsp.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
+x509_vfy_ocsp.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
+x509_vfy_ocsp.o: ../../include/openssl/x509_vfy.h ../../include/openssl/x509_vfy_ocsp.h ../../include/openssl/x509v3.h
+x509_vfy_ocsp.o: ../cryptlib.h ../../include/openssl/ocsp.h x509_vfy_ocsp.c
 x509_vpm.o: ../../e_os.h ../../include/openssl/asn1.h
 x509_vpm.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
 x509_vpm.o: ../../include/openssl/conf.h ../../include/openssl/crypto.h
@@ -404,4 +418,4 @@ x_all.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pkcs7.h
 x_all.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h
 x_all.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
 x_all.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
-x_all.o: ../../include/openssl/x509_vfy.h ../cryptlib.h x_all.c
+x_all.o: ../../include/openssl/x509_vfy.h ../../include/openssl/x509_vfy_ocsp.h ../cryptlib.h x_all.c
diff --git a/crypto/x509/x509.h b/crypto/x509/x509.h
index 092dd74..e5233fe 100644
--- a/crypto/x509/x509.h
+++ b/crypto/x509/x509.h
@@ -276,6 +276,17 @@ typedef struct x509_cert_aux_st
 	STACK_OF(X509_ALGOR) *other;		/* other unspecified info */
 	} X509_CERT_AUX;
 
+/* This struct represents OCSP-related validation
+ * data that can be manually set for certificate
+ */
+#ifndef OPENSSL_NO_OCSP
+typedef struct x509_cert_ocsp_st
+	{
+	char *ocsp_url; /* forced OCSP URL */
+	int ocsp_validate; /* validation mode: if disabled, one has no OCSP */
+	} X509_CERT_OCSP;
+#endif
+ 
 struct x509_st
 	{
 	X509_CINF *cert_info;
@@ -306,6 +317,9 @@ struct x509_st
 	unsigned char sha1_hash[SHA_DIGEST_LENGTH];
 #endif
 	X509_CERT_AUX *aux;
+#ifndef OPENSSL_NO_OCSP
+	X509_CERT_OCSP *ocsp;
+#endif
 	} /* X509 */;
 
 DECLARE_STACK_OF(X509)
@@ -859,6 +873,10 @@ int X509_add1_reject_object(X509 *x, ASN1_OBJECT *obj);
 void X509_trust_clear(X509 *x);
 void X509_reject_clear(X509 *x);
 
+#ifndef OPENSSL_NO_OCSP
+int X509_set0_ocsp(X509 *cert, X509_CERT_OCSP *ocsp);
+#endif
+
 DECLARE_ASN1_FUNCTIONS(X509_REVOKED)
 DECLARE_ASN1_FUNCTIONS(X509_CRL_INFO)
 DECLARE_ASN1_FUNCTIONS(X509_CRL)
diff --git a/crypto/x509/x509_lu.c b/crypto/x509/x509_lu.c
index 38525a8..c2d21e1 100644
--- a/crypto/x509/x509_lu.c
+++ b/crypto/x509/x509_lu.c
@@ -187,6 +187,10 @@ X509_STORE *X509_STORE_new(void)
 	ret->verify=0;
 	ret->verify_cb=0;
 
+#ifndef OPENSSL_NO_OCSP
+	ret->ocsp_process_responder=0;
+#endif
+
 	if ((ret->param = X509_VERIFY_PARAM_new()) == NULL)
 		return NULL;
 
@@ -712,5 +716,13 @@ void X509_STORE_set_verify_cb(X509_STORE *ctx,
 	ctx->verify_cb = verify_cb;
 	}
 
+#ifndef OPENSSL_NO_OCSP
+void X509_STORE_set_ocsp_process_resp(X509_STORE *ctx,
+				  ocsp_process_responder_f func)
+	{
+	ctx->ocsp_process_responder = func;
+	}
+#endif
+
 IMPLEMENT_STACK_OF(X509_LOOKUP)
 IMPLEMENT_STACK_OF(X509_OBJECT)
diff --git a/crypto/x509/x509_txt.c b/crypto/x509/x509_txt.c
index c44f753..d6ecac7 100644
--- a/crypto/x509/x509_txt.c
+++ b/crypto/x509/x509_txt.c
@@ -183,6 +183,22 @@ const char *X509_verify_cert_error_string(long n)
 		return("unsupported or invalid name syntax");
 	case X509_V_ERR_CRL_PATH_VALIDATION_ERROR:
 		return("CRL path validation error");
+	case X509_V_ERR_CERT_UNKNOWN:
+		return("certificate is unknown for OCSP");
+	case X509_V_ERR_UNABLE_TO_FIND_OCSP_URL:
+		return("unable to find OCSP responder url");
+	case X509_V_ERR_UNPARSABLE_OCSP_URL:
+		return("failed to parse OCSP responder url");
+	case X509_V_ERR_SSL_USED_FOR_OCSP:
+		return("ssl connections to OCSP servers are not supported");
+	case X509_V_ERR_OCSP_PROCESS_FUNC_NOT_SET:
+		return("OCSP responder process function is not set");
+	case X509_V_ERR_OCSP_RESPONDER_STATUS_FAIL:
+		return("OCSP responder reports fail");
+	case X509_V_ERR_OCSP_NONCE_VERIFY_ERROR:
+		return("OCSP nonce verification failure");
+	case X509_V_ERR_OCSP_RESPONSE_VERIFICATION:
+		return("OCSP response verification failure");
 
 	default:
 		BIO_snprintf(buf,sizeof buf,"error number %ld",n);
diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c
index b0779db..ab970cc 100644
--- a/crypto/x509/x509_vfy.c
+++ b/crypto/x509/x509_vfy.c
@@ -70,6 +70,8 @@
 #include <openssl/x509v3.h>
 #include <openssl/objects.h>
 
+#include "x509_vfy_ocsp.h"
+
 /* CRL score values */
 
 /* No unhandled critical extensions */
@@ -669,6 +671,16 @@ static int check_trust(X509_STORE_CTX *ctx)
 static int check_revocation(X509_STORE_CTX *ctx)
 	{
 	int i, last, ok;
+
+#ifndef OPENSSL_NO_OCSP
+	/* Check if we need to check against OCSP */
+	if (ctx->param->flags & X509_V_FLAG_OCSP_CHECK)
+	{
+		ok = check_revocation_ocsp(ctx);
+		if (!ok) return ok;
+	}
+#endif
+
 	if (!(ctx->param->flags & X509_V_FLAG_CRL_CHECK))
 		return 1;
 	if (ctx->param->flags & X509_V_FLAG_CRL_CHECK_ALL)
@@ -2205,6 +2217,58 @@ void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param)
 	ctx->param = param;
 	}
 
+#ifndef OPENSSL_NO_OCSP
+void X509_CERT_OCSP_free(X509_CERT_OCSP *ocsp)
+	{
+	if (!ocsp)
+		return;
+	if (ocsp->ocsp_url)
+		OPENSSL_free(ocsp->ocsp_url);
+	OPENSSL_free(ocsp);
+	}
+	
+X509_CERT_OCSP *X509_CERT_OCSP_new(void)
+	{
+	X509_CERT_OCSP *ocsp;
+	ocsp = OPENSSL_malloc(sizeof(X509_CERT_OCSP));
+	memset(ocsp, 0, sizeof(X509_CERT_OCSP));
+	ocsp->ocsp_validate = X509_OCSP_VALIDATE_ENABLED;
+	return ocsp;
+	}
+	
+int X509_set0_ocsp(X509 *cert, X509_CERT_OCSP *ocsp)
+	{
+	if (cert->ocsp)
+		X509_CERT_OCSP_free(cert->ocsp);
+	cert->ocsp = ocsp;
+	return 1;
+	}
+	
+int X509_CERT_OCSP_set1_url(X509_CERT_OCSP *ocsp, char* url)
+	{
+	if (ocsp->ocsp_url)
+		OPENSSL_free(ocsp->ocsp_url);
+		
+	if (url == NULL)
+	{
+		ocsp->ocsp_url = NULL;
+		return 1;
+	}
+	
+	ocsp->ocsp_url = BUF_strdup(url);
+	if (ocsp->ocsp_url)
+		return 1;
+
+	return 0;
+	}
+	
+int X509_CERT_OCSP_set_validate(X509_CERT_OCSP *ocsp, int validate)
+	{
+	ocsp->ocsp_validate = validate;
+	return 1;
+	}
+#endif
+
 IMPLEMENT_STACK_OF(X509)
 IMPLEMENT_ASN1_SET_OF(X509)
 
diff --git a/crypto/x509/x509_vfy.h b/crypto/x509/x509_vfy.h
index fe09b30..7a4b98f 100644
--- a/crypto/x509/x509_vfy.h
+++ b/crypto/x509/x509_vfy.h
@@ -73,6 +73,10 @@
 #include <openssl/crypto.h>
 #include <openssl/symhacks.h>
 
+#ifndef OPENSSL_NO_OCSP
+#include <openssl/x509_vfy_ocsp.h>
+#endif
+
 #ifdef  __cplusplus
 extern "C" {
 #endif
@@ -206,6 +210,10 @@ struct x509_store_st
 
 	CRYPTO_EX_DATA ex_data;
 	int references;
+
+#ifndef OPENSSL_NO_OCSP
+	ocsp_process_responder_f ocsp_process_responder; /* Connect to OCSP responder */
+#endif
 	} /* X509_STORE */;
 
 int X509_STORE_set_depth(X509_STORE *store, int depth);
@@ -357,6 +365,16 @@ void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth);
 /* The application is not happy */
 #define		X509_V_ERR_APPLICATION_VERIFICATION		50
 
+/* OCSP related errors */
+#define		X509_V_ERR_CERT_UNKNOWN		55
+#define		X509_V_ERR_UNABLE_TO_FIND_OCSP_URL		56
+#define		X509_V_ERR_UNPARSABLE_OCSP_URL		57
+#define		X509_V_ERR_SSL_USED_FOR_OCSP		58
+#define		X509_V_ERR_OCSP_PROCESS_FUNC_NOT_SET		59
+#define		X509_V_ERR_OCSP_RESPONDER_STATUS_FAIL		60
+#define		X509_V_ERR_OCSP_NONCE_VERIFY_ERROR		61
+#define		X509_V_ERR_OCSP_RESPONSE_VERIFICATION		62
+
 /* Certificate verify flags */
 
 /* Send issuer+subject checks to verify_cb */
@@ -389,6 +407,12 @@ void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth);
 #define X509_V_FLAG_USE_DELTAS			0x2000
 /* Check selfsigned CA signature */
 #define X509_V_FLAG_CHECK_SS_SIGNATURE		0x4000
+/* Check revocation against OCSP */
+#define X509_V_FLAG_OCSP_CHECK			0x8000
+/* Check revocation against OCSP for whole chain */
+#define X509_V_FLAG_OCSP_CHECK_ALL		0x10000
+/* Disable OCSP nonce */
+#define X509_V_FLAG_OCSP_NO_NONCE		0x20000
 
 
 #define X509_VP_FLAG_DEFAULT			0x1
@@ -422,6 +446,11 @@ int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *pm);
 void X509_STORE_set_verify_cb(X509_STORE *ctx,
 				  int (*verify_cb)(int, X509_STORE_CTX *));
 
+#ifndef OPENSSL_NO_OCSP
+void X509_STORE_set_ocsp_process_resp(X509_STORE *ctx,
+				  ocsp_process_responder_f func);
+#endif
+
 X509_STORE_CTX *X509_STORE_CTX_new(void);
 
 int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x);
@@ -560,6 +589,13 @@ STACK_OF(POLICYQUALINFO) *
 const X509_POLICY_NODE *
 	X509_policy_node_get0_parent(const X509_POLICY_NODE *node);
 
+#ifndef OPENSSL_NO_OCSP
+X509_CERT_OCSP *X509_CERT_OCSP_new();
+void X509_CERT_OCSP_free(X509_CERT_OCSP *ocsp);
+int X509_CERT_OCSP_set1_url(X509_CERT_OCSP *ocsp, char* url);
+int X509_CERT_OCSP_set_validate(X509_CERT_OCSP *ocsp, int validate);
+#endif
+
 #ifdef  __cplusplus
 }
 #endif
diff --git a/crypto/x509/x509_vfy_ocsp.c b/crypto/x509/x509_vfy_ocsp.c
new file mode 100644
index 0000000..983923b
--- /dev/null
+++ b/crypto/x509/x509_vfy_ocsp.c
@@ -0,0 +1,394 @@
+/* crypto/x509/x509_vfy_ocsp.c */
+/* Copyright (C) 2012 Altell Ltd. ([email protected])
+ * All rights reserved.
+ *
+ * This file is a helper to incorporate OCSP check into X509
+ * certificate verification process.
+ * Written by Alexander Komyagin ([email protected]).
+ *
+ */
+
+#ifndef OPENSSL_NO_OCSP
+
+#include <openssl/crypto.h>
+#include <openssl/lhash.h>
+#include <openssl/buffer.h>
+#include <openssl/evp.h>
+#include <openssl/asn1.h>
+#include <openssl/x509.h>
+#include <openssl/ocsp.h>
+#include <openssl/ssl.h>
+#include <stdio.h>
+
+#include "x509_vfy_ocsp.h"
+
+static char *get_ocsp_url(X509 *x, STACK_OF(OPENSSL_STRING) **p_aia)
+{
+	STACK_OF(OPENSSL_STRING) *aia;
+
+	// ok, reading from the cert
+	aia = X509_get1_ocsp(x);
+
+	if (aia)
+	{
+		*p_aia = aia; //thou shalt not lose the given pointer
+		return sk_OPENSSL_STRING_value(aia, 0);
+	}
+
+	return NULL;
+}
+
+int check_cert_ocsp(X509_STORE_CTX *ctx)
+{
+	X509 *x;
+	int cnum;
+	int ok = 1;
+	cnum = ctx->error_depth;
+	x = sk_X509_value(ctx->chain, cnum);
+
+	ctx->current_cert = x;
+	ctx->current_issuer = NULL;
+	ctx->current_crl_score = 0;
+	ctx->current_reasons = 0;
+	ctx->error = 0;
+
+	STACK_OF(OPENSSL_STRING) *aia = NULL;
+	char *url = NULL;
+	char *host = NULL, *port = NULL, *path = NULL;
+	int use_ssl = -1;
+	X509 *px = NULL;
+	OCSP_REQUEST *req = NULL;
+	OCSP_RESPONSE *resp = NULL;
+	OCSP_CERTID *id = NULL;
+	STACK_OF(X509_EXTENSION) *exts;
+	int i;
+	OCSP_BASICRESP *bs = NULL;
+	int status, reason;
+	ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
+	X509_STORE *store = NULL;
+
+	// Get the issuer (must be the next cert in chain)
+	// We know that the last cert in chain is not checked,
+	// so NULL must be an error
+	px = sk_X509_value(ctx->chain, cnum+1);
+	if (! px)
+	{
+		ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT;
+		goto err1;
+	}
+
+	// See if we got any OCSP settings requested for this CA
+	if (px->ocsp)
+	{
+		// If ocsp is disabled for issuer, pretend everything is ok
+		if (px->ocsp->ocsp_validate == X509_OCSP_VALIDATE_DISABLED)
+		{
+			ctx->error = 0;
+			goto err1;
+		}
+
+		// Check if OCSP url is forced
+		if (px->ocsp->ocsp_url)
+			url = px->ocsp->ocsp_url;
+	}
+
+	// Check for embedded URL. According to RFC2560 (sect 3.1), issuer
+	// SHALL specify it in order to use OCSP.
+	if (! url)
+		url = get_ocsp_url(x, &aia);
+
+	// Build up OCSP query from certificate
+	if (! url)
+	{
+		ctx->error = X509_V_ERR_UNABLE_TO_FIND_OCSP_URL;
+		goto err1;
+	}
+
+	if (!OCSP_parse_url(url, &host, &port, &path, &use_ssl))
+	{
+		ctx->error = X509_V_ERR_UNPARSABLE_OCSP_URL;
+		goto err1;
+	}
+
+	//FIXME: ssl connection to OCSP responder is not supported yet
+	if (use_ssl)
+	{
+		ctx->error = X509_V_ERR_SSL_USED_FOR_OCSP;
+		goto err1;
+	}
+
+	req = OCSP_REQUEST_new();
+	if (!req)
+	{
+		ctx->error = X509_V_ERR_OUT_OF_MEM;
+		goto err1;
+	}
+
+	id = OCSP_cert_to_id(NULL, x, px);
+	if (!id)
+	{
+		DBG("Failed getting OCSP cert id");
+		ctx->error = X509_V_ERR_APPLICATION_VERIFICATION;
+		goto err1;
+	}
+
+	if (!OCSP_request_add0_id(req, id))
+	{
+		DBG("Failed adding id to request");
+		OCSP_CERTID_free(id); //otherwise id seems to be freed by req
+		ctx->error = X509_V_ERR_APPLICATION_VERIFICATION;
+		goto err1;
+	}
+
+	// Query server
+	if (! (ctx->param->flags & X509_V_FLAG_OCSP_NO_NONCE))
+		OCSP_request_add1_nonce(req, NULL, -1);
+
+	// If process func is not set it means ctx hadn't come from SSL_CTX,
+	// or it's a bug
+	if (!ctx->ctx->ocsp_process_responder)
+	{
+		ctx->error = X509_V_ERR_OCSP_PROCESS_FUNC_NOT_SET;
+		goto err1;
+	}
+
+	resp = (OCSP_RESPONSE *)ctx->ctx->ocsp_process_responder((void *)req, host, path, port, use_ssl, NULL, -1);
+	if (!resp)
+	{
+		DBG("OCSP responder processing failure");
+		ctx->error = X509_V_ERR_APPLICATION_VERIFICATION;
+		goto err1;
+	}
+
+	i = OCSP_response_status(resp);
+
+	if (i != OCSP_RESPONSE_STATUS_SUCCESSFUL)
+	{
+		DBG("Responder Error: %s (%d)",
+				OCSP_response_status_str(i), i);
+		ctx->error = X509_V_ERR_OCSP_RESPONDER_STATUS_FAIL;
+		goto err1;
+	}
+
+	bs = OCSP_response_get1_basic(resp);
+	if (!bs)
+	{
+		DBG("Error parsing response");
+		ctx->error = X509_V_ERR_APPLICATION_VERIFICATION;
+		goto err1;
+	}
+
+	// Validate responder
+	store = ctx->ctx;
+	if(!store)
+	{
+		DBG("Error getting store!");
+		ctx->error = X509_V_ERR_APPLICATION_VERIFICATION;
+		goto err1;
+	}
+
+	if (! (ctx->param->flags & X509_V_FLAG_OCSP_NO_NONCE))
+	{
+		i = OCSP_check_nonce(req, bs);
+		if (i == -1)
+			DBG("WARNING: no nonce in response");
+		else if (i <= 0)
+		{
+			ctx->error = X509_V_ERR_OCSP_NONCE_VERIFY_ERROR;
+			goto err1;
+		}
+	}
+
+	i = OCSP_basic_verify(bs, NULL, store, 0);
+	if(i <= 0)
+	{
+		ctx->error = X509_V_ERR_OCSP_RESPONSE_VERIFICATION;
+		goto err1;
+	}
+	else
+		DBG("Response verify OK\n");
+
+	// Get response status
+	if(!OCSP_resp_find_status(bs, id, &status, &reason,
+					&rev, &thisupd, &nextupd))
+	{
+		DBG("ERROR: No Status found in OCSP response.");
+		ctx->error = X509_V_ERR_APPLICATION_VERIFICATION;
+		goto err1;
+	}
+
+	DBG("Status: %s", OCSP_cert_status_str(status));
+
+	switch(status)
+	{
+		case V_OCSP_CERTSTATUS_GOOD:
+			ctx->error = 0;
+			break;
+		case V_OCSP_CERTSTATUS_REVOKED:
+			ctx->error = X509_V_ERR_CERT_REVOKED;
+			break;
+		case V_OCSP_CERTSTATUS_UNKNOWN:
+		default:
+			ctx->error = X509_V_ERR_CERT_UNKNOWN;
+	}
+
+err1:
+	//call verify callback if needed
+	if (ctx->error != 0)
+		ok = ctx->verify_cb(0, ctx);
+
+	//free occupied resources
+	if (aia)
+		X509_email_free(aia);
+	if (host)
+		OPENSSL_free(host);
+	if (path)
+		OPENSSL_free(path);
+	if (port)
+		OPENSSL_free(port);
+	if (req)
+		OCSP_REQUEST_free(req);
+	if (resp)
+		OCSP_RESPONSE_free(resp);
+	if (bs)
+		OCSP_BASICRESP_free(bs);
+
+	return ok;
+}
+
+int check_revocation_ocsp(X509_STORE_CTX *ctx)
+{
+	int i, last, ok;
+
+	DBG("check_revocation_ocsp: Here");
+
+	if (!(ctx->param->flags & X509_V_FLAG_OCSP_CHECK))
+		return 1;
+
+	if (ctx->param->purpose == X509_PURPOSE_OCSP_HELPER)
+	{
+		DBG("OCSP won't verify itself ;)");
+		return 1;
+	}
+
+	if (ctx->param->flags & X509_V_FLAG_OCSP_CHECK_ALL)
+		last = sk_X509_num(ctx->chain) - 1;
+	else
+	{
+		// If checking CRL paths this isn't the EE certificate
+		if (ctx->parent)
+			return 1;
+		last = 0;
+	}
+
+	// Note that we won't check the last cert in chain, since it makes
+	// little sense to check revocation status for the self-signed 
+	// root certificate ;)
+	for(i = 0; i < last; i++)
+	{
+		ctx->error_depth = i;
+		ok = check_cert_ocsp(ctx);
+		if (!ok) return ok;
+	}
+	return 1;
+}
+
+int X509_set_cert_ocsp_opt(X509_STORE *cert_ctx, const char *name,
+                           const char *ocsp_url, const int ocsp_validate)
+{
+	FILE *fp = NULL;
+    X509 *x = NULL;
+    int ret = 1;
+    X509_OBJECT *obj = NULL;
+
+    X509_OBJECT *obj_orig = NULL;
+    X509_CERT_OCSP *ocsp = NULL;
+    X509 *cert = NULL;
+
+	if (!cert_ctx || !name)
+	{
+		ret = 0;
+		goto err;
+	}
+
+	// check the value before it goes down the hill
+	if ((ocsp_validate != X509_OCSP_VALIDATE_ENABLED) &&
+	    (ocsp_validate != X509_OCSP_VALIDATE_DISABLED))
+	{
+		DBG("Bad ocsp_validate value");
+		ret = 0;
+		goto err;
+	}
+
+	// read cert file
+	fp = fopen(name, "r");
+	// is it PEM?
+	x = PEM_read_X509_AUX(fp, NULL, NULL, NULL);
+	if (!x)
+	{
+		// or maybe DER?
+		x = d2i_X509_fp(fp, NULL);
+	}
+
+	if (!x) //whatever...
+	{
+		DBG("Failed to parse cert %s", name);
+		ret = 0;
+		goto err;
+	}
+
+	obj=(X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT));
+	if (!obj)
+	{
+		DBG("Failed to allocate object");
+		ret = 0;
+		goto err;
+	}
+
+	obj->type = X509_LU_X509;
+	obj->data.x509 = x;
+
+	X509_OBJECT_up_ref_count(obj);
+
+	// try to find it in store
+	obj_orig = X509_OBJECT_retrieve_match(cert_ctx->objs, obj);
+	if (! obj_orig)
+	{
+		DBG("Can't find cert in store");
+		ret = 0;
+		goto err;
+	}
+	cert = obj_orig->data.x509;
+
+	// create ocsp struct, fill and save it
+	ocsp = X509_CERT_OCSP_new();
+	if (!ocsp)
+	{
+		DBG("Failed allocating ocsp struct");
+		ret = 0;
+		goto err;
+	}
+
+	if (! X509_CERT_OCSP_set1_url(ocsp, ocsp_url))
+	{
+		DBG("Failed setting ocsp_url");
+	}
+
+	if (! X509_CERT_OCSP_set_validate(ocsp, ocsp_validate))
+	{
+		DBG("Failed setting ocsp_validate");
+	}
+
+	ret = X509_set0_ocsp(cert, ocsp);
+
+err:
+	if(x)
+		X509_free(x);
+	if(obj)
+		OPENSSL_free(obj);
+	if(fp)
+		fclose(fp);
+
+	return ret;
+}
+#endif
diff --git a/crypto/x509/x509_vfy_ocsp.h b/crypto/x509/x509_vfy_ocsp.h
new file mode 100644
index 0000000..8a79d82
--- /dev/null
+++ b/crypto/x509/x509_vfy_ocsp.h
@@ -0,0 +1,54 @@
+/* crypto/x509/x509_vfy_ocsp.c */
+/* Copyright (C) 2012 Altell Ltd. ([email protected])
+ * All rights reserved.
+ *
+ * This file is a helper to incorporate OCSP check into X509
+ * certificate verification process.
+ * Written by Alexander Komyagin ([email protected]).
+ * 
+ */
+
+
+#ifndef OPENSSL_NO_OCSP
+
+#ifndef HEADER_X509_VFY_OCSP_H
+#define HEADER_X509_VFY_OCSP_H
+
+#ifndef HEADER_X509_H
+#include <openssl/x509.h>
+#endif
+
+//#define OCSP_VFY_DEBUG
+
+#ifdef OCSP_VFY_DEBUG
+  #include <syslog.h>
+  #define DBG(fmt, args...) do { syslog(LOG_INFO, "%s(%d): " fmt, __FUNCTION__, __LINE__, ##args); } while(0)
+#else
+  #define DBG(fmt, args...) do { /* NOP */ } while(0)
+#endif //OCSP_VFY_DEBUG
+
+#define X509_OCSP_VALIDATE_ENABLED 	0
+#define X509_OCSP_VALIDATE_DISABLED	1
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+		
+typedef void * (*ocsp_process_responder_f)(void *,
+			char *, char *, char *, int,
+			void *,
+			int);
+
+int X509_set_cert_ocsp_opt(X509_STORE *cert_ctx, const char *name, 
+							const char *ocsp_url, const int ocsp_validate);
+
+int check_cert_ocsp(X509_STORE_CTX *ctx);
+int check_revocation_ocsp(X509_STORE_CTX *ctx);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif //HEADER_X509_VFY_OCSP_H
+
+#endif //OPENSSL_NO_OCSP
diff --git a/include/openssl/ocsp_clnt.h b/include/openssl/ocsp_clnt.h
new file mode 120000
index 0000000..137121b
--- /dev/null
+++ b/include/openssl/ocsp_clnt.h
@@ -0,0 +1 @@
+../../ssl/ocsp_clnt.h
\ No newline at end of file
diff --git a/include/openssl/x509_vfy_ocsp.h b/include/openssl/x509_vfy_ocsp.h
new file mode 120000
index 0000000..f53b4a1
--- /dev/null
+++ b/include/openssl/x509_vfy_ocsp.h
@@ -0,0 +1 @@
+../../crypto/x509/x509_vfy_ocsp.h
\ No newline at end of file
diff --git a/ssl/Makefile b/ssl/Makefile
index 07e4028..afb486c 100644
--- a/ssl/Makefile
+++ b/ssl/Makefile
@@ -30,7 +30,7 @@ LIBSRC=	\
 	ssl_lib.c ssl_err2.c ssl_cert.c ssl_sess.c \
 	ssl_ciph.c ssl_stat.c ssl_rsa.c \
 	ssl_asn1.c ssl_txt.c ssl_algs.c \
-	bio_ssl.c ssl_err.c kssl.c tls_srp.c t1_reneg.c
+	bio_ssl.c ssl_err.c kssl.c tls_srp.c t1_reneg.c ocsp_clnt.c
 LIBOBJ= \
 	s2_meth.o  s2_srvr.o  s2_clnt.o  s2_lib.o  s2_enc.o s2_pkt.o \
 	s3_meth.o  s3_srvr.o  s3_clnt.o  s3_lib.o  s3_enc.o s3_pkt.o s3_both.o \
@@ -41,11 +41,11 @@ LIBOBJ= \
 	ssl_lib.o ssl_err2.o ssl_cert.o ssl_sess.o \
 	ssl_ciph.o ssl_stat.o ssl_rsa.o \
 	ssl_asn1.o ssl_txt.o ssl_algs.o \
-	bio_ssl.o ssl_err.o kssl.o tls_srp.o t1_reneg.o
+	bio_ssl.o ssl_err.o kssl.o tls_srp.o t1_reneg.o ocsp_clnt.o
 
 SRC= $(LIBSRC)
 
-EXHEADER= ssl.h ssl2.h ssl3.h ssl23.h tls1.h dtls1.h kssl.h srtp.h
+EXHEADER= ssl.h ssl2.h ssl3.h ssl23.h tls1.h dtls1.h kssl.h srtp.h ocsp_clnt.h
 HEADER=	$(EXHEADER) ssl_locl.h kssl_lcl.h
 
 ALL=    $(GENERAL) $(SRC) $(HEADER)
diff --git a/ssl/ocsp_clnt.c b/ssl/ocsp_clnt.c
new file mode 100644
index 0000000..bb40c9a
--- /dev/null
+++ b/ssl/ocsp_clnt.c
@@ -0,0 +1,184 @@
+/* ssl/ocsp_clnt.c */
+/* Copyright (C) 2012 Altell Ltd. ([email protected])
+ * All rights reserved.
+ *
+ * This file is a helper to incorporate OCSP proto into libssl.
+ * Written by Alexander Komyagin ([email protected]).
+ * 
+ */
+
+#ifndef OPENSSL_NO_OCSP
+ 
+#include <openssl/crypto.h>
+#include <openssl/lhash.h>
+#include <openssl/buffer.h>
+#include <openssl/evp.h>
+#include <openssl/asn1.h>
+#include <openssl/ocsp.h>
+#include <openssl/ssl.h>
+#include <stdio.h>
+
+#ifdef OPENSSL_SYSNAME_WIN32
+#  define openssl_fdset(a,b) FD_SET((unsigned int)a, b)
+#else
+#  define openssl_fdset(a,b) FD_SET(a, b)
+#endif
+
+static OCSP_RESPONSE *query_responder(BIO *cbio, char *path,
+				STACK_OF(CONF_VALUE) *headers,
+				OCSP_REQUEST *req, int req_timeout)
+{
+	int fd;
+	int rv;
+	int i;
+	OCSP_REQ_CTX *ctx = NULL;
+	OCSP_RESPONSE *rsp = NULL;
+	fd_set confds;
+	struct timeval tv;
+
+	if (req_timeout != -1)
+		BIO_set_nbio(cbio, 1);
+
+	rv = BIO_do_connect(cbio);
+
+	if ((rv <= 0) && ((req_timeout == -1) || !BIO_should_retry(cbio)))
+	{
+		DBG("Error connecting BIO");
+		return NULL;
+	}
+
+	if (BIO_get_fd(cbio, &fd) <= 0)
+	{
+		DBG("Can't get connection fd");
+		goto err;
+	}
+
+	if (req_timeout != -1 && rv <= 0)
+	{
+		FD_ZERO(&confds);
+		openssl_fdset(fd, &confds);
+		tv.tv_usec = 0;
+		tv.tv_sec = req_timeout;
+		rv = select(fd + 1, NULL, (void *)&confds, NULL, &tv);
+		if (rv == 0)
+		{
+			DBG("Timeout on connect");
+			return NULL;
+		}
+	}
+
+	ctx = OCSP_sendreq_new(cbio, path, NULL, -1);
+	if (!ctx)
+	{
+		DBG("OCSP_sendreq_new failed");
+		return NULL;
+	}
+
+	for (i = 0; i < sk_CONF_VALUE_num(headers); i++)
+	{
+		CONF_VALUE *hdr = sk_CONF_VALUE_value(headers, i);
+		if (!OCSP_REQ_CTX_add1_header(ctx, hdr->name, hdr->value))
+		{
+			DBG("OCSP_REQ_CTX_add1_header failed");
+			goto err;
+		}
+	}
+
+	if (!OCSP_REQ_CTX_set1_req(ctx, req))
+	{
+		DBG("OCSP_REQ_CTX_set1_req failed");
+		goto err;
+	}
+	
+	for (;;)
+	{
+		rv = OCSP_sendreq_nbio(&rsp, ctx);
+		if (rv != -1)
+			break;
+		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(cbio))
+			rv = select(fd + 1, (void *)&confds, NULL, NULL, &tv);
+		else if (BIO_should_write(cbio))
+			rv = select(fd + 1, NULL, (void *)&confds, NULL, &tv);
+		else
+		{
+			DBG("Unexpected retry condition");
+			goto err;
+		}
+		if (rv == 0)
+		{
+			DBG("Timeout on request");
+			break;
+		}
+		if (rv == -1)
+		{
+			DBG("Select error");
+			break;
+		}
+
+	}
+err:
+	
+	if (ctx)
+		OCSP_REQ_CTX_free(ctx);
+
+	return rsp;
+}
+	
+void *ocsp_process_responder(void *_req,
+			char *host, char *path, char *port, int use_ssl,
+			void *_headers,
+			int req_timeout)
+{
+	BIO *cbio = NULL;
+	SSL_CTX *ctx = NULL;
+	OCSP_RESPONSE *resp = NULL;
+	OCSP_REQUEST *req = (OCSP_REQUEST *)_req;
+	STACK_OF(CONF_VALUE) *headers = (STACK_OF(CONF_VALUE) *)_headers;
+	cbio = BIO_new_connect(host);
+	if (!cbio)
+	{
+		DBG("Error creating connect BIO");
+		goto end;
+	}
+	if (port) BIO_set_conn_port(cbio, port);
+	if (use_ssl == 1)
+	{
+		BIO *sbio;
+#if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3)
+		ctx = SSL_CTX_new(SSLv23_client_method());
+#elif !defined(OPENSSL_NO_SSL3)
+		ctx = SSL_CTX_new(SSLv3_client_method());
+#elif !defined(OPENSSL_NO_SSL2)
+		ctx = SSL_CTX_new(SSLv2_client_method());
+#else
+		DBG("SSL is disabled");
+		goto end;
+#endif
+		if (ctx == NULL)
+		{
+			DBG("Error creating SSL context");
+			goto end;
+		}
+		SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
+		sbio = BIO_new_ssl(ctx, 1);
+		cbio = BIO_push(sbio, cbio);
+	}
+	resp = query_responder(cbio, path, headers, req, req_timeout);
+	if (!resp)
+		DBG("Error querying OCSP responsder");
+
+end:
+	if (cbio)
+		BIO_free_all(cbio);
+	if (ctx)
+		SSL_CTX_free(ctx);
+	return (void *)resp;
+}
+
+#endif
diff --git a/ssl/ocsp_clnt.h b/ssl/ocsp_clnt.h
new file mode 100644
index 0000000..46f2f1e
--- /dev/null
+++ b/ssl/ocsp_clnt.h
@@ -0,0 +1,46 @@
+/* ssl/ocsp_clnt.h */
+/* Copyright (C) 2012 Altell Ltd. ([email protected])
+ * All rights reserved.
+ *
+ * This file is a helper to incorporate OCSP check into X509
+ * certificate verification process.
+ * Written by Alexander Komyagin ([email protected]).
+ * 
+ */
+
+
+#ifndef OPENSSL_NO_OCSP
+
+#ifndef HEADER_OCSP_CLNT_H
+#define HEADER_OCSP_CLNT_H
+
+#ifndef HEADER_X509_H
+#include <openssl/x509.h>
+#endif
+
+#include <openssl/ocsp.h>
+#include <openssl/x509_vfy_ocsp.h>
+
+#ifdef OCSP_VFY_DEBUG
+  #include <syslog.h>
+  #define DBG(fmt, args...) do { syslog(LOG_INFO, "%s(%d): " fmt, __FUNCTION__, __LINE__, ##args); } while(0)
+#else
+  #define DBG(fmt, args...) do { /* NOP */ } while(0)
+#endif //OCSP_VFY_DEBUG
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+void *ocsp_process_responder(void *_req,
+			char *host, char *path, char *port, int use_ssl,
+			void *_headers,
+			int req_timeout);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif //HEADER_OCSP_CLNT_H
+
+#endif //OPENSSL_NO_OCSP
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index f82d071..4808f62 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -160,6 +160,10 @@
 #include <openssl/engine.h>
 #endif
 
+#ifndef OPENSSL_NO_OCSP
+#include <openssl/ocsp_clnt.h>
+#endif
+
 const char *SSL_version_str=OPENSSL_VERSION_TEXT;
 
 SSL3_ENC_METHOD ssl3_undef_enc_method={
@@ -1758,6 +1762,9 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
 	if (ret->sessions == NULL) goto err;
 	ret->cert_store=X509_STORE_new();
 	if (ret->cert_store == NULL) goto err;
+#ifndef OPENSSL_NO_OCSP
+	X509_STORE_set_ocsp_process_resp(ret->cert_store, &ocsp_process_responder);
+#endif
 
 	ssl_create_cipher_list(ret->method,
 		&ret->cipher_list,&ret->cipher_list_by_id,

Reply via email to