danetool is being built even without libgnutls-dane.
[gnutls.git] / doc / examples / ex-ocsp-client.c
blob6373fc24e63f3f525dc2753b8b710258f0b80616
1 /* This example code is placed in the public domain. */
3 #ifdef HAVE_CONFIG_H
4 #include <config.h>
5 #endif
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <gnutls/gnutls.h>
11 #include <gnutls/crypto.h>
12 #include <gnutls/ocsp.h>
13 #ifndef NO_LIBCURL
14 #include <curl/curl.h>
15 #endif
16 #include "read-file.h"
18 size_t get_data (void *buffer, size_t size, size_t nmemb,
19 void *userp);
20 static gnutls_x509_crt_t load_cert (const char *cert_file);
21 static void _response_info (const gnutls_datum_t * data);
22 static void
23 _generate_request (gnutls_datum_t * rdata, gnutls_x509_crt_t cert,
24 gnutls_x509_crt_t issuer);
25 static int
26 _verify_response (gnutls_datum_t * data, gnutls_x509_crt_t cert,
27 gnutls_x509_crt_t signer);
29 /* This program queries an OCSP server.
30 It expects three files. argv[1] containing the certificate to
31 be checked, argv[2] holding the issuer for this certificate,
32 and argv[3] holding a trusted certificate to verify OCSP's response.
33 argv[4] is optional and should hold the server host name.
35 For simplicity the libcurl library is used.
38 int
39 main (int argc, char *argv[])
41 gnutls_datum_t ud, tmp;
42 int ret;
43 gnutls_datum_t req;
44 gnutls_x509_crt_t cert, issuer, signer;
45 #ifndef NO_LIBCURL
46 CURL *handle;
47 struct curl_slist *headers = NULL;
48 #endif
49 int v, seq;
50 const char *cert_file = argv[1];
51 const char *issuer_file = argv[2];
52 const char *signer_file = argv[3];
53 char *hostname = NULL;
55 gnutls_global_init ();
57 if (argc > 4)
58 hostname = argv[4];
60 cert = load_cert (cert_file);
61 issuer = load_cert (issuer_file);
62 signer = load_cert (signer_file);
64 if (hostname == NULL)
67 for (seq = 0;; seq++)
69 ret = gnutls_x509_crt_get_authority_info_access (cert, seq,
70 GNUTLS_IA_OCSP_URI,
71 &tmp,
72 NULL);
73 if (ret == GNUTLS_E_UNKNOWN_ALGORITHM)
74 continue;
75 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
77 fprintf (stderr,
78 "No URI was found in the certificate.\n");
79 exit (1);
81 if (ret < 0)
83 fprintf (stderr, "error: %s\n",
84 gnutls_strerror (ret));
85 exit (1);
88 printf ("CA issuers URI: %.*s\n", tmp.size, tmp.data);
90 hostname = malloc (tmp.size + 1);
91 memcpy (hostname, tmp.data, tmp.size);
92 hostname[tmp.size] = 0;
94 gnutls_free (tmp.data);
95 break;
100 /* Note that the OCSP servers hostname might be available
101 * using gnutls_x509_crt_get_authority_info_access() in the issuer's
102 * certificate */
104 memset (&ud, 0, sizeof (ud));
105 fprintf (stderr, "Connecting to %s\n", hostname);
107 _generate_request (&req, cert, issuer);
109 #ifndef NO_LIBCURL
110 curl_global_init (CURL_GLOBAL_ALL);
112 handle = curl_easy_init ();
113 if (handle == NULL)
114 exit (1);
116 headers =
117 curl_slist_append (headers,
118 "Content-Type: application/ocsp-request");
120 curl_easy_setopt (handle, CURLOPT_HTTPHEADER, headers);
121 curl_easy_setopt (handle, CURLOPT_POSTFIELDS, (void *) req.data);
122 curl_easy_setopt (handle, CURLOPT_POSTFIELDSIZE, req.size);
123 curl_easy_setopt (handle, CURLOPT_URL, hostname);
124 curl_easy_setopt (handle, CURLOPT_WRITEFUNCTION, get_data);
125 curl_easy_setopt (handle, CURLOPT_WRITEDATA, &ud);
127 ret = curl_easy_perform (handle);
128 if (ret != 0)
130 fprintf (stderr, "curl[%d] error %d\n", __LINE__, ret);
131 exit (1);
134 curl_easy_cleanup (handle);
135 #endif
137 _response_info (&ud);
139 v = _verify_response (&ud, cert, signer);
141 gnutls_x509_crt_deinit (cert);
142 gnutls_x509_crt_deinit (issuer);
143 gnutls_x509_crt_deinit (signer);
144 gnutls_global_deinit ();
146 return v;
149 static void
150 _response_info (const gnutls_datum_t * data)
152 gnutls_ocsp_resp_t resp;
153 int ret;
154 gnutls_datum buf;
156 ret = gnutls_ocsp_resp_init (&resp);
157 if (ret < 0)
158 exit (1);
160 ret = gnutls_ocsp_resp_import (resp, data);
161 if (ret < 0)
162 exit (1);
164 ret = gnutls_ocsp_resp_print (resp, GNUTLS_OCSP_PRINT_FULL, &buf);
165 if (ret != 0)
166 exit (1);
168 printf ("%.*s", buf.size, buf.data);
169 gnutls_free (buf.data);
171 gnutls_ocsp_resp_deinit (resp);
174 static gnutls_x509_crt_t
175 load_cert (const char *cert_file)
177 gnutls_x509_crt_t crt;
178 int ret;
179 gnutls_datum_t data;
180 size_t size;
182 ret = gnutls_x509_crt_init (&crt);
183 if (ret < 0)
184 exit (1);
186 data.data = (void *) read_binary_file (cert_file, &size);
187 data.size = size;
189 if (!data.data)
191 fprintf (stderr, "Cannot open file: %s\n", cert_file);
192 exit (1);
195 ret = gnutls_x509_crt_import (crt, &data, GNUTLS_X509_FMT_PEM);
196 free (data.data);
197 if (ret < 0)
199 fprintf (stderr, "Cannot import certificate in %s: %s\n",
200 cert_file, gnutls_strerror (ret));
201 exit (1);
204 return crt;
207 static void
208 _generate_request (gnutls_datum_t * rdata, gnutls_x509_crt_t cert,
209 gnutls_x509_crt_t issuer)
211 gnutls_ocsp_req_t req;
212 int ret;
213 unsigned char noncebuf[23];
214 gnutls_datum_t nonce = { noncebuf, sizeof (noncebuf) };
216 ret = gnutls_ocsp_req_init (&req);
217 if (ret < 0)
218 exit (1);
221 ret = gnutls_ocsp_req_add_cert (req, GNUTLS_DIG_SHA1, issuer, cert);
222 if (ret < 0)
223 exit (1);
225 ret = gnutls_rnd (GNUTLS_RND_RANDOM, nonce.data, nonce.size);
226 if (ret < 0)
227 exit (1);
229 ret = gnutls_ocsp_req_set_nonce (req, 0, &nonce);
230 if (ret < 0)
231 exit (1);
233 ret = gnutls_ocsp_req_export (req, rdata);
234 if (ret != 0)
235 exit (1);
237 gnutls_ocsp_req_deinit (req);
239 return;
242 static int
243 _verify_response (gnutls_datum_t * data, gnutls_x509_crt_t cert,
244 gnutls_x509_crt_t signer)
246 gnutls_ocsp_resp_t resp;
247 int ret;
248 unsigned verify;
250 ret = gnutls_ocsp_resp_init (&resp);
251 if (ret < 0)
252 exit (1);
254 ret = gnutls_ocsp_resp_import (resp, data);
255 if (ret < 0)
256 exit (1);
258 ret = gnutls_ocsp_resp_check_crt (resp, 0, cert);
259 if (ret < 0)
260 exit(1);
262 ret = gnutls_ocsp_resp_verify_direct (resp, signer, &verify, 0);
263 if (ret < 0)
264 exit (1);
266 printf ("Verifying OCSP Response: ");
267 if (verify == 0)
268 printf ("Verification success!\n");
269 else
270 printf ("Verification error!\n");
272 if (verify & GNUTLS_OCSP_VERIFY_SIGNER_NOT_FOUND)
273 printf ("Signer cert not found\n");
275 if (verify & GNUTLS_OCSP_VERIFY_SIGNER_KEYUSAGE_ERROR)
276 printf ("Signer cert keyusage error\n");
278 if (verify & GNUTLS_OCSP_VERIFY_UNTRUSTED_SIGNER)
279 printf ("Signer cert is not trusted\n");
281 if (verify & GNUTLS_OCSP_VERIFY_INSECURE_ALGORITHM)
282 printf ("Insecure algorithm\n");
284 if (verify & GNUTLS_OCSP_VERIFY_SIGNATURE_FAILURE)
285 printf ("Signature failure\n");
287 if (verify & GNUTLS_OCSP_VERIFY_CERT_NOT_ACTIVATED)
288 printf ("Signer cert not yet activated\n");
290 if (verify & GNUTLS_OCSP_VERIFY_CERT_EXPIRED)
291 printf ("Signer cert expired\n");
293 gnutls_ocsp_resp_deinit (resp);
295 return verify;
298 size_t
299 get_data (void *buffer, size_t size, size_t nmemb, void *userp)
301 gnutls_datum_t *ud = userp;
303 size *= nmemb;
305 ud->data = realloc (ud->data, size + ud->size);
306 if (ud->data == NULL)
308 fprintf (stderr, "Not enough memory for the request\n");
309 exit (1);
312 memcpy (&ud->data[ud->size], buffer, size);
313 ud->size += size;
315 return size;