• Main Page
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

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                         (void)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         if (rb_obj_is_instance_of(time_v, rb_cTime)) {
00180                 time_v = rb_funcall(time_v, rb_intern("to_i"), 0);
00181         }
00182         t = NUM2LONG(time_v);
00183         SSL_SESSION_set_timeout(ctx, t);
00184         return ossl_ssl_session_get_timeout(self);
00185 }
00186 
00187 #ifdef HAVE_SSL_SESSION_GET_ID
00188 /*
00189  * call-seq:
00190  *    session.id -> aString
00191  *
00192  * Returns the Session ID.
00193 */
00194 static VALUE ossl_ssl_session_get_id(VALUE self)
00195 {
00196         SSL_SESSION *ctx;
00197         const unsigned char *p = NULL;
00198         unsigned int i = 0;
00199 
00200         GetSSLSession(self, ctx);
00201 
00202         p = SSL_SESSION_get_id(ctx, &i);
00203 
00204         return rb_str_new((const char *) p, i);
00205 }
00206 #endif
00207 
00208 /*
00209  * call-seq:
00210  *    session.to_der -> aString
00211  *
00212  * Returns an ASN1 encoded String that contains the Session object.
00213 */
00214 static VALUE ossl_ssl_session_to_der(VALUE self)
00215 {
00216         SSL_SESSION *ctx;
00217         unsigned char buf[1024*10], *p;
00218         int len;
00219 
00220         GetSSLSession(self, ctx);
00221 
00222         p = buf;
00223         len = i2d_SSL_SESSION(ctx, &p);
00224 
00225         if (len <= 0)
00226                 ossl_raise(eSSLSession, "i2d_SSL_SESSION");
00227         else if (len >= sizeof(buf))
00228                 ossl_raise(eSSLSession, "i2d_SSL_SESSION too large");
00229 
00230         return rb_str_new((const char *) p, len);
00231 }
00232 
00233 /*
00234  * call-seq:
00235  *    session.to_pem -> String
00236  *
00237  * Returns a PEM encoded String that contains the Session object.
00238 */
00239 static VALUE ossl_ssl_session_to_pem(VALUE self)
00240 {
00241         SSL_SESSION *ctx;
00242         BIO *out;
00243         BUF_MEM *buf;
00244         VALUE str;
00245         int i;
00246 
00247         GetSSLSession(self, ctx);
00248 
00249         if (!(out = BIO_new(BIO_s_mem()))) {
00250                 ossl_raise(eSSLSession, "BIO_s_mem()");
00251         }
00252 
00253         if (!(i=PEM_write_bio_SSL_SESSION(out, ctx))) {
00254                 BIO_free(out);
00255                 ossl_raise(eSSLSession, "SSL_SESSION_print()");
00256         }
00257 
00258         BIO_get_mem_ptr(out, &buf);
00259         str = rb_str_new(buf->data, buf->length);
00260         BIO_free(out);
00261 
00262         return str;
00263 }
00264 
00265 
00266 /*
00267  * call-seq:
00268  *    session.to_text -> String
00269  *
00270  * Shows everything in the Session object.
00271 */
00272 static VALUE ossl_ssl_session_to_text(VALUE self)
00273 {
00274         SSL_SESSION *ctx;
00275         BIO *out;
00276         BUF_MEM *buf;
00277         VALUE str;
00278 
00279         GetSSLSession(self, ctx);
00280 
00281         if (!(out = BIO_new(BIO_s_mem()))) {
00282                 ossl_raise(eSSLSession, "BIO_s_mem()");
00283         }
00284 
00285         if (!SSL_SESSION_print(out, ctx)) {
00286                 BIO_free(out);
00287                 ossl_raise(eSSLSession, "SSL_SESSION_print()");
00288         }
00289 
00290         BIO_get_mem_ptr(out, &buf);
00291         str = rb_str_new(buf->data, buf->length);
00292         BIO_free(out);
00293 
00294         return str;
00295 }
00296 
00297 
00298 void Init_ossl_ssl_session(void)
00299 {
00300 #if 0 /* let rdoc know about mOSSL */
00301         mOSSL = rb_define_module("OpenSSL");
00302         mSSL = rb_define_module_under(mOSSL, "SSL");
00303 #endif
00304         cSSLSession = rb_define_class_under(mSSL, "Session", rb_cObject);
00305         eSSLSession = rb_define_class_under(cSSLSession, "SessionError", eOSSLError);
00306 
00307         rb_define_alloc_func(cSSLSession, ossl_ssl_session_alloc);
00308         rb_define_method(cSSLSession, "initialize", ossl_ssl_session_initialize, 1);
00309 
00310         rb_define_method(cSSLSession, "==", ossl_ssl_session_eq, 1);
00311 
00312         rb_define_method(cSSLSession, "time", ossl_ssl_session_get_time, 0);
00313         rb_define_method(cSSLSession, "time=", ossl_ssl_session_set_time, 1);
00314         rb_define_method(cSSLSession, "timeout", ossl_ssl_session_get_timeout, 0);
00315         rb_define_method(cSSLSession, "timeout=", ossl_ssl_session_set_timeout, 1);
00316 
00317 #ifdef HAVE_SSL_SESSION_GET_ID
00318         rb_define_method(cSSLSession, "id", ossl_ssl_session_get_id, 0);
00319 #else
00320         rb_undef_method(cSSLSession, "id");
00321 #endif
00322         rb_define_method(cSSLSession, "to_der", ossl_ssl_session_to_der, 0);
00323         rb_define_method(cSSLSession, "to_pem", ossl_ssl_session_to_pem, 0);
00324         rb_define_method(cSSLSession, "to_text", ossl_ssl_session_to_text, 0);
00325 }
00326 

Generated on Sat Jul 7 2012 15:29:11 for Ruby by  doxygen 1.7.1