Ruby  2.0.0p247(2013-06-27revision41674)
ext/openssl/ossl_ssl_session.c
Go to the documentation of this file.
00001 /*
00002  *  Copyright (C) 2004-2007 Technorama Ltd. <oss-ruby@technorama.net>
00003  */
00004 
00005 #include "ossl.h"
00006 
00007 #define GetSSLSession(obj, sess) do { \
00008         Data_Get_Struct((obj), SSL_SESSION, (sess)); \
00009         if (!(sess)) { \
00010                 ossl_raise(rb_eRuntimeError, "SSL Session wasn't initialized."); \
00011         } \
00012 } while (0)
00013 
00014 #define SafeGetSSLSession(obj, sess) do { \
00015         OSSL_Check_Kind((obj), cSSLSession); \
00016         GetSSLSession((obj), (sess)); \
00017 } while (0)
00018 
00019 
00020 VALUE cSSLSession;
00021 static VALUE eSSLSession;
00022 
00023 static VALUE ossl_ssl_session_alloc(VALUE klass)
00024 {
00025         return Data_Wrap_Struct(klass, 0, SSL_SESSION_free, NULL);
00026 }
00027 
00028 /*
00029  * call-seq:
00030  *    Session.new(SSLSocket | string) => session
00031  *
00032  * === Parameters
00033  * +SSLSocket+ is an OpenSSL::SSL::SSLSocket
00034  * +string+ must be a DER or PEM encoded Session.
00035 */
00036 static VALUE ossl_ssl_session_initialize(VALUE self, VALUE arg1)
00037 {
00038         SSL_SESSION *ctx = NULL;
00039 
00040         if (RDATA(self)->data)
00041                 ossl_raise(eSSLSession, "SSL Session already initialized");
00042 
00043         if (rb_obj_is_instance_of(arg1, cSSLSocket)) {
00044                 SSL *ssl;
00045 
00046                 Data_Get_Struct(arg1, SSL, ssl);
00047 
00048                 if (!ssl || (ctx = SSL_get1_session(ssl)) == NULL)
00049                         ossl_raise(eSSLSession, "no session available");
00050         } else {
00051                 BIO *in = ossl_obj2bio(arg1);
00052 
00053                 ctx = PEM_read_bio_SSL_SESSION(in, NULL, NULL, NULL);
00054 
00055                 if (!ctx) {
00056                         OSSL_BIO_reset(in);
00057                         ctx = d2i_SSL_SESSION_bio(in, NULL);
00058                 }
00059 
00060                 BIO_free(in);
00061 
00062                 if (!ctx)
00063                         ossl_raise(rb_eArgError, "unknown type");
00064         }
00065 
00066         /* should not happen */
00067         if (ctx == NULL)
00068                 ossl_raise(eSSLSession, "ctx not set - internal error");
00069 
00070         RDATA(self)->data = ctx;
00071 
00072         return self;
00073 }
00074 
00075 #if HAVE_SSL_SESSION_CMP == 0
00076 int SSL_SESSION_cmp(const SSL_SESSION *a,const SSL_SESSION *b)
00077 {
00078     if (a->ssl_version != b->ssl_version ||
00079         a->session_id_length != b->session_id_length)
00080         return 1;
00081     return memcmp(a->session_id,b-> session_id, a->session_id_length);
00082 }
00083 #endif
00084 
00085 /*
00086  * call-seq:
00087  *    session1 == session2 -> boolean
00088  *
00089 */
00090 static VALUE ossl_ssl_session_eq(VALUE val1, VALUE val2)
00091 {
00092         SSL_SESSION *ctx1, *ctx2;
00093 
00094         GetSSLSession(val1, ctx1);
00095         SafeGetSSLSession(val2, ctx2);
00096 
00097         switch (SSL_SESSION_cmp(ctx1, ctx2)) {
00098         case 0:         return Qtrue;
00099         default:        return Qfalse;
00100         }
00101 }
00102 
00103 /*
00104  * call-seq:
00105  *    session.time -> Time
00106  *
00107  * Gets start time of the session.
00108  *
00109 */
00110 static VALUE ossl_ssl_session_get_time(VALUE self)
00111 {
00112         SSL_SESSION *ctx;
00113         time_t t;
00114 
00115         GetSSLSession(self, ctx);
00116 
00117         t = SSL_SESSION_get_time(ctx);
00118 
00119         if (t == 0)
00120                 return Qnil;
00121 
00122         return rb_funcall(rb_cTime, rb_intern("at"), 1, TIMET2NUM(t));
00123 }
00124 
00125 /*
00126  * call-seq:
00127  *    session.timeout -> integer
00128  *
00129  * Gets how long until the session expires in seconds.
00130  *
00131 */
00132 static VALUE ossl_ssl_session_get_timeout(VALUE self)
00133 {
00134         SSL_SESSION *ctx;
00135         time_t t;
00136 
00137         GetSSLSession(self, ctx);
00138 
00139         t = SSL_SESSION_get_timeout(ctx);
00140 
00141         return TIMET2NUM(t);
00142 }
00143 
00144 /*
00145  * call-seq:
00146  *    session.time=(Time) -> Time
00147  *    session.time=(integer) -> Time
00148  *
00149  * Sets start time of the session. Time resolution is in seconds.
00150  *
00151 */
00152 static VALUE ossl_ssl_session_set_time(VALUE self, VALUE time_v)
00153 {
00154         SSL_SESSION *ctx;
00155         long t;
00156 
00157         GetSSLSession(self, ctx);
00158         if (rb_obj_is_instance_of(time_v, rb_cTime)) {
00159                 time_v = rb_funcall(time_v, rb_intern("to_i"), 0);
00160         }
00161         t = NUM2LONG(time_v);
00162         SSL_SESSION_set_time(ctx, t);
00163         return ossl_ssl_session_get_time(self);
00164 }
00165 
00166 /*
00167  * call-seq:
00168  *    session.timeout=(integer) -> integer
00169  *
00170  * Sets how long until the session expires in seconds.
00171  *
00172 */
00173 static VALUE ossl_ssl_session_set_timeout(VALUE self, VALUE time_v)
00174 {
00175         SSL_SESSION *ctx;
00176         long t;
00177 
00178         GetSSLSession(self, ctx);
00179         t = NUM2LONG(time_v);
00180         SSL_SESSION_set_timeout(ctx, t);
00181         return ossl_ssl_session_get_timeout(self);
00182 }
00183 
00184 #ifdef HAVE_SSL_SESSION_GET_ID
00185 /*
00186  * call-seq:
00187  *    session.id -> aString
00188  *
00189  * Returns the Session ID.
00190 */
00191 static VALUE ossl_ssl_session_get_id(VALUE self)
00192 {
00193         SSL_SESSION *ctx;
00194         const unsigned char *p = NULL;
00195         unsigned int i = 0;
00196 
00197         GetSSLSession(self, ctx);
00198 
00199         p = SSL_SESSION_get_id(ctx, &i);
00200 
00201         return rb_str_new((const char *) p, i);
00202 }
00203 #endif
00204 
00205 /*
00206  * call-seq:
00207  *    session.to_der -> aString
00208  *
00209  * Returns an ASN1 encoded String that contains the Session object.
00210 */
00211 static VALUE ossl_ssl_session_to_der(VALUE self)
00212 {
00213         SSL_SESSION *ctx;
00214         unsigned char *p;
00215         int len;
00216         VALUE str;
00217 
00218         GetSSLSession(self, ctx);
00219         len = i2d_SSL_SESSION(ctx, NULL);
00220         if (len <= 0) {
00221                 ossl_raise(eSSLSession, "i2d_SSL_SESSION");
00222         }
00223 
00224         str = rb_str_new(0, len);
00225         p = (unsigned char *)RSTRING_PTR(str);
00226         i2d_SSL_SESSION(ctx, &p);
00227         ossl_str_adjust(str, p);
00228         return str;
00229 }
00230 
00231 /*
00232  * call-seq:
00233  *    session.to_pem -> String
00234  *
00235  * Returns a PEM encoded String that contains the Session object.
00236 */
00237 static VALUE ossl_ssl_session_to_pem(VALUE self)
00238 {
00239         SSL_SESSION *ctx;
00240         BIO *out;
00241         BUF_MEM *buf;
00242         VALUE str;
00243         int i;
00244 
00245         GetSSLSession(self, ctx);
00246 
00247         if (!(out = BIO_new(BIO_s_mem()))) {
00248                 ossl_raise(eSSLSession, "BIO_s_mem()");
00249         }
00250 
00251         if (!(i=PEM_write_bio_SSL_SESSION(out, ctx))) {
00252                 BIO_free(out);
00253                 ossl_raise(eSSLSession, "SSL_SESSION_print()");
00254         }
00255 
00256         BIO_get_mem_ptr(out, &buf);
00257         str = rb_str_new(buf->data, buf->length);
00258         BIO_free(out);
00259 
00260         return str;
00261 }
00262 
00263 
00264 /*
00265  * call-seq:
00266  *    session.to_text -> String
00267  *
00268  * Shows everything in the Session object.
00269 */
00270 static VALUE ossl_ssl_session_to_text(VALUE self)
00271 {
00272         SSL_SESSION *ctx;
00273         BIO *out;
00274         BUF_MEM *buf;
00275         VALUE str;
00276 
00277         GetSSLSession(self, ctx);
00278 
00279         if (!(out = BIO_new(BIO_s_mem()))) {
00280                 ossl_raise(eSSLSession, "BIO_s_mem()");
00281         }
00282 
00283         if (!SSL_SESSION_print(out, ctx)) {
00284                 BIO_free(out);
00285                 ossl_raise(eSSLSession, "SSL_SESSION_print()");
00286         }
00287 
00288         BIO_get_mem_ptr(out, &buf);
00289         str = rb_str_new(buf->data, buf->length);
00290         BIO_free(out);
00291 
00292         return str;
00293 }
00294 
00295 
00296 void Init_ossl_ssl_session(void)
00297 {
00298 #if 0
00299         mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
00300         mSSL = rb_define_module_under(mOSSL, "SSL");
00301 #endif
00302         cSSLSession = rb_define_class_under(mSSL, "Session", rb_cObject);
00303         eSSLSession = rb_define_class_under(cSSLSession, "SessionError", eOSSLError);
00304 
00305         rb_define_alloc_func(cSSLSession, ossl_ssl_session_alloc);
00306         rb_define_method(cSSLSession, "initialize", ossl_ssl_session_initialize, 1);
00307 
00308         rb_define_method(cSSLSession, "==", ossl_ssl_session_eq, 1);
00309 
00310         rb_define_method(cSSLSession, "time", ossl_ssl_session_get_time, 0);
00311         rb_define_method(cSSLSession, "time=", ossl_ssl_session_set_time, 1);
00312         rb_define_method(cSSLSession, "timeout", ossl_ssl_session_get_timeout, 0);
00313         rb_define_method(cSSLSession, "timeout=", ossl_ssl_session_set_timeout, 1);
00314 
00315 #ifdef HAVE_SSL_SESSION_GET_ID
00316         rb_define_method(cSSLSession, "id", ossl_ssl_session_get_id, 0);
00317 #else
00318         rb_undef_method(cSSLSession, "id");
00319 #endif
00320         rb_define_method(cSSLSession, "to_der", ossl_ssl_session_to_der, 0);
00321         rb_define_method(cSSLSession, "to_pem", ossl_ssl_session_to_pem, 0);
00322         rb_define_method(cSSLSession, "to_text", ossl_ssl_session_to_text, 0);
00323 }
00324