diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cli.c | 120 | ||||
-rw-r--r-- | src/ocsptool-common.c | 4 |
2 files changed, 67 insertions, 57 deletions
@@ -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); |