_gnutls_strdatum_to_buf() will account for NULL input.
[gnutls.git] / src / ocsptool.c
blob7f93369f1b49aa48e21191089b1fa140065712ac
1 /*
2 * Copyright (C) 2011-2012 Free Software Foundation, Inc.
4 * This file is part of GnuTLS.
6 * GnuTLS is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GnuTLS is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see
18 * <http://www.gnu.org/licenses/>.
21 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
28 #include <gnutls/gnutls.h>
29 #include <gnutls/ocsp.h>
30 #include <gnutls/x509.h>
31 #include <gnutls/crypto.h>
33 /* Gnulib portability files. */
34 #include <error.h>
35 #include <progname.h>
36 #include <version-etc.h>
37 #include <read-file.h>
38 #include <socket.h>
40 #include <ocsptool-common.h>
41 #include <ocsptool-args.h>
43 FILE *outfile;
44 FILE *infile;
45 static unsigned int encoding;
46 unsigned int verbose = 0;
48 static void
49 tls_log_func (int level, const char *str)
51 fprintf (stderr, "|<%d>| %s", level, str);
54 static void
55 request_info (void)
57 gnutls_ocsp_req_t req;
58 int ret;
59 gnutls_datum_t dat;
60 size_t size;
62 ret = gnutls_ocsp_req_init (&req);
63 if (ret < 0)
64 error (EXIT_FAILURE, 0, "ocsp_req_init: %s", gnutls_strerror (ret));
66 if (HAVE_OPT(LOAD_REQUEST))
67 dat.data = (void*)read_binary_file (OPT_ARG(LOAD_REQUEST), &size);
68 else
69 dat.data = (void*)fread_file (infile, &size);
70 if (dat.data == NULL)
71 error (EXIT_FAILURE, errno, "reading request");
72 dat.size = size;
74 ret = gnutls_ocsp_req_import (req, &dat);
75 free (dat.data);
76 if (ret < 0)
77 error (EXIT_FAILURE, 0, "importing request: %s", gnutls_strerror (ret));
79 ret = gnutls_ocsp_req_print (req, GNUTLS_OCSP_PRINT_FULL, &dat);
80 if (ret != 0)
81 error (EXIT_FAILURE, 0, "ocsp_req_print: %s", gnutls_strerror (ret));
83 printf ("%.*s", dat.size, dat.data);
84 gnutls_free (dat.data);
86 gnutls_ocsp_req_deinit (req);
89 static void
90 _response_info (const gnutls_datum_t* data)
92 gnutls_ocsp_resp_t resp;
93 int ret;
94 gnutls_datum buf;
96 ret = gnutls_ocsp_resp_init (&resp);
97 if (ret < 0)
98 error (EXIT_FAILURE, 0, "ocsp_resp_init: %s", gnutls_strerror (ret));
100 ret = gnutls_ocsp_resp_import (resp, data);
101 if (ret < 0)
102 error (EXIT_FAILURE, 0, "importing response: %s", gnutls_strerror (ret));
104 if (ENABLED_OPT(VERBOSE))
105 ret = gnutls_ocsp_resp_print (resp, GNUTLS_OCSP_PRINT_FULL, &buf);
106 else
107 ret = gnutls_ocsp_resp_print (resp, GNUTLS_OCSP_PRINT_COMPACT, &buf);
108 if (ret != 0)
109 error (EXIT_FAILURE, 0, "ocsp_resp_print: %s", gnutls_strerror (ret));
111 printf ("%.*s", buf.size, buf.data);
112 gnutls_free (buf.data);
114 gnutls_ocsp_resp_deinit (resp);
117 static void
118 response_info (void)
120 gnutls_datum_t dat;
121 size_t size;
123 if (HAVE_OPT(LOAD_RESPONSE))
124 dat.data = (void*)read_binary_file (OPT_ARG(LOAD_RESPONSE), &size);
125 else
126 dat.data = (void*)fread_file (infile, &size);
127 if (dat.data == NULL)
128 error (EXIT_FAILURE, errno, "reading response");
129 dat.size = size;
131 _response_info(&dat);
132 gnutls_free (dat.data);
135 static gnutls_x509_crt_t
136 load_issuer (void)
138 gnutls_x509_crt_t crt;
139 int ret;
140 gnutls_datum_t dat;
141 size_t size;
143 if (!HAVE_OPT(LOAD_ISSUER))
144 error (EXIT_FAILURE, 0, "missing --load-issuer");
146 ret = gnutls_x509_crt_init (&crt);
147 if (ret < 0)
148 error (EXIT_FAILURE, 0, "crt_init: %s", gnutls_strerror (ret));
150 dat.data = (void*)read_binary_file (OPT_ARG(LOAD_ISSUER), &size);
151 dat.size = size;
153 if (!dat.data)
154 error (EXIT_FAILURE, errno, "reading --load-issuer: %s", OPT_ARG(LOAD_ISSUER));
156 ret = gnutls_x509_crt_import (crt, &dat, encoding);
157 free (dat.data);
158 if (ret < 0)
159 error (EXIT_FAILURE, 0, "importing --load-issuer: %s: %s",
160 OPT_ARG(LOAD_ISSUER), gnutls_strerror (ret));
162 return crt;
165 static gnutls_x509_crt_t
166 load_cert (void)
168 gnutls_x509_crt_t crt;
169 int ret;
170 gnutls_datum_t dat;
171 size_t size;
173 if (!HAVE_OPT(LOAD_CERT))
174 error (EXIT_FAILURE, 0, "missing --load-cert");
176 ret = gnutls_x509_crt_init (&crt);
177 if (ret < 0)
178 error (EXIT_FAILURE, 0, "crt_init: %s", gnutls_strerror (ret));
180 dat.data = (void*)read_binary_file (OPT_ARG(LOAD_CERT), &size);
181 dat.size = size;
183 if (!dat.data)
184 error (EXIT_FAILURE, errno, "reading --load-cert: %s", OPT_ARG(LOAD_CERT));
186 ret = gnutls_x509_crt_import (crt, &dat, encoding);
187 free (dat.data);
188 if (ret < 0)
189 error (EXIT_FAILURE, 0, "importing --load-cert: %s: %s",
190 OPT_ARG(LOAD_CERT), gnutls_strerror (ret));
192 return crt;
195 static void
196 generate_request (void)
198 gnutls_datum_t dat;
200 _generate_request(load_cert(), load_issuer(), &dat, ENABLED_OPT(NONCE));
202 fwrite (dat.data, 1, dat.size, outfile);
204 gnutls_free (dat.data);
208 static int
209 _verify_response (gnutls_datum_t *data)
211 gnutls_ocsp_resp_t resp;
212 int ret;
213 size_t size;
214 gnutls_x509_crt_t *x509_ca_list = NULL;
215 unsigned int x509_ncas = 0;
216 gnutls_x509_trust_list_t list;
217 gnutls_x509_crt_t signer;
218 unsigned verify;
219 gnutls_datum_t dat;
221 ret = gnutls_ocsp_resp_init (&resp);
222 if (ret < 0)
223 error (EXIT_FAILURE, 0, "ocsp_resp_init: %s", gnutls_strerror (ret));
225 ret = gnutls_ocsp_resp_import (resp, data);
226 if (ret < 0)
227 error (EXIT_FAILURE, 0, "importing response: %s", gnutls_strerror (ret));
229 if (HAVE_OPT(LOAD_TRUST))
231 dat.data = (void*)read_binary_file (OPT_ARG(LOAD_TRUST), &size);
232 if (dat.data == NULL)
233 error (EXIT_FAILURE, errno, "reading --load-trust: %s", OPT_ARG(LOAD_TRUST));
234 dat.size = size;
236 ret = gnutls_x509_trust_list_init (&list, 0);
237 if (ret < 0)
238 error (EXIT_FAILURE, 0, "gnutls_x509_trust_list_init: %s",
239 gnutls_strerror (ret));
241 ret = gnutls_x509_crt_list_import2 (&x509_ca_list, &x509_ncas, &dat,
242 GNUTLS_X509_FMT_PEM, 0);
243 if (ret < 0 || x509_ncas < 1)
244 error (EXIT_FAILURE, 0, "error parsing CAs: %s",
245 gnutls_strerror (ret));
247 if (HAVE_OPT(VERBOSE))
249 unsigned int i;
250 printf ("Trust anchors:\n");
251 for (i = 0; i < x509_ncas; i++)
253 gnutls_datum_t out;
255 ret = gnutls_x509_crt_print (x509_ca_list[i],
256 GNUTLS_CRT_PRINT_ONELINE, &out);
257 if (ret < 0)
258 error (EXIT_FAILURE, 0, "gnutls_x509_crt_print: %s",
259 gnutls_strerror (ret));
261 printf ("%d: %.*s\n", i, out.size, out.data);
262 gnutls_free (out.data);
264 printf("\n");
267 ret = gnutls_x509_trust_list_add_cas (list, x509_ca_list, x509_ncas, 0);
268 if (ret < 0)
269 error (EXIT_FAILURE, 0, "gnutls_x509_trust_add_cas: %s",
270 gnutls_strerror (ret));
272 if (HAVE_OPT(VERBOSE))
273 fprintf (stdout, "Loaded %d trust anchors\n", x509_ncas);
275 ret = gnutls_ocsp_resp_verify (resp, list, &verify, 0);
276 if (ret < 0)
277 error (EXIT_FAILURE, 0, "gnutls_ocsp_resp_verify: %s",
278 gnutls_strerror (ret));
280 else if (HAVE_OPT(LOAD_SIGNER))
282 ret = gnutls_x509_crt_init (&signer);
283 if (ret < 0)
284 error (EXIT_FAILURE, 0, "crt_init: %s", gnutls_strerror (ret));
286 dat.data = (void*)read_binary_file (OPT_ARG(LOAD_SIGNER), &size);
287 if (dat.data == NULL)
288 error (EXIT_FAILURE, errno, "reading --load-signer: %s", OPT_ARG(LOAD_SIGNER));
289 dat.size = size;
291 ret = gnutls_x509_crt_import (signer, &dat, encoding);
292 free (dat.data);
293 if (ret < 0)
294 error (EXIT_FAILURE, 0, "importing --load-signer: %s: %s",
295 OPT_ARG(LOAD_SIGNER), gnutls_strerror (ret));
297 if (HAVE_OPT(VERBOSE))
299 gnutls_datum_t out;
301 ret = gnutls_x509_crt_print (signer, GNUTLS_CRT_PRINT_ONELINE, &out);
302 if (ret < 0)
303 error (EXIT_FAILURE, 0, "gnutls_x509_crt_print: %s",
304 gnutls_strerror (ret));
306 printf ("Signer: %.*s\n", out.size, out.data);
307 gnutls_free (out.data);
308 printf("\n");
311 ret = gnutls_ocsp_resp_verify_direct (resp, signer, &verify, 0);
312 if (ret < 0)
313 error (EXIT_FAILURE, 0, "gnutls_ocsp_resp_verify_direct: %s",
314 gnutls_strerror (ret));
316 else
317 error (EXIT_FAILURE, 0, "missing --load-trust or --load-signer");
319 printf ("Verifying OCSP Response: ");
320 print_ocsp_verify_res (verify);
321 printf (".\n");
323 gnutls_ocsp_resp_deinit (resp);
325 return verify;
328 static void
329 verify_response (void)
331 gnutls_datum_t dat;
332 size_t size;
334 if (HAVE_OPT(LOAD_RESPONSE))
335 dat.data = (void*)read_binary_file (OPT_ARG(LOAD_RESPONSE), &size);
336 else
337 dat.data = (void*)fread_file (infile, &size);
338 if (dat.data == NULL)
339 error (EXIT_FAILURE, errno, "reading response");
340 dat.size = size;
342 _verify_response(&dat);
345 static void ask_server(const char* url)
347 gnutls_datum_t resp_data;
348 int ret, v;
349 gnutls_x509_crt_t cert, issuer;
351 cert = load_cert();
352 issuer = load_issuer();
354 ret = send_ocsp_request(url, cert, issuer, &resp_data, ENABLED_OPT(NONCE));
355 if (ret < 0)
357 fprintf(stderr, "Cannot send OCSP request\n");
358 exit(1);
361 _response_info (&resp_data);
363 if (HAVE_OPT(LOAD_SIGNER) || HAVE_OPT(LOAD_TRUST))
365 fprintf(outfile, "\n");
366 v = _verify_response(&resp_data);
368 else
370 fprintf(stderr, "\nResponse could not be verified (use --load-signer).\n");
371 v = 0;
374 if (HAVE_OPT(OUTFILE) && v == 0)
376 fwrite(resp_data.data, 1, resp_data.size, outfile);
381 main (int argc, char **argv)
383 int ret;
385 set_program_name (argv[0]);
387 if ((ret = gnutls_global_init ()) < 0)
388 error (EXIT_FAILURE, 0, "global_init: %s", gnutls_strerror (ret));
390 optionProcess( &ocsptoolOptions, argc, argv);
392 gnutls_global_set_log_function (tls_log_func);
393 gnutls_global_set_log_level (OPT_VALUE_DEBUG);
395 if (HAVE_OPT(OUTFILE))
397 outfile = fopen (OPT_ARG(OUTFILE), "wb");
398 if (outfile == NULL)
399 error (EXIT_FAILURE, errno, "%s", OPT_ARG(OUTFILE));
401 else
402 outfile = stdout;
404 if (HAVE_OPT(INFILE))
406 infile = fopen (OPT_ARG(INFILE), "rb");
407 if (infile == NULL)
408 error (EXIT_FAILURE, errno, "%s", OPT_ARG(INFILE));
410 else
411 infile = stdin;
413 if (ENABLED_OPT(INDER))
414 encoding = GNUTLS_X509_FMT_DER;
415 else
416 encoding = GNUTLS_X509_FMT_PEM;
418 if (HAVE_OPT(REQUEST_INFO))
419 request_info ();
420 else if (HAVE_OPT(RESPONSE_INFO))
421 response_info ();
422 else if (HAVE_OPT(GENERATE_REQUEST))
423 generate_request ();
424 else if (HAVE_OPT(VERIFY_RESPONSE))
425 verify_response ();
426 else if (HAVE_OPT(ASK))
427 ask_server(OPT_ARG(ASK));
428 else
430 USAGE(1);
433 return 0;