Hi! Attached patch seamlessly integrates OCSP client functionality into
OpenSSL verification routines -- the thing OpenSSL currently missing.

This patch makes it possible for every app that uses OpenSSL for SSL/TLS
connections -- like racoon, openldap, openvpn -- to check certificates
against OCSP responder without any redesign. OCSP checks are
incorporated in the internal certificate revocation check procedure
(just like CRL's check) -- as they should be.

=========================
Easy to use:

Assuming your certificates have embedded OCSP responder URLs, you just
need to add call to

X509_STORE_set_flags(some_x509_store, X509_V_FLAG_OCSP_CHECK);

after you have created SSL_CTX (so you can access X509_STORE object).
Then optionally you can add check for X509_V_ERR_CERT_UNKNOWN
verification status in your SSL verification callback.

=========================
API follows:

1) 2 new verification flags (to use with X509_STORE_set_flags() and
X509_STORE_CTX_set_flags()):
  - X509_V_FLAG_OCSP_CHECK [enable OCSP checks]
  - X509_V_FLAG_OCSP_CHECK_ALL [check the whole chain]

These controls are main and this way OCSP is fully controlled by global
OpenSSL verification parameters.

2) Special OCSP (X509_CERT_OCSP) opts struct with 2 fields added to X509
certificate:
  - char* ocsp_url [forced OCSP responder URL for this cert]
  - int ocsp_validate [enable/disable OCSP check for this cert, enabled
by default]

3) cool stuff!
  - int X509_set_cert_ocsp_opt(X509_STORE *cert_ctx, const char *name,
                        const char *ocsp_url, const int ocsp_validate)
  [ this one sets above-mentioned OCSP options for some cert given it's
filename. Corresponding X509 structure shall be already present in the
cert_ctx. Very handy one.]

=========================
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,10 @@ int MAIN(int argc, char **argv)
 	X509_STORE *cert_ctx=NULL;
 	X509_LOOKUP *lookup=NULL;
 	X509_VERIFY_PARAM *vpm = NULL;
+#ifndef OPENSSL_NO_OCSP
+	char *ocsp_url = NULL;
+	int ocsp_validate = X509_OCSP_VALIDATE_ENABLED;
+#endif
 #ifndef OPENSSL_NO_ENGINE
 	char *engine=NULL;
 #endif
@@ -95,6 +101,9 @@ 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);
+#ifndef OPENSSL_NO_OCSP
+	X509_STORE_set_ocsp_process_resp(cert_ctx, &ocsp_process_responder);
+#endif
 
 	ERR_load_crypto_strings();
 
@@ -123,6 +132,18 @@ int MAIN(int argc, char **argv)
 				if (argc-- < 1) goto end;
 				CAfile= *(++argv);
 				}
+#ifndef OPENSSL_NO_OCSP
+			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));
+				}
+#endif
 			else if (args_verify(&argv, &argc, &badarg, bio_err,
 									&vpm))
 				{
@@ -222,6 +243,20 @@ int MAIN(int argc, char **argv)
 			goto end;
 		}
 
+#ifndef OPENSSL_NO_OCSP
+	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");
+	}
+#endif
+
 	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..787fdf5 100644
--- a/crypto/x509/x509_txt.c
+++ b/crypto/x509/x509_txt.c
@@ -183,6 +183,8 @@ 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");
 
 	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..298eaf9 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,9 @@ 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
+
 /* Certificate verify flags */
 
 /* Send issuer+subject checks to verify_cb */
@@ -389,6 +400,10 @@ 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
 
 
 #define X509_VP_FLAG_DEFAULT			0x1
