zig_example 0.2.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/ext/mkmf.rb +2734 -0
  3. data/ext/openssl/openssl_missing.c +40 -0
  4. data/ext/openssl/openssl_missing.h +238 -0
  5. data/ext/openssl/ossl.c +1295 -0
  6. data/ext/openssl/ossl.h +201 -0
  7. data/ext/openssl/ossl_asn1.c +1891 -0
  8. data/ext/openssl/ossl_asn1.h +62 -0
  9. data/ext/openssl/ossl_bio.c +42 -0
  10. data/ext/openssl/ossl_bio.h +16 -0
  11. data/ext/openssl/ossl_bn.c +1344 -0
  12. data/ext/openssl/ossl_bn.h +26 -0
  13. data/ext/openssl/ossl_cipher.c +1074 -0
  14. data/ext/openssl/ossl_cipher.h +20 -0
  15. data/ext/openssl/ossl_config.c +460 -0
  16. data/ext/openssl/ossl_config.h +16 -0
  17. data/ext/openssl/ossl_digest.c +425 -0
  18. data/ext/openssl/ossl_digest.h +20 -0
  19. data/ext/openssl/ossl_engine.c +568 -0
  20. data/ext/openssl/ossl_engine.h +19 -0
  21. data/ext/openssl/ossl_hmac.c +310 -0
  22. data/ext/openssl/ossl_hmac.h +18 -0
  23. data/ext/openssl/ossl_kdf.c +311 -0
  24. data/ext/openssl/ossl_kdf.h +6 -0
  25. data/ext/openssl/ossl_ns_spki.c +405 -0
  26. data/ext/openssl/ossl_ns_spki.h +19 -0
  27. data/ext/openssl/ossl_ocsp.c +1965 -0
  28. data/ext/openssl/ossl_ocsp.h +23 -0
  29. data/ext/openssl/ossl_pkcs12.c +275 -0
  30. data/ext/openssl/ossl_pkcs12.h +13 -0
  31. data/ext/openssl/ossl_pkcs7.c +1081 -0
  32. data/ext/openssl/ossl_pkcs7.h +36 -0
  33. data/ext/openssl/ossl_pkey.c +1624 -0
  34. data/ext/openssl/ossl_pkey.h +204 -0
  35. data/ext/openssl/ossl_pkey_dh.c +440 -0
  36. data/ext/openssl/ossl_pkey_dsa.c +359 -0
  37. data/ext/openssl/ossl_pkey_ec.c +1655 -0
  38. data/ext/openssl/ossl_pkey_rsa.c +579 -0
  39. data/ext/openssl/ossl_rand.c +200 -0
  40. data/ext/openssl/ossl_rand.h +18 -0
  41. data/ext/openssl/ossl_ssl.c +3142 -0
  42. data/ext/openssl/ossl_ssl.h +36 -0
  43. data/ext/openssl/ossl_ssl_session.c +331 -0
  44. data/ext/openssl/ossl_ts.c +1539 -0
  45. data/ext/openssl/ossl_ts.h +16 -0
  46. data/ext/openssl/ossl_x509.c +256 -0
  47. data/ext/openssl/ossl_x509.h +115 -0
  48. data/ext/openssl/ossl_x509attr.c +324 -0
  49. data/ext/openssl/ossl_x509cert.c +1002 -0
  50. data/ext/openssl/ossl_x509crl.c +545 -0
  51. data/ext/openssl/ossl_x509ext.c +490 -0
  52. data/ext/openssl/ossl_x509name.c +597 -0
  53. data/ext/openssl/ossl_x509req.c +444 -0
  54. data/ext/openssl/ossl_x509revoked.c +300 -0
  55. data/ext/openssl/ossl_x509store.c +986 -0
  56. data/ext/zigrb_100doors/build.zig +0 -12
  57. data/ext/zigrb_100doors/extconf.rb +2 -19
  58. data/ext/zigrb_ackermann/build.zig +0 -12
  59. data/ext/zigrb_ackermann/extconf.rb +2 -19
  60. data/ext/zigrb_lucas_lehmer/build.zig +53 -0
  61. data/ext/zigrb_lucas_lehmer/extconf.rb +3 -0
  62. data/ext/zigrb_lucas_lehmer/src/lucas_lehmer.c +60 -0
  63. data/ext/zigrb_lucas_lehmer/src/lucas_lehmer.h +1 -0
  64. data/ext/zigrb_lucas_lehmer/src/wrapper.zig +42 -0
  65. data/lib/zig_example/version.rb +1 -1
  66. data/lib/zig_example.rb +1 -0
  67. metadata +63 -3
