rubysl-openssl 0.0.1 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +0 -1
  3. data/.travis.yml +7 -0
  4. data/README.md +2 -2
  5. data/Rakefile +0 -1
  6. data/ext/rubysl/openssl/extconf.h +50 -0
  7. data/ext/rubysl/openssl/extconf.rb +144 -0
  8. data/ext/rubysl/openssl/openssl_missing.c +343 -0
  9. data/ext/rubysl/openssl/openssl_missing.h +191 -0
  10. data/ext/rubysl/openssl/ossl.c +552 -0
  11. data/ext/rubysl/openssl/ossl.h +233 -0
  12. data/ext/rubysl/openssl/ossl_asn1.c +1160 -0
  13. data/ext/rubysl/openssl/ossl_asn1.h +59 -0
  14. data/ext/rubysl/openssl/ossl_bio.c +86 -0
  15. data/ext/rubysl/openssl/ossl_bio.h +21 -0
  16. data/ext/rubysl/openssl/ossl_bn.c +852 -0
  17. data/ext/rubysl/openssl/ossl_bn.h +25 -0
  18. data/ext/rubysl/openssl/ossl_cipher.c +569 -0
  19. data/ext/rubysl/openssl/ossl_cipher.h +22 -0
  20. data/ext/rubysl/openssl/ossl_config.c +75 -0
  21. data/ext/rubysl/openssl/ossl_config.h +22 -0
  22. data/ext/rubysl/openssl/ossl_digest.c +259 -0
  23. data/ext/rubysl/openssl/ossl_digest.h +22 -0
  24. data/ext/rubysl/openssl/ossl_engine.c +411 -0
  25. data/ext/rubysl/openssl/ossl_engine.h +20 -0
  26. data/ext/rubysl/openssl/ossl_hmac.c +268 -0
  27. data/ext/rubysl/openssl/ossl_hmac.h +19 -0
  28. data/ext/rubysl/openssl/ossl_ns_spki.c +257 -0
  29. data/ext/rubysl/openssl/ossl_ns_spki.h +21 -0
  30. data/ext/rubysl/openssl/ossl_ocsp.c +769 -0
  31. data/ext/rubysl/openssl/ossl_ocsp.h +24 -0
  32. data/ext/rubysl/openssl/ossl_pkcs12.c +210 -0
  33. data/ext/rubysl/openssl/ossl_pkcs12.h +15 -0
  34. data/ext/rubysl/openssl/ossl_pkcs5.c +99 -0
  35. data/ext/rubysl/openssl/ossl_pkcs5.h +6 -0
  36. data/ext/rubysl/openssl/ossl_pkcs7.c +1039 -0
  37. data/ext/rubysl/openssl/ossl_pkcs7.h +22 -0
  38. data/ext/rubysl/openssl/ossl_pkey.c +240 -0
  39. data/ext/rubysl/openssl/ossl_pkey.h +141 -0
  40. data/ext/rubysl/openssl/ossl_pkey_dh.c +532 -0
  41. data/ext/rubysl/openssl/ossl_pkey_dsa.c +484 -0
  42. data/ext/rubysl/openssl/ossl_pkey_ec.c +1593 -0
  43. data/ext/rubysl/openssl/ossl_pkey_rsa.c +593 -0
  44. data/ext/rubysl/openssl/ossl_rand.c +202 -0
  45. data/ext/rubysl/openssl/ossl_rand.h +20 -0
  46. data/ext/rubysl/openssl/ossl_ssl.c +1484 -0
  47. data/ext/rubysl/openssl/ossl_ssl.h +36 -0
  48. data/ext/rubysl/openssl/ossl_ssl_session.c +307 -0
  49. data/ext/rubysl/openssl/ossl_version.h +16 -0
  50. data/ext/rubysl/openssl/ossl_x509.c +104 -0
  51. data/ext/rubysl/openssl/ossl_x509.h +114 -0
  52. data/ext/rubysl/openssl/ossl_x509attr.c +274 -0
  53. data/ext/rubysl/openssl/ossl_x509cert.c +764 -0
  54. data/ext/rubysl/openssl/ossl_x509crl.c +535 -0
  55. data/ext/rubysl/openssl/ossl_x509ext.c +458 -0
  56. data/ext/rubysl/openssl/ossl_x509name.c +399 -0
  57. data/ext/rubysl/openssl/ossl_x509req.c +466 -0
  58. data/ext/rubysl/openssl/ossl_x509revoked.c +229 -0
  59. data/ext/rubysl/openssl/ossl_x509store.c +625 -0
  60. data/ext/rubysl/openssl/ruby_missing.h +41 -0
  61. data/lib/openssl.rb +1 -0
  62. data/lib/openssl/bn.rb +35 -0
  63. data/lib/openssl/buffering.rb +241 -0
  64. data/lib/openssl/cipher.rb +65 -0
  65. data/lib/openssl/config.rb +316 -0
  66. data/lib/openssl/digest.rb +61 -0
  67. data/lib/openssl/net/ftptls.rb +53 -0
  68. data/lib/openssl/net/telnets.rb +251 -0
  69. data/lib/openssl/pkcs7.rb +25 -0
  70. data/lib/openssl/ssl-internal.rb +187 -0
  71. data/lib/openssl/ssl.rb +1 -0
  72. data/lib/openssl/x509-internal.rb +153 -0
  73. data/lib/openssl/x509.rb +1 -0
  74. data/lib/rubysl/openssl.rb +28 -0
  75. data/lib/rubysl/openssl/version.rb +5 -0
  76. data/rubysl-openssl.gemspec +19 -18
  77. data/spec/cipher_spec.rb +16 -0
  78. data/spec/config/freeze_spec.rb +17 -0
  79. data/spec/hmac/digest_spec.rb +15 -0
  80. data/spec/hmac/hexdigest_spec.rb +15 -0
  81. data/spec/random/pseudo_bytes_spec.rb +5 -0
  82. data/spec/random/random_bytes_spec.rb +5 -0
  83. data/spec/random/shared/random_bytes.rb +28 -0
  84. data/spec/shared/constants.rb +11 -0
  85. data/spec/x509/name/parse_spec.rb +47 -0
  86. metadata +153 -89
  87. data/lib/rubysl-openssl.rb +0 -7
  88. data/lib/rubysl-openssl/version.rb +0 -5
