openssl-custom 2.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +7 -0
  2. data/BSDL +22 -0
  3. data/CONTRIBUTING.md +132 -0
  4. data/History.md +485 -0
  5. data/LICENSE.txt +56 -0
  6. data/README.md +66 -0
  7. data/ext/openssl/extconf.rb +190 -0
  8. data/ext/openssl/openssl_missing.c +106 -0
  9. data/ext/openssl/openssl_missing.h +257 -0
  10. data/ext/openssl/ossl.c +1282 -0
  11. data/ext/openssl/ossl.h +181 -0
  12. data/ext/openssl/ossl_asn1.c +1878 -0
  13. data/ext/openssl/ossl_asn1.h +62 -0
  14. data/ext/openssl/ossl_bio.c +42 -0
  15. data/ext/openssl/ossl_bio.h +16 -0
  16. data/ext/openssl/ossl_bn.c +1270 -0
  17. data/ext/openssl/ossl_bn.h +26 -0
  18. data/ext/openssl/ossl_cipher.c +1075 -0
  19. data/ext/openssl/ossl_cipher.h +20 -0
  20. data/ext/openssl/ossl_config.c +89 -0
  21. data/ext/openssl/ossl_config.h +19 -0
  22. data/ext/openssl/ossl_digest.c +425 -0
  23. data/ext/openssl/ossl_digest.h +20 -0
  24. data/ext/openssl/ossl_engine.c +567 -0
  25. data/ext/openssl/ossl_engine.h +19 -0
  26. data/ext/openssl/ossl_hmac.c +389 -0
  27. data/ext/openssl/ossl_hmac.h +18 -0
  28. data/ext/openssl/ossl_kdf.c +303 -0
  29. data/ext/openssl/ossl_kdf.h +6 -0
  30. data/ext/openssl/ossl_ns_spki.c +405 -0
  31. data/ext/openssl/ossl_ns_spki.h +19 -0
  32. data/ext/openssl/ossl_ocsp.c +2013 -0
  33. data/ext/openssl/ossl_ocsp.h +23 -0
  34. data/ext/openssl/ossl_pkcs12.c +257 -0
  35. data/ext/openssl/ossl_pkcs12.h +13 -0
  36. data/ext/openssl/ossl_pkcs7.c +1098 -0
  37. data/ext/openssl/ossl_pkcs7.h +36 -0
  38. data/ext/openssl/ossl_pkey.c +673 -0
  39. data/ext/openssl/ossl_pkey.h +241 -0
  40. data/ext/openssl/ossl_pkey_dh.c +650 -0
  41. data/ext/openssl/ossl_pkey_dsa.c +664 -0
  42. data/ext/openssl/ossl_pkey_ec.c +1827 -0
  43. data/ext/openssl/ossl_pkey_rsa.c +966 -0
  44. data/ext/openssl/ossl_rand.c +200 -0
  45. data/ext/openssl/ossl_rand.h +18 -0
  46. data/ext/openssl/ossl_ssl.c +3080 -0
  47. data/ext/openssl/ossl_ssl.h +36 -0
  48. data/ext/openssl/ossl_ssl_session.c +332 -0
  49. data/ext/openssl/ossl_ts.c +1524 -0
  50. data/ext/openssl/ossl_ts.h +16 -0
  51. data/ext/openssl/ossl_x509.c +262 -0
  52. data/ext/openssl/ossl_x509.h +115 -0
  53. data/ext/openssl/ossl_x509attr.c +324 -0
  54. data/ext/openssl/ossl_x509cert.c +846 -0
  55. data/ext/openssl/ossl_x509crl.c +542 -0
  56. data/ext/openssl/ossl_x509ext.c +491 -0
  57. data/ext/openssl/ossl_x509name.c +590 -0
  58. data/ext/openssl/ossl_x509req.c +441 -0
  59. data/ext/openssl/ossl_x509revoked.c +300 -0
  60. data/ext/openssl/ossl_x509store.c +902 -0
  61. data/ext/openssl/ruby_missing.h +24 -0
  62. data/lib/openssl/bn.rb +40 -0
  63. data/lib/openssl/buffering.rb +478 -0
  64. data/lib/openssl/cipher.rb +67 -0
  65. data/lib/openssl/config.rb +501 -0
  66. data/lib/openssl/digest.rb +73 -0
  67. data/lib/openssl/hmac.rb +13 -0
  68. data/lib/openssl/marshal.rb +30 -0
  69. data/lib/openssl/pkcs5.rb +22 -0
  70. data/lib/openssl/pkey.rb +42 -0
  71. data/lib/openssl/ssl.rb +542 -0
  72. data/lib/openssl/version.rb +5 -0
  73. data/lib/openssl/x509.rb +369 -0
  74. data/lib/openssl.rb +38 -0
  75. metadata +196 -0
