summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Rühsen <tim.ruehsen@gmx.de>2020-02-09 14:59:00 +0000
committerTim Rühsen <tim.ruehsen@gmx.de>2020-02-09 14:59:00 +0000
commit107c1d382d7ba500b6662ce4213377d9627aeeac (patch)
tree8b9c7325ada69a0ce60ff4b2ab30c8233b14ab0d
parentd9bc5bfc8da34da664413f683debc097f170eb99 (diff)
parentdd423bcb67c02d6d89090705b1b3dfc1999dd296 (diff)
downloadgnutls-107c1d382d7ba500b6662ce4213377d9627aeeac.tar.gz
Merge branch 'wip-save-ocsp-multi' into 'master'
Add option to store all stapled OCSP responses to gnutls-cli See merge request gnutls/gnutls!1189
-rw-r--r--src/cli-args.def11
-rw-r--r--src/cli.c96
2 files changed, 91 insertions, 16 deletions
diff --git a/src/cli-args.def b/src/cli-args.def
index 12b8bb05db..a8760fab90 100644
--- a/src/cli-args.def
+++ b/src/cli-args.def
@@ -172,7 +172,16 @@ flag = {
name = save-ocsp;
arg-type = string;
descrip = "Save the peer's OCSP status response in the provided file";
- doc = "";
+ doc = "";
+ flags-cant = save-ocsp-multi;
+};
+
+flag = {
+ name = save-ocsp-multi;
+ arg-type = string;
+ descrip = "Save all OCSP responses provided by the peer in this file";
+ doc = "The file will contain a list of PEM encoded OCSP status responses if any were provided by the peer, starting with the one for the peer's server certificate.";
+ flags-cant = save-ocsp;
};
flag = {
diff --git a/src/cli.c b/src/cli.c
index f02f842b71..db072b9303 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -358,6 +358,84 @@ static void try_save_cert(gnutls_session_t session)
return;
}
+static void try_save_ocsp_status(gnutls_session_t session)
+{
+ unsigned int cert_num = 0;
+ gnutls_certificate_get_peers(session, &cert_num);
+ if (cert_num == 0) {
+ fprintf(stderr, "no certificates sent by server, so can't get OCSP status!\n");
+ return;
+ }
+
+ const char *path;
+ gnutls_x509_crt_fmt_t type;
+ unsigned int max_out;
+
+ /* This function is called if exactly one of SAVE_OCSP and
+ * SAVE_OCSP_MULTI is set. */
+ if (HAVE_OPT(SAVE_OCSP))
+ {
+ path = OPT_ARG(SAVE_OCSP);
+ type = GNUTLS_X509_FMT_DER;
+ max_out = 1;
+ } else {
+ path = OPT_ARG(SAVE_OCSP_MULTI);
+ type = GNUTLS_X509_FMT_PEM;
+ max_out = cert_num;
+ }
+
+ FILE *fp = fopen(path, "w");
+ if (fp == NULL) {
+ fprintf(stderr, "could not open %s for writing\n", path);
+ exit(1);
+ }
+
+ for (unsigned int i = 0; i < max_out; i++) {
+ gnutls_datum_t oresp;
+ int ret = gnutls_ocsp_status_request_get2(session, i, &oresp);
+ if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
+ fprintf(stderr, "no OCSP response for certificate %u\n", i);
+ continue;
+ } else if (ret < 0) {
+ fprintf(stderr, "error getting OCSP response %u: %s\n",
+ i, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ if (type == GNUTLS_X509_FMT_DER) {
+ /* on success the return value is equal to the
+ * number of items (third parameter) */
+ if (fwrite(oresp.data, oresp.size, 1, fp) != 1) {
+ fprintf(stderr, "writing to %s failed\n", path);
+ exit(1);
+ }
+ continue;
+ }
+
+ gnutls_datum_t t;
+ ret = gnutls_pem_base64_encode_alloc("OCSP RESPONSE",
+ &oresp, &t);
+ if (ret < 0) {
+ fprintf(stderr, "error allocating PEM OCSP response: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ /* on success the return value is equal to the number
+ * of items (third parameter) */
+ if (fwrite(t.data, t.size, 1, fp) != 1) {
+ fprintf(stderr, "writing to %s failed\n", path);
+ exit(1);
+ }
+ gnutls_free(t.data);
+ }
+ if (fclose(fp) != 0) {
+ perror("failed to close OCSP save file");
+ }
+
+ return;
+}
+
static int cert_verify_callback(gnutls_session_t session)
{
int rc;
@@ -367,7 +445,6 @@ static int cert_verify_callback(gnutls_session_t session)
int dane = ENABLED_OPT(DANE);
int ca_verify = ENABLED_OPT(CA_VERIFICATION);
const char *txt_service;
- gnutls_datum_t oresp;
const char *host;
/* On an session with TOFU the PKI/DANE verification
@@ -390,23 +467,12 @@ static int cert_verify_callback(gnutls_session_t session)
}
#ifndef ENABLE_OCSP
- if (HAVE_OPT(SAVE_OCSP) || HAVE_OPT(OCSP)) {
+ if (HAVE_OPT(SAVE_OCSP_MULTI) || HAVE_OPT(SAVE_OCSP) || HAVE_OPT(OCSP)) {
fprintf(stderr, "OCSP is not supported!\n");
}
#else
- rc = gnutls_ocsp_status_request_get(session, &oresp);
- if (rc < 0) {
- oresp.data = NULL;
- oresp.size = 0;
- }
-
- if (HAVE_OPT(SAVE_OCSP) && oresp.data) {
- FILE *fp = fopen(OPT_ARG(SAVE_OCSP), "w");
-
- if (fp != NULL) {
- fwrite(oresp.data, 1, oresp.size, fp);
- fclose(fp);
- }
+ if (HAVE_OPT(SAVE_OCSP_MULTI) || HAVE_OPT(SAVE_OCSP)) {
+ try_save_ocsp_status(session);
}
#endif