static int cert_status_cb(SSL *s, void *arg)
	{
	tlsextstatusctx *srctx = arg;
	BIO *err = srctx->err;
	char *host, *port, *path;
	int use_ssl;
	unsigned char *rspder = NULL;
	int rspderlen;
	STACK_OF(OPENSSL_STRING) *aia = NULL;
	X509 *x = NULL;
	X509_STORE_CTX inctx;
	X509_OBJECT obj;
	OCSP_REQUEST *req = NULL;
	OCSP_RESPONSE *resp = NULL;
	OCSP_CERTID *id = NULL;
	STACK_OF(X509_EXTENSION) *exts;
	int ret = SSL_TLSEXT_ERR_NOACK;
	int i;
#if 0
STACK_OF(OCSP_RESPID) *ids;
SSL_get_tlsext_status_ids(s, &ids);
BIO_printf(err, "cert_status: received %d ids\n", sk_OCSP_RESPID_num(ids));
#endif
	if (srctx->verbose)
		BIO_puts(err, "cert_status: callback called\n");
	x = SSL_get_certificate(s);
	aia = X509_get1_ocsp(x);
	if (aia)
		{
		if (!OCSP_parse_url(sk_OPENSSL_STRING_value(aia, 0),
			&host, &port, &path, &use_ssl))
			{
			BIO_puts(err, "cert_status: can't parse AIA URL\n");
			goto err;
			}
		if (srctx->verbose)
			BIO_printf(err, "cert_status: AIA URL: %s\n",
					sk_OPENSSL_STRING_value(aia, 0));
		}
	else
		{
		if (!srctx->host)
			{
			BIO_puts(srctx->err, "cert_status: no AIA and no default responder URL\n");
			goto done;
			}
		host = srctx->host;
		path = srctx->path;
		port = srctx->port;
		use_ssl = srctx->use_ssl;
		}
	if (!X509_STORE_CTX_init(&inctx,
				SSL_CTX_get_cert_store(SSL_get_SSL_CTX(s)),
				NULL, NULL))
		goto err;
	if (X509_STORE_get_by_subject(&inctx,X509_LU_X509,
				X509_get_issuer_name(x),&obj) <= 0)
		{
		BIO_puts(err, "cert_status: Can't retrieve issuer certificate.\n");
		X509_STORE_CTX_cleanup(&inctx);
		goto done;
		}
	req = OCSP_REQUEST_new();
	if (!req)
		goto err;
	id = OCSP_cert_to_id(NULL, x, obj.data.x509);
	X509_free(obj.data.x509);
	X509_STORE_CTX_cleanup(&inctx);
	if (!id)
		goto err;
	if (!OCSP_request_add0_id(req, id))
		goto err;
	id = NULL;
	SSL_get_tlsext_status_exts(s, &exts);
	for (i = 0; i < sk_X509_EXTENSION_num(exts); i++)
		{
		X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i);
		if (!OCSP_REQUEST_add_ext(req, ext, -1))
			goto err;
		}
	resp = process_responder(err, req, host, path, port, use_ssl, NULL,
					srctx->timeout);
	if (!resp)
		{
		BIO_puts(err, "cert_status: error querying responder\n");
		goto done;
		}
	rspderlen = i2d_OCSP_RESPONSE(resp, &rspder);
	if (rspderlen <= 0)
		goto err;
	SSL_set_tlsext_status_ocsp_resp(s, rspder, rspderlen);
	if (srctx->verbose)
		{
		BIO_puts(err, "cert_status: ocsp response sent:\n");
		OCSP_RESPONSE_print(err, resp, 2);
		}
	ret = SSL_TLSEXT_ERR_OK;
	done:
	if (ret != SSL_TLSEXT_ERR_OK)
		ERR_print_errors(err);
	if (aia)
		{
		OPENSSL_free(host);
		OPENSSL_free(path);
		OPENSSL_free(port);
		X509_email_free(aia);
		}
	if (id)
		OCSP_CERTID_free(id);
	if (req)
		OCSP_REQUEST_free(req);
	if (resp)
		OCSP_RESPONSE_free(resp);
	return ret;
	err:
	ret = SSL_TLSEXT_ERR_ALERT_FATAL;
	goto done;
	}