@@ -0,0 +1,2013 @@
1
+ /*
2
+ * 'OpenSSL for Ruby' project
3
+ * Copyright (C) 2003 Michal Rokos <m.rokos@sh.cvut.cz>
4
+ * Copyright (C) 2003 GOTOU Yuuzou <gotoyuzo@notwork.org>
5
+ * All rights reserved.
6
+ */
7
+ /*
8
+ * This program is licensed under the same licence as Ruby.
9
+ * (See the file 'LICENCE'.)
10
+ */
11
+ #include "ossl.h"
12
+
13
+ #if !defined(OPENSSL_NO_OCSP)
14
+
15
+ #define NewOCSPReq(klass) \
16
+ TypedData_Wrap_Struct((klass), &ossl_ocsp_request_type, 0)
17
+ #define SetOCSPReq(obj, req) do { \
18
+ if(!(req)) ossl_raise(rb_eRuntimeError, "Request wasn't initialized!"); \
19
+ RTYPEDDATA_DATA(obj) = (req); \
20
+ } while (0)
21
+ #define GetOCSPReq(obj, req) do { \
22
+ TypedData_Get_Struct((obj), OCSP_REQUEST, &ossl_ocsp_request_type, (req)); \
23
+ if(!(req)) ossl_raise(rb_eRuntimeError, "Request wasn't initialized!"); \
24
+ } while (0)
25
+
26
+ #define NewOCSPRes(klass) \
27
+ TypedData_Wrap_Struct((klass), &ossl_ocsp_response_type, 0)
28
+ #define SetOCSPRes(obj, res) do { \
29
+ if(!(res)) ossl_raise(rb_eRuntimeError, "Response wasn't initialized!"); \
30
+ RTYPEDDATA_DATA(obj) = (res); \
31
+ } while (0)
32
+ #define GetOCSPRes(obj, res) do { \
33
+ TypedData_Get_Struct((obj), OCSP_RESPONSE, &ossl_ocsp_response_type, (res)); \
34
+ if(!(res)) ossl_raise(rb_eRuntimeError, "Response wasn't initialized!"); \
35
+ } while (0)
36
+
37
+ #define NewOCSPBasicRes(klass) \
38
+ TypedData_Wrap_Struct((klass), &ossl_ocsp_basicresp_type, 0)
39
+ #define SetOCSPBasicRes(obj, res) do { \
40
+ if(!(res)) ossl_raise(rb_eRuntimeError, "Response wasn't initialized!"); \
41
+ RTYPEDDATA_DATA(obj) = (res); \
42
+ } while (0)
43
+ #define GetOCSPBasicRes(obj, res) do { \
44
+ TypedData_Get_Struct((obj), OCSP_BASICRESP, &ossl_ocsp_basicresp_type, (res)); \
45
+ if(!(res)) ossl_raise(rb_eRuntimeError, "Response wasn't initialized!"); \
46
+ } while (0)
47
+
48
+ #define NewOCSPSingleRes(klass) \
49
+ TypedData_Wrap_Struct((klass), &ossl_ocsp_singleresp_type, 0)
50
+ #define SetOCSPSingleRes(obj, res) do { \
51
+ if(!(res)) ossl_raise(rb_eRuntimeError, "SingleResponse wasn't initialized!"); \
52
+ RTYPEDDATA_DATA(obj) = (res); \
53
+ } while (0)
54
+ #define GetOCSPSingleRes(obj, res) do { \
55
+ TypedData_Get_Struct((obj), OCSP_SINGLERESP, &ossl_ocsp_singleresp_type, (res)); \
56
+ if(!(res)) ossl_raise(rb_eRuntimeError, "SingleResponse wasn't initialized!"); \
57
+ } while (0)
58
+
59
+ #define NewOCSPCertId(klass) \
60
+ TypedData_Wrap_Struct((klass), &ossl_ocsp_certid_type, 0)
61
+ #define SetOCSPCertId(obj, cid) do { \
62
+ if(!(cid)) ossl_raise(rb_eRuntimeError, "Cert ID wasn't initialized!"); \
63
+ RTYPEDDATA_DATA(obj) = (cid); \
64
+ } while (0)
65
+ #define GetOCSPCertId(obj, cid) do { \
66
+ TypedData_Get_Struct((obj), OCSP_CERTID, &ossl_ocsp_certid_type, (cid)); \
67
+ if(!(cid)) ossl_raise(rb_eRuntimeError, "Cert ID wasn't initialized!"); \
68
+ } while (0)
69
+
70
+ VALUE mOCSP;
71
+ VALUE eOCSPError;
72
+ VALUE cOCSPReq;
73
+ VALUE cOCSPRes;
74
+ VALUE cOCSPBasicRes;
75
+ VALUE cOCSPSingleRes;
76
+ VALUE cOCSPCertId;
77
+
78
+ static void
79
+ ossl_ocsp_request_free(void *ptr)
80
+ {
81
+ OCSP_REQUEST_free(ptr);
82
+ }
83
+
84
+ static const rb_data_type_t ossl_ocsp_request_type = {
85
+ "OpenSSL/OCSP/REQUEST",
86
+ {
87
+ 0, ossl_ocsp_request_free,
88
+ },
89
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
90
+ };
91
+
92
+ static void
93
+ ossl_ocsp_response_free(void *ptr)
94
+ {
95
+ OCSP_RESPONSE_free(ptr);
96
+ }
97
+
98
+ static const rb_data_type_t ossl_ocsp_response_type = {
99
+ "OpenSSL/OCSP/RESPONSE",
100
+ {
101
+ 0, ossl_ocsp_response_free,
102
+ },
103
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
104
+ };
105
+
106
+ static void
107
+ ossl_ocsp_basicresp_free(void *ptr)
108
+ {
109
+ OCSP_BASICRESP_free(ptr);
110
+ }
111
+
112
+ static const rb_data_type_t ossl_ocsp_basicresp_type = {
113
+ "OpenSSL/OCSP/BASICRESP",
114
+ {
115
+ 0, ossl_ocsp_basicresp_free,
116
+ },
117
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
118
+ };
119
+
120
+ static void
121
+ ossl_ocsp_singleresp_free(void *ptr)
122
+ {
123
+ OCSP_SINGLERESP_free(ptr);
124
+ }
125
+
126
+ static const rb_data_type_t ossl_ocsp_singleresp_type = {
127
+ "OpenSSL/OCSP/SINGLERESP",
128
+ {
129
+ 0, ossl_ocsp_singleresp_free,
130
+ },
131
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
132
+ };
133
+
134
+ static void
135
+ ossl_ocsp_certid_free(void *ptr)
136
+ {
137
+ OCSP_CERTID_free(ptr);
138
+ }
139
+
140
+ static const rb_data_type_t ossl_ocsp_certid_type = {
141
+ "OpenSSL/OCSP/CERTID",
142
+ {
143
+ 0, ossl_ocsp_certid_free,
144
+ },
145
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
146
+ };
147
+
148
+ /*
149
+ * Public
150
+ */
151
+ static VALUE
152
+ ossl_ocspcertid_new(OCSP_CERTID *cid)
153
+ {
154
+ VALUE obj = NewOCSPCertId(cOCSPCertId);
155
+ SetOCSPCertId(obj, cid);
156
+ return obj;
157
+ }
158
+
159
+ /*
160
+ * OCSP::Resquest
161
+ */
162
+ static VALUE
163
+ ossl_ocspreq_alloc(VALUE klass)
164
+ {
165
+ OCSP_REQUEST *req;
166
+ VALUE obj;
167
+
168
+ obj = NewOCSPReq(klass);
169
+ if (!(req = OCSP_REQUEST_new()))
170
+ ossl_raise(eOCSPError, NULL);
171
+ SetOCSPReq(obj, req);
172
+
173
+ return obj;
174
+ }
175
+
176
+ static VALUE
177
+ ossl_ocspreq_initialize_copy(VALUE self, VALUE other)
178
+ {
179
+ OCSP_REQUEST *req, *req_old, *req_new;
180
+
181
+ rb_check_frozen(self);
182
+ GetOCSPReq(self, req_old);
183
+ GetOCSPReq(other, req);
184
+
185
+ req_new = ASN1_item_dup(ASN1_ITEM_rptr(OCSP_REQUEST), req);
186
+ if (!req_new)
187
+ ossl_raise(eOCSPError, "ASN1_item_dup");
188
+
189
+ SetOCSPReq(self, req_new);
190
+ OCSP_REQUEST_free(req_old);
191
+
192
+ return self;
193
+ }
194
+
195
+ /*
196
+ * call-seq:
197
+ * OpenSSL::OCSP::Request.new -> request
198
+ * OpenSSL::OCSP::Request.new(request_der) -> request
199
+ *
200
+ * Creates a new OpenSSL::OCSP::Request. The request may be created empty or
201
+ * from a _request_der_ string.
202
+ */
203
+
204
+ static VALUE
205
+ ossl_ocspreq_initialize(int argc, VALUE *argv, VALUE self)
206
+ {
207
+ VALUE arg;
208
+ OCSP_REQUEST *req, *req_new;
209
+ const unsigned char *p;
210
+
211
+ rb_scan_args(argc, argv, "01", &arg);
212
+ if(!NIL_P(arg)){
213
+ GetOCSPReq(self, req);
214
+ arg = ossl_to_der_if_possible(arg);
215
+ StringValue(arg);
216
+ p = (unsigned char *)RSTRING_PTR(arg);
217
+ req_new = d2i_OCSP_REQUEST(NULL, &p, RSTRING_LEN(arg));
218
+ if (!req_new)
219
+ ossl_raise(eOCSPError, "d2i_OCSP_REQUEST");
220
+ SetOCSPReq(self, req_new);
221
+ OCSP_REQUEST_free(req);
222
+ }
223
+
224
+ return self;
225
+ }
226
+
227
+ /*
228
+ * call-seq:
229
+ * request.add_nonce(nonce = nil) -> request
230
+ *
231
+ * Adds a _nonce_ to the OCSP request. If no nonce is given a random one will
232
+ * be generated.
233
+ *
234
+ * The nonce is used to prevent replay attacks but some servers do not support
235
+ * it.
236
+ */
237
+
238
+ static VALUE
239
+ ossl_ocspreq_add_nonce(int argc, VALUE *argv, VALUE self)
240
+ {
241
+ OCSP_REQUEST *req;
242
+ VALUE val;
243
+ int ret;
244
+
245
+ rb_scan_args(argc, argv, "01", &val);
246
+ if(NIL_P(val)) {
247
+ GetOCSPReq(self, req);
248
+ ret = OCSP_request_add1_nonce(req, NULL, -1);
249
+ }
250
+ else{
251
+ StringValue(val);
252
+ GetOCSPReq(self, req);
253
+ ret = OCSP_request_add1_nonce(req, (unsigned char *)RSTRING_PTR(val), RSTRING_LENINT(val));
254
+ }
255
+ if(!ret) ossl_raise(eOCSPError, NULL);
256
+
257
+ return self;
258
+ }
259
+
260
+ /*
261
+ * call-seq:
262
+ * request.check_nonce(response) -> result
263
+ *
264
+ * Checks the nonce validity for this request and _response_.
265
+ *
266
+ * The return value is one of the following:
267
+ *
268
+ * -1 :: nonce in request only.
269
+ * 0 :: nonces both present and not equal.
270
+ * 1 :: nonces present and equal.
271
+ * 2 :: nonces both absent.
272
+ * 3 :: nonce present in response only.
273
+ *
274
+ * For most responses, clients can check _result_ > 0. If a responder doesn't
275
+ * handle nonces <code>result.nonzero?</code> may be necessary. A result of
276
+ * <code>0</code> is always an error.
277
+ */
278
+
279
+ static VALUE
280
+ ossl_ocspreq_check_nonce(VALUE self, VALUE basic_resp)
281
+ {
282
+ OCSP_REQUEST *req;
283
+ OCSP_BASICRESP *bs;
284
+ int res;
285
+
286
+ GetOCSPReq(self, req);
287
+ GetOCSPBasicRes(basic_resp, bs);
288
+ res = OCSP_check_nonce(req, bs);
289
+
290
+ return INT2NUM(res);
291
+ }
292
+
293
+ /*
294
+ * call-seq:
295
+ * request.add_certid(certificate_id) -> request
296
+ *
297
+ * Adds _certificate_id_ to the request.
298
+ */
299
+
300
+ static VALUE
301
+ ossl_ocspreq_add_certid(VALUE self, VALUE certid)
302
+ {
303
+ OCSP_REQUEST *req;
304
+ OCSP_CERTID *id, *id_new;
305
+
306
+ GetOCSPReq(self, req);
307
+ GetOCSPCertId(certid, id);
308
+
309
+ if (!(id_new = OCSP_CERTID_dup(id)))
310
+ ossl_raise(eOCSPError, "OCSP_CERTID_dup");
311
+ if (!OCSP_request_add0_id(req, id_new)) {
312
+ OCSP_CERTID_free(id_new);
313
+ ossl_raise(eOCSPError, "OCSP_request_add0_id");
314
+ }
315
+
316
+ return self;
317
+ }
318
+
319
+ /*
320
+ * call-seq:
321
+ * request.certid -> [certificate_id, ...]
322
+ *
323
+ * Returns all certificate IDs in this request.
324
+ */
325
+
326
+ static VALUE
327
+ ossl_ocspreq_get_certid(VALUE self)
328
+ {
329
+ OCSP_REQUEST *req;
330
+ OCSP_ONEREQ *one;
331
+ OCSP_CERTID *id;
332
+ VALUE ary, tmp;
333
+ int i, count;
334
+
335
+ GetOCSPReq(self, req);
336
+ count = OCSP_request_onereq_count(req);
337
+ ary = (count > 0) ? rb_ary_new() : Qnil;
338
+ for(i = 0; i < count; i++){
339
+ one = OCSP_request_onereq_get0(req, i);
340
+ tmp = NewOCSPCertId(cOCSPCertId);
341
+ if(!(id = OCSP_CERTID_dup(OCSP_onereq_get0_id(one))))
342
+ ossl_raise(eOCSPError, NULL);
343
+ SetOCSPCertId(tmp, id);
344
+ rb_ary_push(ary, tmp);
345
+ }
346
+
347
+ return ary;
348
+ }
349
+
350
+ /*
351
+ * call-seq:
352
+ * request.sign(cert, key, certs = nil, flags = 0, digest = nil) -> self
353
+ *
354
+ * Signs this OCSP request using _cert_, _key_ and optional _digest_. If
355
+ * _digest_ is not specified, SHA-1 is used. _certs_ is an optional Array of
356
+ * additional certificates which are included in the request in addition to
357
+ * the signer certificate. Note that if _certs_ is +nil+ or not given, flag
358
+ * OpenSSL::OCSP::NOCERTS is enabled. Pass an empty array to include only the
359
+ * signer certificate.
360
+ *
361
+ * _flags_ is a bitwise OR of the following constants:
362
+ *
363
+ * OpenSSL::OCSP::NOCERTS::
364
+ * Don't include any certificates in the request. _certs_ will be ignored.
365
+ */
366
+ static VALUE
367
+ ossl_ocspreq_sign(int argc, VALUE *argv, VALUE self)
368
+ {
369
+ VALUE signer_cert, signer_key, certs, flags, digest;
370
+ OCSP_REQUEST *req;
371
+ X509 *signer;
372
+ EVP_PKEY *key;
373
+ STACK_OF(X509) *x509s = NULL;
374
+ unsigned long flg = 0;
375
+ const EVP_MD *md;
376
+ int ret;
377
+
378
+ rb_scan_args(argc, argv, "23", &signer_cert, &signer_key, &certs, &flags, &digest);
379
+ GetOCSPReq(self, req);
380
+ signer = GetX509CertPtr(signer_cert);
381
+ key = GetPrivPKeyPtr(signer_key);
382
+ if (!NIL_P(flags))
383
+ flg = NUM2INT(flags);
384
+ if (NIL_P(digest))
385
+ md = EVP_sha1();
386
+ else
387
+ md = ossl_evp_get_digestbyname(digest);
388
+ if (NIL_P(certs))
389
+ flg |= OCSP_NOCERTS;
390
+ else
391
+ x509s = ossl_x509_ary2sk(certs);
392
+
393
+ ret = OCSP_request_sign(req, signer, key, md, x509s, flg);
394
+ sk_X509_pop_free(x509s, X509_free);
395
+ if (!ret) ossl_raise(eOCSPError, NULL);
396
+
397
+ return self;
398
+ }
399
+
400
+ /*
401
+ * call-seq:
402
+ * request.verify(certificates, store, flags = 0) -> true or false
403
+ *
404
+ * Verifies this request using the given _certificates_ and _store_.
405
+ * _certificates_ is an array of OpenSSL::X509::Certificate, _store_ is an
406
+ * OpenSSL::X509::Store.
407
+ *
408
+ * Note that +false+ is returned if the request does not have a signature.
409
+ * Use #signed? to check whether the request is signed or not.
410
+ */
411
+
412
+ static VALUE
413
+ ossl_ocspreq_verify(int argc, VALUE *argv, VALUE self)
414
+ {
415
+ VALUE certs, store, flags;
416
+ OCSP_REQUEST *req;
417
+ STACK_OF(X509) *x509s;
418
+ X509_STORE *x509st;
419
+ int flg, result;
420
+
421
+ rb_scan_args(argc, argv, "21", &certs, &store, &flags);
422
+ GetOCSPReq(self, req);
423
+ x509st = GetX509StorePtr(store);
424
+ flg = NIL_P(flags) ? 0 : NUM2INT(flags);
425
+ x509s = ossl_x509_ary2sk(certs);
426
+ result = OCSP_request_verify(req, x509s, x509st, flg);
427
+ sk_X509_pop_free(x509s, X509_free);
428
+ if (result <= 0)
429
+ ossl_clear_error();
430
+
431
+ return result > 0 ? Qtrue : Qfalse;
432
+ }
433
+
434
+ /*
435
+ * Returns this request as a DER-encoded string
436
+ */
437
+
438
+ static VALUE
439
+ ossl_ocspreq_to_der(VALUE self)
440
+ {
441
+ OCSP_REQUEST *req;
442
+ VALUE str;
443
+ unsigned char *p;
444
+ long len;
445
+
446
+ GetOCSPReq(self, req);
447
+ if((len = i2d_OCSP_REQUEST(req, NULL)) <= 0)
448
+ ossl_raise(eOCSPError, NULL);
449
+ str = rb_str_new(0, len);
450
+ p = (unsigned char *)RSTRING_PTR(str);
451
+ if(i2d_OCSP_REQUEST(req, &p) <= 0)
452
+ ossl_raise(eOCSPError, NULL);
453
+ ossl_str_adjust(str, p);
454
+
455
+ return str;
456
+ }
457
+
458
+ /*
459
+ * call-seq:
460
+ * request.signed? -> true or false
461
+ *
462
+ * Returns +true+ if the request is signed, +false+ otherwise. Note that the
463
+ * validity of the signature is *not* checked. Use #verify to verify that.
464
+ */
465
+ static VALUE
466
+ ossl_ocspreq_signed_p(VALUE self)
467
+ {
468
+ OCSP_REQUEST *req;
469
+
470
+ GetOCSPReq(self, req);
471
+ return OCSP_request_is_signed(req) ? Qtrue : Qfalse;
472
+ }
473
+
474
+ /*
475
+ * OCSP::Response
476
+ */
477
+
478
+ /* call-seq:
479
+ * OpenSSL::OCSP::Response.create(status, basic_response = nil) -> response
480
+ *
481
+ * Creates an OpenSSL::OCSP::Response from _status_ and _basic_response_.
482
+ */
483
+
484
+ static VALUE
485
+ ossl_ocspres_s_create(VALUE klass, VALUE status, VALUE basic_resp)
486
+ {
487
+ OCSP_BASICRESP *bs;
488
+ OCSP_RESPONSE *res;
489
+ VALUE obj;
490
+ int st = NUM2INT(status);
491
+
492
+ if(NIL_P(basic_resp)) bs = NULL;
493
+ else GetOCSPBasicRes(basic_resp, bs); /* NO NEED TO DUP */
494
+ obj = NewOCSPRes(klass);
495
+ if(!(res = OCSP_response_create(st, bs)))
496
+ ossl_raise(eOCSPError, NULL);
497
+ SetOCSPRes(obj, res);
498
+
499
+ return obj;
500
+ }
501
+
502
+ static VALUE
503
+ ossl_ocspres_alloc(VALUE klass)
504
+ {
505
+ OCSP_RESPONSE *res;
506
+ VALUE obj;
507
+
508
+ obj = NewOCSPRes(klass);
509
+ if(!(res = OCSP_RESPONSE_new()))
510
+ ossl_raise(eOCSPError, NULL);
511
+ SetOCSPRes(obj, res);
512
+
513
+ return obj;
514
+ }
515
+
516
+ static VALUE
517
+ ossl_ocspres_initialize_copy(VALUE self, VALUE other)
518
+ {
519
+ OCSP_RESPONSE *res, *res_old, *res_new;
520
+
521
+ rb_check_frozen(self);
522
+ GetOCSPRes(self, res_old);
523
+ GetOCSPRes(other, res);
524
+
525
+ res_new = ASN1_item_dup(ASN1_ITEM_rptr(OCSP_RESPONSE), res);
526
+ if (!res_new)
527
+ ossl_raise(eOCSPError, "ASN1_item_dup");
528
+
529
+ SetOCSPRes(self, res_new);
530
+ OCSP_RESPONSE_free(res_old);
531
+
532
+ return self;
533
+ }
534
+
535
+ /*
536
+ * call-seq:
537
+ * OpenSSL::OCSP::Response.new -> response
538
+ * OpenSSL::OCSP::Response.new(response_der) -> response
539
+ *
540
+ * Creates a new OpenSSL::OCSP::Response. The response may be created empty or
541
+ * from a _response_der_ string.
542
+ */
543
+
544
+ static VALUE
545
+ ossl_ocspres_initialize(int argc, VALUE *argv, VALUE self)
546
+ {
547
+ VALUE arg;
548
+ OCSP_RESPONSE *res, *res_new;
549
+ const unsigned char *p;
550
+
551
+ rb_scan_args(argc, argv, "01", &arg);
552
+ if(!NIL_P(arg)){
553
+ GetOCSPRes(self, res);
554
+ arg = ossl_to_der_if_possible(arg);
555
+ StringValue(arg);
556
+ p = (unsigned char *)RSTRING_PTR(arg);
557
+ res_new = d2i_OCSP_RESPONSE(NULL, &p, RSTRING_LEN(arg));
558
+ if (!res_new)
559
+ ossl_raise(eOCSPError, "d2i_OCSP_RESPONSE");
560
+ SetOCSPRes(self, res_new);
561
+ OCSP_RESPONSE_free(res);
562
+ }
563
+
564
+ return self;
565
+ }
566
+
567
+ /*
568
+ * call-seq:
569
+ * response.status -> Integer
570
+ *
571
+ * Returns the status of the response.
572
+ */
573
+
574
+ static VALUE
575
+ ossl_ocspres_status(VALUE self)
576
+ {
577
+ OCSP_RESPONSE *res;
578
+ int st;
579
+
580
+ GetOCSPRes(self, res);
581
+ st = OCSP_response_status(res);
582
+
583
+ return INT2NUM(st);
584
+ }
585
+
586
+ /*
587
+ * call-seq:
588
+ * response.status_string -> String
589
+ *
590
+ * Returns a status string for the response.
591
+ */
592
+
593
+ static VALUE
594
+ ossl_ocspres_status_string(VALUE self)
595
+ {
596
+ OCSP_RESPONSE *res;
597
+ int st;
598
+
599
+ GetOCSPRes(self, res);
600
+ st = OCSP_response_status(res);
601
+
602
+ return rb_str_new2(OCSP_response_status_str(st));
603
+ }
604
+
605
+ /*
606
+ * call-seq:
607
+ * response.basic
608
+ *
609
+ * Returns a BasicResponse for this response
610
+ */
611
+
612
+ static VALUE
613
+ ossl_ocspres_get_basic(VALUE self)
614
+ {
615
+ OCSP_RESPONSE *res;
616
+ OCSP_BASICRESP *bs;
617
+ VALUE ret;
618
+
619
+ GetOCSPRes(self, res);
620
+ ret = NewOCSPBasicRes(cOCSPBasicRes);
621
+ if(!(bs = OCSP_response_get1_basic(res)))
622
+ return Qnil;
623
+ SetOCSPBasicRes(ret, bs);
624
+
625
+ return ret;
626
+ }
627
+
628
+ /*
629
+ * call-seq:
630
+ * response.to_der -> String
631
+ *
632
+ * Returns this response as a DER-encoded string.
633
+ */
634
+
635
+ static VALUE
636
+ ossl_ocspres_to_der(VALUE self)
637
+ {
638
+ OCSP_RESPONSE *res;
639
+ VALUE str;
640
+ long len;
641
+ unsigned char *p;
642
+
643
+ GetOCSPRes(self, res);
644
+ if((len = i2d_OCSP_RESPONSE(res, NULL)) <= 0)
645
+ ossl_raise(eOCSPError, NULL);
646
+ str = rb_str_new(0, len);
647
+ p = (unsigned char *)RSTRING_PTR(str);
648
+ if(i2d_OCSP_RESPONSE(res, &p) <= 0)
649
+ ossl_raise(eOCSPError, NULL);
650
+ ossl_str_adjust(str, p);
651
+
652
+ return str;
653
+ }
654
+
655
+ /*
656
+ * OCSP::BasicResponse
657
+ */
658
+ static VALUE
659
+ ossl_ocspbres_alloc(VALUE klass)
660
+ {
661
+ OCSP_BASICRESP *bs;
662
+ VALUE obj;
663
+
664
+ obj = NewOCSPBasicRes(klass);
665
+ if(!(bs = OCSP_BASICRESP_new()))
666
+ ossl_raise(eOCSPError, NULL);
667
+ SetOCSPBasicRes(obj, bs);
668
+
669
+ return obj;
670
+ }
671
+
672
+ static VALUE
673
+ ossl_ocspbres_initialize_copy(VALUE self, VALUE other)
674
+ {
675
+ OCSP_BASICRESP *bs, *bs_old, *bs_new;
676
+
677
+ rb_check_frozen(self);
678
+ GetOCSPBasicRes(self, bs_old);
679
+ GetOCSPBasicRes(other, bs);
680
+
681
+ bs_new = ASN1_item_dup(ASN1_ITEM_rptr(OCSP_BASICRESP), bs);
682
+ if (!bs_new)
683
+ ossl_raise(eOCSPError, "ASN1_item_dup");
684
+
685
+ SetOCSPBasicRes(self, bs_new);
686
+ OCSP_BASICRESP_free(bs_old);
687
+
688
+ return self;
689
+ }
690
+
691
+ /*
692
+ * call-seq:
693
+ * OpenSSL::OCSP::BasicResponse.new(der_string = nil) -> basic_response
694
+ *
695
+ * Creates a new BasicResponse. If _der_string_ is given, decodes _der_string_
696
+ * as DER.
697
+ */
698
+
699
+ static VALUE
700
+ ossl_ocspbres_initialize(int argc, VALUE *argv, VALUE self)
701
+ {
702
+ VALUE arg;
703
+ OCSP_BASICRESP *res, *res_new;
704
+ const unsigned char *p;
705
+
706
+ rb_scan_args(argc, argv, "01", &arg);
707
+ if (!NIL_P(arg)) {
708
+ GetOCSPBasicRes(self, res);
709
+ arg = ossl_to_der_if_possible(arg);
710
+ StringValue(arg);
711
+ p = (unsigned char *)RSTRING_PTR(arg);
712
+ res_new = d2i_OCSP_BASICRESP(NULL, &p, RSTRING_LEN(arg));
713
+ if (!res_new)
714
+ ossl_raise(eOCSPError, "d2i_OCSP_BASICRESP");
715
+ SetOCSPBasicRes(self, res_new);
716
+ OCSP_BASICRESP_free(res);
717
+ }
718
+
719
+ return self;
720
+ }
721
+
722
+ /*
723
+ * call-seq:
724
+ * basic_response.copy_nonce(request) -> Integer
725
+ *
726
+ * Copies the nonce from _request_ into this response. Returns 1 on success
727
+ * and 0 on failure.
728
+ */
729
+
730
+ static VALUE
731
+ ossl_ocspbres_copy_nonce(VALUE self, VALUE request)
732
+ {
733
+ OCSP_BASICRESP *bs;
734
+ OCSP_REQUEST *req;
735
+ int ret;
736
+
737
+ GetOCSPBasicRes(self, bs);
738
+ GetOCSPReq(request, req);
739
+ ret = OCSP_copy_nonce(bs, req);
740
+
741
+ return INT2NUM(ret);
742
+ }
743
+
744
+ /*
745
+ * call-seq:
746
+ * basic_response.add_nonce(nonce = nil)
747
+ *
748
+ * Adds _nonce_ to this response. If no nonce was provided a random nonce
749
+ * will be added.
750
+ */
751
+
752
+ static VALUE
753
+ ossl_ocspbres_add_nonce(int argc, VALUE *argv, VALUE self)
754
+ {
755
+ OCSP_BASICRESP *bs;
756
+ VALUE val;
757
+ int ret;
758
+
759
+ rb_scan_args(argc, argv, "01", &val);
760
+ if(NIL_P(val)) {
761
+ GetOCSPBasicRes(self, bs);
762
+ ret = OCSP_basic_add1_nonce(bs, NULL, -1);
763
+ }
764
+ else{
765
+ StringValue(val);
766
+ GetOCSPBasicRes(self, bs);
767
+ ret = OCSP_basic_add1_nonce(bs, (unsigned char *)RSTRING_PTR(val), RSTRING_LENINT(val));
768
+ }
769
+ if(!ret) ossl_raise(eOCSPError, NULL);
770
+
771
+ return self;
772
+ }
773
+
774
+ static VALUE
775
+ add_status_convert_time(VALUE obj)
776
+ {
777
+ ASN1_TIME *time;
778
+
779
+ if (RB_INTEGER_TYPE_P(obj))
780
+ time = X509_gmtime_adj(NULL, NUM2INT(obj));
781
+ else
782
+ time = ossl_x509_time_adjust(NULL, obj);
783
+
784
+ if (!time)
785
+ ossl_raise(eOCSPError, NULL);
786
+
787
+ return (VALUE)time;
788
+ }
789
+
790
+ /*
791
+ * call-seq:
792
+ * basic_response.add_status(certificate_id, status, reason, revocation_time, this_update, next_update, extensions) -> basic_response
793
+ *
794
+ * Adds a certificate status for _certificate_id_. _status_ is the status, and
795
+ * must be one of these:
796
+ *
797
+ * - OpenSSL::OCSP::V_CERTSTATUS_GOOD
798
+ * - OpenSSL::OCSP::V_CERTSTATUS_REVOKED
799
+ * - OpenSSL::OCSP::V_CERTSTATUS_UNKNOWN
800
+ *
801
+ * _reason_ and _revocation_time_ can be given only when _status_ is
802
+ * OpenSSL::OCSP::V_CERTSTATUS_REVOKED. _reason_ describes the reason for the
803
+ * revocation, and must be one of OpenSSL::OCSP::REVOKED_STATUS_* constants.
804
+ * _revocation_time_ is the time when the certificate is revoked.
805
+ *
806
+ * _this_update_ and _next_update_ indicate the time at which ths status is
807
+ * verified to be correct and the time at or before which newer information
808
+ * will be available, respectively. _next_update_ is optional.
809
+ *
810
+ * _extensions_ is an Array of OpenSSL::X509::Extension to be included in the
811
+ * SingleResponse. This is also optional.
812
+ *
813
+ * Note that the times, _revocation_time_, _this_update_ and _next_update_
814
+ * can be specified in either of Integer or Time object. If they are Integer, it
815
+ * is treated as the relative seconds from the current time.
816
+ */
817
+ static VALUE
818
+ ossl_ocspbres_add_status(VALUE self, VALUE cid, VALUE status,
819
+ VALUE reason, VALUE revtime,
820
+ VALUE thisupd, VALUE nextupd, VALUE ext)
821
+ {
822
+ OCSP_BASICRESP *bs;
823
+ OCSP_SINGLERESP *single;
824
+ OCSP_CERTID *id;
825
+ ASN1_TIME *ths = NULL, *nxt = NULL, *rev = NULL;
826
+ int st, rsn = 0, error = 0, rstatus = 0;
827
+ long i;
828
+ VALUE tmp;
829
+
830
+ GetOCSPBasicRes(self, bs);
831
+ GetOCSPCertId(cid, id);
832
+ st = NUM2INT(status);
833
+ if (!NIL_P(ext)) { /* All ext's members must be X509::Extension */
834
+ ext = rb_check_array_type(ext);
835
+ for (i = 0; i < RARRAY_LEN(ext); i++)
836
+ OSSL_Check_Kind(RARRAY_AREF(ext, i), cX509Ext);
837
+ }
838
+
839
+ if (st == V_OCSP_CERTSTATUS_REVOKED) {
840
+ rsn = NUM2INT(reason);
841
+ tmp = rb_protect(add_status_convert_time, revtime, &rstatus);
842
+ if (rstatus) goto err;
843
+ rev = (ASN1_TIME *)tmp;
844
+ }
845
+
846
+ tmp = rb_protect(add_status_convert_time, thisupd, &rstatus);
847
+ if (rstatus) goto err;
848
+ ths = (ASN1_TIME *)tmp;
849
+
850
+ if (!NIL_P(nextupd)) {
851
+ tmp = rb_protect(add_status_convert_time, nextupd, &rstatus);
852
+ if (rstatus) goto err;
853
+ nxt = (ASN1_TIME *)tmp;
854
+ }
855
+
856
+ if(!(single = OCSP_basic_add1_status(bs, id, st, rsn, rev, ths, nxt))){
857
+ error = 1;
858
+ goto err;
859
+ }
860
+
861
+ if(!NIL_P(ext)){
862
+ X509_EXTENSION *x509ext;
863
+
864
+ for(i = 0; i < RARRAY_LEN(ext); i++){
865
+ x509ext = GetX509ExtPtr(RARRAY_AREF(ext, i));
866
+ if(!OCSP_SINGLERESP_add_ext(single, x509ext, -1)){
867
+ error = 1;
868
+ goto err;
869
+ }
870
+ }
871
+ }
872
+
873
+ err:
874
+ ASN1_TIME_free(ths);
875
+ ASN1_TIME_free(nxt);
876
+ ASN1_TIME_free(rev);
877
+ if(error) ossl_raise(eOCSPError, NULL);
878
+ if(rstatus) rb_jump_tag(rstatus);
879
+
880
+ return self;
881
+ }
882
+
883
+ /*
884
+ * call-seq:
885
+ * basic_response.status -> statuses
886
+ *
887
+ * Returns an Array of statuses for this response. Each status contains a
888
+ * CertificateId, the status (0 for good, 1 for revoked, 2 for unknown), the
889
+ * reason for the status, the revocation time, the time of this update, the time
890
+ * for the next update and a list of OpenSSL::X509::Extension.
891
+ *
892
+ * This should be superseded by BasicResponse#responses and #find_response that
893
+ * return SingleResponse.
894
+ */
895
+ static VALUE
896
+ ossl_ocspbres_get_status(VALUE self)
897
+ {
898
+ OCSP_BASICRESP *bs;
899
+ OCSP_SINGLERESP *single;
900
+ OCSP_CERTID *cid;
901
+ ASN1_TIME *revtime, *thisupd, *nextupd;
902
+ int status, reason;
903
+ X509_EXTENSION *x509ext;
904
+ VALUE ret, ary, ext;
905
+ int count, ext_count, i, j;
906
+
907
+ GetOCSPBasicRes(self, bs);
908
+ ret = rb_ary_new();
909
+ count = OCSP_resp_count(bs);
910
+ for(i = 0; i < count; i++){
911
+ single = OCSP_resp_get0(bs, i);
912
+ if(!single) continue;
913
+
914
+ revtime = thisupd = nextupd = NULL;
915
+ status = OCSP_single_get0_status(single, &reason, &revtime,
916
+ &thisupd, &nextupd);
917
+ if(status < 0) continue;
918
+ if(!(cid = OCSP_CERTID_dup((OCSP_CERTID *)OCSP_SINGLERESP_get0_id(single)))) /* FIXME */
919
+ ossl_raise(eOCSPError, NULL);
920
+ ary = rb_ary_new();
921
+ rb_ary_push(ary, ossl_ocspcertid_new(cid));
922
+ rb_ary_push(ary, INT2NUM(status));
923
+ rb_ary_push(ary, INT2NUM(reason));
924
+ rb_ary_push(ary, revtime ? asn1time_to_time(revtime) : Qnil);
925
+ rb_ary_push(ary, thisupd ? asn1time_to_time(thisupd) : Qnil);
926
+ rb_ary_push(ary, nextupd ? asn1time_to_time(nextupd) : Qnil);
927
+ ext = rb_ary_new();
928
+ ext_count = OCSP_SINGLERESP_get_ext_count(single);
929
+ for(j = 0; j < ext_count; j++){
930
+ x509ext = OCSP_SINGLERESP_get_ext(single, j);
931
+ rb_ary_push(ext, ossl_x509ext_new(x509ext));
932
+ }
933
+ rb_ary_push(ary, ext);
934
+ rb_ary_push(ret, ary);
935
+ }
936
+
937
+ return ret;
938
+ }
939
+
940
+ static VALUE ossl_ocspsres_new(OCSP_SINGLERESP *);
941
+
942
+ /*
943
+ * call-seq:
944
+ * basic_response.responses -> Array of SingleResponse
945
+ *
946
+ * Returns an Array of SingleResponse for this BasicResponse.
947
+ */
948
+
949
+ static VALUE
950
+ ossl_ocspbres_get_responses(VALUE self)
951
+ {
952
+ OCSP_BASICRESP *bs;
953
+ VALUE ret;
954
+ int count, i;
955
+
956
+ GetOCSPBasicRes(self, bs);
957
+ count = OCSP_resp_count(bs);
958
+ ret = rb_ary_new2(count);
959
+
960
+ for (i = 0; i < count; i++) {
961
+ OCSP_SINGLERESP *sres, *sres_new;
962
+
963
+ sres = OCSP_resp_get0(bs, i);
964
+ sres_new = ASN1_item_dup(ASN1_ITEM_rptr(OCSP_SINGLERESP), sres);
965
+ if (!sres_new)
966
+ ossl_raise(eOCSPError, "ASN1_item_dup");
967
+
968
+ rb_ary_push(ret, ossl_ocspsres_new(sres_new));
969
+ }
970
+
971
+ return ret;
972
+ }
973
+
974
+
975
+ /*
976
+ * call-seq:
977
+ * basic_response.find_response(certificate_id) -> SingleResponse | nil
978
+ *
979
+ * Returns a SingleResponse whose CertId matches with _certificate_id_, or +nil+
980
+ * if this BasicResponse does not contain it.
981
+ */
982
+ static VALUE
983
+ ossl_ocspbres_find_response(VALUE self, VALUE target)
984
+ {
985
+ OCSP_BASICRESP *bs;
986
+ OCSP_SINGLERESP *sres, *sres_new;
987
+ OCSP_CERTID *id;
988
+ int n;
989
+
990
+ GetOCSPCertId(target, id);
991
+ GetOCSPBasicRes(self, bs);
992
+
993
+ if ((n = OCSP_resp_find(bs, id, -1)) == -1)
994
+ return Qnil;
995
+
996
+ sres = OCSP_resp_get0(bs, n);
997
+ sres_new = ASN1_item_dup(ASN1_ITEM_rptr(OCSP_SINGLERESP), sres);
998
+ if (!sres_new)
999
+ ossl_raise(eOCSPError, "ASN1_item_dup");
1000
+
1001
+ return ossl_ocspsres_new(sres_new);
1002
+ }
1003
+
1004
+ /*
1005
+ * call-seq:
1006
+ * basic_response.sign(cert, key, certs = nil, flags = 0, digest = nil) -> self
1007
+ *
1008
+ * Signs this OCSP response using the _cert_, _key_ and optional _digest_. This
1009
+ * behaves in the similar way as OpenSSL::OCSP::Request#sign.
1010
+ *
1011
+ * _flags_ can include:
1012
+ * OpenSSL::OCSP::NOCERTS:: don't include certificates
1013
+ * OpenSSL::OCSP::NOTIME:: don't set producedAt
1014
+ * OpenSSL::OCSP::RESPID_KEY:: use signer's public key hash as responderID
1015
+ */
1016
+
1017
+ static VALUE
1018
+ ossl_ocspbres_sign(int argc, VALUE *argv, VALUE self)
1019
+ {
1020
+ VALUE signer_cert, signer_key, certs, flags, digest;
1021
+ OCSP_BASICRESP *bs;
1022
+ X509 *signer;
1023
+ EVP_PKEY *key;
1024
+ STACK_OF(X509) *x509s = NULL;
1025
+ unsigned long flg = 0;
1026
+ const EVP_MD *md;
1027
+ int ret;
1028
+
1029
+ rb_scan_args(argc, argv, "23", &signer_cert, &signer_key, &certs, &flags, &digest);
1030
+ GetOCSPBasicRes(self, bs);
1031
+ signer = GetX509CertPtr(signer_cert);
1032
+ key = GetPrivPKeyPtr(signer_key);
1033
+ if (!NIL_P(flags))
1034
+ flg = NUM2INT(flags);
1035
+ if (NIL_P(digest))
1036
+ md = EVP_sha1();
1037
+ else
1038
+ md = ossl_evp_get_digestbyname(digest);
1039
+ if (NIL_P(certs))
1040
+ flg |= OCSP_NOCERTS;
1041
+ else
1042
+ x509s = ossl_x509_ary2sk(certs);
1043
+
1044
+ ret = OCSP_basic_sign(bs, signer, key, md, x509s, flg);
1045
+ sk_X509_pop_free(x509s, X509_free);
1046
+ if (!ret) ossl_raise(eOCSPError, NULL);
1047
+
1048
+ return self;
1049
+ }
1050
+
1051
+ /*
1052
+ * call-seq:
1053
+ * basic_response.verify(certificates, store, flags = 0) -> true or false
1054
+ *
1055
+ * Verifies the signature of the response using the given _certificates_ and
1056
+ * _store_. This works in the similar way as OpenSSL::OCSP::Request#verify.
1057
+ */
1058
+ static VALUE
1059
+ ossl_ocspbres_verify(int argc, VALUE *argv, VALUE self)
1060
+ {
1061
+ VALUE certs, store, flags;
1062
+ OCSP_BASICRESP *bs;
1063
+ STACK_OF(X509) *x509s;
1064
+ X509_STORE *x509st;
1065
+ int flg, result;
1066
+
1067
+ rb_scan_args(argc, argv, "21", &certs, &store, &flags);
1068
+ GetOCSPBasicRes(self, bs);
1069
+ x509st = GetX509StorePtr(store);
1070
+ flg = NIL_P(flags) ? 0 : NUM2INT(flags);
1071
+ x509s = ossl_x509_ary2sk(certs);
1072
+ #if (OPENSSL_VERSION_NUMBER < 0x1000202fL) || defined(LIBRESSL_VERSION_NUMBER)
1073
+ /*
1074
+ * OpenSSL had a bug that it doesn't use the certificates in x509s for
1075
+ * verifying the chain. This can be a problem when the response is signed by
1076
+ * a certificate issued by an intermediate CA.
1077
+ *
1078
+ * root_ca
1079
+ * |
1080
+ * intermediate_ca
1081
+ * |-------------|
1082
+ * end_entity ocsp_signer
1083
+ *
1084
+ * When the certificate hierarchy is like this, and the response contains
1085
+ * only ocsp_signer certificate, the following code wrongly fails.
1086
+ *
1087
+ * store = OpenSSL::X509::Store.new; store.add_cert(root_ca)
1088
+ * basic_response.verify([intermediate_ca], store)
1089
+ *
1090
+ * So add the certificates in x509s to the embedded certificates list first.
1091
+ *
1092
+ * This is fixed in OpenSSL 0.9.8zg, 1.0.0s, 1.0.1n, 1.0.2b. But it still
1093
+ * exists in LibreSSL 2.1.10, 2.2.9, 2.3.6, 2.4.1.
1094
+ */
1095
+ if (!(flg & (OCSP_NOCHAIN | OCSP_NOVERIFY)) &&
1096
+ sk_X509_num(x509s) && sk_X509_num(bs->certs)) {
1097
+ int i;
1098
+
1099
+ bs = ASN1_item_dup(ASN1_ITEM_rptr(OCSP_BASICRESP), bs);
1100
+ if (!bs) {
1101
+ sk_X509_pop_free(x509s, X509_free);
1102
+ ossl_raise(eOCSPError, "ASN1_item_dup");
1103
+ }
1104
+
1105
+ for (i = 0; i < sk_X509_num(x509s); i++) {
1106
+ if (!OCSP_basic_add1_cert(bs, sk_X509_value(x509s, i))) {
1107
+ sk_X509_pop_free(x509s, X509_free);
1108
+ OCSP_BASICRESP_free(bs);
1109
+ ossl_raise(eOCSPError, "OCSP_basic_add1_cert");
1110
+ }
1111
+ }
1112
+ result = OCSP_basic_verify(bs, x509s, x509st, flg);
1113
+ OCSP_BASICRESP_free(bs);
1114
+ }
1115
+ else {
1116
+ result = OCSP_basic_verify(bs, x509s, x509st, flg);
1117
+ }
1118
+ #else
1119
+ result = OCSP_basic_verify(bs, x509s, x509st, flg);
1120
+ #endif
1121
+ sk_X509_pop_free(x509s, X509_free);
1122
+ if (result <= 0)
1123
+ ossl_clear_error();
1124
+
1125
+ return result > 0 ? Qtrue : Qfalse;
1126
+ }
1127
+
1128
+ /*
1129
+ * call-seq:
1130
+ * basic_response.to_der -> String
1131
+ *
1132
+ * Encodes this basic response into a DER-encoded string.
1133
+ */
1134
+ static VALUE
1135
+ ossl_ocspbres_to_der(VALUE self)
1136
+ {
1137
+ OCSP_BASICRESP *res;
1138
+ VALUE str;
1139
+ long len;
1140
+ unsigned char *p;
1141
+
1142
+ GetOCSPBasicRes(self, res);
1143
+ if ((len = i2d_OCSP_BASICRESP(res, NULL)) <= 0)
1144
+ ossl_raise(eOCSPError, NULL);
1145
+ str = rb_str_new(0, len);
1146
+ p = (unsigned char *)RSTRING_PTR(str);
1147
+ if (i2d_OCSP_BASICRESP(res, &p) <= 0)
1148
+ ossl_raise(eOCSPError, NULL);
1149
+ ossl_str_adjust(str, p);
1150
+
1151
+ return str;
1152
+ }
1153
+
1154
+ /*
1155
+ * OCSP::SingleResponse
1156
+ */
1157
+ static VALUE
1158
+ ossl_ocspsres_new(OCSP_SINGLERESP *sres)
1159
+ {
1160
+ VALUE obj;
1161
+
1162
+ obj = NewOCSPSingleRes(cOCSPSingleRes);
1163
+ SetOCSPSingleRes(obj, sres);
1164
+
1165
+ return obj;
1166
+ }
1167
+
1168
+ static VALUE
1169
+ ossl_ocspsres_alloc(VALUE klass)
1170
+ {
1171
+ OCSP_SINGLERESP *sres;
1172
+ VALUE obj;
1173
+
1174
+ obj = NewOCSPSingleRes(klass);
1175
+ if (!(sres = OCSP_SINGLERESP_new()))
1176
+ ossl_raise(eOCSPError, NULL);
1177
+ SetOCSPSingleRes(obj, sres);
1178
+
1179
+ return obj;
1180
+ }
1181
+
1182
+ /*
1183
+ * call-seq:
1184
+ * OpenSSL::OCSP::SingleResponse.new(der_string) -> SingleResponse
1185
+ *
1186
+ * Creates a new SingleResponse from _der_string_.
1187
+ */
1188
+ static VALUE
1189
+ ossl_ocspsres_initialize(VALUE self, VALUE arg)
1190
+ {
1191
+ OCSP_SINGLERESP *res, *res_new;
1192
+ const unsigned char *p;
1193
+
1194
+ arg = ossl_to_der_if_possible(arg);
1195
+ StringValue(arg);
1196
+ GetOCSPSingleRes(self, res);
1197
+
1198
+ p = (unsigned char*)RSTRING_PTR(arg);
1199
+ res_new = d2i_OCSP_SINGLERESP(NULL, &p, RSTRING_LEN(arg));
1200
+ if (!res_new)
1201
+ ossl_raise(eOCSPError, "d2i_OCSP_SINGLERESP");
1202
+ SetOCSPSingleRes(self, res_new);
1203
+ OCSP_SINGLERESP_free(res);
1204
+
1205
+ return self;
1206
+ }
1207
+
1208
+ static VALUE
1209
+ ossl_ocspsres_initialize_copy(VALUE self, VALUE other)
1210
+ {
1211
+ OCSP_SINGLERESP *sres, *sres_old, *sres_new;
1212
+
1213
+ rb_check_frozen(self);
1214
+ GetOCSPSingleRes(self, sres_old);
1215
+ GetOCSPSingleRes(other, sres);
1216
+
1217
+ sres_new = ASN1_item_dup(ASN1_ITEM_rptr(OCSP_SINGLERESP), sres);
1218
+ if (!sres_new)
1219
+ ossl_raise(eOCSPError, "ASN1_item_dup");
1220
+
1221
+ SetOCSPSingleRes(self, sres_new);
1222
+ OCSP_SINGLERESP_free(sres_old);
1223
+
1224
+ return self;
1225
+ }
1226
+
1227
+ /*
1228
+ * call-seq:
1229
+ * single_response.check_validity(nsec = 0, maxsec = -1) -> true | false
1230
+ *
1231
+ * Checks the validity of thisUpdate and nextUpdate fields of this
1232
+ * SingleResponse. This checks the current time is within the range thisUpdate
1233
+ * to nextUpdate.
1234
+ *
1235
+ * It is possible that the OCSP request takes a few seconds or the time is not
1236
+ * accurate. To avoid rejecting a valid response, this method allows the times
1237
+ * to be within _nsec_ seconds of the current time.
1238
+ *
1239
+ * Some responders don't set the nextUpdate field. This may cause a very old
1240
+ * response to be considered valid. The _maxsec_ parameter can be used to limit
1241
+ * the age of responses.
1242
+ */
1243
+ static VALUE
1244
+ ossl_ocspsres_check_validity(int argc, VALUE *argv, VALUE self)
1245
+ {
1246
+ OCSP_SINGLERESP *sres;
1247
+ ASN1_GENERALIZEDTIME *this_update, *next_update;
1248
+ VALUE nsec_v, maxsec_v;
1249
+ int nsec, maxsec, status, ret;
1250
+
1251
+ rb_scan_args(argc, argv, "02", &nsec_v, &maxsec_v);
1252
+ nsec = NIL_P(nsec_v) ? 0 : NUM2INT(nsec_v);
1253
+ maxsec = NIL_P(maxsec_v) ? -1 : NUM2INT(maxsec_v);
1254
+
1255
+ GetOCSPSingleRes(self, sres);
1256
+ status = OCSP_single_get0_status(sres, NULL, NULL, &this_update, &next_update);
1257
+ if (status < 0)
1258
+ ossl_raise(eOCSPError, "OCSP_single_get0_status");
1259
+
1260
+ ret = OCSP_check_validity(this_update, next_update, nsec, maxsec);
1261
+
1262
+ if (ret)
1263
+ return Qtrue;
1264
+ else {
1265
+ ossl_clear_error();
1266
+ return Qfalse;
1267
+ }
1268
+ }
1269
+
1270
+ /*
1271
+ * call-seq:
1272
+ * single_response.certid -> CertificateId
1273
+ *
1274
+ * Returns the CertificateId for which this SingleResponse is.
1275
+ */
1276
+ static VALUE
1277
+ ossl_ocspsres_get_certid(VALUE self)
1278
+ {
1279
+ OCSP_SINGLERESP *sres;
1280
+ OCSP_CERTID *id;
1281
+
1282
+ GetOCSPSingleRes(self, sres);
1283
+ id = OCSP_CERTID_dup((OCSP_CERTID *)OCSP_SINGLERESP_get0_id(sres)); /* FIXME */
1284
+
1285
+ return ossl_ocspcertid_new(id);
1286
+ }
1287
+
1288
+ /*
1289
+ * call-seq:
1290
+ * single_response.cert_status -> Integer
1291
+ *
1292
+ * Returns the status of the certificate identified by the certid.
1293
+ * The return value may be one of these constant:
1294
+ *
1295
+ * - V_CERTSTATUS_GOOD
1296
+ * - V_CERTSTATUS_REVOKED
1297
+ * - V_CERTSTATUS_UNKNOWN
1298
+ *
1299
+ * When the status is V_CERTSTATUS_REVOKED, the time at which the certificate
1300
+ * was revoked can be retrieved by #revocation_time.
1301
+ */
1302
+ static VALUE
1303
+ ossl_ocspsres_get_cert_status(VALUE self)
1304
+ {
1305
+ OCSP_SINGLERESP *sres;
1306
+ int status;
1307
+
1308
+ GetOCSPSingleRes(self, sres);
1309
+ status = OCSP_single_get0_status(sres, NULL, NULL, NULL, NULL);
1310
+ if (status < 0)
1311
+ ossl_raise(eOCSPError, "OCSP_single_get0_status");
1312
+
1313
+ return INT2NUM(status);
1314
+ }
1315
+
1316
+ /*
1317
+ * call-seq:
1318
+ * single_response.this_update -> Time
1319
+ */
1320
+ static VALUE
1321
+ ossl_ocspsres_get_this_update(VALUE self)
1322
+ {
1323
+ OCSP_SINGLERESP *sres;
1324
+ int status;
1325
+ ASN1_GENERALIZEDTIME *time;
1326
+
1327
+ GetOCSPSingleRes(self, sres);
1328
+ status = OCSP_single_get0_status(sres, NULL, NULL, &time, NULL);
1329
+ if (status < 0)
1330
+ ossl_raise(eOCSPError, "OCSP_single_get0_status");
1331
+ if (!time)
1332
+ return Qnil;
1333
+
1334
+ return asn1time_to_time(time);
1335
+ }
1336
+
1337
+ /*
1338
+ * call-seq:
1339
+ * single_response.next_update -> Time | nil
1340
+ */
1341
+ static VALUE
1342
+ ossl_ocspsres_get_next_update(VALUE self)
1343
+ {
1344
+ OCSP_SINGLERESP *sres;
1345
+ int status;
1346
+ ASN1_GENERALIZEDTIME *time;
1347
+
1348
+ GetOCSPSingleRes(self, sres);
1349
+ status = OCSP_single_get0_status(sres, NULL, NULL, NULL, &time);
1350
+ if (status < 0)
1351
+ ossl_raise(eOCSPError, "OCSP_single_get0_status");
1352
+ if (!time)
1353
+ return Qnil;
1354
+
1355
+ return asn1time_to_time(time);
1356
+ }
1357
+
1358
+ /*
1359
+ * call-seq:
1360
+ * single_response.revocation_time -> Time | nil
1361
+ */
1362
+ static VALUE
1363
+ ossl_ocspsres_get_revocation_time(VALUE self)
1364
+ {
1365
+ OCSP_SINGLERESP *sres;
1366
+ int status;
1367
+ ASN1_GENERALIZEDTIME *time;
1368
+
1369
+ GetOCSPSingleRes(self, sres);
1370
+ status = OCSP_single_get0_status(sres, NULL, &time, NULL, NULL);
1371
+ if (status < 0)
1372
+ ossl_raise(eOCSPError, "OCSP_single_get0_status");
1373
+ if (status != V_OCSP_CERTSTATUS_REVOKED)
1374
+ ossl_raise(eOCSPError, "certificate is not revoked");
1375
+ if (!time)
1376
+ return Qnil;
1377
+
1378
+ return asn1time_to_time(time);
1379
+ }
1380
+
1381
+ /*
1382
+ * call-seq:
1383
+ * single_response.revocation_reason -> Integer | nil
1384
+ */
1385
+ static VALUE
1386
+ ossl_ocspsres_get_revocation_reason(VALUE self)
1387
+ {
1388
+ OCSP_SINGLERESP *sres;
1389
+ int status, reason;
1390
+
1391
+ GetOCSPSingleRes(self, sres);
1392
+ status = OCSP_single_get0_status(sres, &reason, NULL, NULL, NULL);
1393
+ if (status < 0)
1394
+ ossl_raise(eOCSPError, "OCSP_single_get0_status");
1395
+ if (status != V_OCSP_CERTSTATUS_REVOKED)
1396
+ ossl_raise(eOCSPError, "certificate is not revoked");
1397
+
1398
+ return INT2NUM(reason);
1399
+ }
1400
+
1401
+ /*
1402
+ * call-seq:
1403
+ * single_response.extensions -> Array of X509::Extension
1404
+ */
1405
+ static VALUE
1406
+ ossl_ocspsres_get_extensions(VALUE self)
1407
+ {
1408
+ OCSP_SINGLERESP *sres;
1409
+ X509_EXTENSION *ext;
1410
+ int count, i;
1411
+ VALUE ary;
1412
+
1413
+ GetOCSPSingleRes(self, sres);
1414
+
1415
+ count = OCSP_SINGLERESP_get_ext_count(sres);
1416
+ ary = rb_ary_new2(count);
1417
+ for (i = 0; i < count; i++) {
1418
+ ext = OCSP_SINGLERESP_get_ext(sres, i);
1419
+ rb_ary_push(ary, ossl_x509ext_new(ext)); /* will dup */
1420
+ }
1421
+
1422
+ return ary;
1423
+ }
1424
+
1425
+ /*
1426
+ * call-seq:
1427
+ * single_response.to_der -> String
1428
+ *
1429
+ * Encodes this SingleResponse into a DER-encoded string.
1430
+ */
1431
+ static VALUE
1432
+ ossl_ocspsres_to_der(VALUE self)
1433
+ {
1434
+ OCSP_SINGLERESP *sres;
1435
+ VALUE str;
1436
+ long len;
1437
+ unsigned char *p;
1438
+
1439
+ GetOCSPSingleRes(self, sres);
1440
+ if ((len = i2d_OCSP_SINGLERESP(sres, NULL)) <= 0)
1441
+ ossl_raise(eOCSPError, NULL);
1442
+ str = rb_str_new(0, len);
1443
+ p = (unsigned char *)RSTRING_PTR(str);
1444
+ if (i2d_OCSP_SINGLERESP(sres, &p) <= 0)
1445
+ ossl_raise(eOCSPError, NULL);
1446
+ ossl_str_adjust(str, p);
1447
+
1448
+ return str;
1449
+ }
1450
+
1451
+
1452
+ /*
1453
+ * OCSP::CertificateId
1454
+ */
1455
+ static VALUE
1456
+ ossl_ocspcid_alloc(VALUE klass)
1457
+ {
1458
+ OCSP_CERTID *id;
1459
+ VALUE obj;
1460
+
1461
+ obj = NewOCSPCertId(klass);
1462
+ if(!(id = OCSP_CERTID_new()))
1463
+ ossl_raise(eOCSPError, NULL);
1464
+ SetOCSPCertId(obj, id);
1465
+
1466
+ return obj;
1467
+ }
1468
+
1469
+ static VALUE
1470
+ ossl_ocspcid_initialize_copy(VALUE self, VALUE other)
1471
+ {
1472
+ OCSP_CERTID *cid, *cid_old, *cid_new;
1473
+
1474
+ rb_check_frozen(self);
1475
+ GetOCSPCertId(self, cid_old);
1476
+ GetOCSPCertId(other, cid);
1477
+
1478
+ cid_new = OCSP_CERTID_dup(cid);
1479
+ if (!cid_new)
1480
+ ossl_raise(eOCSPError, "OCSP_CERTID_dup");
1481
+
1482
+ SetOCSPCertId(self, cid_new);
1483
+ OCSP_CERTID_free(cid_old);
1484
+
1485
+ return self;
1486
+ }
1487
+
1488
+ /*
1489
+ * call-seq:
1490
+ * OpenSSL::OCSP::CertificateId.new(subject, issuer, digest = nil) -> certificate_id
1491
+ * OpenSSL::OCSP::CertificateId.new(der_string) -> certificate_id
1492
+ * OpenSSL::OCSP::CertificateId.new(obj) -> certificate_id
1493
+ *
1494
+ * Creates a new OpenSSL::OCSP::CertificateId for the given _subject_ and
1495
+ * _issuer_ X509 certificates. The _digest_ is a digest algorithm that is used
1496
+ * to compute the hash values. This defaults to SHA-1.
1497
+ *
1498
+ * If only one argument is given, decodes it as DER representation of a
1499
+ * certificate ID or generates certificate ID from the object that responds to
1500
+ * the to_der method.
1501
+ */
1502
+ static VALUE
1503
+ ossl_ocspcid_initialize(int argc, VALUE *argv, VALUE self)
1504
+ {
1505
+ OCSP_CERTID *id, *newid;
1506
+ VALUE subject, issuer, digest;
1507
+
1508
+ GetOCSPCertId(self, id);
1509
+ if (rb_scan_args(argc, argv, "12", &subject, &issuer, &digest) == 1) {
1510
+ VALUE arg;
1511
+ const unsigned char *p;
1512
+
1513
+ arg = ossl_to_der_if_possible(subject);
1514
+ StringValue(arg);
1515
+ p = (unsigned char *)RSTRING_PTR(arg);
1516
+ newid = d2i_OCSP_CERTID(NULL, &p, RSTRING_LEN(arg));
1517
+ if (!newid)
1518
+ ossl_raise(eOCSPError, "d2i_OCSP_CERTID");
1519
+ }
1520
+ else {
1521
+ X509 *x509s, *x509i;
1522
+ const EVP_MD *md;
1523
+
1524
+ x509s = GetX509CertPtr(subject); /* NO NEED TO DUP */
1525
+ x509i = GetX509CertPtr(issuer); /* NO NEED TO DUP */
1526
+ md = !NIL_P(digest) ? ossl_evp_get_digestbyname(digest) : NULL;
1527
+
1528
+ newid = OCSP_cert_to_id(md, x509s, x509i);
1529
+ if (!newid)
1530
+ ossl_raise(eOCSPError, "OCSP_cert_to_id");
1531
+ }
1532
+
1533
+ SetOCSPCertId(self, newid);
1534
+ OCSP_CERTID_free(id);
1535
+
1536
+ return self;
1537
+ }
1538
+
1539
+ /*
1540
+ * call-seq:
1541
+ * certificate_id.cmp(other) -> true or false
1542
+ *
1543
+ * Compares this certificate id with _other_ and returns +true+ if they are the
1544
+ * same.
1545
+ */
1546
+ static VALUE
1547
+ ossl_ocspcid_cmp(VALUE self, VALUE other)
1548
+ {
1549
+ OCSP_CERTID *id, *id2;
1550
+ int result;
1551
+
1552
+ GetOCSPCertId(self, id);
1553
+ GetOCSPCertId(other, id2);
1554
+ result = OCSP_id_cmp(id, id2);
1555
+
1556
+ return (result == 0) ? Qtrue : Qfalse;
1557
+ }
1558
+
1559
+ /*
1560
+ * call-seq:
1561
+ * certificate_id.cmp_issuer(other) -> true or false
1562
+ *
1563
+ * Compares this certificate id's issuer with _other_ and returns +true+ if
1564
+ * they are the same.
1565
+ */
1566
+
1567
+ static VALUE
1568
+ ossl_ocspcid_cmp_issuer(VALUE self, VALUE other)
1569
+ {
1570
+ OCSP_CERTID *id, *id2;
1571
+ int result;
1572
+
1573
+ GetOCSPCertId(self, id);
1574
+ GetOCSPCertId(other, id2);
1575
+ result = OCSP_id_issuer_cmp(id, id2);
1576
+
1577
+ return (result == 0) ? Qtrue : Qfalse;
1578
+ }
1579
+
1580
+ /*
1581
+ * call-seq:
1582
+ * certificate_id.serial -> Integer
1583
+ *
1584
+ * Returns the serial number of the certificate for which status is being
1585
+ * requested.
1586
+ */
1587
+ static VALUE
1588
+ ossl_ocspcid_get_serial(VALUE self)
1589
+ {
1590
+ OCSP_CERTID *id;
1591
+ ASN1_INTEGER *serial;
1592
+
1593
+ GetOCSPCertId(self, id);
1594
+ OCSP_id_get0_info(NULL, NULL, NULL, &serial, id);
1595
+
1596
+ return asn1integer_to_num(serial);
1597
+ }
1598
+
1599
+ /*
1600
+ * call-seq:
1601
+ * certificate_id.issuer_name_hash -> String
1602
+ *
1603
+ * Returns the issuerNameHash of this certificate ID, the hash of the
1604
+ * issuer's distinguished name calculated with the hashAlgorithm.
1605
+ */
1606
+ static VALUE
1607
+ ossl_ocspcid_get_issuer_name_hash(VALUE self)
1608
+ {
1609
+ OCSP_CERTID *id;
1610
+ ASN1_OCTET_STRING *name_hash;
1611
+ VALUE ret;
1612
+
1613
+ GetOCSPCertId(self, id);
1614
+ OCSP_id_get0_info(&name_hash, NULL, NULL, NULL, id);
1615
+
1616
+ ret = rb_str_new(NULL, name_hash->length * 2);
1617
+ ossl_bin2hex(name_hash->data, RSTRING_PTR(ret), name_hash->length);
1618
+
1619
+ return ret;
1620
+ }
1621
+
1622
+ /*
1623
+ * call-seq:
1624
+ * certificate_id.issuer_key_hash -> String
1625
+ *
1626
+ * Returns the issuerKeyHash of this certificate ID, the hash of the issuer's
1627
+ * public key.
1628
+ */
1629
+ static VALUE
1630
+ ossl_ocspcid_get_issuer_key_hash(VALUE self)
1631
+ {
1632
+ OCSP_CERTID *id;
1633
+ ASN1_OCTET_STRING *key_hash;
1634
+ VALUE ret;
1635
+
1636
+ GetOCSPCertId(self, id);
1637
+ OCSP_id_get0_info(NULL, NULL, &key_hash, NULL, id);
1638
+
1639
+ ret = rb_str_new(NULL, key_hash->length * 2);
1640
+ ossl_bin2hex(key_hash->data, RSTRING_PTR(ret), key_hash->length);
1641
+
1642
+ return ret;
1643
+ }
1644
+
1645
+ /*
1646
+ * call-seq:
1647
+ * certificate_id.hash_algorithm -> String
1648
+ *
1649
+ * Returns the ln (long name) of the hash algorithm used to generate
1650
+ * the issuerNameHash and the issuerKeyHash values.
1651
+ */
1652
+ static VALUE
1653
+ ossl_ocspcid_get_hash_algorithm(VALUE self)
1654
+ {
1655
+ OCSP_CERTID *id;
1656
+ ASN1_OBJECT *oid;
1657
+ BIO *out;
1658
+
1659
+ GetOCSPCertId(self, id);
1660
+ OCSP_id_get0_info(NULL, &oid, NULL, NULL, id);
1661
+
1662
+ if (!(out = BIO_new(BIO_s_mem())))
1663
+ ossl_raise(eOCSPError, "BIO_new");
1664
+
1665
+ if (!i2a_ASN1_OBJECT(out, oid)) {
1666
+ BIO_free(out);
1667
+ ossl_raise(eOCSPError, "i2a_ASN1_OBJECT");
1668
+ }
1669
+ return ossl_membio2str(out);
1670
+ }
1671
+
1672
+ /*
1673
+ * call-seq:
1674
+ * certificate_id.to_der -> String
1675
+ *
1676
+ * Encodes this certificate identifier into a DER-encoded string.
1677
+ */
1678
+ static VALUE
1679
+ ossl_ocspcid_to_der(VALUE self)
1680
+ {
1681
+ OCSP_CERTID *id;
1682
+ VALUE str;
1683
+ long len;
1684
+ unsigned char *p;
1685
+
1686
+ GetOCSPCertId(self, id);
1687
+ if ((len = i2d_OCSP_CERTID(id, NULL)) <= 0)
1688
+ ossl_raise(eOCSPError, NULL);
1689
+ str = rb_str_new(0, len);
1690
+ p = (unsigned char *)RSTRING_PTR(str);
1691
+ if (i2d_OCSP_CERTID(id, &p) <= 0)
1692
+ ossl_raise(eOCSPError, NULL);
1693
+ ossl_str_adjust(str, p);
1694
+
1695
+ return str;
1696
+ }
1697
+
1698
+ void
1699
+ Init_ossl_ocsp(void)
1700
+ {
1701
+ #if 0
1702
+ mOSSL = rb_define_module("OpenSSL");
1703
+ eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
1704
+ #endif
1705
+
1706
+ /*
1707
+ * OpenSSL::OCSP implements Online Certificate Status Protocol requests
1708
+ * and responses.
1709
+ *
1710
+ * Creating and sending an OCSP request requires a subject certificate
1711
+ * that contains an OCSP URL in an authorityInfoAccess extension and the
1712
+ * issuer certificate for the subject certificate. First, load the issuer
1713
+ * and subject certificates:
1714
+ *
1715
+ * subject = OpenSSL::X509::Certificate.new subject_pem
1716
+ * issuer = OpenSSL::X509::Certificate.new issuer_pem
1717
+ *
1718
+ * To create the request we need to create a certificate ID for the
1719
+ * subject certificate so the CA knows which certificate we are asking
1720
+ * about:
1721
+ *
1722
+ * digest = OpenSSL::Digest.new('SHA1')
1723
+ * certificate_id =
1724
+ * OpenSSL::OCSP::CertificateId.new subject, issuer, digest
1725
+ *
1726
+ * Then create a request and add the certificate ID to it:
1727
+ *
1728
+ * request = OpenSSL::OCSP::Request.new
1729
+ * request.add_certid certificate_id
1730
+ *
1731
+ * Adding a nonce to the request protects against replay attacks but not
1732
+ * all CA process the nonce.
1733
+ *
1734
+ * request.add_nonce
1735
+ *
1736
+ * To submit the request to the CA for verification we need to extract the
1737
+ * OCSP URI from the subject certificate:
1738
+ *
1739
+ * ocsp_uris = subject.ocsp_uris
1740
+ *
1741
+ * require 'uri'
1742
+ *
1743
+ * ocsp_uri = URI ocsp_uris[0]
1744
+ *
1745
+ * To submit the request we'll POST the request to the OCSP URI (per RFC
1746
+ * 2560). Note that we only handle HTTP requests and don't handle any
1747
+ * redirects in this example, so this is insufficient for serious use.
1748
+ *
1749
+ * require 'net/http'
1750
+ *
1751
+ * http_response =
1752
+ * Net::HTTP.start ocsp_uri.hostname, ocsp.port do |http|
1753
+ * http.post ocsp_uri.path, request.to_der,
1754
+ * 'content-type' => 'application/ocsp-request'
1755
+ * end
1756
+ *
1757
+ * response = OpenSSL::OCSP::Response.new http_response.body
1758
+ * response_basic = response.basic
1759
+ *
1760
+ * First we check if the response has a valid signature. Without a valid
1761
+ * signature we cannot trust it. If you get a failure here you may be
1762
+ * missing a system certificate store or may be missing the intermediate
1763
+ * certificates.
1764
+ *
1765
+ * store = OpenSSL::X509::Store.new
1766
+ * store.set_default_paths
1767
+ *
1768
+ * unless response_basic.verify [], store then
1769
+ * raise 'response is not signed by a trusted certificate'
1770
+ * end
1771
+ *
1772
+ * The response contains the status information (success/fail). We can
1773
+ * display the status as a string:
1774
+ *
1775
+ * puts response.status_string #=> successful
1776
+ *
1777
+ * Next we need to know the response details to determine if the response
1778
+ * matches our request. First we check the nonce. Again, not all CAs
1779
+ * support a nonce. See Request#check_nonce for the meanings of the
1780
+ * return values.
1781
+ *
1782
+ * p request.check_nonce basic_response #=> value from -1 to 3
1783
+ *
1784
+ * Then extract the status information for the certificate from the basic
1785
+ * response.
1786
+ *
1787
+ * single_response = basic_response.find_response(certificate_id)
1788
+ *
1789
+ * unless single_response
1790
+ * raise 'basic_response does not have the status for the certificiate'
1791
+ * end
1792
+ *
1793
+ * Then check the validity. A status issued in the future must be rejected.
1794
+ *
1795
+ * unless single_response.check_validity
1796
+ * raise 'this_update is in the future or next_update time has passed'
1797
+ * end
1798
+ *
1799
+ * case single_response.cert_status
1800
+ * when OpenSSL::OCSP::V_CERTSTATUS_GOOD
1801
+ * puts 'certificate is still valid'
1802
+ * when OpenSSL::OCSP::V_CERTSTATUS_REVOKED
1803
+ * puts "certificate has been revoked at #{single_response.revocation_time}"
1804
+ * when OpenSSL::OCSP::V_CERTSTATUS_UNKNOWN
1805
+ * puts 'responder doesn't know about the certificate'
1806
+ * end
1807
+ */
1808
+
1809
+ mOCSP = rb_define_module_under(mOSSL, "OCSP");
1810
+
1811
+ /*
1812
+ * OCSP error class.
1813
+ */
1814
+
1815
+ eOCSPError = rb_define_class_under(mOCSP, "OCSPError", eOSSLError);
1816
+
1817
+ /*
1818
+ * An OpenSSL::OCSP::Request contains the certificate information for
1819
+ * determining if a certificate has been revoked or not. A Request can be
1820
+ * created for a certificate or from a DER-encoded request created
1821
+ * elsewhere.
1822
+ */
1823
+
1824
+ cOCSPReq = rb_define_class_under(mOCSP, "Request", rb_cObject);
1825
+ rb_define_alloc_func(cOCSPReq, ossl_ocspreq_alloc);
1826
+ rb_define_method(cOCSPReq, "initialize_copy", ossl_ocspreq_initialize_copy, 1);
1827
+ rb_define_method(cOCSPReq, "initialize", ossl_ocspreq_initialize, -1);
1828
+ rb_define_method(cOCSPReq, "add_nonce", ossl_ocspreq_add_nonce, -1);
1829
+ rb_define_method(cOCSPReq, "check_nonce", ossl_ocspreq_check_nonce, 1);
1830
+ rb_define_method(cOCSPReq, "add_certid", ossl_ocspreq_add_certid, 1);
1831
+ rb_define_method(cOCSPReq, "certid", ossl_ocspreq_get_certid, 0);
1832
+ rb_define_method(cOCSPReq, "signed?", ossl_ocspreq_signed_p, 0);
1833
+ rb_define_method(cOCSPReq, "sign", ossl_ocspreq_sign, -1);
1834
+ rb_define_method(cOCSPReq, "verify", ossl_ocspreq_verify, -1);
1835
+ rb_define_method(cOCSPReq, "to_der", ossl_ocspreq_to_der, 0);
1836
+
1837
+ /*
1838
+ * An OpenSSL::OCSP::Response contains the status of a certificate check
1839
+ * which is created from an OpenSSL::OCSP::Request.
1840
+ */
1841
+
1842
+ cOCSPRes = rb_define_class_under(mOCSP, "Response", rb_cObject);
1843
+ rb_define_singleton_method(cOCSPRes, "create", ossl_ocspres_s_create, 2);
1844
+ rb_define_alloc_func(cOCSPRes, ossl_ocspres_alloc);
1845
+ rb_define_method(cOCSPRes, "initialize_copy", ossl_ocspres_initialize_copy, 1);
1846
+ rb_define_method(cOCSPRes, "initialize", ossl_ocspres_initialize, -1);
1847
+ rb_define_method(cOCSPRes, "status", ossl_ocspres_status, 0);
1848
+ rb_define_method(cOCSPRes, "status_string", ossl_ocspres_status_string, 0);
1849
+ rb_define_method(cOCSPRes, "basic", ossl_ocspres_get_basic, 0);
1850
+ rb_define_method(cOCSPRes, "to_der", ossl_ocspres_to_der, 0);
1851
+
1852
+ /*
1853
+ * An OpenSSL::OCSP::BasicResponse contains the status of a certificate
1854
+ * check which is created from an OpenSSL::OCSP::Request. A
1855
+ * BasicResponse is more detailed than a Response.
1856
+ */
1857
+
1858
+ cOCSPBasicRes = rb_define_class_under(mOCSP, "BasicResponse", rb_cObject);
1859
+ rb_define_alloc_func(cOCSPBasicRes, ossl_ocspbres_alloc);
1860
+ rb_define_method(cOCSPBasicRes, "initialize_copy", ossl_ocspbres_initialize_copy, 1);
1861
+ rb_define_method(cOCSPBasicRes, "initialize", ossl_ocspbres_initialize, -1);
1862
+ rb_define_method(cOCSPBasicRes, "copy_nonce", ossl_ocspbres_copy_nonce, 1);
1863
+ rb_define_method(cOCSPBasicRes, "add_nonce", ossl_ocspbres_add_nonce, -1);
1864
+ rb_define_method(cOCSPBasicRes, "add_status", ossl_ocspbres_add_status, 7);
1865
+ rb_define_method(cOCSPBasicRes, "status", ossl_ocspbres_get_status, 0);
1866
+ rb_define_method(cOCSPBasicRes, "responses", ossl_ocspbres_get_responses, 0);
1867
+ rb_define_method(cOCSPBasicRes, "find_response", ossl_ocspbres_find_response, 1);
1868
+ rb_define_method(cOCSPBasicRes, "sign", ossl_ocspbres_sign, -1);
1869
+ rb_define_method(cOCSPBasicRes, "verify", ossl_ocspbres_verify, -1);
1870
+ rb_define_method(cOCSPBasicRes, "to_der", ossl_ocspbres_to_der, 0);
1871
+
1872
+ /*
1873
+ * An OpenSSL::OCSP::SingleResponse represents an OCSP SingleResponse
1874
+ * structure, which contains the basic information of the status of the
1875
+ * certificate.
1876
+ */
1877
+ cOCSPSingleRes = rb_define_class_under(mOCSP, "SingleResponse", rb_cObject);
1878
+ rb_define_alloc_func(cOCSPSingleRes, ossl_ocspsres_alloc);
1879
+ rb_define_method(cOCSPSingleRes, "initialize_copy", ossl_ocspsres_initialize_copy, 1);
1880
+ rb_define_method(cOCSPSingleRes, "initialize", ossl_ocspsres_initialize, 1);
1881
+ rb_define_method(cOCSPSingleRes, "check_validity", ossl_ocspsres_check_validity, -1);
1882
+ rb_define_method(cOCSPSingleRes, "certid", ossl_ocspsres_get_certid, 0);
1883
+ rb_define_method(cOCSPSingleRes, "cert_status", ossl_ocspsres_get_cert_status, 0);
1884
+ rb_define_method(cOCSPSingleRes, "this_update", ossl_ocspsres_get_this_update, 0);
1885
+ rb_define_method(cOCSPSingleRes, "next_update", ossl_ocspsres_get_next_update, 0);
1886
+ rb_define_method(cOCSPSingleRes, "revocation_time", ossl_ocspsres_get_revocation_time, 0);
1887
+ rb_define_method(cOCSPSingleRes, "revocation_reason", ossl_ocspsres_get_revocation_reason, 0);
1888
+ rb_define_method(cOCSPSingleRes, "extensions", ossl_ocspsres_get_extensions, 0);
1889
+ rb_define_method(cOCSPSingleRes, "to_der", ossl_ocspsres_to_der, 0);
1890
+
1891
+ /*
1892
+ * An OpenSSL::OCSP::CertificateId identifies a certificate to the CA so
1893
+ * that a status check can be performed.
1894
+ */
1895
+
1896
+ cOCSPCertId = rb_define_class_under(mOCSP, "CertificateId", rb_cObject);
1897
+ rb_define_alloc_func(cOCSPCertId, ossl_ocspcid_alloc);
1898
+ rb_define_method(cOCSPCertId, "initialize_copy", ossl_ocspcid_initialize_copy, 1);
1899
+ rb_define_method(cOCSPCertId, "initialize", ossl_ocspcid_initialize, -1);
1900
+ rb_define_method(cOCSPCertId, "cmp", ossl_ocspcid_cmp, 1);
1901
+ rb_define_method(cOCSPCertId, "cmp_issuer", ossl_ocspcid_cmp_issuer, 1);
1902
+ rb_define_method(cOCSPCertId, "serial", ossl_ocspcid_get_serial, 0);
1903
+ rb_define_method(cOCSPCertId, "issuer_name_hash", ossl_ocspcid_get_issuer_name_hash, 0);
1904
+ rb_define_method(cOCSPCertId, "issuer_key_hash", ossl_ocspcid_get_issuer_key_hash, 0);
1905
+ rb_define_method(cOCSPCertId, "hash_algorithm", ossl_ocspcid_get_hash_algorithm, 0);
1906
+ rb_define_method(cOCSPCertId, "to_der", ossl_ocspcid_to_der, 0);
1907
+
1908
+ /* Internal error in issuer */
1909
+ rb_define_const(mOCSP, "RESPONSE_STATUS_INTERNALERROR", INT2NUM(OCSP_RESPONSE_STATUS_INTERNALERROR));
1910
+
1911
+ /* Illegal confirmation request */
1912
+ rb_define_const(mOCSP, "RESPONSE_STATUS_MALFORMEDREQUEST", INT2NUM(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST));
1913
+
1914
+ /* The certificate was revoked for an unknown reason */
1915
+ rb_define_const(mOCSP, "REVOKED_STATUS_NOSTATUS", INT2NUM(OCSP_REVOKED_STATUS_NOSTATUS));
1916
+
1917
+ /* You must sign the request and resubmit */
1918
+ rb_define_const(mOCSP, "RESPONSE_STATUS_SIGREQUIRED", INT2NUM(OCSP_RESPONSE_STATUS_SIGREQUIRED));
1919
+
1920
+ /* Response has valid confirmations */
1921
+ rb_define_const(mOCSP, "RESPONSE_STATUS_SUCCESSFUL", INT2NUM(OCSP_RESPONSE_STATUS_SUCCESSFUL));
1922
+
1923
+ /* Try again later */
1924
+ rb_define_const(mOCSP, "RESPONSE_STATUS_TRYLATER", INT2NUM(OCSP_RESPONSE_STATUS_TRYLATER));
1925
+
1926
+ /* The certificate subject's name or other information changed */
1927
+ rb_define_const(mOCSP, "REVOKED_STATUS_AFFILIATIONCHANGED", INT2NUM(OCSP_REVOKED_STATUS_AFFILIATIONCHANGED));
1928
+
1929
+ /* This CA certificate was revoked due to a key compromise */
1930
+ rb_define_const(mOCSP, "REVOKED_STATUS_CACOMPROMISE", INT2NUM(OCSP_REVOKED_STATUS_CACOMPROMISE));
1931
+
1932
+ /* The certificate is on hold */
1933
+ rb_define_const(mOCSP, "REVOKED_STATUS_CERTIFICATEHOLD", INT2NUM(OCSP_REVOKED_STATUS_CERTIFICATEHOLD));
1934
+
1935
+ /* The certificate is no longer needed */
1936
+ rb_define_const(mOCSP, "REVOKED_STATUS_CESSATIONOFOPERATION", INT2NUM(OCSP_REVOKED_STATUS_CESSATIONOFOPERATION));
1937
+
1938
+ /* The certificate was revoked due to a key compromise */
1939
+ rb_define_const(mOCSP, "REVOKED_STATUS_KEYCOMPROMISE", INT2NUM(OCSP_REVOKED_STATUS_KEYCOMPROMISE));
1940
+
1941
+ /* The certificate was previously on hold and should now be removed from
1942
+ * the CRL */
1943
+ rb_define_const(mOCSP, "REVOKED_STATUS_REMOVEFROMCRL", INT2NUM(OCSP_REVOKED_STATUS_REMOVEFROMCRL));
1944
+
1945
+ /* The certificate was superseded by a new certificate */
1946
+ rb_define_const(mOCSP, "REVOKED_STATUS_SUPERSEDED", INT2NUM(OCSP_REVOKED_STATUS_SUPERSEDED));
1947
+
1948
+ /* Your request is unauthorized. */
1949
+ rb_define_const(mOCSP, "RESPONSE_STATUS_UNAUTHORIZED", INT2NUM(OCSP_RESPONSE_STATUS_UNAUTHORIZED));
1950
+
1951
+ /* The certificate was revoked for an unspecified reason */
1952
+ rb_define_const(mOCSP, "REVOKED_STATUS_UNSPECIFIED", INT2NUM(OCSP_REVOKED_STATUS_UNSPECIFIED));
1953
+
1954
+ /* Do not include certificates in the response */
1955
+ rb_define_const(mOCSP, "NOCERTS", INT2NUM(OCSP_NOCERTS));
1956
+
1957
+ /* Do not search certificates contained in the response for a signer */
1958
+ rb_define_const(mOCSP, "NOINTERN", INT2NUM(OCSP_NOINTERN));
1959
+
1960
+ /* Do not check the signature on the response */
1961
+ rb_define_const(mOCSP, "NOSIGS", INT2NUM(OCSP_NOSIGS));
1962
+
1963
+ /* Do not verify the certificate chain on the response */
1964
+ rb_define_const(mOCSP, "NOCHAIN", INT2NUM(OCSP_NOCHAIN));
1965
+
1966
+ /* Do not verify the response at all */
1967
+ rb_define_const(mOCSP, "NOVERIFY", INT2NUM(OCSP_NOVERIFY));
1968
+
1969
+ /* Do not check trust */
1970
+ rb_define_const(mOCSP, "NOEXPLICIT", INT2NUM(OCSP_NOEXPLICIT));
1971
+
1972
+ /* (This flag is not used by OpenSSL 1.0.1g) */
1973
+ rb_define_const(mOCSP, "NOCASIGN", INT2NUM(OCSP_NOCASIGN));
1974
+
1975
+ /* (This flag is not used by OpenSSL 1.0.1g) */
1976
+ rb_define_const(mOCSP, "NODELEGATED", INT2NUM(OCSP_NODELEGATED));
1977
+
1978
+ /* Do not make additional signing certificate checks */
1979
+ rb_define_const(mOCSP, "NOCHECKS", INT2NUM(OCSP_NOCHECKS));
1980
+
1981
+ /* Do not verify additional certificates */
1982
+ rb_define_const(mOCSP, "TRUSTOTHER", INT2NUM(OCSP_TRUSTOTHER));
1983
+
1984
+ /* Identify the response by signing the certificate key ID */
1985
+ rb_define_const(mOCSP, "RESPID_KEY", INT2NUM(OCSP_RESPID_KEY));
1986
+
1987
+ /* Do not include producedAt time in response */
1988
+ rb_define_const(mOCSP, "NOTIME", INT2NUM(OCSP_NOTIME));
1989
+
1990
+ /* Indicates the certificate is not revoked but does not necessarily mean
1991
+ * the certificate was issued or that this response is within the
1992
+ * certificate's validity interval */
1993
+ rb_define_const(mOCSP, "V_CERTSTATUS_GOOD", INT2NUM(V_OCSP_CERTSTATUS_GOOD));
1994
+ /* Indicates the certificate has been revoked either permanently or
1995
+ * temporarily (on hold). */
1996
+ rb_define_const(mOCSP, "V_CERTSTATUS_REVOKED", INT2NUM(V_OCSP_CERTSTATUS_REVOKED));
1997
+
1998
+ /* Indicates the responder does not know about the certificate being
1999
+ * requested. */
2000
+ rb_define_const(mOCSP, "V_CERTSTATUS_UNKNOWN", INT2NUM(V_OCSP_CERTSTATUS_UNKNOWN));
2001
+
2002
+ /* The responder ID is based on the key name. */
2003
+ rb_define_const(mOCSP, "V_RESPID_NAME", INT2NUM(V_OCSP_RESPID_NAME));
2004
+
2005
+ /* The responder ID is based on the public key. */
2006
+ rb_define_const(mOCSP, "V_RESPID_KEY", INT2NUM(V_OCSP_RESPID_KEY));
2007
+ }
2008
+ #else
2009
+ void
2010
+ Init_ossl_ocsp(void)
2011
+ {
2012
+ }
2013
+ #endif