summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTim Ruehsen <tim.ruehsen@gmx.de>2015-01-17 14:32:35 +0100
committerNikos Mavrogiannopoulos <nmav@redhat.com>2015-01-19 15:30:08 +0100
commit5250d7558f7654b039aa4a502b662b6f2025bb9a (patch)
treee5822e39bb64218e27c4789e26b39233cf5e03bf /src
parented8e18ed9741915cd73fbc0d39d6fd5f4cf636c6 (diff)
downloadgnutls-5250d7558f7654b039aa4a502b662b6f2025bb9a.tar.gz
OCSP check the whole cert chain
Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
Diffstat (limited to 'src')
-rw-r--r--src/cli.c120
-rw-r--r--src/ocsptool-common.c4
2 files changed, 67 insertions, 57 deletions
diff --git a/src/cli.c b/src/cli.c
index 371b4d3268..e02080d302 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -405,13 +405,15 @@ static int cert_verify_callback(gnutls_session_t session)
return -1;
} else if (ENABLED_OPT(OCSP) && gnutls_ocsp_status_request_is_checked(session, 0) == 0) { /* off-line verification succeeded. Try OCSP */
rc = cert_verify_ocsp(session);
- if (rc == 0) {
+ if (rc == -1) {
printf
- ("*** Verifying (with OCSP) server certificate failed...\n");
+ ("*** Verifying (with OCSP) server certificate chain failed...\n");
if (!insecure && !ssh)
return -1;
- } else if (rc == -1)
- printf("*** OCSP response ignored...\n");
+ } else if (rc == 0)
+ printf("*** OCSP: nothing to check.\n");
+ else
+ printf("*** OCSP: verified %d certificate(s).\n", rc);
}
}
@@ -1808,80 +1810,88 @@ static void init_global_tls_stuff(void)
}
/* OCSP check for the peer's certificate. Should be called
- * only after the certificate list verication is complete.
+ * only after the certificate list verification is complete.
* Returns:
- * 0: certificate is revoked
- * 1: certificate is ok
- * -1: dunno
+ * -1: certificate chain could not be checked fully
+ * >=0: number of certificates verified ok
*/
static int cert_verify_ocsp(gnutls_session_t session)
{
- gnutls_x509_crt_t crt, issuer;
+ gnutls_x509_crt_t cert, issuer;
const gnutls_datum_t *cert_list;
- unsigned int cert_list_size = 0;
- int deinit_issuer = 0;
+ unsigned int cert_list_size = 0, ok = 0;
+ int deinit_issuer = 0, deinit_cert;
gnutls_datum_t resp;
unsigned char noncebuf[23];
gnutls_datum_t nonce = { noncebuf, sizeof(noncebuf) };
int ret;
+ unsigned it;
cert_list = gnutls_certificate_get_peers(session, &cert_list_size);
if (cert_list_size == 0) {
fprintf(stderr, "No certificates found!\n");
- return -1;
+ return 0;
}
- gnutls_x509_crt_init(&crt);
- ret =
- gnutls_x509_crt_import(crt, &cert_list[0],
- GNUTLS_X509_FMT_DER);
- if (ret < 0) {
- fprintf(stderr, "Decoding error: %s\n",
- gnutls_strerror(ret));
- return -1;
- }
+ for (it = 0; it < cert_list_size; it++) {
+ gnutls_x509_crt_init(&cert);
+ if (deinit_cert)
+ gnutls_x509_crt_deinit(cert);
+ gnutls_x509_crt_init(&cert);
+ deinit_cert = 1;
+ ret = gnutls_x509_crt_import(cert, &cert_list[it], GNUTLS_X509_FMT_DER);
+ if (ret < 0) {
+ fprintf(stderr, "Decoding error: %s\n", gnutls_strerror(ret));
+ goto cleanup;
+ }
- ret = gnutls_certificate_get_issuer(xcred, crt, &issuer, 0);
- if (ret < 0 && cert_list_size > 1) {
- gnutls_x509_crt_init(&issuer);
- ret =
- gnutls_x509_crt_import(issuer, &cert_list[1],
- GNUTLS_X509_FMT_DER);
+ if (deinit_issuer) {
+ gnutls_x509_crt_deinit(issuer);
+ deinit_issuer = 0;
+ }
+
+ ret = gnutls_certificate_get_issuer(xcred, cert, &issuer, 0);
+ if (ret < 0 && cert_list_size - it > 1) {
+ gnutls_x509_crt_init(&issuer);
+ deinit_issuer = 1;
+ ret = gnutls_x509_crt_import(issuer, &cert_list[it + 1], GNUTLS_X509_FMT_DER);
+ if (ret < 0) {
+ fprintf(stderr, "Decoding error: %s\n", gnutls_strerror(ret));
+ goto cleanup;
+ }
+ } else if (ret < 0) {
+ fprintf(stderr, "Cannot find issuer\n");
+ goto cleanup;
+ }
+
+ ret = gnutls_rnd(GNUTLS_RND_NONCE, nonce.data, nonce.size);
if (ret < 0) {
- fprintf(stderr, "Decoding error: %s\n",
- gnutls_strerror(ret));
- return -1;
+ fprintf(stderr, "gnutls_rnd: %s", gnutls_strerror(ret));
+ goto cleanup;
}
- deinit_issuer = 1;
- } else if (ret < 0) {
- fprintf(stderr, "Cannot find issuer\n");
- ret = -1;
- goto cleanup;
- }
- ret =
- gnutls_rnd(GNUTLS_RND_NONCE, nonce.data, nonce.size);
- if (ret < 0) {
- fprintf(stderr, "gnutls_rnd: %s",
- gnutls_strerror(ret));
- ret = -1;
- goto cleanup;
- }
+ ret = send_ocsp_request(NULL, cert, issuer, &resp, &nonce);
+ if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
+ continue;
+ }
+ if (ret < 0) {
+ fprintf(stderr, "Cannot contact OCSP server\n");
+ goto cleanup;
+ }
- ret = send_ocsp_request(NULL, crt, issuer, &resp, &nonce);
- if (ret < 0) {
- fprintf(stderr, "Cannot contact OCSP server\n");
- ret = -1;
- goto cleanup;
+ /* verify and check the response for revoked cert */
+ ret = check_ocsp_response(cert, issuer, &resp, &nonce);
+ if (ret == 1)
+ ok++;
+ else
+ break;
}
- /* verify and check the response for revoked cert */
- ret = check_ocsp_response(crt, issuer, &resp, &nonce);
-
- cleanup:
+cleanup:
if (deinit_issuer)
gnutls_x509_crt_deinit(issuer);
- gnutls_x509_crt_deinit(crt);
+ if (deinit_cert)
+ gnutls_x509_crt_deinit(cert);
- return ret;
+ return ok > 1 ? (int) ok : -1;
}
diff --git a/src/ocsptool-common.c b/src/ocsptool-common.c
index 04e24e7fee..ec5903c14b 100644
--- a/src/ocsptool-common.c
+++ b/src/ocsptool-common.c
@@ -176,9 +176,9 @@ int send_ocsp_request(const char *server,
if (ret < 0) {
fprintf(stderr,
- "Cannot find URL from issuer: %s\n",
+ "*** Cannot find OCSP server URI in certificate: %s\n",
gnutls_strerror(ret));
- return -1;
+ return ret;
}
url = malloc(data.size + 1);