@@ -0,0 +1,202 @@
1
+ /*
2
+ * $Id: ossl_rand.c 16692 2008-05-29 18:15:50Z knu $
3
+ * 'OpenSSL for Ruby' project
4
+ * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
5
+ * All rights reserved.
6
+ */
7
+ /*
8
+ * This program is licenced under the same licence as Ruby.
9
+ * (See the file 'LICENCE'.)
10
+ */
11
+ #include "ossl.h"
12
+
13
+ /*
14
+ * Classes
15
+ */
16
+ VALUE mRandom;
17
+ VALUE eRandomError;
18
+
19
+ /*
20
+ * Struct
21
+ */
22
+
23
+ /*
24
+ * Public
25
+ */
26
+
27
+ /*
28
+ * Private
29
+ */
30
+
31
+ /*
32
+ * call-seq:
33
+ * seed(str) -> str
34
+ *
35
+ */
36
+ static VALUE
37
+ ossl_rand_seed(VALUE self, VALUE str)
38
+ {
39
+ StringValue(str);
40
+ RAND_seed(RSTRING_PTR(str), RSTRING_LEN(str));
41
+
42
+ return str;
43
+ }
44
+
45
+ /*
46
+ * call-seq:
47
+ * add(str, entropy) -> self
48
+ *
49
+ */
50
+ static VALUE
51
+ ossl_rand_add(VALUE self, VALUE str, VALUE entropy)
52
+ {
53
+ StringValue(str);
54
+ RAND_add(RSTRING_PTR(str), RSTRING_LEN(str), NUM2DBL(entropy));
55
+
56
+ return self;
57
+ }
58
+
59
+ /*
60
+ * call-seq:
61
+ * load_random_file(filename) -> true
62
+ *
63
+ */
64
+ static VALUE
65
+ ossl_rand_load_file(VALUE self, VALUE filename)
66
+ {
67
+ SafeStringValue(filename);
68
+
69
+ if(!RAND_load_file(RSTRING_PTR(filename), -1)) {
70
+ ossl_raise(eRandomError, NULL);
71
+ }
72
+ return Qtrue;
73
+ }
74
+
75
+ /*
76
+ * call-seq:
77
+ * write_random_file(filename) -> true
78
+ *
79
+ */
80
+ static VALUE
81
+ ossl_rand_write_file(VALUE self, VALUE filename)
82
+ {
83
+ SafeStringValue(filename);
84
+ if (RAND_write_file(RSTRING_PTR(filename)) == -1) {
85
+ ossl_raise(eRandomError, NULL);
86
+ }
87
+ return Qtrue;
88
+ }
89
+
90
+ /*
91
+ * call-seq:
92
+ * random_bytes(length) -> aString
93
+ *
94
+ */
95
+ static VALUE
96
+ ossl_rand_bytes(VALUE self, VALUE len)
97
+ {
98
+ VALUE str;
99
+ int n = NUM2INT(len);
100
+
101
+ str = rb_str_new(0, n);
102
+ if (!RAND_bytes(RSTRING_PTR(str), n)) {
103
+ ossl_raise(eRandomError, NULL);
104
+ }
105
+
106
+ return str;
107
+ }
108
+
109
+ /*
110
+ * call-seq:
111
+ * pseudo_bytes(length) -> aString
112
+ *
113
+ */
114
+ static VALUE
115
+ ossl_rand_pseudo_bytes(VALUE self, VALUE len)
116
+ {
117
+ VALUE str;
118
+ int n = NUM2INT(len);
119
+
120
+ str = rb_str_new(0, n);
121
+ if (!RAND_pseudo_bytes(RSTRING_PTR(str), n)) {
122
+ ossl_raise(eRandomError, NULL);
123
+ }
124
+
125
+ return str;
126
+ }
127
+
128
+ /*
129
+ * call-seq:
130
+ * egd(filename) -> true
131
+ *
132
+ */
133
+ static VALUE
134
+ ossl_rand_egd(VALUE self, VALUE filename)
135
+ {
136
+ SafeStringValue(filename);
137
+
138
+ if(!RAND_egd(RSTRING_PTR(filename))) {
139
+ ossl_raise(eRandomError, NULL);
140
+ }
141
+ return Qtrue;
142
+ }
143
+
144
+ /*
145
+ * call-seq:
146
+ * egd_bytes(filename, length) -> true
147
+ *
148
+ */
149
+ static VALUE
150
+ ossl_rand_egd_bytes(VALUE self, VALUE filename, VALUE len)
151
+ {
152
+ long n = NUM2INT(len);
153
+
154
+ SafeStringValue(filename);
155
+
156
+ if (!RAND_egd_bytes(RSTRING_PTR(filename), n)) {
157
+ ossl_raise(eRandomError, NULL);
158
+ }
159
+ return Qtrue;
160
+ }
161
+
162
+ /*
163
+ * call-seq:
164
+ * status? => true | false
165
+ *
166
+ * Return true if the PRNG has been seeded with enough data, false otherwise.
167
+ */
168
+ static VALUE
169
+ ossl_rand_status(VALUE self)
170
+ {
171
+ return RAND_status() ? Qtrue : Qfalse;
172
+ }
173
+
174
+ #define DEFMETH(class, name, func, argc) \
175
+ rb_define_method(class, name, func, argc); \
176
+ rb_define_singleton_method(class, name, func, argc);
177
+
178
+ /*
179
+ * INIT
180
+ */
181
+ void
182
+ Init_ossl_rand()
183
+ {
184
+ #if 0 /* let rdoc know about mOSSL */
185
+ mOSSL = rb_define_module("OpenSSL");
186
+ #endif
187
+
188
+ mRandom = rb_define_module_under(mOSSL, "Random");
189
+
190
+ eRandomError = rb_define_class_under(mRandom, "RandomError", eOSSLError);
191
+
192
+ DEFMETH(mRandom, "seed", ossl_rand_seed, 1);
193
+ DEFMETH(mRandom, "random_add", ossl_rand_add, 2);
194
+ DEFMETH(mRandom, "load_random_file", ossl_rand_load_file, 1);
195
+ DEFMETH(mRandom, "write_random_file", ossl_rand_write_file, 1);
196
+ DEFMETH(mRandom, "random_bytes", ossl_rand_bytes, 1);
197
+ DEFMETH(mRandom, "pseudo_bytes", ossl_rand_pseudo_bytes, 1);
198
+ DEFMETH(mRandom, "egd", ossl_rand_egd, 1);
199
+ DEFMETH(mRandom, "egd_bytes", ossl_rand_egd_bytes, 2);
200
+ DEFMETH(mRandom, "status?", ossl_rand_status, 0)
201
+ }
202
+
@@ -0,0 +1,20 @@
1
+ /*
2
+ * $Id: ossl_rand.h 11708 2007-02-12 23:01:19Z shyouhei $
3
+ * 'OpenSSL for Ruby' project
4
+ * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
5
+ * All rights reserved.
6
+ */
7
+ /*
8
+ * This program is licenced under the same licence as Ruby.
9
+ * (See the file 'LICENCE'.)
10
+ */
11
+ #if !defined(_OSSL_RAND_H_)
12
+ #define _OSSL_RAND_H_
13
+
14
+ extern VALUE mRandom;
15
+ extern VALUE eRandomError;
16
+
17
+ void Init_ossl_rand(void);
18
+
19
+ #endif /* _OSSL_RAND_H_ */
20
+
@@ -0,0 +1,1484 @@
1
+ /*
2
+ * $Id: ossl_ssl.c 32234 2011-06-26 08:58:06Z shyouhei $
3
+ * 'OpenSSL for Ruby' project
4
+ * Copyright (C) 2000-2002 GOTOU Yuuzou <gotoyuzo@notwork.org>
5
+ * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
6
+ * Copyright (C) 2001-2007 Technorama Ltd. <oss-ruby@technorama.net>
7
+ * All rights reserved.
8
+ */
9
+ /*
10
+ * This program is licenced under the same licence as Ruby.
11
+ * (See the file 'LICENCE'.)
12
+ */
13
+ #include "ossl.h"
14
+ #include <rubysig.h>
15
+ #include <rubyio.h>
16
+
17
+ #if defined(HAVE_UNISTD_H)
18
+ # include <unistd.h> /* for read(), and write() */
19
+ #endif
20
+
21
+ #define numberof(ary) (sizeof(ary)/sizeof(ary[0]))
22
+
23
+ #ifdef _WIN32
24
+ # define TO_SOCKET(s) _get_osfhandle(s)
25
+ #else
26
+ # define TO_SOCKET(s) s
27
+ #endif
28
+
29
+ VALUE mSSL;
30
+ VALUE eSSLError;
31
+ VALUE cSSLContext;
32
+ VALUE cSSLSocket;
33
+
34
+ #define ossl_sslctx_set_cert(o,v) rb_iv_set((o),"@cert",(v))
35
+ #define ossl_sslctx_set_key(o,v) rb_iv_set((o),"@key",(v))
36
+ #define ossl_sslctx_set_client_ca(o,v) rb_iv_set((o),"@client_ca",(v))
37
+ #define ossl_sslctx_set_ca_file(o,v) rb_iv_set((o),"@ca_file",(v))
38
+ #define ossl_sslctx_set_ca_path(o,v) rb_iv_set((o),"@ca_path",(v))
39
+ #define ossl_sslctx_set_timeout(o,v) rb_iv_set((o),"@timeout",(v))
40
+ #define ossl_sslctx_set_verify_mode(o,v) rb_iv_set((o),"@verify_mode",(v))
41
+ #define ossl_sslctx_set_verify_dep(o,v) rb_iv_set((o),"@verify_depth",(v))
42
+ #define ossl_sslctx_set_verify_cb(o,v) rb_iv_set((o),"@verify_callback",(v))
43
+ #define ossl_sslctx_set_options(o,v) rb_iv_set((o),"@options",(v))
44
+ #define ossl_sslctx_set_cert_store(o,v) rb_iv_set((o),"@cert_store",(v))
45
+ #define ossl_sslctx_set_extra_cert(o,v) rb_iv_set((o),"@extra_chain_cert",(v))
46
+ #define ossl_sslctx_set_client_cert_cb(o,v) rb_iv_set((o),"@client_cert_cb",(v))
47
+ #define ossl_sslctx_set_tmp_dh_cb(o,v) rb_iv_set((o),"@tmp_dh_callback",(v))
48
+ #define ossl_sslctx_set_sess_id_ctx(o, v) rb_iv_get((o),"@session_id_context"(v))
49
+
50
+ #define ossl_sslctx_get_cert(o) rb_iv_get((o),"@cert")
51
+ #define ossl_sslctx_get_key(o) rb_iv_get((o),"@key")
52
+ #define ossl_sslctx_get_client_ca(o) rb_iv_get((o),"@client_ca")
53
+ #define ossl_sslctx_get_ca_file(o) rb_iv_get((o),"@ca_file")
54
+ #define ossl_sslctx_get_ca_path(o) rb_iv_get((o),"@ca_path")
55
+ #define ossl_sslctx_get_timeout(o) rb_iv_get((o),"@timeout")
56
+ #define ossl_sslctx_get_verify_mode(o) rb_iv_get((o),"@verify_mode")
57
+ #define ossl_sslctx_get_verify_dep(o) rb_iv_get((o),"@verify_depth")
58
+ #define ossl_sslctx_get_verify_cb(o) rb_iv_get((o),"@verify_callback")
59
+ #define ossl_sslctx_get_options(o) rb_iv_get((o),"@options")
60
+ #define ossl_sslctx_get_cert_store(o) rb_iv_get((o),"@cert_store")
61
+ #define ossl_sslctx_get_extra_cert(o) rb_iv_get((o),"@extra_chain_cert")
62
+ #define ossl_sslctx_get_client_cert_cb(o) rb_iv_get((o),"@client_cert_cb")
63
+ #define ossl_sslctx_get_tmp_dh_cb(o) rb_iv_get((o),"@tmp_dh_callback")
64
+ #define ossl_sslctx_get_sess_id_ctx(o) rb_iv_get((o),"@session_id_context")
65
+
66
+ static const char *ossl_sslctx_attrs[] = {
67
+ "cert", "key", "client_ca", "ca_file", "ca_path",
68
+ "timeout", "verify_mode", "verify_depth",
69
+ "verify_callback", "options", "cert_store", "extra_chain_cert",
70
+ "client_cert_cb", "tmp_dh_callback", "session_id_context",
71
+ "session_get_cb", "session_new_cb", "session_remove_cb",
72
+ };
73
+
74
+ #define ossl_ssl_get_io(o) rb_iv_get((o),"@io")
75
+ #define ossl_ssl_get_ctx(o) rb_iv_get((o),"@context")
76
+ #define ossl_ssl_get_sync_close(o) rb_iv_get((o),"@sync_close")
77
+ #define ossl_ssl_get_x509(o) rb_iv_get((o),"@x509")
78
+ #define ossl_ssl_get_key(o) rb_iv_get((o),"@key")
79
+ #define ossl_ssl_get_tmp_dh(o) rb_iv_get((o),"@tmp_dh")
80
+
81
+ #define ossl_ssl_set_io(o,v) rb_iv_set((o),"@io",(v))
82
+ #define ossl_ssl_set_ctx(o,v) rb_iv_set((o),"@context",(v))
83
+ #define ossl_ssl_set_sync_close(o,v) rb_iv_set((o),"@sync_close",(v))
84
+ #define ossl_ssl_set_x509(o,v) rb_iv_set((o),"@x509",(v))
85
+ #define ossl_ssl_set_key(o,v) rb_iv_set((o),"@key",(v))
86
+ #define ossl_ssl_set_tmp_dh(o,v) rb_iv_set((o),"@tmp_dh",(v))
87
+
88
+ static const char *ossl_ssl_attr_readers[] = { "io", "context", };
89
+ static const char *ossl_ssl_attrs[] = { "sync_close", };
90
+
91
+ ID ID_callback_state;
92
+
93
+ /*
94
+ * SSLContext class
95
+ */
96
+ struct {
97
+ const char *name;
98
+ SSL_METHOD *(*func)(void);
99
+ } ossl_ssl_method_tab[] = {
100
+ #define OSSL_SSL_METHOD_ENTRY(name) { #name, name##_method }
101
+ OSSL_SSL_METHOD_ENTRY(TLSv1),
102
+ OSSL_SSL_METHOD_ENTRY(TLSv1_server),
103
+ OSSL_SSL_METHOD_ENTRY(TLSv1_client),
104
+ #if defined(HAVE_SSLV2_METHOD) && defined(HAVE_SSLV2_SERVER_METHOD) && \
105
+ defined(HAVE_SSLV2_CLIENT_METHOD)
106
+ OSSL_SSL_METHOD_ENTRY(SSLv2),
107
+ OSSL_SSL_METHOD_ENTRY(SSLv2_server),
108
+ OSSL_SSL_METHOD_ENTRY(SSLv2_client),
109
+ #endif
110
+ OSSL_SSL_METHOD_ENTRY(SSLv3),
111
+ OSSL_SSL_METHOD_ENTRY(SSLv3_server),
112
+ OSSL_SSL_METHOD_ENTRY(SSLv3_client),
113
+ OSSL_SSL_METHOD_ENTRY(SSLv23),
114
+ OSSL_SSL_METHOD_ENTRY(SSLv23_server),
115
+ OSSL_SSL_METHOD_ENTRY(SSLv23_client),
116
+ #undef OSSL_SSL_METHOD_ENTRY
117
+ };
118
+
119
+ int ossl_ssl_ex_vcb_idx;
120
+ int ossl_ssl_ex_store_p;
121
+ int ossl_ssl_ex_ptr_idx;
122
+ int ossl_ssl_ex_client_cert_cb_idx;
123
+ int ossl_ssl_ex_tmp_dh_callback_idx;
124
+
125
+ static void
126
+ ossl_sslctx_free(SSL_CTX *ctx)
127
+ {
128
+ if(ctx && SSL_CTX_get_ex_data(ctx, ossl_ssl_ex_store_p)== (void*)1)
129
+ ctx->cert_store = NULL;
130
+ SSL_CTX_free(ctx);
131
+ }
132
+
133
+ static VALUE
134
+ ossl_sslctx_s_alloc(VALUE klass)
135
+ {
136
+ SSL_CTX *ctx;
137
+
138
+ ctx = SSL_CTX_new(SSLv23_method());
139
+ if (!ctx) {
140
+ ossl_raise(eSSLError, "SSL_CTX_new:");
141
+ }
142
+ SSL_CTX_set_mode(ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
143
+ return Data_Wrap_Struct(klass, 0, ossl_sslctx_free, ctx);
144
+ }
145
+
146
+ static VALUE
147
+ ossl_sslctx_set_ssl_version(VALUE self, VALUE ssl_method)
148
+ {
149
+ SSL_METHOD *method = NULL;
150
+ const char *s;
151
+ int i;
152
+
153
+ SSL_CTX *ctx;
154
+ if(TYPE(ssl_method) == T_SYMBOL)
155
+ s = rb_id2name(SYM2ID(ssl_method));
156
+ else
157
+ s = StringValuePtr(ssl_method);
158
+ for (i = 0; i < numberof(ossl_ssl_method_tab); i++) {
159
+ if (strcmp(ossl_ssl_method_tab[i].name, s) == 0) {
160
+ method = ossl_ssl_method_tab[i].func();
161
+ break;
162
+ }
163
+ }
164
+ if (!method) {
165
+ ossl_raise(rb_eArgError, "unknown SSL method `%s'.", s);
166
+ }
167
+ Data_Get_Struct(self, SSL_CTX, ctx);
168
+ if (SSL_CTX_set_ssl_version(ctx, method) != 1) {
169
+ ossl_raise(eSSLError, "SSL_CTX_set_ssl_version:");
170
+ }
171
+
172
+ return ssl_method;
173
+ }
174
+
175
+ /*
176
+ * call-seq:
177
+ * SSLContext.new => ctx
178
+ * SSLContext.new(:TLSv1) => ctx
179
+ * SSLContext.new("SSLv23_client") => ctx
180
+ *
181
+ * You can get a list of valid methods with OpenSSL::SSL::SSLContext::METHODS
182
+ */
183
+ static VALUE
184
+ ossl_sslctx_initialize(int argc, VALUE *argv, VALUE self)
185
+ {
186
+ VALUE ssl_method;
187
+ int i;
188
+
189
+ for(i = 0; i < numberof(ossl_sslctx_attrs); i++){
190
+ char buf[32];
191
+ snprintf(buf, sizeof(buf), "@%s", ossl_sslctx_attrs[i]);
192
+ rb_iv_set(self, buf, Qnil);
193
+ }
194
+ if (rb_scan_args(argc, argv, "01", &ssl_method) == 0){
195
+ return self;
196
+ }
197
+ ossl_sslctx_set_ssl_version(self, ssl_method);
198
+
199
+ return self;
200
+ }
201
+
202
+ static VALUE
203
+ ossl_call_client_cert_cb(VALUE obj)
204
+ {
205
+ VALUE cb, ary, cert, key;
206
+ SSL *ssl;
207
+
208
+ Data_Get_Struct(obj, SSL, ssl);
209
+ cb = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_client_cert_cb_idx);
210
+ if (NIL_P(cb)) return Qfalse;
211
+ ary = rb_funcall(cb, rb_intern("call"), 1, obj);
212
+ Check_Type(ary, T_ARRAY);
213
+ GetX509CertPtr(cert = rb_ary_entry(ary, 0));
214
+ GetPKeyPtr(key = rb_ary_entry(ary, 1));
215
+ ossl_ssl_set_x509(obj, cert);
216
+ ossl_ssl_set_key(obj, key);
217
+
218
+ return Qtrue;
219
+ }
220
+
221
+ static int
222
+ ossl_client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
223
+ {
224
+ VALUE obj;
225
+ int status, success;
226
+
227
+ obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
228
+ success = rb_protect((VALUE(*)_((VALUE)))ossl_call_client_cert_cb,
229
+ obj, &status);
230
+ if (status || !success) return 0;
231
+ *x509 = DupX509CertPtr(ossl_ssl_get_x509(obj));
232
+ *pkey = DupPKeyPtr(ossl_ssl_get_key(obj));
233
+
234
+ return 1;
235
+ }
236
+
237
+ #if !defined(OPENSSL_NO_DH)
238
+ static VALUE
239
+ ossl_call_tmp_dh_callback(VALUE *args)
240
+ {
241
+ SSL *ssl;
242
+ VALUE cb, dh;
243
+ EVP_PKEY *pkey;
244
+
245
+ Data_Get_Struct(args[0], SSL, ssl);
246
+ cb = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_tmp_dh_callback_idx);
247
+ if (NIL_P(cb)) return Qfalse;
248
+ dh = rb_funcall(cb, rb_intern("call"), 3, args[0], args[1], args[2]);
249
+ pkey = GetPKeyPtr(dh);
250
+ if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DH) return Qfalse;
251
+ ossl_ssl_set_tmp_dh(args[0], dh);
252
+
253
+ return Qtrue;
254
+ }
255
+
256
+ static DH*
257
+ ossl_tmp_dh_callback(SSL *ssl, int is_export, int keylength)
258
+ {
259
+ VALUE args[3];
260
+ int status, success;
261
+
262
+ args[0] = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
263
+ args[1] = INT2FIX(is_export);
264
+ args[2] = INT2FIX(keylength);
265
+ success = rb_protect((VALUE(*)_((VALUE)))ossl_call_tmp_dh_callback,
266
+ (VALUE)args, &status);
267
+ if (status || !success) return NULL;
268
+
269
+ return GetPKeyPtr(ossl_ssl_get_tmp_dh(args[0]))->pkey.dh;
270
+ }
271
+
272
+ static DH*
273
+ ossl_default_tmp_dh_callback(SSL *ssl, int is_export, int keylength)
274
+ {
275
+ rb_warning("using default DH parameters.");
276
+
277
+ switch(keylength){
278
+ case 512:
279
+ return OSSL_DEFAULT_DH_512;
280
+ case 1024:
281
+ return OSSL_DEFAULT_DH_1024;
282
+ }
283
+ return NULL;
284
+ }
285
+ #endif /* OPENSSL_NO_DH */
286
+
287
+ static int
288
+ ossl_ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
289
+ {
290
+ VALUE cb;
291
+ SSL *ssl;
292
+
293
+ ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
294
+ cb = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_vcb_idx);
295
+ X509_STORE_CTX_set_ex_data(ctx, ossl_verify_cb_idx, (void*)cb);
296
+ return ossl_verify_cb(preverify_ok, ctx);
297
+ }
298
+
299
+ static VALUE
300
+ ossl_call_session_get_cb(VALUE ary)
301
+ {
302
+ VALUE ssl_obj, sslctx_obj, cb, ret;
303
+
304
+ Check_Type(ary, T_ARRAY);
305
+ ssl_obj = rb_ary_entry(ary, 0);
306
+
307
+ sslctx_obj = rb_iv_get(ssl_obj, "@context");
308
+ if (NIL_P(sslctx_obj)) return Qnil;
309
+ cb = rb_iv_get(sslctx_obj, "@session_get_cb");
310
+ if (NIL_P(cb)) return Qnil;
311
+
312
+ return rb_funcall(cb, rb_intern("call"), 1, ary);
313
+ }
314
+
315
+ /* this method is currently only called for servers (in OpenSSL <= 0.9.8e) */
316
+ static SSL_SESSION *
317
+ ossl_sslctx_session_get_cb(SSL *ssl, unsigned char *buf, int len, int *copy)
318
+ {
319
+ VALUE ary, ssl_obj, ret_obj;
320
+ SSL_SESSION *sess;
321
+ void *ptr;
322
+ int state = 0;
323
+
324
+ OSSL_Debug("SSL SESSION get callback entered");
325
+ if ((ptr = SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx)) == NULL)
326
+ return NULL;
327
+ ssl_obj = (VALUE)ptr;
328
+ ary = rb_ary_new2(2);
329
+ rb_ary_push(ary, ssl_obj);
330
+ rb_ary_push(ary, rb_str_new(buf, len));
331
+
332
+ ret_obj = rb_protect((VALUE(*)_((VALUE)))ossl_call_session_get_cb, ary, &state);
333
+ if (state) {
334
+ rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(state));
335
+ return NULL;
336
+ }
337
+ if (!rb_obj_is_instance_of(ret_obj, cSSLSession))
338
+ return NULL;
339
+
340
+ SafeGetSSLSession(ret_obj, sess);
341
+ *copy = 1;
342
+
343
+ return sess;
344
+ }
345
+
346
+ static VALUE
347
+ ossl_call_session_new_cb(VALUE ary)
348
+ {
349
+ VALUE ssl_obj, sslctx_obj, cb, ret;
350
+
351
+ Check_Type(ary, T_ARRAY);
352
+ ssl_obj = rb_ary_entry(ary, 0);
353
+
354
+ sslctx_obj = rb_iv_get(ssl_obj, "@context");
355
+ if (NIL_P(sslctx_obj)) return Qnil;
356
+ cb = rb_iv_get(sslctx_obj, "@session_new_cb");
357
+ if (NIL_P(cb)) return Qnil;
358
+
359
+ return rb_funcall(cb, rb_intern("call"), 1, ary);
360
+ }
361
+
362
+ /* return 1 normal. return 0 removes the session */
363
+ static int
364
+ ossl_sslctx_session_new_cb(SSL *ssl, SSL_SESSION *sess)
365
+ {
366
+ VALUE ary, ssl_obj, sess_obj, ret_obj;
367
+ void *ptr;
368
+ int state = 0;
369
+
370
+ OSSL_Debug("SSL SESSION new callback entered");
371
+
372
+ if ((ptr = SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx)) == NULL)
373
+ return 1;
374
+ ssl_obj = (VALUE)ptr;
375
+ sess_obj = rb_obj_alloc(cSSLSession);
376
+ CRYPTO_add(&sess->references, 1, CRYPTO_LOCK_SSL_SESSION);
377
+ DATA_PTR(sess_obj) = sess;
378
+
379
+ ary = rb_ary_new2(2);
380
+ rb_ary_push(ary, ssl_obj);
381
+ rb_ary_push(ary, sess_obj);
382
+
383
+ ret_obj = rb_protect((VALUE(*)_((VALUE)))ossl_call_session_new_cb, ary, &state);
384
+ if (state) {
385
+ rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(state));
386
+ return 0; /* what should be returned here??? */
387
+ }
388
+
389
+ return RTEST(ret_obj) ? 1 : 0;
390
+ }
391
+
392
+ static VALUE
393
+ ossl_call_session_remove_cb(VALUE ary)
394
+ {
395
+ VALUE sslctx_obj, cb, ret;
396
+
397
+ Check_Type(ary, T_ARRAY);
398
+ sslctx_obj = rb_ary_entry(ary, 0);
399
+
400
+ cb = rb_iv_get(sslctx_obj, "@session_remove_cb");
401
+ if (NIL_P(cb)) return Qnil;
402
+
403
+ return rb_funcall(cb, rb_intern("call"), 1, ary);
404
+ }
405
+
406
+ static void
407
+ ossl_sslctx_session_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
408
+ {
409
+ VALUE ary, sslctx_obj, sess_obj, ret_obj;
410
+ void *ptr;
411
+ int state = 0;
412
+
413
+ OSSL_Debug("SSL SESSION remove callback entered");
414
+
415
+ if ((ptr = SSL_CTX_get_ex_data(ctx, ossl_ssl_ex_ptr_idx)) == NULL)
416
+ return;
417
+ sslctx_obj = (VALUE)ptr;
418
+ sess_obj = rb_obj_alloc(cSSLSession);
419
+ CRYPTO_add(&sess->references, 1, CRYPTO_LOCK_SSL_SESSION);
420
+ DATA_PTR(sess_obj) = sess;
421
+
422
+ ary = rb_ary_new2(2);
423
+ rb_ary_push(ary, sslctx_obj);
424
+ rb_ary_push(ary, sess_obj);
425
+
426
+ ret_obj = rb_protect((VALUE(*)_((VALUE)))ossl_call_session_new_cb, ary, &state);
427
+ if (state) {
428
+ /*
429
+ the SSL_CTX is frozen, nowhere to save state.
430
+ there is no common accessor method to check it either.
431
+ rb_ivar_set(sslctx_obj, ID_callback_state, INT2NUM(state));
432
+ */
433
+ }
434
+ }
435
+
436
+ static VALUE
437
+ ossl_sslctx_add_extra_chain_cert_i(VALUE i, VALUE arg)
438
+ {
439
+ X509 *x509;
440
+ SSL_CTX *ctx;
441
+
442
+ Data_Get_Struct(arg, SSL_CTX, ctx);
443
+ x509 = DupX509CertPtr(i);
444
+ if(!SSL_CTX_add_extra_chain_cert(ctx, x509)){
445
+ ossl_raise(eSSLError, NULL);
446
+ }
447
+
448
+ return i;
449
+ }
450
+
451
+ /*
452
+ * call-seq:
453
+ * ctx.setup => Qtrue # first time
454
+ * ctx.setup => nil # thereafter
455
+ *
456
+ * This method is called automatically when a new SSLSocket is created.
457
+ * Normally you do not need to call this method (unless you are writing an extension in C).
458
+ */
459
+ static VALUE
460
+ ossl_sslctx_setup(VALUE self)
461
+ {
462
+ SSL_CTX *ctx;
463
+ X509 *cert = NULL, *client_ca = NULL;
464
+ X509_STORE *store;
465
+ EVP_PKEY *key = NULL;
466
+ char *ca_path = NULL, *ca_file = NULL;
467
+ int i, verify_mode;
468
+ VALUE val;
469
+
470
+ if(OBJ_FROZEN(self)) return Qnil;
471
+ Data_Get_Struct(self, SSL_CTX, ctx);
472
+
473
+ #if !defined(OPENSSL_NO_DH)
474
+ if (RTEST(ossl_sslctx_get_tmp_dh_cb(self))){
475
+ SSL_CTX_set_tmp_dh_callback(ctx, ossl_tmp_dh_callback);
476
+ }
477
+ else{
478
+ SSL_CTX_set_tmp_dh_callback(ctx, ossl_default_tmp_dh_callback);
479
+ }
480
+ #endif
481
+ SSL_CTX_set_ex_data(ctx, ossl_ssl_ex_ptr_idx, (void*)self);
482
+
483
+ val = ossl_sslctx_get_cert_store(self);
484
+ if(!NIL_P(val)){
485
+ /*
486
+ * WORKAROUND:
487
+ * X509_STORE can count references, but
488
+ * X509_STORE_free() doesn't care it.
489
+ * So we won't increment it but mark it by ex_data.
490
+ */
491
+ store = GetX509StorePtr(val); /* NO NEED TO DUP */
492
+ SSL_CTX_set_cert_store(ctx, store);
493
+ SSL_CTX_set_ex_data(ctx, ossl_ssl_ex_store_p, (void*)1);
494
+ }
495
+
496
+ val = ossl_sslctx_get_extra_cert(self);
497
+ if(!NIL_P(val)){
498
+ rb_block_call(val, rb_intern("each"), 0, 0, ossl_sslctx_add_extra_chain_cert_i, self);
499
+ }
500
+
501
+ /* private key may be bundled in certificate file. */
502
+ val = ossl_sslctx_get_cert(self);
503
+ cert = NIL_P(val) ? NULL : GetX509CertPtr(val); /* NO DUP NEEDED */
504
+ val = ossl_sslctx_get_key(self);
505
+ key = NIL_P(val) ? NULL : GetPKeyPtr(val); /* NO DUP NEEDED */
506
+ if (cert && key) {
507
+ if (!SSL_CTX_use_certificate(ctx, cert)) {
508
+ /* Adds a ref => Safe to FREE */
509
+ ossl_raise(eSSLError, "SSL_CTX_use_certificate:");
510
+ }
511
+ if (!SSL_CTX_use_PrivateKey(ctx, key)) {
512
+ /* Adds a ref => Safe to FREE */
513
+ ossl_raise(eSSLError, "SSL_CTX_use_PrivateKey:");
514
+ }
515
+ if (!SSL_CTX_check_private_key(ctx)) {
516
+ ossl_raise(eSSLError, "SSL_CTX_check_private_key:");
517
+ }
518
+ }
519
+
520
+ val = ossl_sslctx_get_client_ca(self);
521
+ if(!NIL_P(val)){
522
+ if(TYPE(val) == T_ARRAY){
523
+ for(i = 0; i < RARRAY_LEN(val); i++){
524
+ client_ca = GetX509CertPtr(rb_ary_entry(val, i));
525
+ if (!SSL_CTX_add_client_CA(ctx, client_ca)){
526
+ /* Copies X509_NAME => FREE it. */
527
+ ossl_raise(eSSLError, "SSL_CTX_add_client_CA");
528
+ }
529
+ }
530
+ }
531
+ else{
532
+ client_ca = GetX509CertPtr(val); /* NO DUP NEEDED. */
533
+ if (!SSL_CTX_add_client_CA(ctx, client_ca)){
534
+ /* Copies X509_NAME => FREE it. */
535
+ ossl_raise(eSSLError, "SSL_CTX_add_client_CA");
536
+ }
537
+ }
538
+ }
539
+
540
+ val = ossl_sslctx_get_ca_file(self);
541
+ ca_file = NIL_P(val) ? NULL : StringValuePtr(val);
542
+ val = ossl_sslctx_get_ca_path(self);
543
+ ca_path = NIL_P(val) ? NULL : StringValuePtr(val);
544
+ if(ca_file || ca_path){
545
+ if (!SSL_CTX_load_verify_locations(ctx, ca_file, ca_path))
546
+ rb_warning("can't set verify locations");
547
+ }
548
+
549
+ val = ossl_sslctx_get_verify_mode(self);
550
+ verify_mode = NIL_P(val) ? SSL_VERIFY_NONE : NUM2INT(val);
551
+ SSL_CTX_set_verify(ctx, verify_mode, ossl_ssl_verify_callback);
552
+ if (RTEST(ossl_sslctx_get_client_cert_cb(self)))
553
+ SSL_CTX_set_client_cert_cb(ctx, ossl_client_cert_cb);
554
+
555
+ val = ossl_sslctx_get_timeout(self);
556
+ if(!NIL_P(val)) SSL_CTX_set_timeout(ctx, NUM2LONG(val));
557
+
558
+ val = ossl_sslctx_get_verify_dep(self);
559
+ if(!NIL_P(val)) SSL_CTX_set_verify_depth(ctx, NUM2LONG(val));
560
+
561
+ val = ossl_sslctx_get_options(self);
562
+ if(!NIL_P(val)) {
563
+ SSL_CTX_set_options(ctx, NUM2LONG(val));
564
+ } else {
565
+ SSL_CTX_set_options(ctx, SSL_OP_ALL);
566
+ }
567
+ rb_obj_freeze(self);
568
+
569
+ val = ossl_sslctx_get_sess_id_ctx(self);
570
+ if (!NIL_P(val)){
571
+ StringValue(val);
572
+ if (!SSL_CTX_set_session_id_context(ctx, RSTRING_PTR(val),
573
+ RSTRING_LEN(val))){
574
+ ossl_raise(eSSLError, "SSL_CTX_set_session_id_context:");
575
+ }
576
+ }
577
+
578
+ if (RTEST(rb_iv_get(self, "@session_get_cb"))) {
579
+ SSL_CTX_sess_set_get_cb(ctx, ossl_sslctx_session_get_cb);
580
+ OSSL_Debug("SSL SESSION get callback added");
581
+ }
582
+ if (RTEST(rb_iv_get(self, "@session_new_cb"))) {
583
+ SSL_CTX_sess_set_new_cb(ctx, ossl_sslctx_session_new_cb);
584
+ OSSL_Debug("SSL SESSION new callback added");
585
+ }
586
+ if (RTEST(rb_iv_get(self, "@session_remove_cb"))) {
587
+ SSL_CTX_sess_set_remove_cb(ctx, ossl_sslctx_session_remove_cb);
588
+ OSSL_Debug("SSL SESSION remove callback added");
589
+ }
590
+ return Qtrue;
591
+ }
592
+
593
+ static VALUE
594
+ ossl_ssl_cipher_to_ary(SSL_CIPHER *cipher)
595
+ {
596
+ VALUE ary;
597
+ int bits, alg_bits;
598
+
599
+ ary = rb_ary_new2(4);
600
+ rb_ary_push(ary, rb_str_new2(SSL_CIPHER_get_name(cipher)));
601
+ rb_ary_push(ary, rb_str_new2(SSL_CIPHER_get_version(cipher)));
602
+ bits = SSL_CIPHER_get_bits(cipher, &alg_bits);
603
+ rb_ary_push(ary, INT2FIX(bits));
604
+ rb_ary_push(ary, INT2FIX(alg_bits));
605
+
606
+ return ary;
607
+ }
608
+
609
+ /*
610
+ * call-seq:
611
+ * ctx.ciphers => [[name, version, bits, alg_bits], ...]
612
+ */
613
+ static VALUE
614
+ ossl_sslctx_get_ciphers(VALUE self)
615
+ {
616
+ SSL_CTX *ctx;
617
+ STACK_OF(SSL_CIPHER) *ciphers;
618
+ SSL_CIPHER *cipher;
619
+ VALUE ary;
620
+ int i, num;
621
+
622
+ Data_Get_Struct(self, SSL_CTX, ctx);
623
+ if(!ctx){
624
+ rb_warning("SSL_CTX is not initialized.");
625
+ return Qnil;
626
+ }
627
+ ciphers = ctx->cipher_list;
628
+
629
+ if (!ciphers)
630
+ return rb_ary_new();
631
+
632
+ num = sk_num((STACK*)ciphers);
633
+ ary = rb_ary_new2(num);
634
+ for(i = 0; i < num; i++){
635
+ cipher = (SSL_CIPHER*)sk_value((STACK*)ciphers, i);
636
+ rb_ary_push(ary, ossl_ssl_cipher_to_ary(cipher));
637
+ }
638
+ return ary;
639
+ }
640
+
641
+ /*
642
+ * call-seq:
643
+ * ctx.ciphers = "cipher1:cipher2:..."
644
+ * ctx.ciphers = [name, ...]
645
+ * ctx.ciphers = [[name, version, bits, alg_bits], ...]
646
+ */
647
+ static VALUE
648
+ ossl_sslctx_set_ciphers(VALUE self, VALUE v)
649
+ {
650
+ SSL_CTX *ctx;
651
+ VALUE str, elem;
652
+ int i;
653
+
654
+ rb_check_frozen(self);
655
+ if (NIL_P(v))
656
+ return v;
657
+ else if (TYPE(v) == T_ARRAY) {
658
+ str = rb_str_new(0, 0);
659
+ for (i = 0; i < RARRAY_LEN(v); i++) {
660
+ elem = rb_ary_entry(v, i);
661
+ if (TYPE(elem) == T_ARRAY) elem = rb_ary_entry(elem, 0);
662
+ elem = rb_String(elem);
663
+ rb_str_append(str, elem);
664
+ if (i < RARRAY_LEN(v)-1) rb_str_cat2(str, ":");
665
+ }
666
+ } else {
667
+ str = v;
668
+ StringValue(str);
669
+ }
670
+
671
+ Data_Get_Struct(self, SSL_CTX, ctx);
672
+ if(!ctx){
673
+ ossl_raise(eSSLError, "SSL_CTX is not initialized.");
674
+ return Qnil;
675
+ }
676
+ if (!SSL_CTX_set_cipher_list(ctx, RSTRING_PTR(str))) {
677
+ ossl_raise(eSSLError, "SSL_CTX_set_cipher_list:");
678
+ }
679
+
680
+ return v;
681
+ }
682
+
683
+
684
+ /*
685
+ * call-seq:
686
+ * ctx.session_add(session) -> true | false
687
+ *
688
+ */
689
+ static VALUE
690
+ ossl_sslctx_session_add(VALUE self, VALUE arg)
691
+ {
692
+ SSL_CTX *ctx;
693
+ SSL_SESSION *sess;
694
+
695
+ Data_Get_Struct(self, SSL_CTX, ctx);
696
+ SafeGetSSLSession(arg, sess);
697
+
698
+ return SSL_CTX_add_session(ctx, sess) == 1 ? Qtrue : Qfalse;
699
+ }
700
+
701
+ /*
702
+ * call-seq:
703
+ * ctx.session_remove(session) -> true | false
704
+ *
705
+ */
706
+ static VALUE
707
+ ossl_sslctx_session_remove(VALUE self, VALUE arg)
708
+ {
709
+ SSL_CTX *ctx;
710
+ SSL_SESSION *sess;
711
+
712
+ Data_Get_Struct(self, SSL_CTX, ctx);
713
+ SafeGetSSLSession(arg, sess);
714
+
715
+ return SSL_CTX_remove_session(ctx, sess) == 1 ? Qtrue : Qfalse;
716
+ }
717
+
718
+ /*
719
+ * call-seq:
720
+ * ctx.session_cache_mode -> integer
721
+ *
722
+ */
723
+ static VALUE
724
+ ossl_sslctx_get_session_cache_mode(VALUE self)
725
+ {
726
+ SSL_CTX *ctx;
727
+
728
+ Data_Get_Struct(self, SSL_CTX, ctx);
729
+
730
+ return LONG2NUM(SSL_CTX_get_session_cache_mode(ctx));
731
+ }
732
+
733
+ /*
734
+ * call-seq:
735
+ * ctx.session_cache_mode=(integer) -> integer
736
+ *
737
+ */
738
+ static VALUE
739
+ ossl_sslctx_set_session_cache_mode(VALUE self, VALUE arg)
740
+ {
741
+ SSL_CTX *ctx;
742
+
743
+ Data_Get_Struct(self, SSL_CTX, ctx);
744
+
745
+ SSL_CTX_set_session_cache_mode(ctx, NUM2LONG(arg));
746
+
747
+ return arg;
748
+ }
749
+
750
+ /*
751
+ * call-seq:
752
+ * ctx.session_cache_size -> integer
753
+ *
754
+ */
755
+ static VALUE
756
+ ossl_sslctx_get_session_cache_size(VALUE self)
757
+ {
758
+ SSL_CTX *ctx;
759
+
760
+ Data_Get_Struct(self, SSL_CTX, ctx);
761
+
762
+ return LONG2NUM(SSL_CTX_sess_get_cache_size(ctx));
763
+ }
764
+
765
+ /*
766
+ * call-seq:
767
+ * ctx.session_cache_size=(integer) -> integer
768
+ *
769
+ */
770
+ static VALUE
771
+ ossl_sslctx_set_session_cache_size(VALUE self, VALUE arg)
772
+ {
773
+ SSL_CTX *ctx;
774
+
775
+ Data_Get_Struct(self, SSL_CTX, ctx);
776
+
777
+ SSL_CTX_sess_set_cache_size(ctx, NUM2LONG(arg));
778
+
779
+ return arg;
780
+ }
781
+
782
+ /*
783
+ * call-seq:
784
+ * ctx.session_cache_stats -> Hash
785
+ *
786
+ */
787
+ static VALUE
788
+ ossl_sslctx_get_session_cache_stats(VALUE self)
789
+ {
790
+ SSL_CTX *ctx;
791
+ VALUE hash;
792
+
793
+ Data_Get_Struct(self, SSL_CTX, ctx);
794
+
795
+ hash = rb_hash_new();
796
+ rb_hash_aset(hash, ID2SYM(rb_intern("cache_num")), LONG2NUM(SSL_CTX_sess_number(ctx)));
797
+ rb_hash_aset(hash, ID2SYM(rb_intern("connect")), LONG2NUM(SSL_CTX_sess_connect(ctx)));
798
+ rb_hash_aset(hash, ID2SYM(rb_intern("connect_good")), LONG2NUM(SSL_CTX_sess_connect_good(ctx)));
799
+ rb_hash_aset(hash, ID2SYM(rb_intern("connect_renegotiate")), LONG2NUM(SSL_CTX_sess_connect_renegotiate(ctx)));
800
+ rb_hash_aset(hash, ID2SYM(rb_intern("accept")), LONG2NUM(SSL_CTX_sess_accept(ctx)));
801
+ rb_hash_aset(hash, ID2SYM(rb_intern("accept_good")), LONG2NUM(SSL_CTX_sess_accept_good(ctx)));
802
+ rb_hash_aset(hash, ID2SYM(rb_intern("accept_renegotiate")), LONG2NUM(SSL_CTX_sess_accept_renegotiate(ctx)));
803
+ rb_hash_aset(hash, ID2SYM(rb_intern("cache_hits")), LONG2NUM(SSL_CTX_sess_hits(ctx)));
804
+ rb_hash_aset(hash, ID2SYM(rb_intern("cb_hits")), LONG2NUM(SSL_CTX_sess_cb_hits(ctx)));
805
+ rb_hash_aset(hash, ID2SYM(rb_intern("cache_misses")), LONG2NUM(SSL_CTX_sess_misses(ctx)));
806
+ rb_hash_aset(hash, ID2SYM(rb_intern("cache_full")), LONG2NUM(SSL_CTX_sess_cache_full(ctx)));
807
+ rb_hash_aset(hash, ID2SYM(rb_intern("timeouts")), LONG2NUM(SSL_CTX_sess_timeouts(ctx)));
808
+
809
+ return hash;
810
+ }
811
+
812
+
813
+ /*
814
+ * call-seq:
815
+ * ctx.flush_sessions(time | nil) -> self
816
+ *
817
+ */
818
+ static VALUE
819
+ ossl_sslctx_flush_sessions(int argc, VALUE *argv, VALUE self)
820
+ {
821
+ VALUE arg1;
822
+ SSL_CTX *ctx;
823
+ time_t tm = 0;
824
+ int cb_state;
825
+
826
+ rb_scan_args(argc, argv, "01", &arg1);
827
+
828
+ Data_Get_Struct(self, SSL_CTX, ctx);
829
+
830
+ if (NIL_P(arg1)) {
831
+ tm = time(0);
832
+ } else if (rb_obj_is_instance_of(arg1, rb_cTime)) {
833
+ tm = NUM2LONG(rb_funcall(arg1, rb_intern("to_i"), 0));
834
+ } else {
835
+ rb_raise(rb_eArgError, "arg must be Time or nil");
836
+ }
837
+
838
+ SSL_CTX_flush_sessions(ctx, (long)tm);
839
+
840
+ return self;
841
+ }
842
+
843
+ /*
844
+ * SSLSocket class
845
+ */
846
+ static void
847
+ ossl_ssl_shutdown(SSL *ssl)
848
+ {
849
+ if (ssl) {
850
+ SSL_shutdown(ssl);
851
+ SSL_clear(ssl);
852
+ }
853
+ }
854
+
855
+ static void
856
+ ossl_ssl_free(SSL *ssl)
857
+ {
858
+ ossl_ssl_shutdown(ssl);
859
+ SSL_free(ssl);
860
+ }
861
+
862
+ static VALUE
863
+ ossl_ssl_s_alloc(VALUE klass)
864
+ {
865
+ return Data_Wrap_Struct(klass, 0, ossl_ssl_free, NULL);
866
+ }
867
+
868
+ /*
869
+ * call-seq:
870
+ * SSLSocket.new(io) => aSSLSocket
871
+ * SSLSocket.new(io, ctx) => aSSLSocket
872
+ *
873
+ * === Parameters
874
+ * * +io+ is a real ruby IO object. Not an IO like object that responds to read/write.
875
+ * * +ctx+ is an OpenSSLSSL::SSLContext.
876
+ *
877
+ * The OpenSSL::Buffering module provides additional IO methods.
878
+ *
879
+ * This method will freeze the SSLContext if one is provided;
880
+ * however, session management is still allowed in the frozen SSLContext.
881
+ */
882
+ static VALUE
883
+ ossl_ssl_initialize(int argc, VALUE *argv, VALUE self)
884
+ {
885
+ VALUE io, ctx;
886
+
887
+ if (rb_scan_args(argc, argv, "11", &io, &ctx) == 1) {
888
+ ctx = rb_funcall(cSSLContext, rb_intern("new"), 0);
889
+ }
890
+ OSSL_Check_Kind(ctx, cSSLContext);
891
+ Check_Type(io, T_FILE);
892
+ ossl_ssl_set_io(self, io);
893
+ ossl_ssl_set_ctx(self, ctx);
894
+ ossl_ssl_set_sync_close(self, Qfalse);
895
+ ossl_sslctx_setup(ctx);
896
+ rb_call_super(0, 0);
897
+
898
+ return self;
899
+ }
900
+
901
+ static VALUE
902
+ ossl_ssl_setup(VALUE self)
903
+ {
904
+ VALUE io, v_ctx, cb;
905
+ SSL_CTX *ctx;
906
+ SSL *ssl;
907
+ rb_io_t *fptr;
908
+
909
+ Data_Get_Struct(self, SSL, ssl);
910
+ if(!ssl){
911
+ v_ctx = ossl_ssl_get_ctx(self);
912
+ Data_Get_Struct(v_ctx, SSL_CTX, ctx);
913
+
914
+ ssl = SSL_new(ctx);
915
+ if (!ssl) {
916
+ ossl_raise(eSSLError, "SSL_new:");
917
+ }
918
+ DATA_PTR(self) = ssl;
919
+
920
+ io = ossl_ssl_get_io(self);
921
+ GetOpenFile(io, fptr);
922
+ rb_io_check_readable(fptr);
923
+ rb_io_check_writable(fptr);
924
+ SSL_set_fd(ssl, TO_SOCKET(FPTR_TO_FD(fptr)));
925
+ SSL_set_ex_data(ssl, ossl_ssl_ex_ptr_idx, (void*)self);
926
+ cb = ossl_sslctx_get_verify_cb(v_ctx);
927
+ SSL_set_ex_data(ssl, ossl_ssl_ex_vcb_idx, (void*)cb);
928
+ cb = ossl_sslctx_get_client_cert_cb(v_ctx);
929
+ SSL_set_ex_data(ssl, ossl_ssl_ex_client_cert_cb_idx, (void*)cb);
930
+ cb = ossl_sslctx_get_tmp_dh_cb(v_ctx);
931
+ SSL_set_ex_data(ssl, ossl_ssl_ex_tmp_dh_callback_idx, (void*)cb);
932
+ }
933
+
934
+ return Qtrue;
935
+ }
936
+
937
+ #ifdef _WIN32
938
+ #define ssl_get_error(ssl, ret) (errno = WSAGetLastError(), SSL_get_error(ssl, ret))
939
+ #else
940
+ #define ssl_get_error(ssl, ret) SSL_get_error(ssl, ret)
941
+ #endif
942
+
943
+ static VALUE
944
+ ossl_start_ssl(VALUE self, int (*func)(), const char *funcname)
945
+ {
946
+ SSL *ssl;
947
+ rb_io_t *fptr;
948
+ int ret, ret2;
949
+ VALUE cb_state;
950
+
951
+ rb_ivar_set(self, ID_callback_state, Qnil);
952
+
953
+ Data_Get_Struct(self, SSL, ssl);
954
+ GetOpenFile(ossl_ssl_get_io(self), fptr);
955
+ for(;;){
956
+ if((ret = func(ssl)) > 0) break;
957
+ switch((ret2 = ssl_get_error(ssl, ret))){
958
+ case SSL_ERROR_WANT_WRITE:
959
+ rb_io_wait_writable(FPTR_TO_FD(fptr));
960
+ continue;
961
+ case SSL_ERROR_WANT_READ:
962
+ rb_io_wait_readable(FPTR_TO_FD(fptr));
963
+ continue;
964
+ case SSL_ERROR_SYSCALL:
965
+ if (errno) rb_sys_fail(funcname);
966
+ ossl_raise(eSSLError, "%s SYSCALL returned=%d errno=%d state=%s", funcname, ret2, errno, SSL_state_string_long(ssl));
967
+ default:
968
+ ossl_raise(eSSLError, "%s returned=%d errno=%d state=%s", funcname, ret2, errno, SSL_state_string_long(ssl));
969
+ }
970
+ }
971
+
972
+ cb_state = rb_ivar_get(self, ID_callback_state);
973
+ if (!NIL_P(cb_state))
974
+ rb_jump_tag(NUM2INT(cb_state));
975
+
976
+ return self;
977
+ }
978
+
979
+ /*
980
+ * call-seq:
981
+ * ssl.connect => self
982
+ */
983
+ static VALUE
984
+ ossl_ssl_connect(VALUE self)
985
+ {
986
+ ossl_ssl_setup(self);
987
+ return ossl_start_ssl(self, SSL_connect, "SSL_connect");
988
+ }
989
+
990
+ /*
991
+ * call-seq:
992
+ * ssl.accept => self
993
+ */
994
+ static VALUE
995
+ ossl_ssl_accept(VALUE self)
996
+ {
997
+ ossl_ssl_setup(self);
998
+ return ossl_start_ssl(self, SSL_accept, "SSL_accept");
999
+ }
1000
+
1001
+ /*
1002
+ * call-seq:
1003
+ * ssl.sysread(length) => string
1004
+ * ssl.sysread(length, buffer) => buffer
1005
+ *
1006
+ * === Parameters
1007
+ * * +length+ is a positive integer.
1008
+ * * +buffer+ is a string used to store the result.
1009
+ */
1010
+ static VALUE
1011
+ ossl_ssl_read(int argc, VALUE *argv, VALUE self)
1012
+ {
1013
+ SSL *ssl;
1014
+ int ilen, nread = 0;
1015
+ VALUE len, str;
1016
+ rb_io_t *fptr;
1017
+
1018
+ rb_scan_args(argc, argv, "11", &len, &str);
1019
+ ilen = NUM2INT(len);
1020
+ if(NIL_P(str)) str = rb_str_new(0, ilen);
1021
+ else{
1022
+ StringValue(str);
1023
+ rb_str_modify(str);
1024
+ rb_str_resize(str, ilen);
1025
+ }
1026
+ if(ilen == 0) return str;
1027
+
1028
+ Data_Get_Struct(self, SSL, ssl);
1029
+ GetOpenFile(ossl_ssl_get_io(self), fptr);
1030
+ if (ssl) {
1031
+ if(SSL_pending(ssl) <= 0)
1032
+ rb_thread_wait_fd(FPTR_TO_FD(fptr));
1033
+ for (;;){
1034
+ nread = SSL_read(ssl, RSTRING_PTR(str), RSTRING_LEN(str));
1035
+ switch(ssl_get_error(ssl, nread)){
1036
+ case SSL_ERROR_NONE:
1037
+ goto end;
1038
+ case SSL_ERROR_ZERO_RETURN:
1039
+ rb_eof_error();
1040
+ case SSL_ERROR_WANT_WRITE:
1041
+ rb_io_wait_writable(FPTR_TO_FD(fptr));
1042
+ continue;
1043
+ case SSL_ERROR_WANT_READ:
1044
+ rb_io_wait_readable(FPTR_TO_FD(fptr));
1045
+ continue;
1046
+ case SSL_ERROR_SYSCALL:
1047
+ if(ERR_peek_error() == 0 && nread == 0) rb_eof_error();
1048
+ rb_sys_fail(0);
1049
+ default:
1050
+ ossl_raise(eSSLError, "SSL_read:");
1051
+ }
1052
+ }
1053
+ }
1054
+ else {
1055
+ ID id_sysread = rb_intern("sysread");
1056
+ rb_warning("SSL session is not started yet.");
1057
+ return rb_funcall(ossl_ssl_get_io(self), id_sysread, 2, len, str);
1058
+ }
1059
+
1060
+ end:
1061
+ rb_str_set_len(str, nread);
1062
+ OBJ_TAINT(str);
1063
+
1064
+ return str;
1065
+ }
1066
+
1067
+ /*
1068
+ * call-seq:
1069
+ * ssl.syswrite(string) => integer
1070
+ */
1071
+ static VALUE
1072
+ ossl_ssl_write(VALUE self, VALUE str)
1073
+ {
1074
+ SSL *ssl;
1075
+ int nwrite = 0;
1076
+ rb_io_t *fptr;
1077
+
1078
+ StringValue(str);
1079
+ Data_Get_Struct(self, SSL, ssl);
1080
+ GetOpenFile(ossl_ssl_get_io(self), fptr);
1081
+
1082
+ if (ssl) {
1083
+ for (;;){
1084
+ nwrite = SSL_write(ssl, RSTRING_PTR(str), RSTRING_LEN(str));
1085
+ switch(ssl_get_error(ssl, nwrite)){
1086
+ case SSL_ERROR_NONE:
1087
+ goto end;
1088
+ case SSL_ERROR_WANT_WRITE:
1089
+ rb_io_wait_writable(FPTR_TO_FD(fptr));
1090
+ continue;
1091
+ case SSL_ERROR_WANT_READ:
1092
+ rb_io_wait_readable(FPTR_TO_FD(fptr));
1093
+ continue;
1094
+ case SSL_ERROR_SYSCALL:
1095
+ if (errno) rb_sys_fail(0);
1096
+ default:
1097
+ ossl_raise(eSSLError, "SSL_write:");
1098
+ }
1099
+ }
1100
+ }
1101
+ else {
1102
+ ID id_syswrite = rb_intern("syswrite");
1103
+ rb_warning("SSL session is not started yet.");
1104
+ return rb_funcall(ossl_ssl_get_io(self), id_syswrite, 1, str);
1105
+ }
1106
+
1107
+ end:
1108
+ return INT2NUM(nwrite);
1109
+ }
1110
+
1111
+ /*
1112
+ * call-seq:
1113
+ * ssl.sysclose => nil
1114
+ */
1115
+ static VALUE
1116
+ ossl_ssl_close(VALUE self)
1117
+ {
1118
+ SSL *ssl;
1119
+
1120
+ Data_Get_Struct(self, SSL, ssl);
1121
+ ossl_ssl_shutdown(ssl);
1122
+ if (RTEST(ossl_ssl_get_sync_close(self)))
1123
+ rb_funcall(ossl_ssl_get_io(self), rb_intern("close"), 0);
1124
+
1125
+ return Qnil;
1126
+ }
1127
+
1128
+ /*
1129
+ * call-seq:
1130
+ * ssl.cert => cert or nil
1131
+ */
1132
+ static VALUE
1133
+ ossl_ssl_get_cert(VALUE self)
1134
+ {
1135
+ SSL *ssl;
1136
+ X509 *cert = NULL;
1137
+
1138
+ Data_Get_Struct(self, SSL, ssl);
1139
+ if (ssl) {
1140
+ rb_warning("SSL session is not started yet.");
1141
+ return Qnil;
1142
+ }
1143
+
1144
+ /*
1145
+ * Is this OpenSSL bug? Should add a ref?
1146
+ * TODO: Ask for.
1147
+ */
1148
+ cert = SSL_get_certificate(ssl); /* NO DUPs => DON'T FREE. */
1149
+
1150
+ if (!cert) {
1151
+ return Qnil;
1152
+ }
1153
+ return ossl_x509_new(cert);
1154
+ }
1155
+
1156
+ /*
1157
+ * call-seq:
1158
+ * ssl.peer_cert => cert or nil
1159
+ */
1160
+ static VALUE
1161
+ ossl_ssl_get_peer_cert(VALUE self)
1162
+ {
1163
+ SSL *ssl;
1164
+ X509 *cert = NULL;
1165
+ VALUE obj;
1166
+
1167
+ Data_Get_Struct(self, SSL, ssl);
1168
+
1169
+ if (!ssl){
1170
+ rb_warning("SSL session is not started yet.");
1171
+ return Qnil;
1172
+ }
1173
+
1174
+ cert = SSL_get_peer_certificate(ssl); /* Adds a ref => Safe to FREE. */
1175
+
1176
+ if (!cert) {
1177
+ return Qnil;
1178
+ }
1179
+ obj = ossl_x509_new(cert);
1180
+ X509_free(cert);
1181
+
1182
+ return obj;
1183
+ }
1184
+
1185
+ /*
1186
+ * call-seq:
1187
+ * ssl.peer_cert_chain => [cert, ...] or nil
1188
+ */
1189
+ static VALUE
1190
+ ossl_ssl_get_peer_cert_chain(VALUE self)
1191
+ {
1192
+ SSL *ssl;
1193
+ STACK_OF(X509) *chain;
1194
+ X509 *cert;
1195
+ VALUE ary;
1196
+ int i, num;
1197
+
1198
+ Data_Get_Struct(self, SSL, ssl);
1199
+ if(!ssl){
1200
+ rb_warning("SSL session is not started yet.");
1201
+ return Qnil;
1202
+ }
1203
+ chain = SSL_get_peer_cert_chain(ssl);
1204
+ if(!chain) return Qnil;
1205
+ num = sk_X509_num(chain);
1206
+ ary = rb_ary_new2(num);
1207
+ for (i = 0; i < num; i++){
1208
+ cert = sk_X509_value(chain, i);
1209
+ rb_ary_push(ary, ossl_x509_new(cert));
1210
+ }
1211
+
1212
+ return ary;
1213
+ }
1214
+
1215
+ /*
1216
+ * call-seq:
1217
+ * ssl.cipher => [name, version, bits, alg_bits]
1218
+ */
1219
+ static VALUE
1220
+ ossl_ssl_get_cipher(VALUE self)
1221
+ {
1222
+ SSL *ssl;
1223
+ SSL_CIPHER *cipher;
1224
+
1225
+ Data_Get_Struct(self, SSL, ssl);
1226
+ if (!ssl) {
1227
+ rb_warning("SSL session is not started yet.");
1228
+ return Qnil;
1229
+ }
1230
+ cipher = SSL_get_current_cipher(ssl);
1231
+
1232
+ return ossl_ssl_cipher_to_ary(cipher);
1233
+ }
1234
+
1235
+ /*
1236
+ * call-seq:
1237
+ * ssl.state => string
1238
+ */
1239
+ static VALUE
1240
+ ossl_ssl_get_state(VALUE self)
1241
+ {
1242
+ SSL *ssl;
1243
+ VALUE ret;
1244
+
1245
+ Data_Get_Struct(self, SSL, ssl);
1246
+ if (!ssl) {
1247
+ rb_warning("SSL session is not started yet.");
1248
+ return Qnil;
1249
+ }
1250
+ ret = rb_str_new2(SSL_state_string(ssl));
1251
+ if (ruby_verbose) {
1252
+ rb_str_cat2(ret, ": ");
1253
+ rb_str_cat2(ret, SSL_state_string_long(ssl));
1254
+ }
1255
+ return ret;
1256
+ }
1257
+
1258
+ /*
1259
+ * call-seq:
1260
+ * ssl.pending => integer
1261
+ */
1262
+ static VALUE
1263
+ ossl_ssl_pending(VALUE self)
1264
+ {
1265
+ SSL *ssl;
1266
+
1267
+ Data_Get_Struct(self, SSL, ssl);
1268
+ if (!ssl) {
1269
+ rb_warning("SSL session is not started yet.");
1270
+ return Qnil;
1271
+ }
1272
+
1273
+ return INT2NUM(SSL_pending(ssl));
1274
+ }
1275
+
1276
+ /*
1277
+ * call-seq:
1278
+ * ssl.session_reused? -> true | false
1279
+ *
1280
+ */
1281
+ static VALUE
1282
+ ossl_ssl_session_reused(VALUE self)
1283
+ {
1284
+ SSL *ssl;
1285
+
1286
+ Data_Get_Struct(self, SSL, ssl);
1287
+ if (!ssl) {
1288
+ rb_warning("SSL session is not started yet.");
1289
+ return Qnil;
1290
+ }
1291
+
1292
+ switch(SSL_session_reused(ssl)) {
1293
+ case 1: return Qtrue;
1294
+ case 0: return Qfalse;
1295
+ default: ossl_raise(eSSLError, "SSL_session_reused");
1296
+ }
1297
+ }
1298
+
1299
+ /*
1300
+ * call-seq:
1301
+ * ssl.session = session -> session
1302
+ *
1303
+ */
1304
+ static VALUE
1305
+ ossl_ssl_set_session(VALUE self, VALUE arg1)
1306
+ {
1307
+ SSL *ssl;
1308
+ SSL_SESSION *sess;
1309
+
1310
+ /* why is ossl_ssl_setup delayed? */
1311
+ ossl_ssl_setup(self);
1312
+
1313
+ Data_Get_Struct(self, SSL, ssl);
1314
+ if (!ssl) {
1315
+ rb_warning("SSL session is not started yet.");
1316
+ return Qnil;
1317
+ }
1318
+
1319
+ SafeGetSSLSession(arg1, sess);
1320
+
1321
+ if (SSL_set_session(ssl, sess) != 1)
1322
+ ossl_raise(eSSLError, "SSL_set_session");
1323
+
1324
+ return arg1;
1325
+ }
1326
+
1327
+ static VALUE
1328
+ ossl_ssl_get_verify_result(VALUE self)
1329
+ {
1330
+ SSL *ssl;
1331
+
1332
+ Data_Get_Struct(self, SSL, ssl);
1333
+ if (!ssl) {
1334
+ rb_warning("SSL session is not started yet.");
1335
+ return Qnil;
1336
+ }
1337
+
1338
+ return INT2FIX(SSL_get_verify_result(ssl));
1339
+ }
1340
+
1341
+ void
1342
+ Init_ossl_ssl()
1343
+ {
1344
+ int i;
1345
+ VALUE ary;
1346
+
1347
+ #if 0 /* let rdoc know about mOSSL */
1348
+ mOSSL = rb_define_module("OpenSSL");
1349
+ #endif
1350
+
1351
+ ID_callback_state = rb_intern("@callback_state");
1352
+
1353
+ ossl_ssl_ex_vcb_idx = SSL_get_ex_new_index(0,"ossl_ssl_ex_vcb_idx",0,0,0);
1354
+ ossl_ssl_ex_store_p = SSL_get_ex_new_index(0,"ossl_ssl_ex_store_p",0,0,0);
1355
+ ossl_ssl_ex_ptr_idx = SSL_get_ex_new_index(0,"ossl_ssl_ex_ptr_idx",0,0,0);
1356
+ ossl_ssl_ex_client_cert_cb_idx =
1357
+ SSL_get_ex_new_index(0,"ossl_ssl_ex_client_cert_cb_idx",0,0,0);
1358
+ ossl_ssl_ex_tmp_dh_callback_idx =
1359
+ SSL_get_ex_new_index(0,"ossl_ssl_ex_tmp_dh_callback_idx",0,0,0);
1360
+
1361
+ mSSL = rb_define_module_under(mOSSL, "SSL");
1362
+ eSSLError = rb_define_class_under(mSSL, "SSLError", eOSSLError);
1363
+
1364
+ Init_ossl_ssl_session();
1365
+
1366
+ /* class SSLContext
1367
+ *
1368
+ * The following attributes are available but don't show up in rdoc.
1369
+ * All attributes must be set before calling SSLSocket.new(io, ctx).
1370
+ * * ssl_version, cert, key, client_ca, ca_file, ca_path, timeout,
1371
+ * * verify_mode, verify_depth client_cert_cb, tmp_dh_callback,
1372
+ * * session_id_context, session_add_cb, session_new_cb, session_remove_cb
1373
+ */
1374
+ cSSLContext = rb_define_class_under(mSSL, "SSLContext", rb_cObject);
1375
+ rb_define_alloc_func(cSSLContext, ossl_sslctx_s_alloc);
1376
+ for(i = 0; i < numberof(ossl_sslctx_attrs); i++)
1377
+ rb_attr(cSSLContext, rb_intern(ossl_sslctx_attrs[i]), 1, 1, Qfalse);
1378
+ rb_define_alias(cSSLContext, "ssl_timeout", "timeout");
1379
+ rb_define_method(cSSLContext, "initialize", ossl_sslctx_initialize, -1);
1380
+ rb_define_method(cSSLContext, "ssl_version=", ossl_sslctx_set_ssl_version, 1);
1381
+ rb_define_method(cSSLContext, "ciphers", ossl_sslctx_get_ciphers, 0);
1382
+ rb_define_method(cSSLContext, "ciphers=", ossl_sslctx_set_ciphers, 1);
1383
+
1384
+ rb_define_method(cSSLContext, "setup", ossl_sslctx_setup, 0);
1385
+
1386
+
1387
+ rb_define_const(cSSLContext, "SESSION_CACHE_OFF", LONG2FIX(SSL_SESS_CACHE_OFF));
1388
+ rb_define_const(cSSLContext, "SESSION_CACHE_CLIENT", LONG2FIX(SSL_SESS_CACHE_CLIENT)); /* doesn't actually do anything in 0.9.8e */
1389
+ rb_define_const(cSSLContext, "SESSION_CACHE_SERVER", LONG2FIX(SSL_SESS_CACHE_SERVER));
1390
+ rb_define_const(cSSLContext, "SESSION_CACHE_BOTH", LONG2FIX(SSL_SESS_CACHE_BOTH)); /* no different than CACHE_SERVER in 0.9.8e */
1391
+ rb_define_const(cSSLContext, "SESSION_CACHE_NO_AUTO_CLEAR", LONG2FIX(SSL_SESS_CACHE_NO_AUTO_CLEAR));
1392
+ rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL_LOOKUP", LONG2FIX(SSL_SESS_CACHE_NO_INTERNAL_LOOKUP));
1393
+ rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL_STORE", LONG2FIX(SSL_SESS_CACHE_NO_INTERNAL_STORE));
1394
+ rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL", LONG2FIX(SSL_SESS_CACHE_NO_INTERNAL));
1395
+ rb_define_method(cSSLContext, "session_add", ossl_sslctx_session_add, 1);
1396
+ rb_define_method(cSSLContext, "session_remove", ossl_sslctx_session_remove, 1);
1397
+ rb_define_method(cSSLContext, "session_cache_mode", ossl_sslctx_get_session_cache_mode, 0);
1398
+ rb_define_method(cSSLContext, "session_cache_mode=", ossl_sslctx_set_session_cache_mode, 1);
1399
+ rb_define_method(cSSLContext, "session_cache_size", ossl_sslctx_get_session_cache_size, 0);
1400
+ rb_define_method(cSSLContext, "session_cache_size=", ossl_sslctx_set_session_cache_size, 1);
1401
+ rb_define_method(cSSLContext, "session_cache_stats", ossl_sslctx_get_session_cache_stats, 0);
1402
+ rb_define_method(cSSLContext, "flush_sessions", ossl_sslctx_flush_sessions, -1);
1403
+
1404
+ ary = rb_ary_new2(numberof(ossl_ssl_method_tab));
1405
+ for (i = 0; i < numberof(ossl_ssl_method_tab); i++) {
1406
+ rb_ary_push(ary, ID2SYM(rb_intern(ossl_ssl_method_tab[i].name)));
1407
+ }
1408
+ rb_obj_freeze(ary);
1409
+ /* holds a list of available SSL/TLS methods */
1410
+ rb_define_const(cSSLContext, "METHODS", ary);
1411
+
1412
+ /* class SSLSocket
1413
+ *
1414
+ * The following attributes are available but don't show up in rdoc.
1415
+ * * io, context, sync_close
1416
+ *
1417
+ */
1418
+ cSSLSocket = rb_define_class_under(mSSL, "SSLSocket", rb_cObject);
1419
+ rb_define_alloc_func(cSSLSocket, ossl_ssl_s_alloc);
1420
+ for(i = 0; i < numberof(ossl_ssl_attr_readers); i++)
1421
+ rb_attr(cSSLSocket, rb_intern(ossl_ssl_attr_readers[i]), 1, 0, Qfalse);
1422
+ for(i = 0; i < numberof(ossl_ssl_attrs); i++)
1423
+ rb_attr(cSSLSocket, rb_intern(ossl_ssl_attrs[i]), 1, 1, Qfalse);
1424
+ rb_define_alias(cSSLSocket, "to_io", "io");
1425
+ rb_define_method(cSSLSocket, "initialize", ossl_ssl_initialize, -1);
1426
+ rb_define_method(cSSLSocket, "connect", ossl_ssl_connect, 0);
1427
+ rb_define_method(cSSLSocket, "accept", ossl_ssl_accept, 0);
1428
+ rb_define_method(cSSLSocket, "sysread", ossl_ssl_read, -1);
1429
+ rb_define_method(cSSLSocket, "syswrite", ossl_ssl_write, 1);
1430
+ rb_define_method(cSSLSocket, "sysclose", ossl_ssl_close, 0);
1431
+ rb_define_method(cSSLSocket, "cert", ossl_ssl_get_cert, 0);
1432
+ rb_define_method(cSSLSocket, "peer_cert", ossl_ssl_get_peer_cert, 0);
1433
+ rb_define_method(cSSLSocket, "peer_cert_chain", ossl_ssl_get_peer_cert_chain, 0);
1434
+ rb_define_method(cSSLSocket, "cipher", ossl_ssl_get_cipher, 0);
1435
+ rb_define_method(cSSLSocket, "state", ossl_ssl_get_state, 0);
1436
+ rb_define_method(cSSLSocket, "pending", ossl_ssl_pending, 0);
1437
+ rb_define_method(cSSLSocket, "session_reused?", ossl_ssl_session_reused, 0);
1438
+ rb_define_method(cSSLSocket, "session=", ossl_ssl_set_session, 1);
1439
+ rb_define_method(cSSLSocket, "verify_result", ossl_ssl_get_verify_result, 0);
1440
+
1441
+ #define ossl_ssl_def_const(x) rb_define_const(mSSL, #x, INT2FIX(SSL_##x))
1442
+
1443
+ ossl_ssl_def_const(VERIFY_NONE);
1444
+ ossl_ssl_def_const(VERIFY_PEER);
1445
+ ossl_ssl_def_const(VERIFY_FAIL_IF_NO_PEER_CERT);
1446
+ ossl_ssl_def_const(VERIFY_CLIENT_ONCE);
1447
+ /* Introduce constants included in OP_ALL. These constants are mostly for
1448
+ * unset some bits in OP_ALL such as;
1449
+ * ctx.options = OP_ALL & ~OP_DONT_INSERT_EMPTY_FRAGMENTS
1450
+ */
1451
+ ossl_ssl_def_const(OP_MICROSOFT_SESS_ID_BUG);
1452
+ ossl_ssl_def_const(OP_NETSCAPE_CHALLENGE_BUG);
1453
+ ossl_ssl_def_const(OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG);
1454
+ ossl_ssl_def_const(OP_SSLREF2_REUSE_CERT_TYPE_BUG);
1455
+ ossl_ssl_def_const(OP_MICROSOFT_BIG_SSLV3_BUFFER);
1456
+ ossl_ssl_def_const(OP_MSIE_SSLV2_RSA_PADDING);
1457
+ ossl_ssl_def_const(OP_SSLEAY_080_CLIENT_DH_BUG);
1458
+ ossl_ssl_def_const(OP_TLS_D5_BUG);
1459
+ ossl_ssl_def_const(OP_TLS_BLOCK_PADDING_BUG);
1460
+ ossl_ssl_def_const(OP_DONT_INSERT_EMPTY_FRAGMENTS);
1461
+ ossl_ssl_def_const(OP_ALL);
1462
+ #if defined(SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION)
1463
+ ossl_ssl_def_const(OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
1464
+ #endif
1465
+ #if defined(SSL_OP_SINGLE_ECDH_USE)
1466
+ ossl_ssl_def_const(OP_SINGLE_ECDH_USE);
1467
+ #endif
1468
+ ossl_ssl_def_const(OP_SINGLE_DH_USE);
1469
+ ossl_ssl_def_const(OP_EPHEMERAL_RSA);
1470
+ #if defined(SSL_OP_CIPHER_SERVER_PREFERENCE)
1471
+ ossl_ssl_def_const(OP_CIPHER_SERVER_PREFERENCE);
1472
+ #endif
1473
+ ossl_ssl_def_const(OP_TLS_ROLLBACK_BUG);
1474
+ ossl_ssl_def_const(OP_NO_SSLv2);
1475
+ ossl_ssl_def_const(OP_NO_SSLv3);
1476
+ ossl_ssl_def_const(OP_NO_TLSv1);
1477
+ #if defined(SSL_OP_NO_TICKET)
1478
+ ossl_ssl_def_const(OP_NO_TICKET);
1479
+ #endif
1480
+ ossl_ssl_def_const(OP_PKCS1_CHECK_1);
1481
+ ossl_ssl_def_const(OP_PKCS1_CHECK_2);
1482
+ ossl_ssl_def_const(OP_NETSCAPE_CA_DN_BUG);
1483
+ ossl_ssl_def_const(OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG);
1484
+ }