00001
00002
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
00030
00031
00032
00033
00034
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
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
00087
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
00105
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
00125
00126
00127
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
00171
00172
00173
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
00191
00192
00193
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
00216
00217
00218
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
00249
00250
00251
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
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