MINOR: ssl: load the ocsp in/from the ckch

Don't try to load the files containing the issuer and the OCSP response
each time we generate a SSL_CTX.

The .ocsp and the .issuer are now loaded in the struct
cert_key_and_chain only once and then loaded from this structure when
creating a SSL_CTX.
diff --git a/include/types/ssl_sock.h b/include/types/ssl_sock.h
index 6f06efd..839ef7a 100644
--- a/include/types/ssl_sock.h
+++ b/include/types/ssl_sock.h
@@ -99,6 +99,8 @@
 	STACK_OF(X509) *chain;
 	DH *dh;
 	struct buffer *sctl;
+	struct buffer *ocsp_response;
+	X509 *ocsp_issuer;
 };
 
 /*
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index bd1a6cc..6a78114 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -871,11 +871,11 @@
 
 /*
  * This function load the OCSP Resonse in DER format contained in file at
- * path 'ocsp_path' and call 'ssl_sock_load_ocsp_response'
+ * path 'ocsp_path'
  *
  * Returns 0 on success, 1 in error case.
  */
-static int ssl_sock_load_ocsp_response_from_file(const char *ocsp_path, struct certificate_ocsp *ocsp, OCSP_CERTID *cid, char **err)
+static int ssl_sock_load_ocsp_response_from_file(const char *ocsp_path, struct buffer **ocsp_response, char **err)
 {
 	int fd = -1;
 	int r = 0;
@@ -903,10 +903,16 @@
 		trash.data += r;
 	}
 
+	*ocsp_response = calloc(1, sizeof(**ocsp_response));
+	if (!chunk_dup(*ocsp_response, &trash)) {
+		free(*ocsp_response);
+		*ocsp_response = NULL;
+		goto end;
+	}
+
 	close(fd);
 	fd = -1;
 
-	ret = ssl_sock_load_ocsp_response(&trash, ocsp, cid, err);
 end:
 	if (fd != -1)
 		close(fd);
@@ -1165,85 +1171,38 @@
 
 /*
  * This function enables the handling of OCSP status extension on 'ctx' if a
- * file name 'cert_path' suffixed using ".ocsp" is present.
- * To enable OCSP status extension, the issuer's certificate is mandatory.
- * It should be present in the certificate's extra chain builded from file
- * 'cert_path'. If not found, the issuer certificate is loaded from a file
- * named 'cert_path' suffixed using '.issuer'.
+ * ocsp_response buffer was found in the cert_key_and_chain.  To enable OCSP
+ * status extension, the issuer's certificate is mandatory.  It should be
+ * present in ckch->ocsp_issuer.
  *
- * In addition, ".ocsp" file content is loaded as a DER format of an OCSP
- * response. If file is empty or content is not a valid OCSP response,
- * OCSP status extension is enabled but OCSP response is ignored (a warning
- * is displayed).
+ * In addition, the ckch->ocsp_reponse buffer is loaded as a DER format of an
+ * OCSP response. If file is empty or content is not a valid OCSP response,
+ * OCSP status extension is enabled but OCSP response is ignored (a warning is
+ * displayed).
  *
  * Returns 1 if no ".ocsp" file found, 0 if OCSP status extension is
  * successfully enabled, or -1 in other error case.
  */
-static int ssl_sock_load_ocsp(SSL_CTX *ctx, const char *cert_path)
+static int ssl_sock_load_ocsp(SSL_CTX *ctx, const struct cert_key_and_chain *ckch)
 {
 
-	BIO *in = NULL;
-	X509 *x, *xi = NULL, *issuer = NULL;
-	STACK_OF(X509) *chain = NULL;
+	X509 *x = NULL, *issuer = NULL;
 	OCSP_CERTID *cid = NULL;
-	SSL *ssl;
 	char ocsp_path[MAXPATHLEN+1];
 	int i, ret = -1;
-	struct stat st;
 	struct certificate_ocsp *ocsp = NULL, *iocsp;
 	char *warn = NULL;
 	unsigned char *p;
-	pem_password_cb *passwd_cb;
-	void *passwd_cb_userdata;
 	void (*callback) (void);
 
-	snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
-
-	if (stat(ocsp_path, &st))
-		return 1;
-
-	ssl = SSL_new(ctx);
-	if (!ssl)
-		goto out;
 
-	x = SSL_get_certificate(ssl);
+	x = ckch->cert;
 	if (!x)
 		goto out;
 
-	/* Try to lookup for issuer in certificate extra chain */
-	SSL_CTX_get_extra_chain_certs(ctx, &chain);
-	for (i = 0; i < sk_X509_num(chain); i++) {
-		issuer = sk_X509_value(chain, i);
-		if (X509_check_issued(issuer, x) == X509_V_OK)
-			break;
-		else
-			issuer = NULL;
-	}
-
-	/* If not found try to load issuer from a suffixed file */
-	if (!issuer) {
-		char issuer_path[MAXPATHLEN+1];
-
-		in = BIO_new(BIO_s_file());
-		if (!in)
-			goto out;
-
-		snprintf(issuer_path, MAXPATHLEN+1, "%s.issuer", cert_path);
-		if (BIO_read_filename(in, issuer_path) <= 0)
-			goto out;
-
-		passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
-		passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
-
-		xi = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
-		if (!xi)
-			goto out;
-
-		if (X509_check_issued(xi, x) != X509_V_OK)
-			goto out;
-
-		issuer = xi;
-	}
+	issuer = ckch->ocsp_issuer;
+	if (!issuer)
+		goto out;
 
 	cid = OCSP_cert_to_id(0, x, issuer);
 	if (!cid)
@@ -1324,21 +1283,12 @@
 	ret = 0;
 
 	warn = NULL;
-	if (ssl_sock_load_ocsp_response_from_file(ocsp_path, iocsp, cid, &warn)) {
+	if (ssl_sock_load_ocsp_response(ckch->ocsp_response, ocsp, cid, &warn)) {
 		memprintf(&warn, "Loading '%s': %s. Content will be ignored", ocsp_path, warn ? warn : "failure");
 		ha_warning("%s.\n", warn);
 	}
 
 out:
-	if (ssl)
-		SSL_free(ssl);
-
-	if (in)
-		BIO_free(in);
-
-	if (xi)
-		X509_free(xi);
-
 	if (cid)
 		OCSP_CERTID_free(cid);
 
@@ -3013,6 +2963,18 @@
 				err && *err ? *err : "", path);
 		ret = 1;
 		goto end;
+	}
+
+	ret = 0;
+
+	/* don't try to do the next operations if we feed the ckch from the cli */
+	if (buf)
+		goto end;
+
+	ERR_clear_error();
+	if (in) {
+		BIO_free(in);
+		in = NULL;
 	}
 
 #if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
