[ << ] | [ < ] | [ Up ] | [ > ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
8.3 OCSP example
Generate OCSP request
A small tool to generate OCSP requests.
/* This example code is placed in the public domain. */ #ifdef HAVE_CONFIG_H #include <config.h> #endif #include <stdio.h> #include <stdlib.h> #include <string.h> #include <gnutls/gnutls.h> #include <gnutls/crypto.h> #include <gnutls/ocsp.h> #ifndef NO_LIBCURL #include <curl/curl.h> #endif #include "read-file.h" size_t get_data (void *buffer, size_t size, size_t nmemb, void *userp); static gnutls_x509_crt_t load_cert (const char *cert_file); static void _response_info (const gnutls_datum_t * data); static void _generate_request (gnutls_datum_t * rdata, const char *cert_file, const char *issuer_file); static int _verify_response (gnutls_datum_t * data, const char *signer_file); /* This program queries an OCSP server. It expects three files. argv[1] containing the certificate to be checked, argv[2] holding the issuer for this certificate, and argv[3] holding a trusted certificate to verify OCSP's response. argv[4] is optional and should hold the server host name. For simplicity the libcurl library is used. */ int main (int argc, char *argv[]) { gnutls_datum_t ud, tmp; int ret; gnutls_datum_t req; #ifndef NO_LIBCURL CURL *handle; struct curl_slist *headers = NULL; #endif int v, seq; const char *cert_file = argv[1]; const char *issuer_file = argv[2]; const char *signer_file = argv[3]; char *hostname = NULL; gnutls_global_init (); if (argc > 4) hostname = argv[4]; if (hostname == NULL) { gnutls_x509_crt_t cert = load_cert (cert_file); for (seq = 0;; seq++) { ret = gnutls_x509_crt_get_authority_info_access (cert, seq, GNUTLS_IA_OCSP_URI, &tmp, NULL); if (ret == GNUTLS_E_UNKNOWN_ALGORITHM) continue; if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { fprintf (stderr, "No URI was found in the certificate.\n"); exit (1); } if (ret < 0) { fprintf (stderr, "error: %s\n", gnutls_strerror (ret)); exit (1); } printf ("CA issuers URI: %.*s\n", tmp.size, tmp.data); hostname = malloc (tmp.size + 1); memcpy (hostname, tmp.data, tmp.size); hostname[tmp.size] = 0; gnutls_free (tmp.data); break; } gnutls_x509_crt_deinit (cert); } /* Note that the OCSP servers hostname might be available * using gnutls_x509_crt_get_authority_info_access() in the issuer's * certificate */ memset (&ud, 0, sizeof (ud)); fprintf (stderr, "Connecting to %s\n", hostname); _generate_request (&req, cert_file, issuer_file); #ifndef NO_LIBCURL curl_global_init (CURL_GLOBAL_ALL); handle = curl_easy_init (); if (handle == NULL) exit (1); headers = curl_slist_append (headers, "Content-Type: application/ocsp-request"); curl_easy_setopt (handle, CURLOPT_HTTPHEADER, headers); curl_easy_setopt (handle, CURLOPT_POSTFIELDS, (void *) req.data); curl_easy_setopt (handle, CURLOPT_POSTFIELDSIZE, req.size); curl_easy_setopt (handle, CURLOPT_URL, hostname); curl_easy_setopt (handle, CURLOPT_WRITEFUNCTION, get_data); curl_easy_setopt (handle, CURLOPT_WRITEDATA, &ud); ret = curl_easy_perform (handle); if (ret != 0) { fprintf (stderr, "curl[%d] error %d\n", __LINE__, ret); exit (1); } curl_easy_cleanup (handle); #endif _response_info (&ud); v = _verify_response (&ud, signer_file); gnutls_global_deinit (); return v; } static void _response_info (const gnutls_datum_t * data) { gnutls_ocsp_resp_t resp; int ret; gnutls_datum buf; ret = gnutls_ocsp_resp_init (&resp); if (ret < 0) exit (1); ret = gnutls_ocsp_resp_import (resp, data); if (ret < 0) exit (1); ret = gnutls_ocsp_resp_print (resp, GNUTLS_OCSP_PRINT_FULL, &buf); if (ret != 0) exit (1); printf ("%.*s", buf.size, buf.data); gnutls_free (buf.data); gnutls_ocsp_resp_deinit (resp); } static gnutls_x509_crt_t load_cert (const char *cert_file) { gnutls_x509_crt_t crt; int ret; gnutls_datum_t data; size_t size; ret = gnutls_x509_crt_init (&crt); if (ret < 0) exit (1); data.data = (void *) read_binary_file (cert_file, &size); data.size = size; if (!data.data) { fprintf (stderr, "Cannot open file: %s\n", cert_file); exit (1); } ret = gnutls_x509_crt_import (crt, &data, GNUTLS_X509_FMT_PEM); free (data.data); if (ret < 0) { fprintf (stderr, "Cannot import certificate in %s: %s\n", cert_file, gnutls_strerror (ret)); exit (1); } return crt; } static void _generate_request (gnutls_datum_t * rdata, const char *cert_file, const char *issuer_file) { gnutls_ocsp_req_t req; int ret; gnutls_x509_crt_t issuer, cert; unsigned char noncebuf[23]; gnutls_datum_t nonce = { noncebuf, sizeof (noncebuf) }; ret = gnutls_ocsp_req_init (&req); if (ret < 0) exit (1); issuer = load_cert (issuer_file); cert = load_cert (cert_file); ret = gnutls_ocsp_req_add_cert (req, GNUTLS_DIG_SHA1, issuer, cert); if (ret < 0) exit (1); gnutls_x509_crt_deinit (issuer); gnutls_x509_crt_deinit (cert); ret = gnutls_rnd (GNUTLS_RND_RANDOM, nonce.data, nonce.size); if (ret < 0) exit (1); ret = gnutls_ocsp_req_set_nonce (req, 0, &nonce); if (ret < 0) exit (1); ret = gnutls_ocsp_req_export (req, rdata); if (ret != 0) exit (1); gnutls_ocsp_req_deinit (req); return; } static int _verify_response (gnutls_datum_t * data, const char *signer_file) { gnutls_ocsp_resp_t resp; int ret; size_t size; gnutls_x509_crt_t signer; unsigned verify; gnutls_datum_t dat; ret = gnutls_ocsp_resp_init (&resp); if (ret < 0) exit (1); ret = gnutls_ocsp_resp_import (resp, data); if (ret < 0) exit (1); ret = gnutls_x509_crt_init (&signer); if (ret < 0) exit (1); dat.data = (void *) read_binary_file (signer_file, &size); if (dat.data == NULL) exit (1); dat.size = size; ret = gnutls_x509_crt_import (signer, &dat, GNUTLS_X509_FMT_PEM); free (dat.data); if (ret < 0) exit (1); ret = gnutls_ocsp_resp_verify_direct (resp, signer, &verify, 0); if (ret < 0) exit (1); printf ("Verifying OCSP Response: "); if (verify == 0) printf ("Verification success!\n"); else printf ("Verification error!\n"); if (verify & GNUTLS_OCSP_VERIFY_SIGNER_NOT_FOUND) printf ("Signer cert not found\n"); if (verify & GNUTLS_OCSP_VERIFY_SIGNER_KEYUSAGE_ERROR) printf ("Signer cert keyusage error\n"); if (verify & GNUTLS_OCSP_VERIFY_UNTRUSTED_SIGNER) printf ("Signer cert is not trusted\n"); if (verify & GNUTLS_OCSP_VERIFY_INSECURE_ALGORITHM) printf ("Insecure algorithm\n"); if (verify & GNUTLS_OCSP_VERIFY_SIGNATURE_FAILURE) printf ("Signature failure\n"); if (verify & GNUTLS_OCSP_VERIFY_CERT_NOT_ACTIVATED) printf ("Signer cert not yet activated\n"); if (verify & GNUTLS_OCSP_VERIFY_CERT_EXPIRED) printf ("Signer cert expired\n"); gnutls_ocsp_resp_deinit (resp); return verify; } size_t get_data (void *buffer, size_t size, size_t nmemb, void *userp) { gnutls_datum_t *ud = userp; size *= nmemb; ud->data = realloc (ud->data, size + ud->size); if (ud->data == NULL) { fprintf (stderr, "Not enough memory for the request\n"); exit (1); } memcpy (&ud->data[ud->size], buffer, size); ud->size += size; return size; }
[ << ] | [ < ] | [ Up ] | [ > ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This document was generated on March 2, 2012 using texi2html 5.0.