['static int cert_status_cb(SSL *s, void *arg)\n\t{\n\ttlsextstatusctx *srctx = arg;\n\tBIO *err = srctx->err;\n\tchar *host, *port, *path;\n\tint use_ssl;\n\tunsigned char *rspder = NULL;\n\tint rspderlen;\n\tSTACK_OF(OPENSSL_STRING) *aia = NULL;\n\tX509 *x = NULL;\n\tX509_STORE_CTX inctx;\n\tX509_OBJECT obj;\n\tOCSP_REQUEST *req = NULL;\n\tOCSP_RESPONSE *resp = NULL;\n\tOCSP_CERTID *id = NULL;\n\tSTACK_OF(X509_EXTENSION) *exts;\n\tint ret = SSL_TLSEXT_ERR_NOACK;\n\tint i;\n#if 0\nSTACK_OF(OCSP_RESPID) *ids;\nSSL_get_tlsext_status_ids(s, &ids);\nBIO_printf(err, "cert_status: received %d ids\\n", sk_OCSP_RESPID_num(ids));\n#endif\n\tif (srctx->verbose)\n\t\tBIO_puts(err, "cert_status: callback called\\n");\n\tx = SSL_get_certificate(s);\n\taia = X509_get1_ocsp(x);\n\tif (aia)\n\t\t{\n\t\tif (!OCSP_parse_url(sk_OPENSSL_STRING_value(aia, 0),\n\t\t\t&host, &port, &path, &use_ssl))\n\t\t\t{\n\t\t\tBIO_puts(err, "cert_status: can\'t parse AIA URL\\n");\n\t\t\tgoto err;\n\t\t\t}\n\t\tif (srctx->verbose)\n\t\t\tBIO_printf(err, "cert_status: AIA URL: %s\\n",\n\t\t\t\t\tsk_OPENSSL_STRING_value(aia, 0));\n\t\t}\n\telse\n\t\t{\n\t\tif (!srctx->host)\n\t\t\t{\n\t\t\tBIO_puts(srctx->err, "cert_status: no AIA and no default responder URL\\n");\n\t\t\tgoto done;\n\t\t\t}\n\t\thost = srctx->host;\n\t\tpath = srctx->path;\n\t\tport = srctx->port;\n\t\tuse_ssl = srctx->use_ssl;\n\t\t}\n\tif (!X509_STORE_CTX_init(&inctx,\n\t\t\t\tSSL_CTX_get_cert_store(SSL_get_SSL_CTX(s)),\n\t\t\t\tNULL, NULL))\n\t\tgoto err;\n\tif (X509_STORE_get_by_subject(&inctx,X509_LU_X509,\n\t\t\t\tX509_get_issuer_name(x),&obj) <= 0)\n\t\t{\n\t\tBIO_puts(err, "cert_status: Can\'t retrieve issuer certificate.\\n");\n\t\tX509_STORE_CTX_cleanup(&inctx);\n\t\tgoto done;\n\t\t}\n\treq = OCSP_REQUEST_new();\n\tif (!req)\n\t\tgoto err;\n\tid = OCSP_cert_to_id(NULL, x, obj.data.x509);\n\tX509_free(obj.data.x509);\n\tX509_STORE_CTX_cleanup(&inctx);\n\tif (!id)\n\t\tgoto err;\n\tif (!OCSP_request_add0_id(req, id))\n\t\tgoto err;\n\tid = NULL;\n\tSSL_get_tlsext_status_exts(s, &exts);\n\tfor (i = 0; i < sk_X509_EXTENSION_num(exts); i++)\n\t\t{\n\t\tX509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i);\n\t\tif (!OCSP_REQUEST_add_ext(req, ext, -1))\n\t\t\tgoto err;\n\t\t}\n\tresp = process_responder(err, req, host, path, port, use_ssl, NULL,\n\t\t\t\t\tsrctx->timeout);\n\tif (!resp)\n\t\t{\n\t\tBIO_puts(err, "cert_status: error querying responder\\n");\n\t\tgoto done;\n\t\t}\n\trspderlen = i2d_OCSP_RESPONSE(resp, &rspder);\n\tif (rspderlen <= 0)\n\t\tgoto err;\n\tSSL_set_tlsext_status_ocsp_resp(s, rspder, rspderlen);\n\tif (srctx->verbose)\n\t\t{\n\t\tBIO_puts(err, "cert_status: ocsp response sent:\\n");\n\t\tOCSP_RESPONSE_print(err, resp, 2);\n\t\t}\n\tret = SSL_TLSEXT_ERR_OK;\n\tdone:\n\tif (ret != SSL_TLSEXT_ERR_OK)\n\t\tERR_print_errors(err);\n\tif (aia)\n\t\t{\n\t\tOPENSSL_free(host);\n\t\tOPENSSL_free(path);\n\t\tOPENSSL_free(port);\n\t\tX509_email_free(aia);\n\t\t}\n\tif (id)\n\t\tOCSP_CERTID_free(id);\n\tif (req)\n\t\tOCSP_REQUEST_free(req);\n\tif (resp)\n\t\tOCSP_RESPONSE_free(resp);\n\treturn ret;\n\terr:\n\tret = SSL_TLSEXT_ERR_ALERT_FATAL;\n\tgoto done;\n\t}', 'int BIO_puts(BIO *b, const char *in)\n\t{\n\tint i;\n\tlong (*cb)(BIO *,int,const char *,int,long,long);\n\tif ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL))\n\t\t{\n\t\tBIOerr(BIO_F_BIO_PUTS,BIO_R_UNSUPPORTED_METHOD);\n\t\treturn(-2);\n\t\t}\n\tcb=b->callback;\n\tif ((cb != NULL) &&\n\t\t((i=(int)cb(b,BIO_CB_PUTS,in,0,0L,1L)) <= 0))\n\t\t\treturn(i);\n\tif (!b->init)\n\t\t{\n\t\tBIOerr(BIO_F_BIO_PUTS,BIO_R_UNINITIALIZED);\n\t\treturn(-2);\n\t\t}\n\ti=b->method->bputs(b,in);\n\tif (i > 0) b->num_write+=(unsigned long)i;\n\tif (cb != NULL)\n\t\ti=(int)cb(b,BIO_CB_PUTS|BIO_CB_RETURN,in,0,\n\t\t\t0L,(long)i);\n\treturn(i);\n\t}', 'X509 *SSL_get_certificate(const SSL *s)\n\t{\n\tif (s->cert != NULL)\n\t\treturn(s->cert->key->x509);\n\telse\n\t\treturn(NULL);\n\t}']