|
Ruby 1.9.2p290(2011-07-09revision32553)
|
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
1.7.3