@@ -422,6 +437,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 +580,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..d879eb8
--- /dev/null
+++ b/crypto/x509/x509_vfy_ocsp.c
@@ -0,0 +1,422 @@
+/* crypto/x509/x509_vfy_ocsp.c */
+/* Copyright (C) 2012 Altell Ltd. (komya...@altell.ru)
+ * All rights reserved.
+ *
+ * This file is a helper to incorporate OCSP check into X509
+ * certificate verification process.
+ * Written by Alexander Komyagin (komya...@altell.ru).
+ *
+ */
+
+#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;
+
+	/* try to get forced url */
+	if (x->ocsp && x->ocsp->ocsp_url)
+		return x->ocsp->ocsp_url;
+
+	/* 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;
+
+	DBG("check_cert_ocsp: Checking certificate %d", cnum);
+
+	STACK_OF(OPENSSL_STRING) *aia = NULL;
+	char *url;
+	char *host = NULL, *port = NULL, *path = NULL;
+	int use_ssl = -1;
+	X509_OBJECT obj;
+	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;
+
+	DBG("OCSP START!");
+
+	// Build up OCSP query from certificate
+	url = get_ocsp_url(x, &aia);
+	// can't figure out the url, will look for the issuer
+	if (! url)
+	{
+		DBG("cert_status: Looking for the issuer's OCSP url.\n");
+
+		if (X509_STORE_get_by_subject(ctx,X509_LU_X509,
+				X509_get_issuer_name(x),&obj) <= 0)
+		{
+			DBG("cert_status: Can't retrieve issuer certificate.\n");
+			ctx->error = X509_V_ERR_APPLICATION_VERIFICATION;
+			goto err1;
+		}
+
+		px = obj.data.x509;
+		// If ocsp is disabled for issuer, pretend everything is ok
+		if (px->ocsp && (px->ocsp->ocsp_validate == X509_OCSP_VALIDATE_DISABLED))
+		{
+			DBG("cert_status: OCSP is disabled for issuer's cert, ignoring");
+			ctx->error = 0;
+			goto err1;
+		}
+
+		url = get_ocsp_url(px, &aia);
+
+		//you gave love a bad name
+		if (! url)
+		{
+			DBG("cert_status: Can't find any OCSP responder URL.\n");
+			ctx->error = X509_V_ERR_APPLICATION_VERIFICATION;
+			goto err1;
+		}
+	}
+
+	if (!OCSP_parse_url(url, &host, &port, &path, &use_ssl))
+	{
+		DBG("cert_status: can't parse default URL");
+		ctx->error = X509_V_ERR_APPLICATION_VERIFICATION;
+		goto err1;
+	}
+
+	DBG("Host: %s, port: %s, use_ssl: %d", host, port, use_ssl);
+
+	//FIXME: ssl connection to OCSP responder is not supported yet
+	if (use_ssl)
+	{
+		DBG("ssl connection to OCSP responder is not supported yet");
+		ctx->error = X509_V_ERR_APPLICATION_VERIFICATION;
+		goto err1;
+	}
+
+	// get issuer if haven't done it already
+	if (! px)
+	{
+		if (X509_STORE_get_by_subject(ctx,X509_LU_X509,
+					X509_get_issuer_name(x),&obj) <= 0)
+		{
+			DBG("cert_status: Can't retrieve issuer certificate.\n");
+			ctx->error = X509_V_ERR_APPLICATION_VERIFICATION;
+			goto err1;
+		}
+
+		px = obj.data.x509;
+	}
+
+	req = OCSP_REQUEST_new();
+	if (!req)
+	{
+		DBG("Failed allocating new request");
+		ctx->error = X509_V_ERR_APPLICATION_VERIFICATION;
+		goto err1;
+	}
+
+	id = OCSP_cert_to_id(NULL, x, obj.data.x509);
+	if (!id)
+	{
+		DBG("Failed getting OCSP certificate id");
+		ctx->error = X509_V_ERR_APPLICATION_VERIFICATION;
+		goto err1;
+	}
+
+	if (!OCSP_request_add0_id(req, id))
+	{
+		DBG("Failed adding id to OCSP request");
+		OCSP_CERTID_free(id); //otherwise id seems to be freed by req
+		ctx->error = X509_V_ERR_APPLICATION_VERIFICATION;
+		goto err1;
+	}
+
+	// Query server
+	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)
+	{
+		DBG("ocsp_process_responder function is not set");
+		ctx->error = X509_V_ERR_APPLICATION_VERIFICATION;
+		goto err1;
+	}
+
+	resp = (OCSP_RESPONSE *)ctx->ctx->ocsp_process_responder((void *)req, host, path, port, use_ssl, NULL, -1);
+	if (!resp)
+	{
+		DBG("Failed processing responder");
+		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_APPLICATION_VERIFICATION;
+		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;
+	}
+
+	i = OCSP_check_nonce(req, bs);
+	if (i == -1)
+		DBG("WARNING: no nonce in response");
+	else if (i <= 0)
+	{
+		DBG("Nonce Verify error");
+		ctx->error = X509_V_ERR_APPLICATION_VERIFICATION;
+		goto err1;
+	}
+
+	i = OCSP_basic_verify(bs, NULL, store, 0);
+	if(i <= 0)
+	{
+		DBG("Response Verify Failure");
+		ctx->error = X509_V_ERR_APPLICATION_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.");
+		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;
+	}
+
+	DBG("OCSP OK!");
+
+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 (px)
+		X509_free(px);
+	if (req)
+		OCSP_REQUEST_free(req);
+	if (resp)
+		OCSP_RESPONSE_free(resp);
+	if (bs)
+		OCSP_BASICRESP_free(bs);
+
+	DBG("OCSP FINISHED!");
+
+	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;
+	}
+
+	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..a9e34a9
--- /dev/null
+++ b/crypto/x509/x509_vfy_ocsp.h
@@ -0,0 +1,50 @@
+/* crypto/x509/x509_vfy_ocsp.c */
+/* Copyright (C) 2012 Altell Ltd. (komya...@altell.ru)
+ * All rights reserved.
+ *
+ * This file is a helper to incorporate OCSP check into X509
+ * certificate verification process.
+ * Written by Alexander Komyagin (komya...@altell.ru).
+ * 
+ */
+
+
+#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
+
+#include <syslog.h>
+
+//#define DBG(fmt, args...) do { syslog(LOG_INFO, "%s(%d): " fmt, __FUNCTION__, __LINE__, ##args); } while(0)
+#define DBG(fmt, args...) do { /* NOP */ } while(0)
+
+#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. (komya...@altell.ru)
+ * All rights reserved.
+ *
+ * This file is a helper to incorporate OCSP proto into libssl.
+ * Written by Alexander Komyagin (komya...@altell.ru).
+ * 
+ */
+
+#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..eb09cec
--- /dev/null
+++ b/ssl/ocsp_clnt.h
@@ -0,0 +1,43 @@
+/* ssl/ocsp_clnt.h */
+/* Copyright (C) 2012 Altell Ltd. (komya...@altell.ru)
+ * All rights reserved.
+ *
+ * This file is a helper to incorporate OCSP check into X509
+ * certificate verification process.
+ * Written by Alexander Komyagin (komya...@altell.ru).
+ * 
+ */
+
+
+#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>
+#include <syslog.h>
+
+//#define DBG(fmt, args...) do { syslog(LOG_INFO, "%s(%d): " fmt, __FUNCTION__, __LINE__, ##args); } while(0)
+#define DBG(fmt, args...) do { /* NOP */ } while(0)
+
+#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