openssl-custom 2.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,846 @@
1
+ /*
2
+ * 'OpenSSL for Ruby' project
3
+ * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
4
+ * All rights reserved.
5
+ */
6
+ /*
7
+ * This program is licensed under the same licence as Ruby.
8
+ * (See the file 'LICENCE'.)
9
+ */
10
+ #include "ossl.h"
11
+
12
+ #define NewX509(klass) \
13
+ TypedData_Wrap_Struct((klass), &ossl_x509_type, 0)
14
+ #define SetX509(obj, x509) do { \
15
+ if (!(x509)) { \
16
+ ossl_raise(rb_eRuntimeError, "CERT wasn't initialized!"); \
17
+ } \
18
+ RTYPEDDATA_DATA(obj) = (x509); \
19
+ } while (0)
20
+ #define GetX509(obj, x509) do { \
21
+ TypedData_Get_Struct((obj), X509, &ossl_x509_type, (x509)); \
22
+ if (!(x509)) { \
23
+ ossl_raise(rb_eRuntimeError, "CERT wasn't initialized!"); \
24
+ } \
25
+ } while (0)
26
+
27
+ /*
28
+ * Classes
29
+ */
30
+ VALUE cX509Cert;
31
+ VALUE eX509CertError;
32
+
33
+ static void
34
+ ossl_x509_free(void *ptr)
35
+ {
36
+ X509_free(ptr);
37
+ }
38
+
39
+ static const rb_data_type_t ossl_x509_type = {
40
+ "OpenSSL/X509",
41
+ {
42
+ 0, ossl_x509_free,
43
+ },
44
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
45
+ };
46
+
47
+ /*
48
+ * Public
49
+ */
50
+ VALUE
51
+ ossl_x509_new(X509 *x509)
52
+ {
53
+ X509 *new;
54
+ VALUE obj;
55
+
56
+ obj = NewX509(cX509Cert);
57
+ if (!x509) {
58
+ new = X509_new();
59
+ } else {
60
+ new = X509_dup(x509);
61
+ }
62
+ if (!new) {
63
+ ossl_raise(eX509CertError, NULL);
64
+ }
65
+ SetX509(obj, new);
66
+
67
+ return obj;
68
+ }
69
+
70
+ X509 *
71
+ GetX509CertPtr(VALUE obj)
72
+ {
73
+ X509 *x509;
74
+
75
+ GetX509(obj, x509);
76
+
77
+ return x509;
78
+ }
79
+
80
+ X509 *
81
+ DupX509CertPtr(VALUE obj)
82
+ {
83
+ X509 *x509;
84
+
85
+ GetX509(obj, x509);
86
+
87
+ X509_up_ref(x509);
88
+
89
+ return x509;
90
+ }
91
+
92
+ /*
93
+ * Private
94
+ */
95
+ static VALUE
96
+ ossl_x509_alloc(VALUE klass)
97
+ {
98
+ X509 *x509;
99
+ VALUE obj;
100
+
101
+ obj = NewX509(klass);
102
+ x509 = X509_new();
103
+ if (!x509) ossl_raise(eX509CertError, NULL);
104
+ SetX509(obj, x509);
105
+
106
+ return obj;
107
+ }
108
+
109
+ /*
110
+ * call-seq:
111
+ * Certificate.new => cert
112
+ * Certificate.new(string) => cert
113
+ */
114
+ static VALUE
115
+ ossl_x509_initialize(int argc, VALUE *argv, VALUE self)
116
+ {
117
+ BIO *in;
118
+ X509 *x509, *x = DATA_PTR(self);
119
+ VALUE arg;
120
+
121
+ if (rb_scan_args(argc, argv, "01", &arg) == 0) {
122
+ /* create just empty X509Cert */
123
+ return self;
124
+ }
125
+ arg = ossl_to_der_if_possible(arg);
126
+ in = ossl_obj2bio(&arg);
127
+ x509 = PEM_read_bio_X509(in, &x, NULL, NULL);
128
+ DATA_PTR(self) = x;
129
+ if (!x509) {
130
+ OSSL_BIO_reset(in);
131
+ x509 = d2i_X509_bio(in, &x);
132
+ DATA_PTR(self) = x;
133
+ }
134
+ BIO_free(in);
135
+ if (!x509) ossl_raise(eX509CertError, NULL);
136
+
137
+ return self;
138
+ }
139
+
140
+ static VALUE
141
+ ossl_x509_copy(VALUE self, VALUE other)
142
+ {
143
+ X509 *a, *b, *x509;
144
+
145
+ rb_check_frozen(self);
146
+ if (self == other) return self;
147
+
148
+ GetX509(self, a);
149
+ GetX509(other, b);
150
+
151
+ x509 = X509_dup(b);
152
+ if (!x509) ossl_raise(eX509CertError, NULL);
153
+
154
+ DATA_PTR(self) = x509;
155
+ X509_free(a);
156
+
157
+ return self;
158
+ }
159
+
160
+ /*
161
+ * call-seq:
162
+ * cert.to_der => string
163
+ */
164
+ static VALUE
165
+ ossl_x509_to_der(VALUE self)
166
+ {
167
+ X509 *x509;
168
+ VALUE str;
169
+ long len;
170
+ unsigned char *p;
171
+
172
+ GetX509(self, x509);
173
+ if ((len = i2d_X509(x509, NULL)) <= 0)
174
+ ossl_raise(eX509CertError, NULL);
175
+ str = rb_str_new(0, len);
176
+ p = (unsigned char *)RSTRING_PTR(str);
177
+ if (i2d_X509(x509, &p) <= 0)
178
+ ossl_raise(eX509CertError, NULL);
179
+ ossl_str_adjust(str, p);
180
+
181
+ return str;
182
+ }
183
+
184
+ /*
185
+ * call-seq:
186
+ * cert.to_pem => string
187
+ */
188
+ static VALUE
189
+ ossl_x509_to_pem(VALUE self)
190
+ {
191
+ X509 *x509;
192
+ BIO *out;
193
+ VALUE str;
194
+
195
+ GetX509(self, x509);
196
+ out = BIO_new(BIO_s_mem());
197
+ if (!out) ossl_raise(eX509CertError, NULL);
198
+
199
+ if (!PEM_write_bio_X509(out, x509)) {
200
+ BIO_free(out);
201
+ ossl_raise(eX509CertError, NULL);
202
+ }
203
+ str = ossl_membio2str(out);
204
+
205
+ return str;
206
+ }
207
+
208
+ /*
209
+ * call-seq:
210
+ * cert.to_text => string
211
+ */
212
+ static VALUE
213
+ ossl_x509_to_text(VALUE self)
214
+ {
215
+ X509 *x509;
216
+ BIO *out;
217
+ VALUE str;
218
+
219
+ GetX509(self, x509);
220
+
221
+ out = BIO_new(BIO_s_mem());
222
+ if (!out) ossl_raise(eX509CertError, NULL);
223
+
224
+ if (!X509_print(out, x509)) {
225
+ BIO_free(out);
226
+ ossl_raise(eX509CertError, NULL);
227
+ }
228
+ str = ossl_membio2str(out);
229
+
230
+ return str;
231
+ }
232
+
233
+ #if 0
234
+ /*
235
+ * Makes from X509 X509_REQuest
236
+ */
237
+ static VALUE
238
+ ossl_x509_to_req(VALUE self)
239
+ {
240
+ X509 *x509;
241
+ X509_REQ *req;
242
+ VALUE obj;
243
+
244
+ GetX509(self, x509);
245
+ if (!(req = X509_to_X509_REQ(x509, NULL, EVP_md5()))) {
246
+ ossl_raise(eX509CertError, NULL);
247
+ }
248
+ obj = ossl_x509req_new(req);
249
+ X509_REQ_free(req);
250
+
251
+ return obj;
252
+ }
253
+ #endif
254
+
255
+ /*
256
+ * call-seq:
257
+ * cert.version => integer
258
+ */
259
+ static VALUE
260
+ ossl_x509_get_version(VALUE self)
261
+ {
262
+ X509 *x509;
263
+
264
+ GetX509(self, x509);
265
+
266
+ return LONG2NUM(X509_get_version(x509));
267
+ }
268
+
269
+ /*
270
+ * call-seq:
271
+ * cert.version = integer => integer
272
+ */
273
+ static VALUE
274
+ ossl_x509_set_version(VALUE self, VALUE version)
275
+ {
276
+ X509 *x509;
277
+ long ver;
278
+
279
+ if ((ver = NUM2LONG(version)) < 0) {
280
+ ossl_raise(eX509CertError, "version must be >= 0!");
281
+ }
282
+ GetX509(self, x509);
283
+ if (!X509_set_version(x509, ver)) {
284
+ ossl_raise(eX509CertError, NULL);
285
+ }
286
+
287
+ return version;
288
+ }
289
+
290
+ /*
291
+ * call-seq:
292
+ * cert.serial => integer
293
+ */
294
+ static VALUE
295
+ ossl_x509_get_serial(VALUE self)
296
+ {
297
+ X509 *x509;
298
+
299
+ GetX509(self, x509);
300
+
301
+ return asn1integer_to_num(X509_get_serialNumber(x509));
302
+ }
303
+
304
+ /*
305
+ * call-seq:
306
+ * cert.serial = integer => integer
307
+ */
308
+ static VALUE
309
+ ossl_x509_set_serial(VALUE self, VALUE num)
310
+ {
311
+ X509 *x509;
312
+
313
+ GetX509(self, x509);
314
+ X509_set_serialNumber(x509, num_to_asn1integer(num, X509_get_serialNumber(x509)));
315
+
316
+ return num;
317
+ }
318
+
319
+ /*
320
+ * call-seq:
321
+ * cert.signature_algorithm => string
322
+ */
323
+ static VALUE
324
+ ossl_x509_get_signature_algorithm(VALUE self)
325
+ {
326
+ X509 *x509;
327
+ BIO *out;
328
+ VALUE str;
329
+
330
+ GetX509(self, x509);
331
+ out = BIO_new(BIO_s_mem());
332
+ if (!out) ossl_raise(eX509CertError, NULL);
333
+
334
+ if (!i2a_ASN1_OBJECT(out, X509_get0_tbs_sigalg(x509)->algorithm)) {
335
+ BIO_free(out);
336
+ ossl_raise(eX509CertError, NULL);
337
+ }
338
+ str = ossl_membio2str(out);
339
+
340
+ return str;
341
+ }
342
+
343
+ /*
344
+ * call-seq:
345
+ * cert.subject => name
346
+ */
347
+ static VALUE
348
+ ossl_x509_get_subject(VALUE self)
349
+ {
350
+ X509 *x509;
351
+ X509_NAME *name;
352
+
353
+ GetX509(self, x509);
354
+ if (!(name = X509_get_subject_name(x509))) { /* NO DUP - don't free! */
355
+ ossl_raise(eX509CertError, NULL);
356
+ }
357
+
358
+ return ossl_x509name_new(name);
359
+ }
360
+
361
+ /*
362
+ * call-seq:
363
+ * cert.subject = name => name
364
+ */
365
+ static VALUE
366
+ ossl_x509_set_subject(VALUE self, VALUE subject)
367
+ {
368
+ X509 *x509;
369
+
370
+ GetX509(self, x509);
371
+ if (!X509_set_subject_name(x509, GetX509NamePtr(subject))) { /* DUPs name */
372
+ ossl_raise(eX509CertError, NULL);
373
+ }
374
+
375
+ return subject;
376
+ }
377
+
378
+ /*
379
+ * call-seq:
380
+ * cert.issuer => name
381
+ */
382
+ static VALUE
383
+ ossl_x509_get_issuer(VALUE self)
384
+ {
385
+ X509 *x509;
386
+ X509_NAME *name;
387
+
388
+ GetX509(self, x509);
389
+ if(!(name = X509_get_issuer_name(x509))) { /* NO DUP - don't free! */
390
+ ossl_raise(eX509CertError, NULL);
391
+ }
392
+
393
+ return ossl_x509name_new(name);
394
+ }
395
+
396
+ /*
397
+ * call-seq:
398
+ * cert.issuer = name => name
399
+ */
400
+ static VALUE
401
+ ossl_x509_set_issuer(VALUE self, VALUE issuer)
402
+ {
403
+ X509 *x509;
404
+
405
+ GetX509(self, x509);
406
+ if (!X509_set_issuer_name(x509, GetX509NamePtr(issuer))) { /* DUPs name */
407
+ ossl_raise(eX509CertError, NULL);
408
+ }
409
+
410
+ return issuer;
411
+ }
412
+
413
+ /*
414
+ * call-seq:
415
+ * cert.not_before => time
416
+ */
417
+ static VALUE
418
+ ossl_x509_get_not_before(VALUE self)
419
+ {
420
+ X509 *x509;
421
+ const ASN1_TIME *asn1time;
422
+
423
+ GetX509(self, x509);
424
+ if (!(asn1time = X509_get0_notBefore(x509))) {
425
+ ossl_raise(eX509CertError, NULL);
426
+ }
427
+
428
+ return asn1time_to_time(asn1time);
429
+ }
430
+
431
+ /*
432
+ * call-seq:
433
+ * cert.not_before = time => time
434
+ */
435
+ static VALUE
436
+ ossl_x509_set_not_before(VALUE self, VALUE time)
437
+ {
438
+ X509 *x509;
439
+ ASN1_TIME *asn1time;
440
+
441
+ GetX509(self, x509);
442
+ asn1time = ossl_x509_time_adjust(NULL, time);
443
+ if (!X509_set1_notBefore(x509, asn1time)) {
444
+ ASN1_TIME_free(asn1time);
445
+ ossl_raise(eX509CertError, "X509_set_notBefore");
446
+ }
447
+ ASN1_TIME_free(asn1time);
448
+
449
+ return time;
450
+ }
451
+
452
+ /*
453
+ * call-seq:
454
+ * cert.not_after => time
455
+ */
456
+ static VALUE
457
+ ossl_x509_get_not_after(VALUE self)
458
+ {
459
+ X509 *x509;
460
+ const ASN1_TIME *asn1time;
461
+
462
+ GetX509(self, x509);
463
+ if (!(asn1time = X509_get0_notAfter(x509))) {
464
+ ossl_raise(eX509CertError, NULL);
465
+ }
466
+
467
+ return asn1time_to_time(asn1time);
468
+ }
469
+
470
+ /*
471
+ * call-seq:
472
+ * cert.not_after = time => time
473
+ */
474
+ static VALUE
475
+ ossl_x509_set_not_after(VALUE self, VALUE time)
476
+ {
477
+ X509 *x509;
478
+ ASN1_TIME *asn1time;
479
+
480
+ GetX509(self, x509);
481
+ asn1time = ossl_x509_time_adjust(NULL, time);
482
+ if (!X509_set1_notAfter(x509, asn1time)) {
483
+ ASN1_TIME_free(asn1time);
484
+ ossl_raise(eX509CertError, "X509_set_notAfter");
485
+ }
486
+ ASN1_TIME_free(asn1time);
487
+
488
+ return time;
489
+ }
490
+
491
+ /*
492
+ * call-seq:
493
+ * cert.public_key => key
494
+ */
495
+ static VALUE
496
+ ossl_x509_get_public_key(VALUE self)
497
+ {
498
+ X509 *x509;
499
+ EVP_PKEY *pkey;
500
+
501
+ GetX509(self, x509);
502
+ if (!(pkey = X509_get_pubkey(x509))) { /* adds an reference */
503
+ ossl_raise(eX509CertError, NULL);
504
+ }
505
+
506
+ return ossl_pkey_new(pkey); /* NO DUP - OK */
507
+ }
508
+
509
+ /*
510
+ * call-seq:
511
+ * cert.public_key = key
512
+ */
513
+ static VALUE
514
+ ossl_x509_set_public_key(VALUE self, VALUE key)
515
+ {
516
+ X509 *x509;
517
+ EVP_PKEY *pkey;
518
+
519
+ GetX509(self, x509);
520
+ pkey = GetPKeyPtr(key);
521
+ ossl_pkey_check_public_key(pkey);
522
+ if (!X509_set_pubkey(x509, pkey))
523
+ ossl_raise(eX509CertError, "X509_set_pubkey");
524
+ return key;
525
+ }
526
+
527
+ /*
528
+ * call-seq:
529
+ * cert.sign(key, digest) => self
530
+ */
531
+ static VALUE
532
+ ossl_x509_sign(VALUE self, VALUE key, VALUE digest)
533
+ {
534
+ X509 *x509;
535
+ EVP_PKEY *pkey;
536
+ const EVP_MD *md;
537
+
538
+ pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
539
+ md = ossl_evp_get_digestbyname(digest);
540
+ GetX509(self, x509);
541
+ if (!X509_sign(x509, pkey, md)) {
542
+ ossl_raise(eX509CertError, NULL);
543
+ }
544
+
545
+ return self;
546
+ }
547
+
548
+ /*
549
+ * call-seq:
550
+ * cert.verify(key) => true | false
551
+ *
552
+ * Verifies the signature of the certificate, with the public key _key_. _key_
553
+ * must be an instance of OpenSSL::PKey.
554
+ */
555
+ static VALUE
556
+ ossl_x509_verify(VALUE self, VALUE key)
557
+ {
558
+ X509 *x509;
559
+ EVP_PKEY *pkey;
560
+
561
+ GetX509(self, x509);
562
+ pkey = GetPKeyPtr(key);
563
+ ossl_pkey_check_public_key(pkey);
564
+ switch (X509_verify(x509, pkey)) {
565
+ case 1:
566
+ return Qtrue;
567
+ case 0:
568
+ ossl_clear_error();
569
+ return Qfalse;
570
+ default:
571
+ ossl_raise(eX509CertError, NULL);
572
+ }
573
+ }
574
+
575
+ /*
576
+ * call-seq:
577
+ * cert.check_private_key(key) -> true | false
578
+ *
579
+ * Returns +true+ if _key_ is the corresponding private key to the Subject
580
+ * Public Key Information, +false+ otherwise.
581
+ */
582
+ static VALUE
583
+ ossl_x509_check_private_key(VALUE self, VALUE key)
584
+ {
585
+ X509 *x509;
586
+ EVP_PKEY *pkey;
587
+
588
+ /* not needed private key, but should be */
589
+ pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
590
+ GetX509(self, x509);
591
+ if (!X509_check_private_key(x509, pkey)) {
592
+ ossl_clear_error();
593
+ return Qfalse;
594
+ }
595
+
596
+ return Qtrue;
597
+ }
598
+
599
+ /*
600
+ * call-seq:
601
+ * cert.extensions => [extension...]
602
+ */
603
+ static VALUE
604
+ ossl_x509_get_extensions(VALUE self)
605
+ {
606
+ X509 *x509;
607
+ int count, i;
608
+ X509_EXTENSION *ext;
609
+ VALUE ary;
610
+
611
+ GetX509(self, x509);
612
+ count = X509_get_ext_count(x509);
613
+ if (count < 0) {
614
+ return rb_ary_new();
615
+ }
616
+ ary = rb_ary_new2(count);
617
+ for (i=0; i<count; i++) {
618
+ ext = X509_get_ext(x509, i); /* NO DUP - don't free! */
619
+ rb_ary_push(ary, ossl_x509ext_new(ext));
620
+ }
621
+
622
+ return ary;
623
+ }
624
+
625
+ /*
626
+ * call-seq:
627
+ * cert.extensions = [ext...] => [ext...]
628
+ */
629
+ static VALUE
630
+ ossl_x509_set_extensions(VALUE self, VALUE ary)
631
+ {
632
+ X509 *x509;
633
+ X509_EXTENSION *ext;
634
+ long i;
635
+
636
+ Check_Type(ary, T_ARRAY);
637
+ /* All ary's members should be X509Extension */
638
+ for (i=0; i<RARRAY_LEN(ary); i++) {
639
+ OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Ext);
640
+ }
641
+ GetX509(self, x509);
642
+ while ((ext = X509_delete_ext(x509, 0)))
643
+ X509_EXTENSION_free(ext);
644
+ for (i=0; i<RARRAY_LEN(ary); i++) {
645
+ ext = GetX509ExtPtr(RARRAY_AREF(ary, i));
646
+ if (!X509_add_ext(x509, ext, -1)) { /* DUPs ext */
647
+ ossl_raise(eX509CertError, NULL);
648
+ }
649
+ }
650
+
651
+ return ary;
652
+ }
653
+
654
+ /*
655
+ * call-seq:
656
+ * cert.add_extension(extension) => extension
657
+ */
658
+ static VALUE
659
+ ossl_x509_add_extension(VALUE self, VALUE extension)
660
+ {
661
+ X509 *x509;
662
+ X509_EXTENSION *ext;
663
+
664
+ GetX509(self, x509);
665
+ ext = GetX509ExtPtr(extension);
666
+ if (!X509_add_ext(x509, ext, -1)) { /* DUPs ext - FREE it */
667
+ ossl_raise(eX509CertError, NULL);
668
+ }
669
+
670
+ return extension;
671
+ }
672
+
673
+ static VALUE
674
+ ossl_x509_inspect(VALUE self)
675
+ {
676
+ return rb_sprintf("#<%"PRIsVALUE": subject=%+"PRIsVALUE", "
677
+ "issuer=%+"PRIsVALUE", serial=%+"PRIsVALUE", "
678
+ "not_before=%+"PRIsVALUE", not_after=%+"PRIsVALUE">",
679
+ rb_obj_class(self),
680
+ ossl_x509_get_subject(self),
681
+ ossl_x509_get_issuer(self),
682
+ ossl_x509_get_serial(self),
683
+ ossl_x509_get_not_before(self),
684
+ ossl_x509_get_not_after(self));
685
+ }
686
+
687
+ /*
688
+ * call-seq:
689
+ * cert1 == cert2 -> true | false
690
+ *
691
+ * Compares the two certificates. Note that this takes into account all fields,
692
+ * not just the issuer name and the serial number.
693
+ */
694
+ static VALUE
695
+ ossl_x509_eq(VALUE self, VALUE other)
696
+ {
697
+ X509 *a, *b;
698
+
699
+ GetX509(self, a);
700
+ if (!rb_obj_is_kind_of(other, cX509Cert))
701
+ return Qfalse;
702
+ GetX509(other, b);
703
+
704
+ return !X509_cmp(a, b) ? Qtrue : Qfalse;
705
+ }
706
+
707
+ /*
708
+ * INIT
709
+ */
710
+ void
711
+ Init_ossl_x509cert(void)
712
+ {
713
+ #if 0
714
+ mOSSL = rb_define_module("OpenSSL");
715
+ eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
716
+ mX509 = rb_define_module_under(mOSSL, "X509");
717
+ #endif
718
+
719
+ eX509CertError = rb_define_class_under(mX509, "CertificateError", eOSSLError);
720
+
721
+ /* Document-class: OpenSSL::X509::Certificate
722
+ *
723
+ * Implementation of an X.509 certificate as specified in RFC 5280.
724
+ * Provides access to a certificate's attributes and allows certificates
725
+ * to be read from a string, but also supports the creation of new
726
+ * certificates from scratch.
727
+ *
728
+ * === Reading a certificate from a file
729
+ *
730
+ * Certificate is capable of handling DER-encoded certificates and
731
+ * certificates encoded in OpenSSL's PEM format.
732
+ *
733
+ * raw = File.read "cert.cer" # DER- or PEM-encoded
734
+ * certificate = OpenSSL::X509::Certificate.new raw
735
+ *
736
+ * === Saving a certificate to a file
737
+ *
738
+ * A certificate may be encoded in DER format
739
+ *
740
+ * cert = ...
741
+ * File.open("cert.cer", "wb") { |f| f.print cert.to_der }
742
+ *
743
+ * or in PEM format
744
+ *
745
+ * cert = ...
746
+ * File.open("cert.pem", "wb") { |f| f.print cert.to_pem }
747
+ *
748
+ * X.509 certificates are associated with a private/public key pair,
749
+ * typically a RSA, DSA or ECC key (see also OpenSSL::PKey::RSA,
750
+ * OpenSSL::PKey::DSA and OpenSSL::PKey::EC), the public key itself is
751
+ * stored within the certificate and can be accessed in form of an
752
+ * OpenSSL::PKey. Certificates are typically used to be able to associate
753
+ * some form of identity with a key pair, for example web servers serving
754
+ * pages over HTTPs use certificates to authenticate themselves to the user.
755
+ *
756
+ * The public key infrastructure (PKI) model relies on trusted certificate
757
+ * authorities ("root CAs") that issue these certificates, so that end
758
+ * users need to base their trust just on a selected few authorities
759
+ * that themselves again vouch for subordinate CAs issuing their
760
+ * certificates to end users.
761
+ *
762
+ * The OpenSSL::X509 module provides the tools to set up an independent
763
+ * PKI, similar to scenarios where the 'openssl' command line tool is
764
+ * used for issuing certificates in a private PKI.
765
+ *
766
+ * === Creating a root CA certificate and an end-entity certificate
767
+ *
768
+ * First, we need to create a "self-signed" root certificate. To do so,
769
+ * we need to generate a key first. Please note that the choice of "1"
770
+ * as a serial number is considered a security flaw for real certificates.
771
+ * Secure choices are integers in the two-digit byte range and ideally
772
+ * not sequential but secure random numbers, steps omitted here to keep
773
+ * the example concise.
774
+ *
775
+ * root_key = OpenSSL::PKey::RSA.new 2048 # the CA's public/private key
776
+ * root_ca = OpenSSL::X509::Certificate.new
777
+ * root_ca.version = 2 # cf. RFC 5280 - to make it a "v3" certificate
778
+ * root_ca.serial = 1
779
+ * root_ca.subject = OpenSSL::X509::Name.parse "/DC=org/DC=ruby-lang/CN=Ruby CA"
780
+ * root_ca.issuer = root_ca.subject # root CA's are "self-signed"
781
+ * root_ca.public_key = root_key.public_key
782
+ * root_ca.not_before = Time.now
783
+ * root_ca.not_after = root_ca.not_before + 2 * 365 * 24 * 60 * 60 # 2 years validity
784
+ * ef = OpenSSL::X509::ExtensionFactory.new
785
+ * ef.subject_certificate = root_ca
786
+ * ef.issuer_certificate = root_ca
787
+ * root_ca.add_extension(ef.create_extension("basicConstraints","CA:TRUE",true))
788
+ * root_ca.add_extension(ef.create_extension("keyUsage","keyCertSign, cRLSign", true))
789
+ * root_ca.add_extension(ef.create_extension("subjectKeyIdentifier","hash",false))
790
+ * root_ca.add_extension(ef.create_extension("authorityKeyIdentifier","keyid:always",false))
791
+ * root_ca.sign(root_key, OpenSSL::Digest.new('SHA256'))
792
+ *
793
+ * The next step is to create the end-entity certificate using the root CA
794
+ * certificate.
795
+ *
796
+ * key = OpenSSL::PKey::RSA.new 2048
797
+ * cert = OpenSSL::X509::Certificate.new
798
+ * cert.version = 2
799
+ * cert.serial = 2
800
+ * cert.subject = OpenSSL::X509::Name.parse "/DC=org/DC=ruby-lang/CN=Ruby certificate"
801
+ * cert.issuer = root_ca.subject # root CA is the issuer
802
+ * cert.public_key = key.public_key
803
+ * cert.not_before = Time.now
804
+ * cert.not_after = cert.not_before + 1 * 365 * 24 * 60 * 60 # 1 years validity
805
+ * ef = OpenSSL::X509::ExtensionFactory.new
806
+ * ef.subject_certificate = cert
807
+ * ef.issuer_certificate = root_ca
808
+ * cert.add_extension(ef.create_extension("keyUsage","digitalSignature", true))
809
+ * cert.add_extension(ef.create_extension("subjectKeyIdentifier","hash",false))
810
+ * cert.sign(root_key, OpenSSL::Digest.new('SHA256'))
811
+ *
812
+ */
813
+ cX509Cert = rb_define_class_under(mX509, "Certificate", rb_cObject);
814
+
815
+ rb_define_alloc_func(cX509Cert, ossl_x509_alloc);
816
+ rb_define_method(cX509Cert, "initialize", ossl_x509_initialize, -1);
817
+ rb_define_method(cX509Cert, "initialize_copy", ossl_x509_copy, 1);
818
+
819
+ rb_define_method(cX509Cert, "to_der", ossl_x509_to_der, 0);
820
+ rb_define_method(cX509Cert, "to_pem", ossl_x509_to_pem, 0);
821
+ rb_define_alias(cX509Cert, "to_s", "to_pem");
822
+ rb_define_method(cX509Cert, "to_text", ossl_x509_to_text, 0);
823
+ rb_define_method(cX509Cert, "version", ossl_x509_get_version, 0);
824
+ rb_define_method(cX509Cert, "version=", ossl_x509_set_version, 1);
825
+ rb_define_method(cX509Cert, "signature_algorithm", ossl_x509_get_signature_algorithm, 0);
826
+ rb_define_method(cX509Cert, "serial", ossl_x509_get_serial, 0);
827
+ rb_define_method(cX509Cert, "serial=", ossl_x509_set_serial, 1);
828
+ rb_define_method(cX509Cert, "subject", ossl_x509_get_subject, 0);
829
+ rb_define_method(cX509Cert, "subject=", ossl_x509_set_subject, 1);
830
+ rb_define_method(cX509Cert, "issuer", ossl_x509_get_issuer, 0);
831
+ rb_define_method(cX509Cert, "issuer=", ossl_x509_set_issuer, 1);
832
+ rb_define_method(cX509Cert, "not_before", ossl_x509_get_not_before, 0);
833
+ rb_define_method(cX509Cert, "not_before=", ossl_x509_set_not_before, 1);
834
+ rb_define_method(cX509Cert, "not_after", ossl_x509_get_not_after, 0);
835
+ rb_define_method(cX509Cert, "not_after=", ossl_x509_set_not_after, 1);
836
+ rb_define_method(cX509Cert, "public_key", ossl_x509_get_public_key, 0);
837
+ rb_define_method(cX509Cert, "public_key=", ossl_x509_set_public_key, 1);
838
+ rb_define_method(cX509Cert, "sign", ossl_x509_sign, 2);
839
+ rb_define_method(cX509Cert, "verify", ossl_x509_verify, 1);
840
+ rb_define_method(cX509Cert, "check_private_key", ossl_x509_check_private_key, 1);
841
+ rb_define_method(cX509Cert, "extensions", ossl_x509_get_extensions, 0);
842
+ rb_define_method(cX509Cert, "extensions=", ossl_x509_set_extensions, 1);
843
+ rb_define_method(cX509Cert, "add_extension", ossl_x509_add_extension, 1);
844
+ rb_define_method(cX509Cert, "inspect", ossl_x509_inspect, 0);
845
+ rb_define_method(cX509Cert, "==", ossl_x509_eq, 1);
846
+ }