@@ -0,0 +1,1002 @@
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, *x509_orig = RTYPEDDATA_DATA(self);
119
+ VALUE arg;
120
+
121
+ rb_check_frozen(self);
122
+ if (rb_scan_args(argc, argv, "01", &arg) == 0) {
123
+ /* create just empty X509Cert */
124
+ return self;
125
+ }
126
+ arg = ossl_to_der_if_possible(arg);
127
+ in = ossl_obj2bio(&arg);
128
+ x509 = d2i_X509_bio(in, NULL);
129
+ if (!x509) {
130
+ OSSL_BIO_reset(in);
131
+ x509 = PEM_read_bio_X509(in, NULL, NULL, NULL);
132
+ }
133
+ BIO_free(in);
134
+ if (!x509)
135
+ ossl_raise(eX509CertError, "PEM_read_bio_X509");
136
+
137
+ RTYPEDDATA_DATA(self) = x509;
138
+ X509_free(x509_orig);
139
+
140
+ return self;
141
+ }
142
+
143
+ static VALUE
144
+ ossl_x509_copy(VALUE self, VALUE other)
145
+ {
146
+ X509 *a, *b, *x509;
147
+
148
+ rb_check_frozen(self);
149
+ if (self == other) return self;
150
+
151
+ GetX509(self, a);
152
+ GetX509(other, b);
153
+
154
+ x509 = X509_dup(b);
155
+ if (!x509) ossl_raise(eX509CertError, NULL);
156
+
157
+ DATA_PTR(self) = x509;
158
+ X509_free(a);
159
+
160
+ return self;
161
+ }
162
+
163
+ /*
164
+ * call-seq:
165
+ * cert.to_der => string
166
+ */
167
+ static VALUE
168
+ ossl_x509_to_der(VALUE self)
169
+ {
170
+ X509 *x509;
171
+ VALUE str;
172
+ long len;
173
+ unsigned char *p;
174
+
175
+ GetX509(self, x509);
176
+ if ((len = i2d_X509(x509, NULL)) <= 0)
177
+ ossl_raise(eX509CertError, NULL);
178
+ str = rb_str_new(0, len);
179
+ p = (unsigned char *)RSTRING_PTR(str);
180
+ if (i2d_X509(x509, &p) <= 0)
181
+ ossl_raise(eX509CertError, NULL);
182
+ ossl_str_adjust(str, p);
183
+
184
+ return str;
185
+ }
186
+
187
+ /*
188
+ * call-seq:
189
+ * cert.to_pem => string
190
+ */
191
+ static VALUE
192
+ ossl_x509_to_pem(VALUE self)
193
+ {
194
+ X509 *x509;
195
+ BIO *out;
196
+ VALUE str;
197
+
198
+ GetX509(self, x509);
199
+ out = BIO_new(BIO_s_mem());
200
+ if (!out) ossl_raise(eX509CertError, NULL);
201
+
202
+ if (!PEM_write_bio_X509(out, x509)) {
203
+ BIO_free(out);
204
+ ossl_raise(eX509CertError, NULL);
205
+ }
206
+ str = ossl_membio2str(out);
207
+
208
+ return str;
209
+ }
210
+
211
+ /*
212
+ * call-seq:
213
+ * cert.to_text => string
214
+ */
215
+ static VALUE
216
+ ossl_x509_to_text(VALUE self)
217
+ {
218
+ X509 *x509;
219
+ BIO *out;
220
+ VALUE str;
221
+
222
+ GetX509(self, x509);
223
+
224
+ out = BIO_new(BIO_s_mem());
225
+ if (!out) ossl_raise(eX509CertError, NULL);
226
+
227
+ if (!X509_print(out, x509)) {
228
+ BIO_free(out);
229
+ ossl_raise(eX509CertError, NULL);
230
+ }
231
+ str = ossl_membio2str(out);
232
+
233
+ return str;
234
+ }
235
+
236
+ #if 0
237
+ /*
238
+ * Makes from X509 X509_REQuest
239
+ */
240
+ static VALUE
241
+ ossl_x509_to_req(VALUE self)
242
+ {
243
+ X509 *x509;
244
+ X509_REQ *req;
245
+ VALUE obj;
246
+
247
+ GetX509(self, x509);
248
+ if (!(req = X509_to_X509_REQ(x509, NULL, EVP_md5()))) {
249
+ ossl_raise(eX509CertError, NULL);
250
+ }
251
+ obj = ossl_x509req_new(req);
252
+ X509_REQ_free(req);
253
+
254
+ return obj;
255
+ }
256
+ #endif
257
+
258
+ /*
259
+ * call-seq:
260
+ * cert.version => integer
261
+ */
262
+ static VALUE
263
+ ossl_x509_get_version(VALUE self)
264
+ {
265
+ X509 *x509;
266
+
267
+ GetX509(self, x509);
268
+
269
+ return LONG2NUM(X509_get_version(x509));
270
+ }
271
+
272
+ /*
273
+ * call-seq:
274
+ * cert.version = integer => integer
275
+ */
276
+ static VALUE
277
+ ossl_x509_set_version(VALUE self, VALUE version)
278
+ {
279
+ X509 *x509;
280
+ long ver;
281
+
282
+ if ((ver = NUM2LONG(version)) < 0) {
283
+ ossl_raise(eX509CertError, "version must be >= 0!");
284
+ }
285
+ GetX509(self, x509);
286
+ if (!X509_set_version(x509, ver)) {
287
+ ossl_raise(eX509CertError, NULL);
288
+ }
289
+
290
+ return version;
291
+ }
292
+
293
+ /*
294
+ * call-seq:
295
+ * cert.serial => integer
296
+ */
297
+ static VALUE
298
+ ossl_x509_get_serial(VALUE self)
299
+ {
300
+ X509 *x509;
301
+
302
+ GetX509(self, x509);
303
+
304
+ return asn1integer_to_num(X509_get_serialNumber(x509));
305
+ }
306
+
307
+ /*
308
+ * call-seq:
309
+ * cert.serial = integer => integer
310
+ */
311
+ static VALUE
312
+ ossl_x509_set_serial(VALUE self, VALUE num)
313
+ {
314
+ X509 *x509;
315
+
316
+ GetX509(self, x509);
317
+ X509_set_serialNumber(x509, num_to_asn1integer(num, X509_get_serialNumber(x509)));
318
+
319
+ return num;
320
+ }
321
+
322
+ /*
323
+ * call-seq:
324
+ * cert.signature_algorithm => string
325
+ */
326
+ static VALUE
327
+ ossl_x509_get_signature_algorithm(VALUE self)
328
+ {
329
+ X509 *x509;
330
+ BIO *out;
331
+ VALUE str;
332
+
333
+ GetX509(self, x509);
334
+ out = BIO_new(BIO_s_mem());
335
+ if (!out) ossl_raise(eX509CertError, NULL);
336
+
337
+ if (!i2a_ASN1_OBJECT(out, X509_get0_tbs_sigalg(x509)->algorithm)) {
338
+ BIO_free(out);
339
+ ossl_raise(eX509CertError, NULL);
340
+ }
341
+ str = ossl_membio2str(out);
342
+
343
+ return str;
344
+ }
345
+
346
+ /*
347
+ * call-seq:
348
+ * cert.subject => name
349
+ */
350
+ static VALUE
351
+ ossl_x509_get_subject(VALUE self)
352
+ {
353
+ X509 *x509;
354
+ X509_NAME *name;
355
+
356
+ GetX509(self, x509);
357
+ if (!(name = X509_get_subject_name(x509))) { /* NO DUP - don't free! */
358
+ ossl_raise(eX509CertError, NULL);
359
+ }
360
+
361
+ return ossl_x509name_new(name);
362
+ }
363
+
364
+ /*
365
+ * call-seq:
366
+ * cert.subject = name => name
367
+ */
368
+ static VALUE
369
+ ossl_x509_set_subject(VALUE self, VALUE subject)
370
+ {
371
+ X509 *x509;
372
+
373
+ GetX509(self, x509);
374
+ if (!X509_set_subject_name(x509, GetX509NamePtr(subject))) { /* DUPs name */
375
+ ossl_raise(eX509CertError, NULL);
376
+ }
377
+
378
+ return subject;
379
+ }
380
+
381
+ /*
382
+ * call-seq:
383
+ * cert.issuer => name
384
+ */
385
+ static VALUE
386
+ ossl_x509_get_issuer(VALUE self)
387
+ {
388
+ X509 *x509;
389
+ X509_NAME *name;
390
+
391
+ GetX509(self, x509);
392
+ if(!(name = X509_get_issuer_name(x509))) { /* NO DUP - don't free! */
393
+ ossl_raise(eX509CertError, NULL);
394
+ }
395
+
396
+ return ossl_x509name_new(name);
397
+ }
398
+
399
+ /*
400
+ * call-seq:
401
+ * cert.issuer = name => name
402
+ */
403
+ static VALUE
404
+ ossl_x509_set_issuer(VALUE self, VALUE issuer)
405
+ {
406
+ X509 *x509;
407
+
408
+ GetX509(self, x509);
409
+ if (!X509_set_issuer_name(x509, GetX509NamePtr(issuer))) { /* DUPs name */
410
+ ossl_raise(eX509CertError, NULL);
411
+ }
412
+
413
+ return issuer;
414
+ }
415
+
416
+ /*
417
+ * call-seq:
418
+ * cert.not_before => time
419
+ */
420
+ static VALUE
421
+ ossl_x509_get_not_before(VALUE self)
422
+ {
423
+ X509 *x509;
424
+ const ASN1_TIME *asn1time;
425
+
426
+ GetX509(self, x509);
427
+ if (!(asn1time = X509_get0_notBefore(x509))) {
428
+ ossl_raise(eX509CertError, NULL);
429
+ }
430
+
431
+ return asn1time_to_time(asn1time);
432
+ }
433
+
434
+ /*
435
+ * call-seq:
436
+ * cert.not_before = time => time
437
+ */
438
+ static VALUE
439
+ ossl_x509_set_not_before(VALUE self, VALUE time)
440
+ {
441
+ X509 *x509;
442
+ ASN1_TIME *asn1time;
443
+
444
+ GetX509(self, x509);
445
+ asn1time = ossl_x509_time_adjust(NULL, time);
446
+ if (!X509_set1_notBefore(x509, asn1time)) {
447
+ ASN1_TIME_free(asn1time);
448
+ ossl_raise(eX509CertError, "X509_set_notBefore");
449
+ }
450
+ ASN1_TIME_free(asn1time);
451
+
452
+ return time;
453
+ }
454
+
455
+ /*
456
+ * call-seq:
457
+ * cert.not_after => time
458
+ */
459
+ static VALUE
460
+ ossl_x509_get_not_after(VALUE self)
461
+ {
462
+ X509 *x509;
463
+ const ASN1_TIME *asn1time;
464
+
465
+ GetX509(self, x509);
466
+ if (!(asn1time = X509_get0_notAfter(x509))) {
467
+ ossl_raise(eX509CertError, NULL);
468
+ }
469
+
470
+ return asn1time_to_time(asn1time);
471
+ }
472
+
473
+ /*
474
+ * call-seq:
475
+ * cert.not_after = time => time
476
+ */
477
+ static VALUE
478
+ ossl_x509_set_not_after(VALUE self, VALUE time)
479
+ {
480
+ X509 *x509;
481
+ ASN1_TIME *asn1time;
482
+
483
+ GetX509(self, x509);
484
+ asn1time = ossl_x509_time_adjust(NULL, time);
485
+ if (!X509_set1_notAfter(x509, asn1time)) {
486
+ ASN1_TIME_free(asn1time);
487
+ ossl_raise(eX509CertError, "X509_set_notAfter");
488
+ }
489
+ ASN1_TIME_free(asn1time);
490
+
491
+ return time;
492
+ }
493
+
494
+ /*
495
+ * call-seq:
496
+ * cert.public_key => key
497
+ */
498
+ static VALUE
499
+ ossl_x509_get_public_key(VALUE self)
500
+ {
501
+ X509 *x509;
502
+ EVP_PKEY *pkey;
503
+
504
+ GetX509(self, x509);
505
+ if (!(pkey = X509_get_pubkey(x509))) { /* adds an reference */
506
+ ossl_raise(eX509CertError, NULL);
507
+ }
508
+
509
+ return ossl_pkey_new(pkey); /* NO DUP - OK */
510
+ }
511
+
512
+ /*
513
+ * call-seq:
514
+ * cert.public_key = key
515
+ */
516
+ static VALUE
517
+ ossl_x509_set_public_key(VALUE self, VALUE key)
518
+ {
519
+ X509 *x509;
520
+ EVP_PKEY *pkey;
521
+
522
+ GetX509(self, x509);
523
+ pkey = GetPKeyPtr(key);
524
+ ossl_pkey_check_public_key(pkey);
525
+ if (!X509_set_pubkey(x509, pkey))
526
+ ossl_raise(eX509CertError, "X509_set_pubkey");
527
+ return key;
528
+ }
529
+
530
+ /*
531
+ * call-seq:
532
+ * cert.sign(key, digest) => self
533
+ */
534
+ static VALUE
535
+ ossl_x509_sign(VALUE self, VALUE key, VALUE digest)
536
+ {
537
+ X509 *x509;
538
+ EVP_PKEY *pkey;
539
+ const EVP_MD *md;
540
+
541
+ pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
542
+ md = ossl_evp_get_digestbyname(digest);
543
+ GetX509(self, x509);
544
+ if (!X509_sign(x509, pkey, md)) {
545
+ ossl_raise(eX509CertError, NULL);
546
+ }
547
+
548
+ return self;
549
+ }
550
+
551
+ /*
552
+ * call-seq:
553
+ * cert.verify(key) => true | false
554
+ *
555
+ * Verifies the signature of the certificate, with the public key _key_. _key_
556
+ * must be an instance of OpenSSL::PKey.
557
+ */
558
+ static VALUE
559
+ ossl_x509_verify(VALUE self, VALUE key)
560
+ {
561
+ X509 *x509;
562
+ EVP_PKEY *pkey;
563
+
564
+ GetX509(self, x509);
565
+ pkey = GetPKeyPtr(key);
566
+ ossl_pkey_check_public_key(pkey);
567
+ switch (X509_verify(x509, pkey)) {
568
+ case 1:
569
+ return Qtrue;
570
+ case 0:
571
+ ossl_clear_error();
572
+ return Qfalse;
573
+ default:
574
+ ossl_raise(eX509CertError, NULL);
575
+ }
576
+ }
577
+
578
+ /*
579
+ * call-seq:
580
+ * cert.check_private_key(key) -> true | false
581
+ *
582
+ * Returns +true+ if _key_ is the corresponding private key to the Subject
583
+ * Public Key Information, +false+ otherwise.
584
+ */
585
+ static VALUE
586
+ ossl_x509_check_private_key(VALUE self, VALUE key)
587
+ {
588
+ X509 *x509;
589
+ EVP_PKEY *pkey;
590
+
591
+ /* not needed private key, but should be */
592
+ pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
593
+ GetX509(self, x509);
594
+ if (!X509_check_private_key(x509, pkey)) {
595
+ ossl_clear_error();
596
+ return Qfalse;
597
+ }
598
+
599
+ return Qtrue;
600
+ }
601
+
602
+ /*
603
+ * call-seq:
604
+ * cert.extensions => [extension...]
605
+ */
606
+ static VALUE
607
+ ossl_x509_get_extensions(VALUE self)
608
+ {
609
+ X509 *x509;
610
+ int count, i;
611
+ X509_EXTENSION *ext;
612
+ VALUE ary;
613
+
614
+ GetX509(self, x509);
615
+ count = X509_get_ext_count(x509);
616
+ if (count < 0) {
617
+ return rb_ary_new();
618
+ }
619
+ ary = rb_ary_new2(count);
620
+ for (i=0; i<count; i++) {
621
+ ext = X509_get_ext(x509, i); /* NO DUP - don't free! */
622
+ rb_ary_push(ary, ossl_x509ext_new(ext));
623
+ }
624
+
625
+ return ary;
626
+ }
627
+
628
+ /*
629
+ * call-seq:
630
+ * cert.extensions = [ext...] => [ext...]
631
+ */
632
+ static VALUE
633
+ ossl_x509_set_extensions(VALUE self, VALUE ary)
634
+ {
635
+ X509 *x509;
636
+ X509_EXTENSION *ext;
637
+ long i;
638
+
639
+ Check_Type(ary, T_ARRAY);
640
+ /* All ary's members should be X509Extension */
641
+ for (i=0; i<RARRAY_LEN(ary); i++) {
642
+ OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Ext);
643
+ }
644
+ GetX509(self, x509);
645
+ for (i = X509_get_ext_count(x509); i > 0; i--)
646
+ X509_EXTENSION_free(X509_delete_ext(x509, 0));
647
+ for (i=0; i<RARRAY_LEN(ary); i++) {
648
+ ext = GetX509ExtPtr(RARRAY_AREF(ary, i));
649
+ if (!X509_add_ext(x509, ext, -1)) { /* DUPs ext */
650
+ ossl_raise(eX509CertError, "X509_add_ext");
651
+ }
652
+ }
653
+
654
+ return ary;
655
+ }
656
+
657
+ /*
658
+ * call-seq:
659
+ * cert.add_extension(extension) => extension
660
+ */
661
+ static VALUE
662
+ ossl_x509_add_extension(VALUE self, VALUE extension)
663
+ {
664
+ X509 *x509;
665
+ X509_EXTENSION *ext;
666
+
667
+ GetX509(self, x509);
668
+ ext = GetX509ExtPtr(extension);
669
+ if (!X509_add_ext(x509, ext, -1)) { /* DUPs ext - FREE it */
670
+ ossl_raise(eX509CertError, NULL);
671
+ }
672
+
673
+ return extension;
674
+ }
675
+
676
+ static VALUE
677
+ ossl_x509_inspect(VALUE self)
678
+ {
679
+ return rb_sprintf("#<%"PRIsVALUE": subject=%+"PRIsVALUE", "
680
+ "issuer=%+"PRIsVALUE", serial=%+"PRIsVALUE", "
681
+ "not_before=%+"PRIsVALUE", not_after=%+"PRIsVALUE">",
682
+ rb_obj_class(self),
683
+ ossl_x509_get_subject(self),
684
+ ossl_x509_get_issuer(self),
685
+ ossl_x509_get_serial(self),
686
+ ossl_x509_get_not_before(self),
687
+ ossl_x509_get_not_after(self));
688
+ }
689
+
690
+ /*
691
+ * call-seq:
692
+ * cert1 == cert2 -> true | false
693
+ *
694
+ * Compares the two certificates. Note that this takes into account all fields,
695
+ * not just the issuer name and the serial number.
696
+ */
697
+ static VALUE
698
+ ossl_x509_eq(VALUE self, VALUE other)
699
+ {
700
+ X509 *a, *b;
701
+
702
+ GetX509(self, a);
703
+ if (!rb_obj_is_kind_of(other, cX509Cert))
704
+ return Qfalse;
705
+ GetX509(other, b);
706
+
707
+ return !X509_cmp(a, b) ? Qtrue : Qfalse;
708
+ }
709
+
710
+ struct load_chained_certificates_arguments {
711
+ VALUE certificates;
712
+ X509 *certificate;
713
+ };
714
+
715
+ static VALUE
716
+ load_chained_certificates_append_push(VALUE _arguments) {
717
+ struct load_chained_certificates_arguments *arguments = (struct load_chained_certificates_arguments*)_arguments;
718
+
719
+ if (arguments->certificates == Qnil) {
720
+ arguments->certificates = rb_ary_new();
721
+ }
722
+
723
+ rb_ary_push(arguments->certificates, ossl_x509_new(arguments->certificate));
724
+
725
+ return Qnil;
726
+ }
727
+
728
+ static VALUE
729
+ load_chained_certificate_append_ensure(VALUE _arguments) {
730
+ struct load_chained_certificates_arguments *arguments = (struct load_chained_certificates_arguments*)_arguments;
731
+
732
+ X509_free(arguments->certificate);
733
+
734
+ return Qnil;
735
+ }
736
+
737
+ inline static VALUE
738
+ load_chained_certificates_append(VALUE certificates, X509 *certificate) {
739
+ struct load_chained_certificates_arguments arguments;
740
+ arguments.certificates = certificates;
741
+ arguments.certificate = certificate;
742
+
743
+ rb_ensure(load_chained_certificates_append_push, (VALUE)&arguments, load_chained_certificate_append_ensure, (VALUE)&arguments);
744
+
745
+ return arguments.certificates;
746
+ }
747
+
748
+ static VALUE
749
+ load_chained_certificates_PEM(BIO *in) {
750
+ VALUE certificates = Qnil;
751
+ X509 *certificate = PEM_read_bio_X509(in, NULL, NULL, NULL);
752
+
753
+ /* If we cannot read even one certificate: */
754
+ if (certificate == NULL) {
755
+ /* If we cannot read one certificate because we could not read the PEM encoding: */
756
+ if (ERR_GET_REASON(ERR_peek_last_error()) == PEM_R_NO_START_LINE) {
757
+ ossl_clear_error();
758
+ }
759
+
760
+ if (ERR_peek_last_error())
761
+ ossl_raise(eX509CertError, NULL);
762
+ else
763
+ return Qnil;
764
+ }
765
+
766
+ certificates = load_chained_certificates_append(Qnil, certificate);
767
+
768
+ while ((certificate = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
769
+ load_chained_certificates_append(certificates, certificate);
770
+ }
771
+
772
+ /* We tried to read one more certificate but could not read start line: */
773
+ if (ERR_GET_REASON(ERR_peek_last_error()) == PEM_R_NO_START_LINE) {
774
+ /* This is not an error, it means we are finished: */
775
+ ossl_clear_error();
776
+
777
+ return certificates;
778
+ }
779
+
780
+ /* Alternatively, if we reached the end of the file and there was no error: */
781
+ if (BIO_eof(in) && !ERR_peek_last_error()) {
782
+ return certificates;
783
+ } else {
784
+ /* Otherwise, we tried to read a certificate but failed somewhere: */
785
+ ossl_raise(eX509CertError, NULL);
786
+ }
787
+ }
788
+
789
+ static VALUE
790
+ load_chained_certificates_DER(BIO *in) {
791
+ X509 *certificate = d2i_X509_bio(in, NULL);
792
+
793
+ /* If we cannot read one certificate: */
794
+ if (certificate == NULL) {
795
+ /* Ignore error. We could not load. */
796
+ ossl_clear_error();
797
+
798
+ return Qnil;
799
+ }
800
+
801
+ return load_chained_certificates_append(Qnil, certificate);
802
+ }
803
+
804
+ static VALUE
805
+ load_chained_certificates(VALUE _io) {
806
+ BIO *in = (BIO*)_io;
807
+ VALUE certificates = Qnil;
808
+
809
+ /*
810
+ DER is a binary format and it may contain octets within it that look like
811
+ PEM encoded certificates. So we need to check DER first.
812
+ */
813
+ certificates = load_chained_certificates_DER(in);
814
+
815
+ if (certificates != Qnil)
816
+ return certificates;
817
+
818
+ OSSL_BIO_reset(in);
819
+
820
+ certificates = load_chained_certificates_PEM(in);
821
+
822
+ if (certificates != Qnil)
823
+ return certificates;
824
+
825
+ /* Otherwise we couldn't read the output correctly so fail: */
826
+ ossl_raise(eX509CertError, "Could not detect format of certificate data!");
827
+ }
828
+
829
+ static VALUE
830
+ load_chained_certificates_ensure(VALUE _io) {
831
+ BIO *in = (BIO*)_io;
832
+
833
+ BIO_free(in);
834
+
835
+ return Qnil;
836
+ }
837
+
838
+ /*
839
+ * call-seq:
840
+ * OpenSSL::X509::Certificate.load(string) -> [certs...]
841
+ * OpenSSL::X509::Certificate.load(file) -> [certs...]
842
+ *
843
+ * Read the chained certificates from the given input. Supports both PEM
844
+ * and DER encoded certificates.
845
+ *
846
+ * PEM is a text format and supports more than one certificate.
847
+ *
848
+ * DER is a binary format and only supports one certificate.
849
+ *
850
+ * If the file is empty, or contains only unrelated data, an
851
+ * +OpenSSL::X509::CertificateError+ exception will be raised.
852
+ */
853
+ static VALUE
854
+ ossl_x509_load(VALUE klass, VALUE buffer)
855
+ {
856
+ BIO *in = ossl_obj2bio(&buffer);
857
+
858
+ return rb_ensure(load_chained_certificates, (VALUE)in, load_chained_certificates_ensure, (VALUE)in);
859
+ }
860
+
861
+ /*
862
+ * INIT
863
+ */
864
+ void
865
+ Init_ossl_x509cert(void)
866
+ {
867
+ #if 0
868
+ mOSSL = rb_define_module("OpenSSL");
869
+ eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
870
+ mX509 = rb_define_module_under(mOSSL, "X509");
871
+ #endif
872
+
873
+ eX509CertError = rb_define_class_under(mX509, "CertificateError", eOSSLError);
874
+
875
+ /* Document-class: OpenSSL::X509::Certificate
876
+ *
877
+ * Implementation of an X.509 certificate as specified in RFC 5280.
878
+ * Provides access to a certificate's attributes and allows certificates
879
+ * to be read from a string, but also supports the creation of new
880
+ * certificates from scratch.
881
+ *
882
+ * === Reading a certificate from a file
883
+ *
884
+ * Certificate is capable of handling DER-encoded certificates and
885
+ * certificates encoded in OpenSSL's PEM format.
886
+ *
887
+ * raw = File.binread "cert.cer" # DER- or PEM-encoded
888
+ * certificate = OpenSSL::X509::Certificate.new raw
889
+ *
890
+ * === Saving a certificate to a file
891
+ *
892
+ * A certificate may be encoded in DER format
893
+ *
894
+ * cert = ...
895
+ * File.open("cert.cer", "wb") { |f| f.print cert.to_der }
896
+ *
897
+ * or in PEM format
898
+ *
899
+ * cert = ...
900
+ * File.open("cert.pem", "wb") { |f| f.print cert.to_pem }
901
+ *
902
+ * X.509 certificates are associated with a private/public key pair,
903
+ * typically a RSA, DSA or ECC key (see also OpenSSL::PKey::RSA,
904
+ * OpenSSL::PKey::DSA and OpenSSL::PKey::EC), the public key itself is
905
+ * stored within the certificate and can be accessed in form of an
906
+ * OpenSSL::PKey. Certificates are typically used to be able to associate
907
+ * some form of identity with a key pair, for example web servers serving
908
+ * pages over HTTPs use certificates to authenticate themselves to the user.
909
+ *
910
+ * The public key infrastructure (PKI) model relies on trusted certificate
911
+ * authorities ("root CAs") that issue these certificates, so that end
912
+ * users need to base their trust just on a selected few authorities
913
+ * that themselves again vouch for subordinate CAs issuing their
914
+ * certificates to end users.
915
+ *
916
+ * The OpenSSL::X509 module provides the tools to set up an independent
917
+ * PKI, similar to scenarios where the 'openssl' command line tool is
918
+ * used for issuing certificates in a private PKI.
919
+ *
920
+ * === Creating a root CA certificate and an end-entity certificate
921
+ *
922
+ * First, we need to create a "self-signed" root certificate. To do so,
923
+ * we need to generate a key first. Please note that the choice of "1"
924
+ * as a serial number is considered a security flaw for real certificates.
925
+ * Secure choices are integers in the two-digit byte range and ideally
926
+ * not sequential but secure random numbers, steps omitted here to keep
927
+ * the example concise.
928
+ *
929
+ * root_key = OpenSSL::PKey::RSA.new 2048 # the CA's public/private key
930
+ * root_ca = OpenSSL::X509::Certificate.new
931
+ * root_ca.version = 2 # cf. RFC 5280 - to make it a "v3" certificate
932
+ * root_ca.serial = 1
933
+ * root_ca.subject = OpenSSL::X509::Name.parse "/DC=org/DC=ruby-lang/CN=Ruby CA"
934
+ * root_ca.issuer = root_ca.subject # root CA's are "self-signed"
935
+ * root_ca.public_key = root_key.public_key
936
+ * root_ca.not_before = Time.now
937
+ * root_ca.not_after = root_ca.not_before + 2 * 365 * 24 * 60 * 60 # 2 years validity
938
+ * ef = OpenSSL::X509::ExtensionFactory.new
939
+ * ef.subject_certificate = root_ca
940
+ * ef.issuer_certificate = root_ca
941
+ * root_ca.add_extension(ef.create_extension("basicConstraints","CA:TRUE",true))
942
+ * root_ca.add_extension(ef.create_extension("keyUsage","keyCertSign, cRLSign", true))
943
+ * root_ca.add_extension(ef.create_extension("subjectKeyIdentifier","hash",false))
944
+ * root_ca.add_extension(ef.create_extension("authorityKeyIdentifier","keyid:always",false))
945
+ * root_ca.sign(root_key, OpenSSL::Digest.new('SHA256'))
946
+ *
947
+ * The next step is to create the end-entity certificate using the root CA
948
+ * certificate.
949
+ *
950
+ * key = OpenSSL::PKey::RSA.new 2048
951
+ * cert = OpenSSL::X509::Certificate.new
952
+ * cert.version = 2
953
+ * cert.serial = 2
954
+ * cert.subject = OpenSSL::X509::Name.parse "/DC=org/DC=ruby-lang/CN=Ruby certificate"
955
+ * cert.issuer = root_ca.subject # root CA is the issuer
956
+ * cert.public_key = key.public_key
957
+ * cert.not_before = Time.now
958
+ * cert.not_after = cert.not_before + 1 * 365 * 24 * 60 * 60 # 1 years validity
959
+ * ef = OpenSSL::X509::ExtensionFactory.new
960
+ * ef.subject_certificate = cert
961
+ * ef.issuer_certificate = root_ca
962
+ * cert.add_extension(ef.create_extension("keyUsage","digitalSignature", true))
963
+ * cert.add_extension(ef.create_extension("subjectKeyIdentifier","hash",false))
964
+ * cert.sign(root_key, OpenSSL::Digest.new('SHA256'))
965
+ *
966
+ */
967
+ cX509Cert = rb_define_class_under(mX509, "Certificate", rb_cObject);
968
+
969
+ rb_define_singleton_method(cX509Cert, "load", ossl_x509_load, 1);
970
+
971
+ rb_define_alloc_func(cX509Cert, ossl_x509_alloc);
972
+ rb_define_method(cX509Cert, "initialize", ossl_x509_initialize, -1);
973
+ rb_define_method(cX509Cert, "initialize_copy", ossl_x509_copy, 1);
974
+
975
+ rb_define_method(cX509Cert, "to_der", ossl_x509_to_der, 0);
976
+ rb_define_method(cX509Cert, "to_pem", ossl_x509_to_pem, 0);
977
+ rb_define_alias(cX509Cert, "to_s", "to_pem");
978
+ rb_define_method(cX509Cert, "to_text", ossl_x509_to_text, 0);
979
+ rb_define_method(cX509Cert, "version", ossl_x509_get_version, 0);
980
+ rb_define_method(cX509Cert, "version=", ossl_x509_set_version, 1);
981
+ rb_define_method(cX509Cert, "signature_algorithm", ossl_x509_get_signature_algorithm, 0);
982
+ rb_define_method(cX509Cert, "serial", ossl_x509_get_serial, 0);
983
+ rb_define_method(cX509Cert, "serial=", ossl_x509_set_serial, 1);
984
+ rb_define_method(cX509Cert, "subject", ossl_x509_get_subject, 0);
985
+ rb_define_method(cX509Cert, "subject=", ossl_x509_set_subject, 1);
986
+ rb_define_method(cX509Cert, "issuer", ossl_x509_get_issuer, 0);
987
+ rb_define_method(cX509Cert, "issuer=", ossl_x509_set_issuer, 1);
988
+ rb_define_method(cX509Cert, "not_before", ossl_x509_get_not_before, 0);
989
+ rb_define_method(cX509Cert, "not_before=", ossl_x509_set_not_before, 1);
990
+ rb_define_method(cX509Cert, "not_after", ossl_x509_get_not_after, 0);
991
+ rb_define_method(cX509Cert, "not_after=", ossl_x509_set_not_after, 1);
992
+ rb_define_method(cX509Cert, "public_key", ossl_x509_get_public_key, 0);
993
+ rb_define_method(cX509Cert, "public_key=", ossl_x509_set_public_key, 1);
994
+ rb_define_method(cX509Cert, "sign", ossl_x509_sign, 2);
995
+ rb_define_method(cX509Cert, "verify", ossl_x509_verify, 1);
996
+ rb_define_method(cX509Cert, "check_private_key", ossl_x509_check_private_key, 1);
997
+ rb_define_method(cX509Cert, "extensions", ossl_x509_get_extensions, 0);
998
+ rb_define_method(cX509Cert, "extensions=", ossl_x509_set_extensions, 1);
999
+ rb_define_method(cX509Cert, "add_extension", ossl_x509_add_extension, 1);
1000
+ rb_define_method(cX509Cert, "inspect", ossl_x509_inspect, 0);
1001
+ rb_define_method(cX509Cert, "==", ossl_x509_eq, 1);
1002
+ }