+# ifndef DISABLE_OCSP
+
+static STACK_OF(X509) *
+chain_from_pem_file(const uschar * file)
+{
+BIO * bp;
+X509 * x;
+STACK_OF(X509) * sk;
+
+if (!(sk = sk_X509_new_null())) return NULL;
+if (!(bp = BIO_new_file(CS file, "r"))) return NULL;
+while ((x = PEM_read_bio_X509(bp, NULL, 0, NULL)))
+ sk_X509_push(sk, x);
+BIO_free(bp);
+return sk;
+}
+
+
+
+static void
+cert_stack_free(STACK_OF(X509) * sk)
+{
+while (sk_X509_num(sk) > 0) (void) sk_X509_pop(sk);
+sk_X509_free(sk);
+}
+
+
+static int
+tls_client_stapling_cb(SSL *s, void *arg)
+{
+const unsigned char *p;
+int len;
+OCSP_RESPONSE *rsp;
+OCSP_BASICRESP *bs;
+STACK_OF(X509) * sk;
+int ret = 1;
+
+len = SSL_get_tlsext_status_ocsp_resp(s, &p);
+/*BIO_printf(arg, "OCSP response: ");*/
+if (!p)
+ {
+ BIO_printf(arg, "no response received\n");
+ return 1;
+ }
+if(!(rsp = d2i_OCSP_RESPONSE(NULL, &p, len)))
+ {
+ BIO_printf(arg, "response parse error\n");
+ BIO_dump_indent(arg, (char *)p, len, 4);
+ return 0;
+ }
+if(!(bs = OCSP_response_get1_basic(rsp)))
+ {
+ BIO_printf(arg, "error parsing response\n");
+ return 0;
+ }
+
+
+if (!(sk = chain_from_pem_file(ocsp_stapling)))
+ {
+ BIO_printf(arg, "error in cert setup\n");
+ return 0;
+ }
+
+/* OCSP_basic_verify takes a "store" arg, but does not
+use it for the chain verification, which is all we do
+when OCSP_NOVERIFY is set. The content from the wire
+(in "bs") and a cert-stack "sk" are all that is used. */
+
+if(OCSP_basic_verify(bs, sk, NULL, OCSP_NOVERIFY) <= 0)
+ {
+ BIO_printf(arg, "Response Verify Failure\n");
+ ERR_print_errors(arg);
+ ret = 0;
+ }
+else
+ BIO_printf(arg, "Response verify OK\n");
+
+cert_stack_free(sk);
+return ret;
+}
+# endif /*DISABLE_OCSP*/
+
+