Ruby 1.9.2p136(2010-12-25revision30365)

- 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 */
    00108 static VALUE ossl_ssl_session_get_time(VALUE self)
    00109 {
    00110         SSL_SESSION *ctx;
    00111         time_t t;
    00112
    00113         GetSSLSession(self, ctx);
    00114
    00115         t = SSL_SESSION_get_time(ctx);
    00116
    00117         if (t == 0)
    00118                 return Qnil;
    00119
    00120         return rb_funcall(rb_cTime, rb_intern("at"), 1, TIMET2NUM(t));
    00121 }
    00122
    00123 /*
    00124  * call-seq:
    00125  *    session.timeout -> integer
    00126  *
    00127  * How long until the session expires in seconds.
    00128  *
    00129 */
    00130 static VALUE ossl_ssl_session_get_timeout(VALUE self)
    00131 {
    00132         SSL_SESSION *ctx;
    00133         time_t t;
    00134
    00135         GetSSLSession(self, ctx);
    00136
    00137         t = SSL_SESSION_get_timeout(ctx);
    00138
    00139         return TIMET2NUM(t);
    00140 }
    00141
    00142 #define SSLSESSION_SET_TIME(func)                                               \
    00143         static VALUE ossl_ssl_session_set_##func(VALUE self, VALUE time_v)      \
    00144         {                                                                       \
    00145                 SSL_SESSION *ctx;                                               \
    00146                 unsigned long t;                                                \
    00147                                                                                 \
    00148                 GetSSLSession(self, ctx);                                       \
    00149                                                                                 \
    00150                 if (rb_obj_is_instance_of(time_v, rb_cTime)) {                  \
    00151                         time_v = rb_funcall(time_v, rb_intern("to_i"), 0);      \
    00152                 } else if (FIXNUM_P(time_v)) {                                  \
    00153                         ;                                                       \
    00154                 } else {                                                        \
    00155                         rb_raise(rb_eArgError, "unknown type");                 \
    00156                 }                                                               \
    00157                                                                                 \
    00158                 t = NUM2ULONG(time_v);                                          \
    00159                                                                                 \
    00160                 SSL_SESSION_set_##func(ctx, t);                                 \
    00161                                                                                 \
    00162                 return ossl_ssl_session_get_##func(self);                       \
    00163         }
    00164
    00165 SSLSESSION_SET_TIME(time)
    00166 SSLSESSION_SET_TIME(timeout)
    00167
    00168 #ifdef HAVE_SSL_SESSION_GET_ID
    00169 /*
    00170  * call-seq:
    00171  *    session.id -> aString
    00172  *
    00173  * Returns the Session ID.
    00174 */
    00175 static VALUE ossl_ssl_session_get_id(VALUE self)
    00176 {
    00177         SSL_SESSION *ctx;
    00178         const unsigned char *p = NULL;
    00179         unsigned int i = 0;
    00180
    00181         GetSSLSession(self, ctx);
    00182
    00183         p = SSL_SESSION_get_id(ctx, &i);
    00184
    00185         return rb_str_new((const char *) p, i);
    00186 }
    00187 #endif
    00188
    00189 /*
    00190  * call-seq:
    00191  *    session.to_der -> aString
    00192  *
    00193  * Returns an ASN1 encoded String that contains the Session object.
    00194 */
    00195 static VALUE ossl_ssl_session_to_der(VALUE self)
    00196 {
    00197         SSL_SESSION *ctx;
    00198         unsigned char buf[1024*10], *p;
    00199         int len;
    00200
    00201         GetSSLSession(self, ctx);
    00202
    00203         p = buf;
    00204         len = i2d_SSL_SESSION(ctx, &p);
    00205
    00206         if (len <= 0)
    00207                 ossl_raise(eSSLSession, "i2d_SSL_SESSION");
    00208         else if (len >= sizeof(buf))
    00209                 ossl_raise(eSSLSession, "i2d_SSL_SESSION too large");
    00210
    00211         return rb_str_new((const char *) p, len);
    00212 }
    00213
    00214 /*
    00215  * call-seq:
    00216  *    session.to_pem -> String
    00217  *
    00218  * Returns a PEM encoded String that contains the Session object.
    00219 */
    00220 static VALUE ossl_ssl_session_to_pem(VALUE self)
    00221 {
    00222         SSL_SESSION *ctx;
    00223         BIO *out;
    00224         BUF_MEM *buf;
    00225         VALUE str;
    00226         int i;
    00227
    00228         GetSSLSession(self, ctx);
    00229
    00230         if (!(out = BIO_new(BIO_s_mem()))) {
    00231                 ossl_raise(eSSLSession, "BIO_s_mem()");
    00232         }
    00233
    00234         if (!(i=PEM_write_bio_SSL_SESSION(out, ctx))) {
    00235                 BIO_free(out);
    00236                 ossl_raise(eSSLSession, "SSL_SESSION_print()");
    00237         }
    00238
    00239         BIO_get_mem_ptr(out, &buf);
    00240         str = rb_str_new(buf->data, buf->length);
    00241         BIO_free(out);
    00242
    00243         return str;
    00244 }
    00245
    00246
    00247 /*
    00248  * call-seq:
    00249  *    session.to_text -> String
    00250  *
    00251  * Shows everything in the Session object.
    00252 */
    00253 static VALUE ossl_ssl_session_to_text(VALUE self)
    00254 {
    00255         SSL_SESSION *ctx;
    00256         BIO *out;
    00257         BUF_MEM *buf;
    00258         VALUE str;
    00259
    00260         GetSSLSession(self, ctx);
    00261
    00262         if (!(out = BIO_new(BIO_s_mem()))) {
    00263                 ossl_raise(eSSLSession, "BIO_s_mem()");
    00264         }
    00265
    00266         if (!SSL_SESSION_print(out, ctx)) {
    00267                 BIO_free(out);
    00268                 ossl_raise(eSSLSession, "SSL_SESSION_print()");
    00269         }
    00270
    00271         BIO_get_mem_ptr(out, &buf);
    00272         str = rb_str_new(buf->data, buf->length);
    00273         BIO_free(out);
    00274
    00275         return str;
    00276 }
    00277
    00278
    00279 void Init_ossl_ssl_session(void)
    00280 {
    00281 #if 0 /* let rdoc know about mOSSL */
    00282         mOSSL = rb_define_module("OpenSSL");
    00283         mSSL = rb_define_module_under(mOSSL, "SSL");
    00284 #endif
    00285         cSSLSession = rb_define_class_under(mSSL, "Session", rb_cObject);
    00286         eSSLSession = rb_define_class_under(cSSLSession, "SessionError", eOSSLError);
    00287
    00288         rb_define_alloc_func(cSSLSession, ossl_ssl_session_alloc);
    00289         rb_define_method(cSSLSession, "initialize", ossl_ssl_session_initialize, 1);
    00290
    00291         rb_define_method(cSSLSession, "==", ossl_ssl_session_eq, 1);
    00292
    00293         rb_define_method(cSSLSession, "time", ossl_ssl_session_get_time, 0);
    00294         rb_define_method(cSSLSession, "time=", ossl_ssl_session_set_time, 1);
    00295         rb_define_method(cSSLSession, "timeout", ossl_ssl_session_get_timeout, 0);
    00296         rb_define_method(cSSLSession, "timeout=", ossl_ssl_session_set_timeout, 1);
    00297
    00298 #ifdef HAVE_SSL_SESSION_GET_ID
    00299         rb_define_method(cSSLSession, "id", ossl_ssl_session_get_id, 0);
    00300 #else
    00301         rb_undef_method(cSSLSession, "id");
    00302 #endif
    00303         rb_define_method(cSSLSession, "to_der", ossl_ssl_session_to_der, 0);
    00304         rb_define_method(cSSLSession, "to_pem", ossl_ssl_session_to_pem, 0);
    00305         rb_define_method(cSSLSession, "to_text", ossl_ssl_session_to_text, 0);
    00306 }
    00307