Ruby
2.0.0p247(2013-06-27revision41674)
|
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