Ruby 2.0.0p247(2013-06-27revision41674)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

ossl_ssl_session.c
Go to the documentation of this file.
1 /*
2 * Copyright (C) 2004-2007 Technorama Ltd. <oss-ruby@technorama.net>
3 */
4
5 #include "ossl.h"
6
7 #define GetSSLSession(obj, sess) do { \
8 Data_Get_Struct((obj), SSL_SESSION, (sess)); \
9 if (!(sess)) { \
10 ossl_raise(rb_eRuntimeError, "SSL Session wasn't initialized."); \
11 } \
12 } while (0)
13
14 #define SafeGetSSLSession(obj, sess) do { \
15 OSSL_Check_Kind((obj), cSSLSession); \
16 GetSSLSession((obj), (sess)); \
17 } while (0)
18
19
20 VALUE cSSLSession;
21 static VALUE eSSLSession;
22
23 static VALUE ossl_ssl_session_alloc(VALUE klass)
24 {
25 return Data_Wrap_Struct(klass, 0, SSL_SESSION_free, NULL);
26 }
27
28 /*
29 * call-seq:
30 * Session.new(SSLSocket | string) => session
31 *
32 * === Parameters
33 * +SSLSocket+ is an OpenSSL::SSL::SSLSocket
34 * +string+ must be a DER or PEM encoded Session.
35 */
36 static VALUE ossl_ssl_session_initialize(VALUE self, VALUE arg1)
37 {
38 SSL_SESSION *ctx = NULL;
39
40 if (RDATA(self)->data)
41 ossl_raise(eSSLSession, "SSL Session already initialized");
42
43 if (rb_obj_is_instance_of(arg1, cSSLSocket)) {
44 SSL *ssl;
45
46 Data_Get_Struct(arg1, SSL, ssl);
47
48 if (!ssl || (ctx = SSL_get1_session(ssl)) == NULL)
49 ossl_raise(eSSLSession, "no session available");
50 } else {
51 BIO *in = ossl_obj2bio(arg1);
52
53 ctx = PEM_read_bio_SSL_SESSION(in, NULL, NULL, NULL);
54
55 if (!ctx) {
56 OSSL_BIO_reset(in);
57 ctx = d2i_SSL_SESSION_bio(in, NULL);
58 }
59
60 BIO_free(in);
61
62 if (!ctx)
63 ossl_raise(rb_eArgError, "unknown type");
64 }
65
66 /* should not happen */
67 if (ctx == NULL)
68 ossl_raise(eSSLSession, "ctx not set - internal error");
69
70 RDATA(self)->data = ctx;
71
72 return self;
73 }
74
75 #if HAVE_SSL_SESSION_CMP == 0
76 int SSL_SESSION_cmp(const SSL_SESSION *a,const SSL_SESSION *b)
77 {
78 if (a->ssl_version != b->ssl_version ||
79 a->session_id_length != b->session_id_length)
80 return 1;
81 return memcmp(a->session_id,b-> session_id, a->session_id_length);
82 }
83 #endif
84
85 /*
86 * call-seq:
87 * session1 == session2 -> boolean
88 *
89 */
90 static VALUE ossl_ssl_session_eq(VALUE val1, VALUE val2)
91 {
92 SSL_SESSION *ctx1, *ctx2;
93
94 GetSSLSession(val1, ctx1);
95 SafeGetSSLSession(val2, ctx2);
96
97 switch (SSL_SESSION_cmp(ctx1, ctx2)) {
98 case 0: return Qtrue;
99 default: return Qfalse;
100 }
101 }
102
103 /*
104 * call-seq:
105 * session.time -> Time
106 *
107 * Gets start time of the session.
108 *
109 */
110 static VALUE ossl_ssl_session_get_time(VALUE self)
111 {
112 SSL_SESSION *ctx;
113 time_t t;
114
115 GetSSLSession(self, ctx);
116
117 t = SSL_SESSION_get_time(ctx);
118
119 if (t == 0)
120 return Qnil;
121
122 return rb_funcall(rb_cTime, rb_intern("at"), 1, TIMET2NUM(t));
123 }
124
125 /*
126 * call-seq:
127 * session.timeout -> integer
128 *
129 * Gets how long until the session expires in seconds.
130 *
131 */
132 static VALUE ossl_ssl_session_get_timeout(VALUE self)
133 {
134 SSL_SESSION *ctx;
135 time_t t;
136
137 GetSSLSession(self, ctx);
138
139 t = SSL_SESSION_get_timeout(ctx);
140
141 return TIMET2NUM(t);
142 }
143
144 /*
145 * call-seq:
146 * session.time=(Time) -> Time
147 * session.time=(integer) -> Time
148 *
149 * Sets start time of the session. Time resolution is in seconds.
150 *
151 */
152 static VALUE ossl_ssl_session_set_time(VALUE self, VALUE time_v)
153 {
154 SSL_SESSION *ctx;
155 long t;
156
157 GetSSLSession(self, ctx);
158 if (rb_obj_is_instance_of(time_v, rb_cTime)) {
159 time_v = rb_funcall(time_v, rb_intern("to_i"), 0);
160 }
161 t = NUM2LONG(time_v);
162 SSL_SESSION_set_time(ctx, t);
163 return ossl_ssl_session_get_time(self);
164 }
165
166 /*
167 * call-seq:
168 * session.timeout=(integer) -> integer
169 *
170 * Sets how long until the session expires in seconds.
171 *
172 */
173 static VALUE ossl_ssl_session_set_timeout(VALUE self, VALUE time_v)
174 {
175 SSL_SESSION *ctx;
176 long t;
177
178 GetSSLSession(self, ctx);
179 t = NUM2LONG(time_v);
180 SSL_SESSION_set_timeout(ctx, t);
181 return ossl_ssl_session_get_timeout(self);
182 }
183
184 #ifdef HAVE_SSL_SESSION_GET_ID
185 /*
186 * call-seq:
187 * session.id -> aString
188 *
189 * Returns the Session ID.
190 */
191 static VALUE ossl_ssl_session_get_id(VALUE self)
192 {
193 SSL_SESSION *ctx;
194 const unsigned char *p = NULL;
195 unsigned int i = 0;
196
197 GetSSLSession(self, ctx);
198
199 p = SSL_SESSION_get_id(ctx, &i);
200
201 return rb_str_new((const char *) p, i);
202 }
203 #endif
204
205 /*
206 * call-seq:
207 * session.to_der -> aString
208 *
209 * Returns an ASN1 encoded String that contains the Session object.
210 */
211 static VALUE ossl_ssl_session_to_der(VALUE self)
212 {
213 SSL_SESSION *ctx;
214 unsigned char *p;
215 int len;
216 VALUE str;
217
218 GetSSLSession(self, ctx);
219 len = i2d_SSL_SESSION(ctx, NULL);
220 if (len <= 0) {
221 ossl_raise(eSSLSession, "i2d_SSL_SESSION");
222 }
223
224 str = rb_str_new(0, len);
225 p = (unsigned char *)RSTRING_PTR(str);
226 i2d_SSL_SESSION(ctx, &p);
227 ossl_str_adjust(str, p);
228 return str;
229 }
230
231 /*
232 * call-seq:
233 * session.to_pem -> String
234 *
235 * Returns a PEM encoded String that contains the Session object.
236 */
237 static VALUE ossl_ssl_session_to_pem(VALUE self)
238 {
239 SSL_SESSION *ctx;
240 BIO *out;
241 BUF_MEM *buf;
242 VALUE str;
243 int i;
244
245 GetSSLSession(self, ctx);
246
247 if (!(out = BIO_new(BIO_s_mem()))) {
248 ossl_raise(eSSLSession, "BIO_s_mem()");
249 }
250
251 if (!(i=PEM_write_bio_SSL_SESSION(out, ctx))) {
252 BIO_free(out);
253 ossl_raise(eSSLSession, "SSL_SESSION_print()");
254 }
255
256 BIO_get_mem_ptr(out, &buf);
257 str = rb_str_new(buf->data, buf->length);
258 BIO_free(out);
259
260 return str;
261 }
262
263
264 /*
265 * call-seq:
266 * session.to_text -> String
267 *
268 * Shows everything in the Session object.
269 */
270 static VALUE ossl_ssl_session_to_text(VALUE self)
271 {
272 SSL_SESSION *ctx;
273 BIO *out;
274 BUF_MEM *buf;
275 VALUE str;
276
277 GetSSLSession(self, ctx);
278
279 if (!(out = BIO_new(BIO_s_mem()))) {
280 ossl_raise(eSSLSession, "BIO_s_mem()");
281 }
282
283 if (!SSL_SESSION_print(out, ctx)) {
284 BIO_free(out);
285 ossl_raise(eSSLSession, "SSL_SESSION_print()");
286 }
287
288 BIO_get_mem_ptr(out, &buf);
289 str = rb_str_new(buf->data, buf->length);
290 BIO_free(out);
291
292 return str;
293 }
294
295
296 void Init_ossl_ssl_session(void)
297 {
298 #if 0
299 mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
300 mSSL = rb_define_module_under(mOSSL, "SSL");
301 #endif
302 cSSLSession = rb_define_class_under(mSSL, "Session", rb_cObject);
303 eSSLSession = rb_define_class_under(cSSLSession, "SessionError", eOSSLError);
304
305 rb_define_alloc_func(cSSLSession, ossl_ssl_session_alloc);
306 rb_define_method(cSSLSession, "initialize", ossl_ssl_session_initialize, 1);
307
308 rb_define_method(cSSLSession, "==", ossl_ssl_session_eq, 1);
309
310 rb_define_method(cSSLSession, "time", ossl_ssl_session_get_time, 0);
311 rb_define_method(cSSLSession, "time=", ossl_ssl_session_set_time, 1);
312 rb_define_method(cSSLSession, "timeout", ossl_ssl_session_get_timeout, 0);
313 rb_define_method(cSSLSession, "timeout=", ossl_ssl_session_set_timeout, 1);
314
315 #ifdef HAVE_SSL_SESSION_GET_ID
316 rb_define_method(cSSLSession, "id", ossl_ssl_session_get_id, 0);
317 #else
318 rb_undef_method(cSSLSession, "id");
319 #endif
320 rb_define_method(cSSLSession, "to_der", ossl_ssl_session_to_der, 0);
321 rb_define_method(cSSLSession, "to_pem", ossl_ssl_session_to_pem, 0);
322 rb_define_method(cSSLSession, "to_text", ossl_ssl_session_to_text, 0);
323 }
324