2 * Copyright (C) 2011-2012 Free Software Foundation, Inc.
3 * Author: Simon Josefsson
5 * This file is part of GnuTLS.
7 * The GnuTLS is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public License
9 * as published by the Free Software Foundation; either version 3 of
10 * the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>
22 /* Online Certificate Status Protocol - RFC 2560
25 #include <gnutls_int.h>
26 #include <gnutls_global.h>
27 #include <gnutls_errors.h>
29 #include <gnutls_pk.h>
30 #include "algorithms.h"
32 #include <gnutls/ocsp.h>
34 /* I18n of error codes. */
36 #define _(String) dgettext (PACKAGE, String)
38 #define addf _gnutls_buffer_append_printf
39 #define adds _gnutls_buffer_append_str
42 print_req (gnutls_buffer_st
* str
, gnutls_ocsp_req_t req
)
49 int version
= gnutls_ocsp_req_get_version (req
);
51 addf (str
, "error: get_version: %s\n", gnutls_strerror (version
));
53 addf (str
, _("\tVersion: %d\n"), version
);
56 /* XXX requestorName */
59 addf (str
, "\tRequest List:\n");
60 for (indx
= 0; ; indx
++)
62 gnutls_digest_algorithm_t digest
;
63 gnutls_datum_t in
, ik
, sn
;
65 ret
= gnutls_ocsp_req_get_cert_id (req
, indx
, &digest
, &in
, &ik
, &sn
);
66 if (ret
== GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
)
68 addf (str
, "\t\tCertificate ID:\n");
69 if (ret
!= GNUTLS_E_SUCCESS
)
71 addf (str
, "error: get_cert_id: %s\n",
72 gnutls_strerror (ret
));
75 addf (str
, "\t\t\tHash Algorithm: %s\n",
76 _gnutls_digest_get_name (digest
));
78 adds (str
, "\t\t\tIssuer Name Hash: ");
79 _gnutls_buffer_hexprint (str
, in
.data
, in
.size
);
82 adds (str
, "\t\t\tIssuer Key Hash: ");
83 _gnutls_buffer_hexprint (str
, ik
.data
, ik
.size
);
86 adds (str
, "\t\t\tSerial Number: ");
87 _gnutls_buffer_hexprint (str
, sn
.data
, sn
.size
);
90 gnutls_free (in
.data
);
91 gnutls_free (ik
.data
);
92 gnutls_free (sn
.data
);
94 /* XXX singleRequestExtensions */
97 for (indx
= 0; ; indx
++)
100 unsigned int critical
;
103 ret
= gnutls_ocsp_req_get_extension (req
, indx
, &oid
, &critical
, &data
);
104 if (ret
== GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
)
106 else if (ret
!= GNUTLS_E_SUCCESS
)
108 addf (str
, "error: get_extension: %s\n",
109 gnutls_strerror (ret
));
113 adds (str
, "\tExtensions:\n");
115 if (memcmp (oid
.data
, GNUTLS_OCSP_NONCE
, oid
.size
) == 0)
117 gnutls_datum_t nonce
;
118 unsigned int critical
;
120 ret
= gnutls_ocsp_req_get_nonce (req
, &critical
, &nonce
);
121 if (ret
!= GNUTLS_E_SUCCESS
)
123 addf (str
, "error: get_nonce: %s\n",
124 gnutls_strerror (ret
));
128 addf (str
, "\t\tNonce%s: ", critical
? " (critical)" : "");
129 _gnutls_buffer_hexprint (str
, nonce
.data
, nonce
.size
);
131 gnutls_free (nonce
.data
);
136 addf (str
, "\t\tUnknown extension %s (%s):\n", oid
.data
,
137 critical
? "critical" : "not critical");
139 addf (str
, _("\t\t\tASCII: "));
140 _gnutls_buffer_asciiprint (str
, (char*)data
.data
, data
.size
);
143 addf (str
, _("\t\t\tHexdump: "));
144 _gnutls_buffer_hexprint (str
, (char*)data
.data
, data
.size
);
148 gnutls_free (oid
.data
);
149 gnutls_free (data
.data
);
156 * gnutls_ocsp_req_print:
157 * @req: The structure to be printed
158 * @format: Indicate the format to use
159 * @out: Newly allocated datum with (0) terminated string.
161 * This function will pretty print a OCSP request, suitable for
162 * display to a human.
164 * If the format is %GNUTLS_PRINT_FULL then all fields of the request
165 * will be output, on multiple lines.
167 * The output @out->data needs to be deallocate using gnutls_free().
169 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
170 * negative error value.
173 gnutls_ocsp_req_print (gnutls_ocsp_req_t req
,
174 gnutls_ocsp_print_formats_t format
,
175 gnutls_datum_t
* out
)
177 gnutls_buffer_st str
;
180 if (format
!= GNUTLS_OCSP_PRINT_FULL
)
183 return GNUTLS_E_INVALID_REQUEST
;
186 _gnutls_buffer_init (&str
);
188 _gnutls_buffer_append_str (&str
, _("OCSP Request Information:\n"));
190 print_req (&str
, req
);
192 _gnutls_buffer_append_data (&str
, "\0", 1);
194 rc
= _gnutls_buffer_to_datum (&str
, out
);
195 if (rc
!= GNUTLS_E_SUCCESS
)
201 return GNUTLS_E_SUCCESS
;
205 print_resp (gnutls_buffer_st
* str
, gnutls_ocsp_resp_t resp
,
206 gnutls_ocsp_print_formats_t format
)
211 ret
= gnutls_ocsp_resp_get_status (resp
);
214 addf (str
, "error: ocsp_resp_get_status: %s\n",
215 gnutls_strerror (ret
));
219 adds (str
, "\tResponse Status: ");
222 case GNUTLS_OCSP_RESP_SUCCESSFUL
:
223 adds (str
, "Successful\n");
226 case GNUTLS_OCSP_RESP_MALFORMEDREQUEST
:
227 adds (str
, "malformedRequest\n");
230 case GNUTLS_OCSP_RESP_INTERNALERROR
:
231 adds (str
, "internalError\n");
234 case GNUTLS_OCSP_RESP_TRYLATER
:
235 adds (str
, "tryLater\n");
238 case GNUTLS_OCSP_RESP_SIGREQUIRED
:
239 adds (str
, "sigRequired\n");
242 case GNUTLS_OCSP_RESP_UNAUTHORIZED
:
243 adds (str
, "unauthorized\n");
247 adds (str
, "unknown\n");
254 ret
= gnutls_ocsp_resp_get_response (resp
, &oid
, NULL
);
257 addf (str
, "error: get_response: %s\n", gnutls_strerror (ret
));
261 adds (str
, "\tResponse Type: ");
262 #define OCSP_BASIC "1.3.6.1.5.5.7.48.1.1"
264 if (oid
.size
== sizeof (OCSP_BASIC
)
265 && memcmp (oid
.data
, OCSP_BASIC
, oid
.size
) == 0)
267 adds (str
, "Basic OCSP Response\n");
268 gnutls_free (oid
.data
);
272 addf (str
, "Unknown response type (%.*s)\n", oid
.size
, oid
.data
);
273 gnutls_free (oid
.data
);
280 int version
= gnutls_ocsp_resp_get_version (resp
);
282 addf (str
, "error: get_version: %s\n", gnutls_strerror (version
));
284 addf (str
, _("\tVersion: %d\n"), version
);
293 ret
= gnutls_ocsp_resp_get_responder (resp
, &dn
);
295 addf (str
, "error: get_dn: %s\n", gnutls_strerror (ret
));
298 addf (str
, _("\tResponder ID: %.*s\n"), dn
.size
, dn
.data
);
299 gnutls_free (dn
.data
);
305 size_t max
= sizeof (s
);
307 time_t tim
= gnutls_ocsp_resp_get_produced (resp
);
309 if (tim
== (time_t) -1)
310 addf (str
, "error: ocsp_resp_get_produced\n");
311 else if (gmtime_r (&tim
, &t
) == NULL
)
312 addf (str
, "error: gmtime_r (%ld)\n", (unsigned long) tim
);
313 else if (strftime (s
, max
, "%a %b %d %H:%M:%S UTC %Y", &t
) == 0)
314 addf (str
, "error: strftime (%ld)\n", (unsigned long) tim
);
316 addf (str
, _("\tProduced At: %s\n"), s
);
319 addf (str
, "\tResponses:\n");
320 for (indx
= 0; ; indx
++)
322 gnutls_digest_algorithm_t digest
;
323 gnutls_datum_t in
, ik
, sn
;
324 unsigned int cert_status
;
327 time_t revocation_time
;
328 unsigned int revocation_reason
;
330 ret
= gnutls_ocsp_resp_get_single (resp
,
332 &digest
, &in
, &ik
, &sn
,
338 if (ret
== GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
)
340 addf (str
, "\t\tCertificate ID:\n");
341 if (ret
!= GNUTLS_E_SUCCESS
)
343 addf (str
, "error: get_singleresponse: %s\n",
344 gnutls_strerror (ret
));
347 addf (str
, "\t\t\tHash Algorithm: %s\n",
348 _gnutls_digest_get_name (digest
));
350 adds (str
, "\t\t\tIssuer Name Hash: ");
351 _gnutls_buffer_hexprint (str
, in
.data
, in
.size
);
354 adds (str
, "\t\t\tIssuer Key Hash: ");
355 _gnutls_buffer_hexprint (str
, ik
.data
, ik
.size
);
358 adds (str
, "\t\t\tSerial Number: ");
359 _gnutls_buffer_hexprint (str
, sn
.data
, sn
.size
);
362 gnutls_free (in
.data
);
363 gnutls_free (ik
.data
);
364 gnutls_free (sn
.data
);
367 const char *p
= NULL
;
371 case GNUTLS_OCSP_CERT_GOOD
:
375 case GNUTLS_OCSP_CERT_REVOKED
:
379 case GNUTLS_OCSP_CERT_UNKNOWN
:
384 addf (str
, "\t\tCertificate Status: unexpected value %d\n",
390 addf (str
, "\t\tCertificate Status: %s\n", p
);
393 /* XXX revocation reason */
395 if (cert_status
== GNUTLS_OCSP_CERT_REVOKED
)
398 size_t max
= sizeof (s
);
401 if (revocation_time
== (time_t) -1)
402 addf (str
, "error: revocation_time\n");
403 else if (gmtime_r (&revocation_time
, &t
) == NULL
)
404 addf (str
, "error: gmtime_r (%ld)\n",
405 (unsigned long) revocation_time
);
406 else if (strftime (s
, max
, "%a %b %d %H:%M:%S UTC %Y", &t
) == 0)
407 addf (str
, "error: strftime (%ld)\n",
408 (unsigned long) revocation_time
);
410 addf (str
, _("\t\tRevocation time: %s\n"), s
);
415 size_t max
= sizeof (s
);
418 if (this_update
== (time_t) -1)
419 addf (str
, "error: this_update\n");
420 else if (gmtime_r (&this_update
, &t
) == NULL
)
421 addf (str
, "error: gmtime_r (%ld)\n", (unsigned long) this_update
);
422 else if (strftime (s
, max
, "%a %b %d %H:%M:%S UTC %Y", &t
) == 0)
423 addf (str
, "error: strftime (%ld)\n", (unsigned long) this_update
);
425 addf (str
, _("\t\tThis Update: %s\n"), s
);
430 size_t max
= sizeof (s
);
433 if (next_update
== (time_t) -1)
434 addf (str
, "error: next_update\n");
435 else if (gmtime_r (&next_update
, &t
) == NULL
)
436 addf (str
, "error: gmtime_r (%ld)\n", (unsigned long) next_update
);
437 else if (strftime (s
, max
, "%a %b %d %H:%M:%S UTC %Y", &t
) == 0)
438 addf (str
, "error: strftime (%ld)\n", (unsigned long) next_update
);
440 addf (str
, _("\t\tNext Update: %s\n"), s
);
443 /* XXX singleRequestExtensions */
446 adds (str
, "\tExtensions:\n");
447 for (indx
= 0; ; indx
++)
450 unsigned int critical
;
453 ret
= gnutls_ocsp_resp_get_extension (resp
, indx
, &oid
, &critical
, &data
);
454 if (ret
== GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
)
456 else if (ret
!= GNUTLS_E_SUCCESS
)
458 addf (str
, "error: get_extension: %s\n",
459 gnutls_strerror (ret
));
463 if (memcmp (oid
.data
, GNUTLS_OCSP_NONCE
, oid
.size
) == 0)
465 gnutls_datum_t nonce
;
466 unsigned int critical
;
468 ret
= gnutls_ocsp_resp_get_nonce (resp
, &critical
, &nonce
);
469 if (ret
!= GNUTLS_E_SUCCESS
)
471 addf (str
, "error: get_nonce: %s\n",
472 gnutls_strerror (ret
));
476 addf (str
, "\t\tNonce%s: ", critical
? " (critical)" : "");
477 _gnutls_buffer_hexprint (str
, nonce
.data
, nonce
.size
);
479 gnutls_free (nonce
.data
);
484 addf (str
, "\t\tUnknown extension %s (%s):\n", oid
.data
,
485 critical
? "critical" : "not critical");
487 addf (str
, _("\t\t\tASCII: "));
488 _gnutls_buffer_asciiprint (str
, (char*)data
.data
, data
.size
);
491 addf (str
, _("\t\t\tHexdump: "));
492 _gnutls_buffer_hexprint (str
, (char*)data
.data
, data
.size
);
496 gnutls_free (oid
.data
);
497 gnutls_free (data
.data
);
501 if (format
== GNUTLS_OCSP_PRINT_FULL
)
505 ret
= gnutls_ocsp_resp_get_signature_algorithm (resp
);
507 addf (str
, "retor: get_signature_algorithm: %s\n",
508 gnutls_strerror (ret
));
511 const char *name
= gnutls_sign_algorithm_get_name (ret
);
514 addf (str
, _("\tSignature Algorithm: %s\n"), name
);
516 if (ret
== GNUTLS_SIGN_RSA_MD5
|| ret
== GNUTLS_SIGN_RSA_MD2
)
518 adds (str
, _("warning: signed using a broken signature "
519 "algorithm that can be forged.\n"));
522 ret
= gnutls_ocsp_resp_get_signature (resp
, &sig
);
524 addf (str
, "error: get_signature: %s\n", gnutls_strerror (ret
));
527 adds (str
, _("\tSignature:\n"));
528 _gnutls_buffer_hexdump (str
, sig
.data
, sig
.size
, "\t\t");
530 gnutls_free (sig
.data
);
535 if (format
== GNUTLS_OCSP_PRINT_FULL
)
537 gnutls_x509_crt_t
*certs
;
541 ret
= gnutls_ocsp_resp_get_certs (resp
, &certs
, &ncerts
);
543 addf (str
, "error: get_certs: %s\n", gnutls_strerror (ret
));
546 for (i
= 0; i
< ncerts
; i
++)
550 ret
= gnutls_x509_crt_print (certs
[i
], GNUTLS_CRT_PRINT_FULL
,
553 addf (str
, "error: crt_print: %s\n", gnutls_strerror (ret
));
556 addf (str
, "%.*s", out
.size
, out
.data
);
557 gnutls_free (out
.data
);
560 ret
= gnutls_x509_crt_export (certs
[i
], GNUTLS_X509_FMT_PEM
,
562 if (ret
!= GNUTLS_E_SHORT_MEMORY_BUFFER
)
563 addf (str
, "error: crt_export: %s\n", gnutls_strerror (ret
));
566 out
.data
= gnutls_malloc (s
);
567 if (out
.data
== NULL
)
568 addf (str
, "error: malloc: %s\n",
569 gnutls_strerror (GNUTLS_E_MEMORY_ERROR
));
572 ret
= gnutls_x509_crt_export (certs
[i
], GNUTLS_X509_FMT_PEM
,
575 addf (str
, "%.*s", out
.size
, out
.data
);
576 gnutls_free (out
.data
);
580 gnutls_x509_crt_deinit (certs
[i
]);
588 * gnutls_ocsp_resp_print:
589 * @resp: The structure to be printed
590 * @format: Indicate the format to use
591 * @out: Newly allocated datum with (0) terminated string.
593 * This function will pretty print a OCSP response, suitable for
594 * display to a human.
596 * If the format is %GNUTLS_PRINT_FULL then all fields of the response
597 * will be output, on multiple lines.
599 * The output @out->data needs to be deallocate using gnutls_free().
601 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
602 * negative error value.
605 gnutls_ocsp_resp_print (gnutls_ocsp_resp_t resp
,
606 gnutls_ocsp_print_formats_t format
,
607 gnutls_datum_t
* out
)
609 gnutls_buffer_st str
;
612 _gnutls_buffer_init (&str
);
614 _gnutls_buffer_append_str (&str
, _("OCSP Response Information:\n"));
616 print_resp (&str
, resp
, format
);
618 _gnutls_buffer_append_data (&str
, "\0", 1);
620 rc
= _gnutls_buffer_to_datum (&str
, out
);
621 if (rc
!= GNUTLS_E_SUCCESS
)
627 return GNUTLS_E_SUCCESS
;