openssl 2.0.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of openssl might be problematic. Click here for more details.

Files changed (71) hide show
  1. checksums.yaml +7 -0
  2. data/BSDL +22 -0
  3. data/CONTRIBUTING.md +130 -0
  4. data/History.md +118 -0
  5. data/LICENSE.txt +56 -0
  6. data/README.md +70 -0
  7. data/ext/openssl/deprecation.rb +26 -0
  8. data/ext/openssl/extconf.rb +158 -0
  9. data/ext/openssl/openssl_missing.c +173 -0
  10. data/ext/openssl/openssl_missing.h +244 -0
  11. data/ext/openssl/ossl.c +1201 -0
  12. data/ext/openssl/ossl.h +222 -0
  13. data/ext/openssl/ossl_asn1.c +1992 -0
  14. data/ext/openssl/ossl_asn1.h +66 -0
  15. data/ext/openssl/ossl_bio.c +87 -0
  16. data/ext/openssl/ossl_bio.h +19 -0
  17. data/ext/openssl/ossl_bn.c +1153 -0
  18. data/ext/openssl/ossl_bn.h +23 -0
  19. data/ext/openssl/ossl_cipher.c +1085 -0
  20. data/ext/openssl/ossl_cipher.h +20 -0
  21. data/ext/openssl/ossl_config.c +89 -0
  22. data/ext/openssl/ossl_config.h +19 -0
  23. data/ext/openssl/ossl_digest.c +453 -0
  24. data/ext/openssl/ossl_digest.h +20 -0
  25. data/ext/openssl/ossl_engine.c +580 -0
  26. data/ext/openssl/ossl_engine.h +19 -0
  27. data/ext/openssl/ossl_hmac.c +398 -0
  28. data/ext/openssl/ossl_hmac.h +18 -0
  29. data/ext/openssl/ossl_ns_spki.c +406 -0
  30. data/ext/openssl/ossl_ns_spki.h +19 -0
  31. data/ext/openssl/ossl_ocsp.c +2013 -0
  32. data/ext/openssl/ossl_ocsp.h +23 -0
  33. data/ext/openssl/ossl_pkcs12.c +259 -0
  34. data/ext/openssl/ossl_pkcs12.h +13 -0
  35. data/ext/openssl/ossl_pkcs5.c +180 -0
  36. data/ext/openssl/ossl_pkcs5.h +6 -0
  37. data/ext/openssl/ossl_pkcs7.c +1125 -0
  38. data/ext/openssl/ossl_pkcs7.h +20 -0
  39. data/ext/openssl/ossl_pkey.c +435 -0
  40. data/ext/openssl/ossl_pkey.h +245 -0
  41. data/ext/openssl/ossl_pkey_dh.c +650 -0
  42. data/ext/openssl/ossl_pkey_dsa.c +672 -0
  43. data/ext/openssl/ossl_pkey_ec.c +1899 -0
  44. data/ext/openssl/ossl_pkey_rsa.c +768 -0
  45. data/ext/openssl/ossl_rand.c +238 -0
  46. data/ext/openssl/ossl_rand.h +18 -0
  47. data/ext/openssl/ossl_ssl.c +2679 -0
  48. data/ext/openssl/ossl_ssl.h +41 -0
  49. data/ext/openssl/ossl_ssl_session.c +352 -0
  50. data/ext/openssl/ossl_version.h +15 -0
  51. data/ext/openssl/ossl_x509.c +186 -0
  52. data/ext/openssl/ossl_x509.h +119 -0
  53. data/ext/openssl/ossl_x509attr.c +328 -0
  54. data/ext/openssl/ossl_x509cert.c +860 -0
  55. data/ext/openssl/ossl_x509crl.c +565 -0
  56. data/ext/openssl/ossl_x509ext.c +480 -0
  57. data/ext/openssl/ossl_x509name.c +547 -0
  58. data/ext/openssl/ossl_x509req.c +492 -0
  59. data/ext/openssl/ossl_x509revoked.c +279 -0
  60. data/ext/openssl/ossl_x509store.c +846 -0
  61. data/ext/openssl/ruby_missing.h +32 -0
  62. data/lib/openssl.rb +21 -0
  63. data/lib/openssl/bn.rb +39 -0
  64. data/lib/openssl/buffering.rb +451 -0
  65. data/lib/openssl/cipher.rb +67 -0
  66. data/lib/openssl/config.rb +473 -0
  67. data/lib/openssl/digest.rb +78 -0
  68. data/lib/openssl/pkey.rb +44 -0
  69. data/lib/openssl/ssl.rb +416 -0
  70. data/lib/openssl/x509.rb +176 -0
  71. metadata +178 -0
