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,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
+ }