@@ -3033,6 +2995,71 @@
 	}
 #endif
 
+	/* try to load an ocsp response file */
+	{
+		char fp[MAXPATHLEN+1];
+		struct stat st;
+
+		snprintf(fp, MAXPATHLEN+1, "%s.ocsp", path);
+		if (stat(fp, &st) == 0) {
+			if (ssl_sock_load_ocsp_response_from_file(fp, &ckch->ocsp_response, err)) {
+				ret = 1;
+				goto end;
+			}
+		}
+	}
+
+	if (ckch->ocsp_response) {
+		X509 *issuer;
+		int i;
+
+		/* check if one of the certificate of the chain is the issuer */
+		for (i = 0; i < sk_X509_num(ckch->chain); i++) {
+			issuer = sk_X509_value(ckch->chain, i);
+			if (X509_check_issued(issuer, ckch->cert) == X509_V_OK) {
+				ckch->ocsp_issuer = issuer;
+				break;
+			} else
+				issuer = NULL;
+		}
+
+		/* if no issuer was found, try to load an issuer from the .issuer */
+		if (!issuer) {
+			struct stat st;
+			char fp[MAXPATHLEN+1];
+
+			snprintf(fp, MAXPATHLEN+1, "%s.issuer", path);
+			if (stat(fp, &st) == 0) {
+				if (BIO_read_filename(in, fp) <= 0) {
+					memprintf(err, "%s '%s.issuer' is present but cannot be read or parsed'.\n",
+						  *err ? *err : "", fp);
+					ret = 1;
+					goto end;
+				}
+
+				issuer = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
+				if (!issuer) {
+					memprintf(err, "%s '%s.issuer' is present but cannot be read or parsed'.\n",
+						  *err ? *err : "", fp);
+					ret = 1;
+					goto end;
+				}
+
+				if (X509_check_issued(ckch->ocsp_issuer, ckch->cert) != X509_V_OK) {
+					memprintf(err, "%s '%s.issuer' is not an issuer'.\n",
+						  *err ? *err : "", fp);
+					ret = 1;
+					goto end;
+				}
+			} else {
+				memprintf(err, "%sNo issuer found, cannot use the OCSP response'.\n",
+				          *err ? *err : "");
+				ret = 1;
+				goto end;
+			}
+		}
+	}
+
 	ret = 0;
 
 end:
@@ -3113,6 +3140,20 @@
 	}
 #endif
 
+#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
+	/* Load OCSP Info into context */
+	if (ckch->ocsp_response) {
+		if (ssl_sock_load_ocsp(ctx, ckch) < 0) {
+			if (err)
+				memprintf(err, "%s '%s.ocsp' is present and activates OCSP but it is impossible to compute the OCSP certificate ID (maybe the issuer could not be found)'.\n",
+				          *err ? *err : "", path);
+			return 1;
+		}
+	}
+#elif (defined OPENSSL_IS_BORINGSSL)
+	ssl_sock_set_ocsp_response_from_file(cur_ctx, cur_file);
+#endif
+
 	return 0;
 }
 
@@ -3424,19 +3465,6 @@
 						goto end;
 					}
 
-#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
-					/* Load OCSP Info into context */
-					/* TODO: store OCSP in ckch */
-					if (ssl_sock_load_ocsp(cur_ctx, cur_file) < 0) {
-						if (err)
-							memprintf(err, "%s '%s.ocsp' is present and activates OCSP but it is impossible to compute the OCSP certificate ID (maybe the issuer could not be found)'.\n",
-							          *err ? *err : "", cur_file);
-						rv = 1;
-						goto end;
-					}
-#elif (defined OPENSSL_IS_BORINGSSL)
-					ssl_sock_set_ocsp_response_from_file(cur_ctx, cur_file);
-#endif
 				}
 			}
 
@@ -3631,17 +3659,6 @@
 	 * the tree, so it will be discovered and cleaned in time.
 	 */
 
-#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
-	if (ssl_sock_load_ocsp(ctx, path) < 0) {
-		if (err)
-			memprintf(err, "%s '%s.ocsp' is present and activates OCSP but it is impossible to compute the OCSP certificate ID (maybe the issuer could not be found)'.\n",
-				  *err ? *err : "", path);
-		goto error;
-	}
-#elif (defined OPENSSL_IS_BORINGSSL)
-	ssl_sock_set_ocsp_response_from_file(ctx, path);
-#endif
-
 #ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
 	if (bind_conf->default_ctx) {
 		memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",