@@ -0,0 +1,279 @@
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 NewX509Rev(klass) \
13
+ TypedData_Wrap_Struct((klass), &ossl_x509rev_type, 0)
14
+ #define SetX509Rev(obj, rev) do { \
15
+ if (!(rev)) { \
16
+ ossl_raise(rb_eRuntimeError, "REV wasn't initialized!"); \
17
+ } \
18
+ RTYPEDDATA_DATA(obj) = (rev); \
19
+ } while (0)
20
+ #define GetX509Rev(obj, rev) do { \
21
+ TypedData_Get_Struct((obj), X509_REVOKED, &ossl_x509rev_type, (rev)); \
22
+ if (!(rev)) { \
23
+ ossl_raise(rb_eRuntimeError, "REV wasn't initialized!"); \
24
+ } \
25
+ } while (0)
26
+ #define SafeGetX509Rev(obj, rev) do { \
27
+ OSSL_Check_Kind((obj), cX509Rev); \
28
+ GetX509Rev((obj), (rev)); \
29
+ } while (0)
30
+
31
+ /*
32
+ * Classes
33
+ */
34
+ VALUE cX509Rev;
35
+ VALUE eX509RevError;
36
+
37
+ static void
38
+ ossl_x509rev_free(void *ptr)
39
+ {
40
+ X509_REVOKED_free(ptr);
41
+ }
42
+
43
+ static const rb_data_type_t ossl_x509rev_type = {
44
+ "OpenSSL/X509/REV",
45
+ {
46
+ 0, ossl_x509rev_free,
47
+ },
48
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
49
+ };
50
+
51
+ /*
52
+ * PUBLIC
53
+ */
54
+ VALUE
55
+ ossl_x509revoked_new(X509_REVOKED *rev)
56
+ {
57
+ X509_REVOKED *new;
58
+ VALUE obj;
59
+
60
+ obj = NewX509Rev(cX509Rev);
61
+ if (!rev) {
62
+ new = X509_REVOKED_new();
63
+ } else {
64
+ new = X509_REVOKED_dup(rev);
65
+ }
66
+ if (!new) {
67
+ ossl_raise(eX509RevError, NULL);
68
+ }
69
+ SetX509Rev(obj, new);
70
+
71
+ return obj;
72
+ }
73
+
74
+ X509_REVOKED *
75
+ DupX509RevokedPtr(VALUE obj)
76
+ {
77
+ X509_REVOKED *rev, *new;
78
+
79
+ SafeGetX509Rev(obj, rev);
80
+ if (!(new = X509_REVOKED_dup(rev))) {
81
+ ossl_raise(eX509RevError, NULL);
82
+ }
83
+
84
+ return new;
85
+ }
86
+
87
+ /*
88
+ * PRIVATE
89
+ */
90
+ static VALUE
91
+ ossl_x509revoked_alloc(VALUE klass)
92
+ {
93
+ X509_REVOKED *rev;
94
+ VALUE obj;
95
+
96
+ obj = NewX509Rev(klass);
97
+ if (!(rev = X509_REVOKED_new())) {
98
+ ossl_raise(eX509RevError, NULL);
99
+ }
100
+ SetX509Rev(obj, rev);
101
+
102
+ return obj;
103
+ }
104
+
105
+ static VALUE
106
+ ossl_x509revoked_initialize(int argc, VALUE *argv, VALUE self)
107
+ {
108
+ /* EMPTY */
109
+ return self;
110
+ }
111
+
112
+ static VALUE
113
+ ossl_x509revoked_initialize_copy(VALUE self, VALUE other)
114
+ {
115
+ X509_REVOKED *rev, *rev_other, *rev_new;
116
+
117
+ rb_check_frozen(self);
118
+ GetX509Rev(self, rev);
119
+ SafeGetX509Rev(other, rev_other);
120
+
121
+ rev_new = X509_REVOKED_dup(rev_other);
122
+ if (!rev_new)
123
+ ossl_raise(eX509RevError, "X509_REVOKED_dup");
124
+
125
+ SetX509Rev(self, rev_new);
126
+ X509_REVOKED_free(rev);
127
+
128
+ return self;
129
+ }
130
+
131
+ static VALUE
132
+ ossl_x509revoked_get_serial(VALUE self)
133
+ {
134
+ X509_REVOKED *rev;
135
+
136
+ GetX509Rev(self, rev);
137
+
138
+ return asn1integer_to_num(X509_REVOKED_get0_serialNumber(rev));
139
+ }
140
+
141
+ static VALUE
142
+ ossl_x509revoked_set_serial(VALUE self, VALUE num)
143
+ {
144
+ X509_REVOKED *rev;
145
+ ASN1_INTEGER *asn1int;
146
+
147
+ GetX509Rev(self, rev);
148
+ asn1int = num_to_asn1integer(num, NULL);
149
+ if (!X509_REVOKED_set_serialNumber(rev, asn1int)) {
150
+ ASN1_INTEGER_free(asn1int);
151
+ ossl_raise(eX509RevError, "X509_REVOKED_set_serialNumber");
152
+ }
153
+ ASN1_INTEGER_free(asn1int);
154
+
155
+ return num;
156
+ }
157
+
158
+ static VALUE
159
+ ossl_x509revoked_get_time(VALUE self)
160
+ {
161
+ X509_REVOKED *rev;
162
+
163
+ GetX509Rev(self, rev);
164
+
165
+ return asn1time_to_time(X509_REVOKED_get0_revocationDate(rev));
166
+ }
167
+
168
+ static VALUE
169
+ ossl_x509revoked_set_time(VALUE self, VALUE time)
170
+ {
171
+ X509_REVOKED *rev;
172
+ ASN1_TIME *asn1time;
173
+
174
+ GetX509Rev(self, rev);
175
+ asn1time = ossl_x509_time_adjust(NULL, time);
176
+ if (!X509_REVOKED_set_revocationDate(rev, asn1time)) {
177
+ ASN1_TIME_free(asn1time);
178
+ ossl_raise(eX509RevError, "X509_REVOKED_set_revocationDate");
179
+ }
180
+ ASN1_TIME_free(asn1time);
181
+
182
+ return time;
183
+ }
184
+ /*
185
+ * Gets X509v3 extensions as array of X509Ext objects
186
+ */
187
+ static VALUE
188
+ ossl_x509revoked_get_extensions(VALUE self)
189
+ {
190
+ X509_REVOKED *rev;
191
+ int count, i;
192
+ X509_EXTENSION *ext;
193
+ VALUE ary;
194
+
195
+ GetX509Rev(self, rev);
196
+ count = X509_REVOKED_get_ext_count(rev);
197
+ if (count < 0) {
198
+ OSSL_Debug("count < 0???");
199
+ return rb_ary_new();
200
+ }
201
+ ary = rb_ary_new2(count);
202
+ for (i=0; i<count; i++) {
203
+ ext = X509_REVOKED_get_ext(rev, i);
204
+ rb_ary_push(ary, ossl_x509ext_new(ext));
205
+ }
206
+
207
+ return ary;
208
+ }
209
+
210
+ /*
211
+ * Sets X509_EXTENSIONs
212
+ */
213
+ static VALUE
214
+ ossl_x509revoked_set_extensions(VALUE self, VALUE ary)
215
+ {
216
+ X509_REVOKED *rev;
217
+ X509_EXTENSION *ext;
218
+ long i;
219
+ VALUE item;
220
+
221
+ Check_Type(ary, T_ARRAY);
222
+ for (i=0; i<RARRAY_LEN(ary); i++) {
223
+ OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Ext);
224
+ }
225
+ GetX509Rev(self, rev);
226
+ while ((ext = X509_REVOKED_delete_ext(rev, 0)))
227
+ X509_EXTENSION_free(ext);
228
+ for (i=0; i<RARRAY_LEN(ary); i++) {
229
+ item = RARRAY_AREF(ary, i);
230
+ ext = GetX509ExtPtr(item);
231
+ if(!X509_REVOKED_add_ext(rev, ext, -1)) {
232
+ ossl_raise(eX509RevError, NULL);
233
+ }
234
+ }
235
+
236
+ return ary;
237
+ }
238
+
239
+ static VALUE
240
+ ossl_x509revoked_add_extension(VALUE self, VALUE ext)
241
+ {
242
+ X509_REVOKED *rev;
243
+
244
+ GetX509Rev(self, rev);
245
+ if (!X509_REVOKED_add_ext(rev, GetX509ExtPtr(ext), -1)) {
246
+ ossl_raise(eX509RevError, NULL);
247
+ }
248
+
249
+ return ext;
250
+ }
251
+
252
+ /*
253
+ * INIT
254
+ */
255
+ void
256
+ Init_ossl_x509revoked(void)
257
+ {
258
+ #if 0
259
+ mOSSL = rb_define_module("OpenSSL");
260
+ eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
261
+ mX509 = rb_define_module_under(mOSSL, "X509");
262
+ #endif
263
+
264
+ eX509RevError = rb_define_class_under(mX509, "RevokedError", eOSSLError);
265
+
266
+ cX509Rev = rb_define_class_under(mX509, "Revoked", rb_cObject);
267
+
268
+ rb_define_alloc_func(cX509Rev, ossl_x509revoked_alloc);
269
+ rb_define_method(cX509Rev, "initialize", ossl_x509revoked_initialize, -1);
270
+ rb_define_copy_func(cX509Rev, ossl_x509revoked_initialize_copy);
271
+
272
+ rb_define_method(cX509Rev, "serial", ossl_x509revoked_get_serial, 0);
273
+ rb_define_method(cX509Rev, "serial=", ossl_x509revoked_set_serial, 1);
274
+ rb_define_method(cX509Rev, "time", ossl_x509revoked_get_time, 0);
275
+ rb_define_method(cX509Rev, "time=", ossl_x509revoked_set_time, 1);
276
+ rb_define_method(cX509Rev, "extensions", ossl_x509revoked_get_extensions, 0);
277
+ rb_define_method(cX509Rev, "extensions=", ossl_x509revoked_set_extensions, 1);
278
+ rb_define_method(cX509Rev, "add_extension", ossl_x509revoked_add_extension, 1);
279
+ }
@@ -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 NewX509Store(klass) \
13
+ TypedData_Wrap_Struct((klass), &ossl_x509store_type, 0)
14
+ #define SetX509Store(obj, st) do { \
15
+ if (!(st)) { \
16
+ ossl_raise(rb_eRuntimeError, "STORE wasn't initialized!"); \
17
+ } \
18
+ RTYPEDDATA_DATA(obj) = (st); \
19
+ } while (0)
20
+ #define GetX509Store(obj, st) do { \
21
+ TypedData_Get_Struct((obj), X509_STORE, &ossl_x509store_type, (st)); \
22
+ if (!(st)) { \
23
+ ossl_raise(rb_eRuntimeError, "STORE wasn't initialized!"); \
24
+ } \
25
+ } while (0)
26
+ #define SafeGetX509Store(obj, st) do { \
27
+ OSSL_Check_Kind((obj), cX509Store); \
28
+ GetX509Store((obj), (st)); \
29
+ } while (0)
30
+
31
+ #define NewX509StCtx(klass) \
32
+ TypedData_Wrap_Struct((klass), &ossl_x509stctx_type, 0)
33
+ #define SetX509StCtx(obj, ctx) do { \
34
+ if (!(ctx)) { \
35
+ ossl_raise(rb_eRuntimeError, "STORE_CTX wasn't initialized!"); \
36
+ } \
37
+ RTYPEDDATA_DATA(obj) = (ctx); \
38
+ } while (0)
39
+ #define GetX509StCtx(obj, ctx) do { \
40
+ TypedData_Get_Struct((obj), X509_STORE_CTX, &ossl_x509stctx_type, (ctx)); \
41
+ if (!(ctx)) { \
42
+ ossl_raise(rb_eRuntimeError, "STORE_CTX is out of scope!"); \
43
+ } \
44
+ } while (0)
45
+ #define SafeGetX509StCtx(obj, storep) do { \
46
+ OSSL_Check_Kind((obj), cX509StoreContext); \
47
+ GetX509Store((obj), (ctx)); \
48
+ } while (0)
49
+
50
+ /*
51
+ * Classes
52
+ */
53
+ VALUE cX509Store;
54
+ VALUE cX509StoreContext;
55
+ VALUE eX509StoreError;
56
+
57
+ static void
58
+ ossl_x509store_free(void *ptr)
59
+ {
60
+ X509_STORE_free(ptr);
61
+ }
62
+
63
+ static const rb_data_type_t ossl_x509store_type = {
64
+ "OpenSSL/X509/STORE",
65
+ {
66
+ 0, ossl_x509store_free,
67
+ },
68
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
69
+ };
70
+
71
+ /*
72
+ * Public functions
73
+ */
74
+ VALUE
75
+ ossl_x509store_new(X509_STORE *store)
76
+ {
77
+ VALUE obj;
78
+
79
+ obj = NewX509Store(cX509Store);
80
+ SetX509Store(obj, store);
81
+
82
+ return obj;
83
+ }
84
+
85
+ X509_STORE *
86
+ GetX509StorePtr(VALUE obj)
87
+ {
88
+ X509_STORE *store;
89
+
90
+ SafeGetX509Store(obj, store);
91
+
92
+ return store;
93
+ }
94
+
95
+ X509_STORE *
96
+ DupX509StorePtr(VALUE obj)
97
+ {
98
+ X509_STORE *store;
99
+
100
+ SafeGetX509Store(obj, store);
101
+ X509_STORE_up_ref(store);
102
+
103
+ return store;
104
+ }
105
+
106
+ /*
107
+ * Private functions
108
+ */
109
+ static int
110
+ x509store_verify_cb(int ok, X509_STORE_CTX *ctx)
111
+ {
112
+ VALUE proc;
113
+
114
+ proc = (VALUE)X509_STORE_CTX_get_ex_data(ctx, ossl_store_ctx_ex_verify_cb_idx);
115
+ if (!proc)
116
+ proc = (VALUE)X509_STORE_get_ex_data(X509_STORE_CTX_get0_store(ctx), ossl_store_ex_verify_cb_idx);
117
+ if (!proc)
118
+ return ok;
119
+
120
+ return ossl_verify_cb_call(proc, ok, ctx);
121
+ }
122
+
123
+ static VALUE
124
+ ossl_x509store_alloc(VALUE klass)
125
+ {
126
+ X509_STORE *store;
127
+ VALUE obj;
128
+
129
+ obj = NewX509Store(klass);
130
+ if((store = X509_STORE_new()) == NULL){
131
+ ossl_raise(eX509StoreError, NULL);
132
+ }
133
+ SetX509Store(obj, store);
134
+
135
+ return obj;
136
+ }
137
+
138
+ /*
139
+ * General callback for OpenSSL verify
140
+ */
141
+ static VALUE
142
+ ossl_x509store_set_vfy_cb(VALUE self, VALUE cb)
143
+ {
144
+ X509_STORE *store;
145
+
146
+ GetX509Store(self, store);
147
+ X509_STORE_set_ex_data(store, ossl_store_ex_verify_cb_idx, (void *)cb);
148
+ rb_iv_set(self, "@verify_callback", cb);
149
+
150
+ return cb;
151
+ }
152
+
153
+
154
+ /*
155
+ * call-seq:
156
+ * X509::Store.new => store
157
+ *
158
+ * Creates a new X509::Store.
159
+ */
160
+ static VALUE
161
+ ossl_x509store_initialize(int argc, VALUE *argv, VALUE self)
162
+ {
163
+ X509_STORE *store;
164
+
165
+ /* BUG: This method takes any number of arguments but appears to ignore them. */
166
+ GetX509Store(self, store);
167
+ #if !defined(HAVE_OPAQUE_OPENSSL)
168
+ /* [Bug #405] [Bug #1678] [Bug #3000]; already fixed? */
169
+ store->ex_data.sk = NULL;
170
+ #endif
171
+ X509_STORE_set_verify_cb(store, x509store_verify_cb);
172
+ ossl_x509store_set_vfy_cb(self, Qnil);
173
+
174
+ /* last verification status */
175
+ rb_iv_set(self, "@error", Qnil);
176
+ rb_iv_set(self, "@error_string", Qnil);
177
+ rb_iv_set(self, "@chain", Qnil);
178
+ rb_iv_set(self, "@time", Qnil);
179
+
180
+ return self;
181
+ }
182
+
183
+ /*
184
+ * call-seq:
185
+ * store.flags = flag
186
+ *
187
+ * Sets +flag+ to the Store. +flag+ consists of zero or more of the constants
188
+ * defined in with name V_FLAG_* or'ed together.
189
+ */
190
+ static VALUE
191
+ ossl_x509store_set_flags(VALUE self, VALUE flags)
192
+ {
193
+ X509_STORE *store;
194
+ long f = NUM2LONG(flags);
195
+
196
+ GetX509Store(self, store);
197
+ X509_STORE_set_flags(store, f);
198
+
199
+ return flags;
200
+ }
201
+
202
+ /*
203
+ * call-seq:
204
+ * store.purpose = purpose
205
+ *
206
+ * Sets the store's purpose to +purpose+. If specified, the verifications on
207
+ * the store will check every untrusted certificate's extensions are consistent
208
+ * with the purpose. The purpose is specified by constants:
209
+ *
210
+ * * X509::PURPOSE_SSL_CLIENT
211
+ * * X509::PURPOSE_SSL_SERVER
212
+ * * X509::PURPOSE_NS_SSL_SERVER
213
+ * * X509::PURPOSE_SMIME_SIGN
214
+ * * X509::PURPOSE_SMIME_ENCRYPT
215
+ * * X509::PURPOSE_CRL_SIGN
216
+ * * X509::PURPOSE_ANY
217
+ * * X509::PURPOSE_OCSP_HELPER
218
+ * * X509::PURPOSE_TIMESTAMP_SIGN
219
+ */
220
+ static VALUE
221
+ ossl_x509store_set_purpose(VALUE self, VALUE purpose)
222
+ {
223
+ X509_STORE *store;
224
+ int p = NUM2INT(purpose);
225
+
226
+ GetX509Store(self, store);
227
+ X509_STORE_set_purpose(store, p);
228
+
229
+ return purpose;
230
+ }
231
+
232
+ /*
233
+ * call-seq:
234
+ * store.trust = trust
235
+ */
236
+ static VALUE
237
+ ossl_x509store_set_trust(VALUE self, VALUE trust)
238
+ {
239
+ X509_STORE *store;
240
+ int t = NUM2INT(trust);
241
+
242
+ GetX509Store(self, store);
243
+ X509_STORE_set_trust(store, t);
244
+
245
+ return trust;
246
+ }
247
+
248
+ /*
249
+ * call-seq:
250
+ * store.time = time
251
+ *
252
+ * Sets the time to be used in verifications.
253
+ */
254
+ static VALUE
255
+ ossl_x509store_set_time(VALUE self, VALUE time)
256
+ {
257
+ rb_iv_set(self, "@time", time);
258
+ return time;
259
+ }
260
+
261
+ /*
262
+ * call-seq:
263
+ * store.add_file(file) -> self
264
+ *
265
+ * Adds the certificates in +file+ to the certificate store. The +file+ can
266
+ * contain multiple PEM-encoded certificates.
267
+ */
268
+ static VALUE
269
+ ossl_x509store_add_file(VALUE self, VALUE file)
270
+ {
271
+ X509_STORE *store;
272
+ X509_LOOKUP *lookup;
273
+ char *path = NULL;
274
+
275
+ if(file != Qnil){
276
+ rb_check_safe_obj(file);
277
+ path = StringValueCStr(file);
278
+ }
279
+ GetX509Store(self, store);
280
+ lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
281
+ if(lookup == NULL) ossl_raise(eX509StoreError, NULL);
282
+ if(X509_LOOKUP_load_file(lookup, path, X509_FILETYPE_PEM) != 1){
283
+ ossl_raise(eX509StoreError, NULL);
284
+ }
285
+
286
+ return self;
287
+ }
288
+
289
+ /*
290
+ * call-seq:
291
+ * store.add_path(path) -> self
292
+ *
293
+ * Adds +path+ as the hash dir to be looked up by the store.
294
+ */
295
+ static VALUE
296
+ ossl_x509store_add_path(VALUE self, VALUE dir)
297
+ {
298
+ X509_STORE *store;
299
+ X509_LOOKUP *lookup;
300
+ char *path = NULL;
301
+
302
+ if(dir != Qnil){
303
+ rb_check_safe_obj(dir);
304
+ path = StringValueCStr(dir);
305
+ }
306
+ GetX509Store(self, store);
307
+ lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
308
+ if(lookup == NULL) ossl_raise(eX509StoreError, NULL);
309
+ if(X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM) != 1){
310
+ ossl_raise(eX509StoreError, NULL);
311
+ }
312
+
313
+ return self;
314
+ }
315
+
316
+ /*
317
+ * call-seq:
318
+ * store.set_default_paths
319
+ *
320
+ * Configures +store+ to look up CA certificates from the system default
321
+ * certificate store as needed basis. The location of the store can usually be
322
+ * determined by:
323
+ *
324
+ * * OpenSSL::X509::DEFAULT_CERT_FILE
325
+ * * OpenSSL::X509::DEFAULT_CERT_DIR
326
+ */
327
+ static VALUE
328
+ ossl_x509store_set_default_paths(VALUE self)
329
+ {
330
+ X509_STORE *store;
331
+
332
+ GetX509Store(self, store);
333
+ if (X509_STORE_set_default_paths(store) != 1){
334
+ ossl_raise(eX509StoreError, NULL);
335
+ }
336
+
337
+ return Qnil;
338
+ }
339
+
340
+ /*
341
+ * call-seq:
342
+ * store.add_cert(cert)
343
+ *
344
+ * Adds the OpenSSL::X509::Certificate +cert+ to the certificate store.
345
+ */
346
+ static VALUE
347
+ ossl_x509store_add_cert(VALUE self, VALUE arg)
348
+ {
349
+ X509_STORE *store;
350
+ X509 *cert;
351
+
352
+ cert = GetX509CertPtr(arg); /* NO NEED TO DUP */
353
+ GetX509Store(self, store);
354
+ if (X509_STORE_add_cert(store, cert) != 1){
355
+ ossl_raise(eX509StoreError, NULL);
356
+ }
357
+
358
+ return self;
359
+ }
360
+
361
+ /*
362
+ * call-seq:
363
+ * store.add_crl(crl) -> self
364
+ *
365
+ * Adds the OpenSSL::X509::CRL +crl+ to the store.
366
+ */
367
+ static VALUE
368
+ ossl_x509store_add_crl(VALUE self, VALUE arg)
369
+ {
370
+ X509_STORE *store;
371
+ X509_CRL *crl;
372
+
373
+ crl = GetX509CRLPtr(arg); /* NO NEED TO DUP */
374
+ GetX509Store(self, store);
375
+ if (X509_STORE_add_crl(store, crl) != 1){
376
+ ossl_raise(eX509StoreError, NULL);
377
+ }
378
+
379
+ return self;
380
+ }
381
+
382
+ static VALUE ossl_x509stctx_get_err(VALUE);
383
+ static VALUE ossl_x509stctx_get_err_string(VALUE);
384
+ static VALUE ossl_x509stctx_get_chain(VALUE);
385
+
386
+ /*
387
+ * call-seq:
388
+ * store.verify(cert, chain = nil) -> true | false
389
+ *
390
+ * Performs a certificate verification on the OpenSSL::X509::Certificate +cert+.
391
+ *
392
+ * +chain+ can be an array of OpenSSL::X509::Certificate that is used to
393
+ * construct the certificate chain.
394
+ *
395
+ * If a block is given, it overrides the callback set by #verify_callback=.
396
+ *
397
+ * After finishing the verification, the error information can be retrieved by
398
+ * #error, #error_string, and the resuting complete certificate chain can be
399
+ * retrieved by #chain.
400
+ */
401
+ static VALUE
402
+ ossl_x509store_verify(int argc, VALUE *argv, VALUE self)
403
+ {
404
+ VALUE cert, chain;
405
+ VALUE ctx, proc, result;
406
+
407
+ rb_scan_args(argc, argv, "11", &cert, &chain);
408
+ ctx = rb_funcall(cX509StoreContext, rb_intern("new"), 3, self, cert, chain);
409
+ proc = rb_block_given_p() ? rb_block_proc() :
410
+ rb_iv_get(self, "@verify_callback");
411
+ rb_iv_set(ctx, "@verify_callback", proc);
412
+ result = rb_funcall(ctx, rb_intern("verify"), 0);
413
+
414
+ rb_iv_set(self, "@error", ossl_x509stctx_get_err(ctx));
415
+ rb_iv_set(self, "@error_string", ossl_x509stctx_get_err_string(ctx));
416
+ rb_iv_set(self, "@chain", ossl_x509stctx_get_chain(ctx));
417
+
418
+ return result;
419
+ }
420
+
421
+ /*
422
+ * Public Functions
423
+ */
424
+ static void ossl_x509stctx_free(void*);
425
+
426
+
427
+ static const rb_data_type_t ossl_x509stctx_type = {
428
+ "OpenSSL/X509/STORE_CTX",
429
+ {
430
+ 0, ossl_x509stctx_free,
431
+ },
432
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
433
+ };
434
+
435
+
436
+ VALUE
437
+ ossl_x509stctx_new(X509_STORE_CTX *ctx)
438
+ {
439
+ VALUE obj;
440
+
441
+ obj = NewX509StCtx(cX509StoreContext);
442
+ SetX509StCtx(obj, ctx);
443
+
444
+ return obj;
445
+ }
446
+
447
+ VALUE
448
+ ossl_x509stctx_clear_ptr(VALUE obj)
449
+ {
450
+ OSSL_Check_Kind(obj, cX509StoreContext);
451
+ RDATA(obj)->data = NULL;
452
+
453
+ return obj;
454
+ }
455
+
456
+ /*
457
+ * Private functions
458
+ */
459
+ static void
460
+ ossl_x509stctx_free(void *ptr)
461
+ {
462
+ X509_STORE_CTX *ctx = ptr;
463
+ if (X509_STORE_CTX_get0_untrusted(ctx))
464
+ sk_X509_pop_free(X509_STORE_CTX_get0_untrusted(ctx), X509_free);
465
+ if (X509_STORE_CTX_get0_cert(ctx))
466
+ X509_free(X509_STORE_CTX_get0_cert(ctx));
467
+ X509_STORE_CTX_free(ctx);
468
+ }
469
+
470
+ static VALUE
471
+ ossl_x509stctx_alloc(VALUE klass)
472
+ {
473
+ X509_STORE_CTX *ctx;
474
+ VALUE obj;
475
+
476
+ obj = NewX509StCtx(klass);
477
+ if((ctx = X509_STORE_CTX_new()) == NULL){
478
+ ossl_raise(eX509StoreError, NULL);
479
+ }
480
+ SetX509StCtx(obj, ctx);
481
+
482
+ return obj;
483
+ }
484
+
485
+ static VALUE ossl_x509stctx_set_flags(VALUE, VALUE);
486
+ static VALUE ossl_x509stctx_set_purpose(VALUE, VALUE);
487
+ static VALUE ossl_x509stctx_set_trust(VALUE, VALUE);
488
+ static VALUE ossl_x509stctx_set_time(VALUE, VALUE);
489
+
490
+ /*
491
+ * call-seq:
492
+ * StoreContext.new(store, cert = nil, chain = nil)
493
+ */
494
+ static VALUE
495
+ ossl_x509stctx_initialize(int argc, VALUE *argv, VALUE self)
496
+ {
497
+ VALUE store, cert, chain, t;
498
+ X509_STORE_CTX *ctx;
499
+ X509_STORE *x509st;
500
+ X509 *x509 = NULL;
501
+ STACK_OF(X509) *x509s = NULL;
502
+
503
+ rb_scan_args(argc, argv, "12", &store, &cert, &chain);
504
+ GetX509StCtx(self, ctx);
505
+ SafeGetX509Store(store, x509st);
506
+ if(!NIL_P(cert)) x509 = DupX509CertPtr(cert); /* NEED TO DUP */
507
+ if(!NIL_P(chain)) x509s = ossl_x509_ary2sk(chain);
508
+ if(X509_STORE_CTX_init(ctx, x509st, x509, x509s) != 1){
509
+ sk_X509_pop_free(x509s, X509_free);
510
+ ossl_raise(eX509StoreError, NULL);
511
+ }
512
+ if (!NIL_P(t = rb_iv_get(store, "@time")))
513
+ ossl_x509stctx_set_time(self, t);
514
+ rb_iv_set(self, "@verify_callback", rb_iv_get(store, "@verify_callback"));
515
+ rb_iv_set(self, "@cert", cert);
516
+
517
+ return self;
518
+ }
519
+
520
+ /*
521
+ * call-seq:
522
+ * stctx.verify -> true | false
523
+ */
524
+ static VALUE
525
+ ossl_x509stctx_verify(VALUE self)
526
+ {
527
+ X509_STORE_CTX *ctx;
528
+
529
+ GetX509StCtx(self, ctx);
530
+ X509_STORE_CTX_set_ex_data(ctx, ossl_store_ctx_ex_verify_cb_idx,
531
+ (void *)rb_iv_get(self, "@verify_callback"));
532
+
533
+ switch (X509_verify_cert(ctx)) {
534
+ case 1:
535
+ return Qtrue;
536
+ case 0:
537
+ ossl_clear_error();
538
+ return Qfalse;
539
+ default:
540
+ ossl_raise(eX509CertError, NULL);
541
+ }
542
+ }
543
+
544
+ /*
545
+ * call-seq:
546
+ * stctx.chain -> Array of X509::Certificate
547
+ */
548
+ static VALUE
549
+ ossl_x509stctx_get_chain(VALUE self)
550
+ {
551
+ X509_STORE_CTX *ctx;
552
+ STACK_OF(X509) *chain;
553
+ X509 *x509;
554
+ int i, num;
555
+ VALUE ary;
556
+
557
+ GetX509StCtx(self, ctx);
558
+ if((chain = X509_STORE_CTX_get0_chain(ctx)) == NULL){
559
+ return Qnil;
560
+ }
561
+ if((num = sk_X509_num(chain)) < 0){
562
+ OSSL_Debug("certs in chain < 0???");
563
+ return rb_ary_new();
564
+ }
565
+ ary = rb_ary_new2(num);
566
+ for(i = 0; i < num; i++) {
567
+ x509 = sk_X509_value(chain, i);
568
+ rb_ary_push(ary, ossl_x509_new(x509));
569
+ }
570
+
571
+ return ary;
572
+ }
573
+
574
+ /*
575
+ * call-seq:
576
+ * stctx.error -> Integer
577
+ */
578
+ static VALUE
579
+ ossl_x509stctx_get_err(VALUE self)
580
+ {
581
+ X509_STORE_CTX *ctx;
582
+
583
+ GetX509StCtx(self, ctx);
584
+
585
+ return INT2NUM(X509_STORE_CTX_get_error(ctx));
586
+ }
587
+
588
+ /*
589
+ * call-seq:
590
+ * stctx.error = error_code
591
+ */
592
+ static VALUE
593
+ ossl_x509stctx_set_error(VALUE self, VALUE err)
594
+ {
595
+ X509_STORE_CTX *ctx;
596
+
597
+ GetX509StCtx(self, ctx);
598
+ X509_STORE_CTX_set_error(ctx, NUM2INT(err));
599
+
600
+ return err;
601
+ }
602
+
603
+ /*
604
+ * call-seq:
605
+ * stctx.error_string -> String
606
+ *
607
+ * Returns the error string corresponding to the error code retrieved by #error.
608
+ */
609
+ static VALUE
610
+ ossl_x509stctx_get_err_string(VALUE self)
611
+ {
612
+ X509_STORE_CTX *ctx;
613
+ long err;
614
+
615
+ GetX509StCtx(self, ctx);
616
+ err = X509_STORE_CTX_get_error(ctx);
617
+
618
+ return rb_str_new2(X509_verify_cert_error_string(err));
619
+ }
620
+
621
+ /*
622
+ * call-seq:
623
+ * stctx.error_depth -> Integer
624
+ */
625
+ static VALUE
626
+ ossl_x509stctx_get_err_depth(VALUE self)
627
+ {
628
+ X509_STORE_CTX *ctx;
629
+
630
+ GetX509StCtx(self, ctx);
631
+
632
+ return INT2NUM(X509_STORE_CTX_get_error_depth(ctx));
633
+ }
634
+
635
+ /*
636
+ * call-seq:
637
+ * stctx.current_cert -> X509::Certificate
638
+ */
639
+ static VALUE
640
+ ossl_x509stctx_get_curr_cert(VALUE self)
641
+ {
642
+ X509_STORE_CTX *ctx;
643
+
644
+ GetX509StCtx(self, ctx);
645
+
646
+ return ossl_x509_new(X509_STORE_CTX_get_current_cert(ctx));
647
+ }
648
+
649
+ /*
650
+ * call-seq:
651
+ * stctx.current_crl -> X509::CRL
652
+ */
653
+ static VALUE
654
+ ossl_x509stctx_get_curr_crl(VALUE self)
655
+ {
656
+ X509_STORE_CTX *ctx;
657
+ X509_CRL *crl;
658
+
659
+ GetX509StCtx(self, ctx);
660
+ crl = X509_STORE_CTX_get0_current_crl(ctx);
661
+ if (!crl)
662
+ return Qnil;
663
+
664
+ return ossl_x509crl_new(crl);
665
+ }
666
+
667
+ /*
668
+ * call-seq:
669
+ * stctx.flags = flags
670
+ *
671
+ * Sets the verification flags to the context. See Store#flags=.
672
+ */
673
+ static VALUE
674
+ ossl_x509stctx_set_flags(VALUE self, VALUE flags)
675
+ {
676
+ X509_STORE_CTX *store;
677
+ long f = NUM2LONG(flags);
678
+
679
+ GetX509StCtx(self, store);
680
+ X509_STORE_CTX_set_flags(store, f);
681
+
682
+ return flags;
683
+ }
684
+
685
+ /*
686
+ * call-seq:
687
+ * stctx.purpose = purpose
688
+ *
689
+ * Sets the purpose of the context. See Store#purpose=.
690
+ */
691
+ static VALUE
692
+ ossl_x509stctx_set_purpose(VALUE self, VALUE purpose)
693
+ {
694
+ X509_STORE_CTX *store;
695
+ int p = NUM2INT(purpose);
696
+
697
+ GetX509StCtx(self, store);
698
+ X509_STORE_CTX_set_purpose(store, p);
699
+
700
+ return purpose;
701
+ }
702
+
703
+ /*
704
+ * call-seq:
705
+ * stctx.trust = trust
706
+ */
707
+ static VALUE
708
+ ossl_x509stctx_set_trust(VALUE self, VALUE trust)
709
+ {
710
+ X509_STORE_CTX *store;
711
+ int t = NUM2INT(trust);
712
+
713
+ GetX509StCtx(self, store);
714
+ X509_STORE_CTX_set_trust(store, t);
715
+
716
+ return trust;
717
+ }
718
+
719
+ /*
720
+ * call-seq:
721
+ * stctx.time = time
722
+ *
723
+ * Sets the time used in the verification. If not set, the current time is used.
724
+ */
725
+ static VALUE
726
+ ossl_x509stctx_set_time(VALUE self, VALUE time)
727
+ {
728
+ X509_STORE_CTX *store;
729
+ long t;
730
+
731
+ t = NUM2LONG(rb_Integer(time));
732
+ GetX509StCtx(self, store);
733
+ X509_STORE_CTX_set_time(store, 0, t);
734
+
735
+ return time;
736
+ }
737
+
738
+ /*
739
+ * INIT
740
+ */
741
+ void
742
+ Init_ossl_x509store(void)
743
+ {
744
+ #if 0
745
+ mOSSL = rb_define_module("OpenSSL");
746
+ eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
747
+ mX509 = rb_define_module_under(mOSSL, "X509");
748
+ #endif
749
+
750
+ eX509StoreError = rb_define_class_under(mX509, "StoreError", eOSSLError);
751
+
752
+ /* Document-class: OpenSSL::X509::Store
753
+ *
754
+ * The X509 certificate store holds trusted CA certificates used to verify
755
+ * peer certificates.
756
+ *
757
+ * The easiest way to create a useful certificate store is:
758
+ *
759
+ * cert_store = OpenSSL::X509::Store.new
760
+ * cert_store.set_default_paths
761
+ *
762
+ * This will use your system's built-in certificates.
763
+ *
764
+ * If your system does not have a default set of certificates you can obtain
765
+ * a set extracted from Mozilla CA certificate store by cURL maintainers
766
+ * here: https://curl.haxx.se/docs/caextract.html (You may wish to use the
767
+ * firefox-db2pem.sh script to extract the certificates from a local install
768
+ * to avoid man-in-the-middle attacks.)
769
+ *
770
+ * After downloading or generating a cacert.pem from the above link you
771
+ * can create a certificate store from the pem file like this:
772
+ *
773
+ * cert_store = OpenSSL::X509::Store.new
774
+ * cert_store.add_file 'cacert.pem'
775
+ *
776
+ * The certificate store can be used with an SSLSocket like this:
777
+ *
778
+ * ssl_context = OpenSSL::SSL::SSLContext.new
779
+ * ssl_context.verify_mode = OpenSSL::SSL::VERIFY_PEER
780
+ * ssl_context.cert_store = cert_store
781
+ *
782
+ * tcp_socket = TCPSocket.open 'example.com', 443
783
+ *
784
+ * ssl_socket = OpenSSL::SSL::SSLSocket.new tcp_socket, ssl_context
785
+ */
786
+
787
+ cX509Store = rb_define_class_under(mX509, "Store", rb_cObject);
788
+ /*
789
+ * The callback for additional certificate verification. It is invoked for
790
+ * each untrusted certificate in the chain.
791
+ *
792
+ * The callback is invoked with two values, a boolean that indicates if the
793
+ * pre-verification by OpenSSL has succeeded or not, and the StoreContext in
794
+ * use. The callback must return either true or false.
795
+ */
796
+ rb_attr(cX509Store, rb_intern("verify_callback"), 1, 0, Qfalse);
797
+ /*
798
+ * The error code set by the last call of #verify.
799
+ */
800
+ rb_attr(cX509Store, rb_intern("error"), 1, 0, Qfalse);
801
+ /*
802
+ * The description for the error code set by the last call of #verify.
803
+ */
804
+ rb_attr(cX509Store, rb_intern("error_string"), 1, 0, Qfalse);
805
+ /*
806
+ * The certificate chain constructed by the last call of #verify.
807
+ */
808
+ rb_attr(cX509Store, rb_intern("chain"), 1, 0, Qfalse);
809
+ rb_define_alloc_func(cX509Store, ossl_x509store_alloc);
810
+ rb_define_method(cX509Store, "initialize", ossl_x509store_initialize, -1);
811
+ rb_undef_method(cX509Store, "initialize_copy");
812
+ rb_define_method(cX509Store, "verify_callback=", ossl_x509store_set_vfy_cb, 1);
813
+ rb_define_method(cX509Store, "flags=", ossl_x509store_set_flags, 1);
814
+ rb_define_method(cX509Store, "purpose=", ossl_x509store_set_purpose, 1);
815
+ rb_define_method(cX509Store, "trust=", ossl_x509store_set_trust, 1);
816
+ rb_define_method(cX509Store, "time=", ossl_x509store_set_time, 1);
817
+ rb_define_method(cX509Store, "add_path", ossl_x509store_add_path, 1);
818
+ rb_define_method(cX509Store, "add_file", ossl_x509store_add_file, 1);
819
+ rb_define_method(cX509Store, "set_default_paths", ossl_x509store_set_default_paths, 0);
820
+ rb_define_method(cX509Store, "add_cert", ossl_x509store_add_cert, 1);
821
+ rb_define_method(cX509Store, "add_crl", ossl_x509store_add_crl, 1);
822
+ rb_define_method(cX509Store, "verify", ossl_x509store_verify, -1);
823
+
824
+ /*
825
+ * Document-class: OpenSSL::X509::StoreContext
826
+ *
827
+ * A StoreContext is used while validating a single certificate and holds
828
+ * the status involved.
829
+ */
830
+ cX509StoreContext = rb_define_class_under(mX509,"StoreContext", rb_cObject);
831
+ rb_define_alloc_func(cX509StoreContext, ossl_x509stctx_alloc);
832
+ rb_define_method(cX509StoreContext, "initialize", ossl_x509stctx_initialize, -1);
833
+ rb_undef_method(cX509StoreContext, "initialize_copy");
834
+ rb_define_method(cX509StoreContext, "verify", ossl_x509stctx_verify, 0);
835
+ rb_define_method(cX509StoreContext, "chain", ossl_x509stctx_get_chain,0);
836
+ rb_define_method(cX509StoreContext, "error", ossl_x509stctx_get_err, 0);
837
+ rb_define_method(cX509StoreContext, "error=", ossl_x509stctx_set_error, 1);
838
+ rb_define_method(cX509StoreContext, "error_string", ossl_x509stctx_get_err_string,0);
839
+ rb_define_method(cX509StoreContext, "error_depth", ossl_x509stctx_get_err_depth, 0);
840
+ rb_define_method(cX509StoreContext, "current_cert", ossl_x509stctx_get_curr_cert, 0);
841
+ rb_define_method(cX509StoreContext, "current_crl", ossl_x509stctx_get_curr_crl, 0);
842
+ rb_define_method(cX509StoreContext, "flags=", ossl_x509stctx_set_flags, 1);
843
+ rb_define_method(cX509StoreContext, "purpose=", ossl_x509stctx_set_purpose, 1);
844
+ rb_define_method(cX509StoreContext, "trust=", ossl_x509stctx_set_trust, 1);
845
+ rb_define_method(cX509StoreContext, "time=", ossl_x509stctx_set_time, 1);
846
+ }