1 /* t-ocsp.c - Basic tests for the OCSP subsystem.
2 * Copyright (C) 2003 g10 Code GmbH
4 * This file is part of KSBA.
6 * KSBA is free software; you can redistribute it and/or modify
7 * it 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 * KSBA is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU 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 <http://www.gnu.org/licenses/>.
29 #include "../src/ksba.h"
33 #include "oidtranstbl.h"
40 /* Return the description for OID; if no description is available
43 get_oid_desc (const char *oid)
48 for (i=0; oidtranstbl[i].oid; i++)
49 if (!strcmp (oidtranstbl[i].oid, oid))
50 return oidtranstbl[i].desc;
55 static unsigned char *
56 read_file (const char *fname, size_t *r_length)
63 fp = fopen (fname, "rb");
66 fprintf (stderr, "can't open `%s': %s\n", fname, strerror (errno));
70 if (fstat (fileno(fp), &st))
72 fprintf (stderr, "can't stat `%s': %s\n", fname, strerror (errno));
78 buf = xmalloc (buflen+1);
79 if (fread (buf, buflen, 1, fp) != 1)
81 fprintf (stderr, "error reading `%s': %s\n", fname, strerror (errno));
95 get_one_cert (const char *fname)
102 fp = fopen (fname, "r");
105 fprintf (stderr, "%s:%d: can't open `%s': %s\n",
106 __FILE__, __LINE__, fname, strerror (errno));
110 err = ksba_reader_new (&r);
113 err = ksba_reader_set_file (r, fp);
116 err = ksba_cert_new (&cert);
120 err = ksba_cert_read_der (cert, r);
121 fail_if_err2 (fname, err);
126 /* Create a request for the DER encoded certificate in the file
127 CERT_FNAME and its issuer's certificate in the file
128 ISSUER_CERT_FNAME. */
130 one_request (const char *cert_fname, const char *issuer_cert_fname)
133 ksba_cert_t cert = get_one_cert (cert_fname);
134 ksba_cert_t issuer_cert = get_one_cert (issuer_cert_fname);
136 unsigned char *request;
139 err = ksba_ocsp_new (&ocsp);
142 err = ksba_ocsp_add_target (ocsp, cert, issuer_cert);
144 ksba_cert_release (cert);
145 ksba_cert_release (issuer_cert);
148 ksba_ocsp_set_nonce (ocsp, "ABCDEFGHIJKLMNOP", 16);
150 err = ksba_ocsp_build_request (ocsp, &request, &requestlen);
152 ksba_ocsp_release (ocsp);
154 printf ("OCSP request of length %u created\n", (unsigned int)requestlen);
157 FILE *fp = fopen ("a.req", "wb");
159 fail ("can't create output file `a.req'");
160 if (fwrite (request, requestlen, 1, fp) != 1)
161 fail ("can't write output");
170 one_response (const char *cert_fname, const char *issuer_cert_fname,
171 char *response_fname)
175 unsigned char *request, *response;
176 size_t requestlen, responselen;
177 ksba_cert_t cert = get_one_cert (cert_fname);
178 ksba_cert_t issuer_cert = get_one_cert (issuer_cert_fname);
179 ksba_ocsp_response_status_t response_status;
182 err = ksba_ocsp_new (&ocsp);
185 /* We need to build a request, so that the context is properly
186 prepared for the response. */
187 err = ksba_ocsp_add_target (ocsp, cert, issuer_cert);
189 ksba_cert_release (issuer_cert);
192 ksba_ocsp_set_nonce (ocsp, "ABCDEFGHIJKLMNOP", 16);
194 err = ksba_ocsp_build_request (ocsp, &request, &requestlen);
198 /* Now for the response. */
199 response = read_file (response_fname, &responselen);
203 err = ksba_ocsp_parse_response (ocsp, response, responselen,
206 switch (response_status)
208 case KSBA_OCSP_RSPSTATUS_SUCCESS: t = "success"; break;
209 case KSBA_OCSP_RSPSTATUS_MALFORMED: t = "malformed"; break;
210 case KSBA_OCSP_RSPSTATUS_INTERNAL: t = "internal error"; break;
211 case KSBA_OCSP_RSPSTATUS_TRYLATER: t = "try later"; break;
212 case KSBA_OCSP_RSPSTATUS_SIGREQUIRED: t = "must sign request"; break;
213 case KSBA_OCSP_RSPSTATUS_UNAUTHORIZED: t = "unauthorized"; break;
214 case KSBA_OCSP_RSPSTATUS_REPLAYED: t = "replay detected"; break;
215 case KSBA_OCSP_RSPSTATUS_OTHER: t = "other (unknown)"; break;
216 case KSBA_OCSP_RSPSTATUS_NONE: t = "no status"; break;
217 default: fail ("impossible response_status"); break;
219 printf ("response status ..: %s\n", t);
221 if (response_status == KSBA_OCSP_RSPSTATUS_SUCCESS
222 || response_status == KSBA_OCSP_RSPSTATUS_REPLAYED)
224 ksba_status_t status;
225 ksba_crl_reason_t reason;
226 ksba_isotime_t this_update, next_update, revocation_time, produced_at;
231 err = ksba_ocsp_get_responder_id (ocsp, &name, &keyid);
233 printf ("responder id .....: ");
235 printf ("`%s'", name);
242 sigval = ksba_ocsp_get_sig_val (ocsp, produced_at);
243 printf ("signature value ..: ");
245 printf ("\nproduced at ......: ");
246 print_time (produced_at);
248 err = ksba_ocsp_get_status (ocsp, cert,
249 &status, this_update, next_update,
250 revocation_time, &reason);
252 printf ("certificate status: %s\n",
253 status == KSBA_STATUS_GOOD? "good":
254 status == KSBA_STATUS_REVOKED? "revoked":
255 status == KSBA_STATUS_UNKNOWN? "unknown":
256 status == KSBA_STATUS_NONE? "none": "?");
257 if (status == KSBA_STATUS_REVOKED)
259 printf ("revocation time ..: ");
260 print_time (revocation_time);
261 printf ("\nrevocation reason : %s\n",
262 reason == KSBA_CRLREASON_UNSPECIFIED? "unspecified":
263 reason == KSBA_CRLREASON_KEY_COMPROMISE? "key compromise":
264 reason == KSBA_CRLREASON_CA_COMPROMISE? "CA compromise":
265 reason == KSBA_CRLREASON_AFFILIATION_CHANGED?
266 "affiliation changed":
267 reason == KSBA_CRLREASON_SUPERSEDED? "superseeded":
268 reason == KSBA_CRLREASON_CESSATION_OF_OPERATION?
269 "cessation of operation":
270 reason == KSBA_CRLREASON_CERTIFICATE_HOLD?
271 "certificate on hold":
272 reason == KSBA_CRLREASON_REMOVE_FROM_CRL? "removed from CRL":
273 reason == KSBA_CRLREASON_PRIVILEGE_WITHDRAWN?
274 "privilege withdrawn":
275 reason == KSBA_CRLREASON_AA_COMPROMISE? "AA compromise":
276 reason == KSBA_CRLREASON_OTHER? "other":"?");
278 printf ("this update ......: ");
279 print_time (this_update);
280 printf ("\nnext update ......: ");
281 print_time (next_update);
287 for (cert_idx=0; (acert = ksba_ocsp_get_cert (ocsp, cert_idx));
289 ksba_cert_release (acert);
290 printf ("extra certificates: %d\n", cert_idx );
296 const unsigned char *der;
299 for (idx=0; !(err=ksba_ocsp_get_extension (ocsp, NULL, idx,
301 &der, &derlen)); idx++)
303 const char *s = get_oid_desc (oid);
304 printf ("%sresp-extn ..%s: %s%s%s%s (",
307 s?"(":"", s?s:"", s?") ":"", oid);
308 print_hex (der, derlen);
312 if (err && gpg_err_code (err) != GPG_ERR_EOF)
315 for (idx=0; !(err=ksba_ocsp_get_extension (ocsp, cert, idx,
317 &der, &derlen)); idx++)
319 const char *s = get_oid_desc (oid);
320 printf ("%ssngl-extn ..%s: %s%s%s%s (",
323 s?"(":"", s?s:"", s?") ":"", oid);
324 print_hex (der, derlen);
328 if (err && gpg_err_code (err) != GPG_ERR_EOF)
334 ksba_cert_release (cert);
335 ksba_ocsp_release (ocsp);
341 my_hash_buffer (void *arg, const char *oid,
342 const void *buffer, size_t length, size_t resultsize,
343 unsigned char *result, size_t *resultlen)
345 (void)arg; /* Not used. */
347 if (oid && strcmp (oid, "1.3.14.3.2.26"))
348 return gpg_error (GPG_ERR_NOT_SUPPORTED); /* We only support SHA-1. */
350 return gpg_error (GPG_ERR_BUFFER_TOO_SHORT);
351 sha1_hash_buffer (result, buffer, length);
359 /* ( printf "POST / HTTP/1.0\r\nContent-Type: application/ocsp-request\r\nContent-Length: `wc -c <a.req | tr -d ' '`\r\n\r\n"; cat a.req ) | nc -v ocsp.openvalidation.org 8088 | sed '1,/^\r$/d' >a.rsp
361 Openvalidation test reponders:
363 Port: 80 Standard configuration. OCSP Responder will accept
364 all proper requests and send a signed response.
365 Port: 8080 Response does not contain any attached certificates.
366 Client must accept this response
367 Port: 8081 Never replies nonce. Insecure but standard conform mode.
368 Client application should warn in case of replay-attacks.
369 Port: 8082 The OCSP Responder will sign the response with randomized
370 bytecode. Client should NOT accept this response.
371 Port: 8083 OCSP response will always be revoked.
372 Port: 8084 OCSP response will always be unknown.
373 Port: 8085 OCSP response will always be malformed.
374 Port: 8086 OCSP response will always be internal error.
375 Port: 8087 OCSP response will always be try later.
376 Port: 8088 OCSP response will always be signature required.
377 Port: 8089 OCSP response will always be unauth.
378 Port: 8090 Standard configuration with full Debuglogs. Access the
379 logs at http://www.openvalidation.org/en/test/logs.html
384 main (int argc, char **argv)
387 int response_mode = 0;
388 const char *srcdir = getenv ("srcdir");
393 ksba_set_hash_buffer_function (my_hash_buffer, NULL);
399 while (argc && last_argc != argc )
402 if (!strcmp (*argv, "--help"))
405 "usage: ./t-ocsp [options] {CERTFILE ISSUERCERTFILE}\n"
406 " ./t-ocsp [options] --response {CERTFILE ISSUERCERTFILE RESPONSEFILE}\n"
408 " Options are --verbose and --debug");
411 if (!strcmp (*argv, "--verbose"))
416 else if (!strcmp (*argv, "--debug"))
421 else if (!strcmp (*argv, "--response"))
426 else if (!strcmp (*argv, "--no-nonce"))
436 for ( ; argc > 2; argc -=3, argv += 3)
437 one_response (*argv, argv[1], argv[2]);
439 fputs ("warning: extra argument ignored\n", stderr);
443 for ( ; argc > 1; argc -=2, argv += 2)
444 one_request (*argv, argv[1]);
446 fputs ("warning: extra argument ignored\n", stderr);
451 const char *cert_fname;
452 const char *issuer_cert_fname;
453 const char *response_fname;
455 { "samples/ov-userrev.crt", "samples/ov-root-ca-cert.crt", NULL },
460 for (idx=0; files[idx].cert_fname; idx++)
464 f1 = prepend_srcdir (files[idx].cert_fname);
465 f2 = prepend_srcdir (files[idx].issuer_cert_fname);
466 one_request (f1, f2);