Ruby  3.1.0dev(2021-09-10revisionb76ad15ed0da636161de0243c547ee1e6fc95681)
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 
8 static VALUE eSSLSession;
9 
10 static void
11 ossl_ssl_session_free(void *ptr)
12 {
13  SSL_SESSION_free(ptr);
14 }
15 
17  "OpenSSL/SSL/Session",
18  {
19  0, ossl_ssl_session_free,
20  },
22 };
23 
24 static VALUE ossl_ssl_session_alloc(VALUE klass)
25 {
27 }
28 
29 /*
30  * call-seq:
31  * Session.new(ssl_socket) -> Session
32  * Session.new(string) -> Session
33  *
34  * Creates a new Session object from an instance of SSLSocket or DER/PEM encoded
35  * String.
36  */
37 static VALUE
38 ossl_ssl_session_initialize(VALUE self, VALUE arg1)
39 {
40  SSL_SESSION *ctx;
41 
42  if (RTYPEDDATA_DATA(self))
43  ossl_raise(eSSLSession, "SSL Session already initialized");
44 
45  if (rb_obj_is_instance_of(arg1, cSSLSocket)) {
46  SSL *ssl;
47 
48  GetSSL(arg1, ssl);
49 
50  if ((ctx = SSL_get1_session(ssl)) == NULL)
51  ossl_raise(eSSLSession, "no session available");
52  }
53  else {
54  BIO *in = ossl_obj2bio(&arg1);
55 
56  ctx = d2i_SSL_SESSION_bio(in, NULL);
57  if (!ctx) {
59  ctx = PEM_read_bio_SSL_SESSION(in, NULL, NULL, NULL);
60  }
61  BIO_free(in);
62  if (!ctx)
63  ossl_raise(rb_eArgError, "unknown type");
64  }
65 
66  RTYPEDDATA_DATA(self) = ctx;
67 
68  return self;
69 }
70 
71 static VALUE
72 ossl_ssl_session_initialize_copy(VALUE self, VALUE other)
73 {
74  SSL_SESSION *sess, *sess_other, *sess_new;
75 
76  rb_check_frozen(self);
77  sess = RTYPEDDATA_DATA(self); /* XXX */
78  GetSSLSession(other, sess_other);
79 
80  sess_new = ASN1_dup((i2d_of_void *)i2d_SSL_SESSION, (d2i_of_void *)d2i_SSL_SESSION,
81  (char *)sess_other);
82  if (!sess_new)
83  ossl_raise(eSSLSession, "ASN1_dup");
84 
85  RTYPEDDATA_DATA(self) = sess_new;
86  SSL_SESSION_free(sess);
87 
88  return self;
89 }
90 
91 static int
92 ossl_SSL_SESSION_cmp(const SSL_SESSION *a, const SSL_SESSION *b)
93 {
94  unsigned int a_len;
95  const unsigned char *a_sid = SSL_SESSION_get_id(a, &a_len);
96  unsigned int b_len;
97  const unsigned char *b_sid = SSL_SESSION_get_id(b, &b_len);
98 
100  return 1;
101  if (a_len != b_len)
102  return 1;
103 
104  return CRYPTO_memcmp(a_sid, b_sid, a_len);
105 }
106 
107 /*
108  * call-seq:
109  * session1 == session2 -> boolean
110  *
111  * Returns +true+ if the two Session is the same, +false+ if not.
112  */
113 static VALUE ossl_ssl_session_eq(VALUE val1, VALUE val2)
114 {
115  SSL_SESSION *ctx1, *ctx2;
116 
117  GetSSLSession(val1, ctx1);
118  GetSSLSession(val2, ctx2);
119 
120  switch (ossl_SSL_SESSION_cmp(ctx1, ctx2)) {
121  case 0: return Qtrue;
122  default: return Qfalse;
123  }
124 }
125 
126 /*
127  * call-seq:
128  * session.time -> Time
129  *
130  * Returns the time at which the session was established.
131  */
132 static VALUE
133 ossl_ssl_session_get_time(VALUE self)
134 {
135  SSL_SESSION *ctx;
136  long t;
137 
138  GetSSLSession(self, ctx);
139  t = SSL_SESSION_get_time(ctx);
140  if (t == 0)
141  return Qnil;
142 
143  return rb_funcall(rb_cTime, rb_intern("at"), 1, LONG2NUM(t));
144 }
145 
146 /*
147  * call-seq:
148  * session.timeout -> Integer
149  *
150  * Returns the timeout value set for the session, in seconds from the
151  * established time.
152  *
153  */
154 static VALUE
155 ossl_ssl_session_get_timeout(VALUE self)
156 {
157  SSL_SESSION *ctx;
158  long t;
159 
160  GetSSLSession(self, ctx);
161  t = SSL_SESSION_get_timeout(ctx);
162 
163  return LONG2NUM(t);
164 }
165 
166 /*
167  * call-seq:
168  * session.time = time
169  * session.time = integer
170  *
171  * Sets start time of the session. Time resolution is in seconds.
172  *
173  */
174 static VALUE ossl_ssl_session_set_time(VALUE self, VALUE time_v)
175 {
176  SSL_SESSION *ctx;
177  long t;
178 
179  GetSSLSession(self, ctx);
180  if (rb_obj_is_instance_of(time_v, rb_cTime)) {
181  time_v = rb_funcall(time_v, rb_intern("to_i"), 0);
182  }
183  t = NUM2LONG(time_v);
184  SSL_SESSION_set_time(ctx, t);
185  return ossl_ssl_session_get_time(self);
186 }
187 
188 /*
189  * call-seq:
190  * session.timeout = integer
191  *
192  * Sets how long until the session expires in seconds.
193  */
194 static VALUE ossl_ssl_session_set_timeout(VALUE self, VALUE time_v)
195 {
196  SSL_SESSION *ctx;
197  long t;
198 
199  GetSSLSession(self, ctx);
200  t = NUM2LONG(time_v);
201  SSL_SESSION_set_timeout(ctx, t);
202  return ossl_ssl_session_get_timeout(self);
203 }
204 
205 /*
206  * call-seq:
207  * session.id -> String
208  *
209  * Returns the Session ID.
210 */
211 static VALUE ossl_ssl_session_get_id(VALUE self)
212 {
213  SSL_SESSION *ctx;
214  const unsigned char *p = NULL;
215  unsigned int i = 0;
216 
217  GetSSLSession(self, ctx);
218 
219  p = SSL_SESSION_get_id(ctx, &i);
220 
221  return rb_str_new((const char *) p, i);
222 }
223 
224 /*
225  * call-seq:
226  * session.to_der -> String
227  *
228  * Returns an ASN1 encoded String that contains the Session object.
229  */
230 static VALUE ossl_ssl_session_to_der(VALUE self)
231 {
232  SSL_SESSION *ctx;
233  unsigned char *p;
234  int len;
235  VALUE str;
236 
237  GetSSLSession(self, ctx);
238  len = i2d_SSL_SESSION(ctx, NULL);
239  if (len <= 0) {
240  ossl_raise(eSSLSession, "i2d_SSL_SESSION");
241  }
242 
243  str = rb_str_new(0, len);
244  p = (unsigned char *)RSTRING_PTR(str);
245  i2d_SSL_SESSION(ctx, &p);
246  ossl_str_adjust(str, p);
247  return str;
248 }
249 
250 /*
251  * call-seq:
252  * session.to_pem -> String
253  *
254  * Returns a PEM encoded String that contains the Session object.
255  */
256 static VALUE ossl_ssl_session_to_pem(VALUE self)
257 {
258  SSL_SESSION *ctx;
259  BIO *out;
260 
261  GetSSLSession(self, ctx);
262 
263  if (!(out = BIO_new(BIO_s_mem()))) {
264  ossl_raise(eSSLSession, "BIO_s_mem()");
265  }
266 
267  if (!PEM_write_bio_SSL_SESSION(out, ctx)) {
268  BIO_free(out);
269  ossl_raise(eSSLSession, "SSL_SESSION_print()");
270  }
271 
272 
273  return ossl_membio2str(out);
274 }
275 
276 
277 /*
278  * call-seq:
279  * session.to_text -> String
280  *
281  * Shows everything in the Session object. This is for diagnostic purposes.
282  */
283 static VALUE ossl_ssl_session_to_text(VALUE self)
284 {
285  SSL_SESSION *ctx;
286  BIO *out;
287 
288  GetSSLSession(self, ctx);
289 
290  if (!(out = BIO_new(BIO_s_mem()))) {
291  ossl_raise(eSSLSession, "BIO_s_mem()");
292  }
293 
294  if (!SSL_SESSION_print(out, ctx)) {
295  BIO_free(out);
296  ossl_raise(eSSLSession, "SSL_SESSION_print()");
297  }
298 
299  return ossl_membio2str(out);
300 }
301 
302 
304 {
305 #if 0
306  mOSSL = rb_define_module("OpenSSL");
309 #endif
311  eSSLSession = rb_define_class_under(cSSLSession, "SessionError", eOSSLError);
312 
313  rb_define_alloc_func(cSSLSession, ossl_ssl_session_alloc);
314  rb_define_method(cSSLSession, "initialize", ossl_ssl_session_initialize, 1);
315  rb_define_method(cSSLSession, "initialize_copy", ossl_ssl_session_initialize_copy, 1);
316 
317  rb_define_method(cSSLSession, "==", ossl_ssl_session_eq, 1);
318 
319  rb_define_method(cSSLSession, "time", ossl_ssl_session_get_time, 0);
320  rb_define_method(cSSLSession, "time=", ossl_ssl_session_set_time, 1);
321  rb_define_method(cSSLSession, "timeout", ossl_ssl_session_get_timeout, 0);
322  rb_define_method(cSSLSession, "timeout=", ossl_ssl_session_set_timeout, 1);
323  rb_define_method(cSSLSession, "id", ossl_ssl_session_get_id, 0);
324  rb_define_method(cSSLSession, "to_der", ossl_ssl_session_to_der, 0);
325  rb_define_method(cSSLSession, "to_pem", ossl_ssl_session_to_pem, 0);
326  rb_define_method(cSSLSession, "to_text", ossl_ssl_session_to_text, 0);
327 }
GetSSL
#define GetSSL(obj, ssl)
Definition: ossl_ssl.h:13
TypedData_Wrap_Struct
#define TypedData_Wrap_Struct(klass, data_type, sval)
Definition: rtypeddata.h:101
rb_define_module_under
VALUE rb_define_module_under(VALUE outer, const char *name)
Definition: class.c:914
rb_intern
ID rb_intern(const char *)
Definition: symbol.c:784
ossl_membio2str
VALUE ossl_membio2str(BIO *bio)
Definition: ossl_bio.c:29
SSL_SESSION_get_protocol_version
#define SSL_SESSION_get_protocol_version(s)
ossl_obj2bio
BIO * ossl_obj2bio(volatile VALUE *pobj)
Definition: ossl_bio.c:13
rb_eArgError
VALUE rb_eArgError
Definition: error.c:1094
OSSL_BIO_reset
#define OSSL_BIO_reset(bio)
Definition: ossl.h:115
rb_define_module
VALUE rb_define_module(const char *name)
Definition: class.c:887
LONG2NUM
#define LONG2NUM
Definition: long.h:50
ossl.h
ptr
struct RIMemo * ptr
Definition: debug.c:87
ossl_str_adjust
#define ossl_str_adjust(str, p)
Definition: ossl.h:88
GetSSLSession
#define GetSSLSession(obj, sess)
Definition: ossl_ssl.h:20
ossl_ssl_session_type
const rb_data_type_t ossl_ssl_session_type
Definition: ossl_ssl_session.c:16
rb_str_new
#define rb_str_new(str, len)
Definition: string.h:213
RUBY_TYPED_FREE_IMMEDIATELY
@ RUBY_TYPED_FREE_IMMEDIATELY
Definition: rtypeddata.h:62
cSSLSocket
VALUE cSSLSocket
Definition: ossl_ssl.c:36
mOSSL
VALUE mOSSL
Definition: ossl.c:237
rb_define_alloc_func
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
rb_obj_is_instance_of
VALUE rb_obj_is_instance_of(VALUE, VALUE)
Determines if obj is an instance of c.
Definition: object.c:713
rb_cObject
VALUE rb_cObject
Object class.
Definition: object.c:50
Qfalse
#define Qfalse
Definition: special_consts.h:50
len
uint8_t len
Definition: escape.c:17
Qnil
#define Qnil
Definition: special_consts.h:51
ossl_raise
void ossl_raise(VALUE exc, const char *fmt,...)
Definition: ossl.c:299
NULL
#define NULL
Definition: regenc.h:69
RTYPEDDATA_DATA
#define RTYPEDDATA_DATA(v)
Definition: rtypeddata.h:47
cSSLSession
VALUE cSSLSession
Definition: ossl_ssl_session.c:7
Qtrue
#define Qtrue
Definition: special_consts.h:52
npn_select_cb_common_args::in
const unsigned char * in
Definition: ossl_ssl.c:592
VALUE
unsigned long VALUE
Definition: value.h:38
rb_funcall
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:1113
mSSL
VALUE mSSL
Definition: ossl_ssl.c:32
RSTRING_PTR
#define RSTRING_PTR(string)
Definition: fbuffer.h:19
str
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
NUM2LONG
#define NUM2LONG
Definition: long.h:51
rb_check_frozen
#define rb_check_frozen
Definition: error.h:72
rb_data_type_struct
Definition: rtypeddata.h:70
t
#define t
Definition: symbol.c:253
rb_cTime
VALUE rb_cTime
Definition: time.c:647
Init_ossl_ssl_session
void Init_ossl_ssl_session(void)
Definition: ossl_ssl_session.c:303
eOSSLError
VALUE eOSSLError
Definition: ossl.c:242
rb_define_class_under
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:809
rb_define_method
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
Definition: cxxanyargs.hpp:655
rb_eStandardError
VALUE rb_eStandardError
Definition: error.c:1090