00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "ossl.h"
00014
00015 #if defined(HAVE_UNISTD_H)
00016 # include <unistd.h>
00017 #endif
00018
00019 #define numberof(ary) (int)(sizeof(ary)/sizeof(ary[0]))
00020
00021 #ifdef _WIN32
00022 # define TO_SOCKET(s) _get_osfhandle(s)
00023 #else
00024 # define TO_SOCKET(s) s
00025 #endif
00026
00027 VALUE mSSL;
00028 VALUE eSSLError;
00029 VALUE cSSLContext;
00030 VALUE cSSLSocket;
00031
00032 #define ossl_sslctx_set_cert(o,v) rb_iv_set((o),"@cert",(v))
00033 #define ossl_sslctx_set_key(o,v) rb_iv_set((o),"@key",(v))
00034 #define ossl_sslctx_set_client_ca(o,v) rb_iv_set((o),"@client_ca",(v))
00035 #define ossl_sslctx_set_ca_file(o,v) rb_iv_set((o),"@ca_file",(v))
00036 #define ossl_sslctx_set_ca_path(o,v) rb_iv_set((o),"@ca_path",(v))
00037 #define ossl_sslctx_set_timeout(o,v) rb_iv_set((o),"@timeout",(v))
00038 #define ossl_sslctx_set_verify_mode(o,v) rb_iv_set((o),"@verify_mode",(v))
00039 #define ossl_sslctx_set_verify_dep(o,v) rb_iv_set((o),"@verify_depth",(v))
00040 #define ossl_sslctx_set_verify_cb(o,v) rb_iv_set((o),"@verify_callback",(v))
00041 #define ossl_sslctx_set_options(o,v) rb_iv_set((o),"@options",(v))
00042 #define ossl_sslctx_set_cert_store(o,v) rb_iv_set((o),"@cert_store",(v))
00043 #define ossl_sslctx_set_extra_cert(o,v) rb_iv_set((o),"@extra_chain_cert",(v))
00044 #define ossl_sslctx_set_client_cert_cb(o,v) rb_iv_set((o),"@client_cert_cb",(v))
00045 #define ossl_sslctx_set_tmp_dh_cb(o,v) rb_iv_set((o),"@tmp_dh_callback",(v))
00046 #define ossl_sslctx_set_sess_id_ctx(o, v) rb_iv_get((o),"@session_id_context"(v))
00047
00048 #define ossl_sslctx_get_cert(o) rb_iv_get((o),"@cert")
00049 #define ossl_sslctx_get_key(o) rb_iv_get((o),"@key")
00050 #define ossl_sslctx_get_client_ca(o) rb_iv_get((o),"@client_ca")
00051 #define ossl_sslctx_get_ca_file(o) rb_iv_get((o),"@ca_file")
00052 #define ossl_sslctx_get_ca_path(o) rb_iv_get((o),"@ca_path")
00053 #define ossl_sslctx_get_timeout(o) rb_iv_get((o),"@timeout")
00054 #define ossl_sslctx_get_verify_mode(o) rb_iv_get((o),"@verify_mode")
00055 #define ossl_sslctx_get_verify_dep(o) rb_iv_get((o),"@verify_depth")
00056 #define ossl_sslctx_get_verify_cb(o) rb_iv_get((o),"@verify_callback")
00057 #define ossl_sslctx_get_options(o) rb_iv_get((o),"@options")
00058 #define ossl_sslctx_get_cert_store(o) rb_iv_get((o),"@cert_store")
00059 #define ossl_sslctx_get_extra_cert(o) rb_iv_get((o),"@extra_chain_cert")
00060 #define ossl_sslctx_get_client_cert_cb(o) rb_iv_get((o),"@client_cert_cb")
00061 #define ossl_sslctx_get_tmp_dh_cb(o) rb_iv_get((o),"@tmp_dh_callback")
00062 #define ossl_sslctx_get_sess_id_ctx(o) rb_iv_get((o),"@session_id_context")
00063
00064 static const char *ossl_sslctx_attrs[] = {
00065 "cert", "key", "client_ca", "ca_file", "ca_path",
00066 "timeout", "verify_mode", "verify_depth",
00067 "verify_callback", "options", "cert_store", "extra_chain_cert",
00068 "client_cert_cb", "tmp_dh_callback", "session_id_context",
00069 "session_get_cb", "session_new_cb", "session_remove_cb",
00070 #ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
00071 "servername_cb",
00072 #endif
00073 };
00074
00075 #define ossl_ssl_get_io(o) rb_iv_get((o),"@io")
00076 #define ossl_ssl_get_ctx(o) rb_iv_get((o),"@context")
00077 #define ossl_ssl_get_sync_close(o) rb_iv_get((o),"@sync_close")
00078 #define ossl_ssl_get_x509(o) rb_iv_get((o),"@x509")
00079 #define ossl_ssl_get_key(o) rb_iv_get((o),"@key")
00080 #define ossl_ssl_get_tmp_dh(o) rb_iv_get((o),"@tmp_dh")
00081
00082 #define ossl_ssl_set_io(o,v) rb_iv_set((o),"@io",(v))
00083 #define ossl_ssl_set_ctx(o,v) rb_iv_set((o),"@context",(v))
00084 #define ossl_ssl_set_sync_close(o,v) rb_iv_set((o),"@sync_close",(v))
00085 #define ossl_ssl_set_x509(o,v) rb_iv_set((o),"@x509",(v))
00086 #define ossl_ssl_set_key(o,v) rb_iv_set((o),"@key",(v))
00087 #define ossl_ssl_set_tmp_dh(o,v) rb_iv_set((o),"@tmp_dh",(v))
00088
00089 static const char *ossl_ssl_attr_readers[] = { "io", "context", };
00090 static const char *ossl_ssl_attrs[] = {
00091 #ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
00092 "hostname",
00093 #endif
00094 "sync_close",
00095 };
00096
00097 ID ID_callback_state;
00098
00099
00100
00101
00102 struct {
00103 const char *name;
00104 SSL_METHOD *(*func)(void);
00105 } ossl_ssl_method_tab[] = {
00106 #define OSSL_SSL_METHOD_ENTRY(name) { #name, (SSL_METHOD *(*)(void))name##_method }
00107 OSSL_SSL_METHOD_ENTRY(TLSv1),
00108 OSSL_SSL_METHOD_ENTRY(TLSv1_server),
00109 OSSL_SSL_METHOD_ENTRY(TLSv1_client),
00110 OSSL_SSL_METHOD_ENTRY(SSLv2),
00111 OSSL_SSL_METHOD_ENTRY(SSLv2_server),
00112 OSSL_SSL_METHOD_ENTRY(SSLv2_client),
00113 OSSL_SSL_METHOD_ENTRY(SSLv3),
00114 OSSL_SSL_METHOD_ENTRY(SSLv3_server),
00115 OSSL_SSL_METHOD_ENTRY(SSLv3_client),
00116 OSSL_SSL_METHOD_ENTRY(SSLv23),
00117 OSSL_SSL_METHOD_ENTRY(SSLv23_server),
00118 OSSL_SSL_METHOD_ENTRY(SSLv23_client),
00119 #undef OSSL_SSL_METHOD_ENTRY
00120 };
00121
00122 int ossl_ssl_ex_vcb_idx;
00123 int ossl_ssl_ex_store_p;
00124 int ossl_ssl_ex_ptr_idx;
00125 int ossl_ssl_ex_client_cert_cb_idx;
00126 int ossl_ssl_ex_tmp_dh_callback_idx;
00127
00128 static void
00129 ossl_sslctx_free(SSL_CTX *ctx)
00130 {
00131 if(ctx && SSL_CTX_get_ex_data(ctx, ossl_ssl_ex_store_p)== (void*)1)
00132 ctx->cert_store = NULL;
00133 SSL_CTX_free(ctx);
00134 }
00135
00136 static VALUE
00137 ossl_sslctx_s_alloc(VALUE klass)
00138 {
00139 SSL_CTX *ctx;
00140
00141 ctx = SSL_CTX_new(SSLv23_method());
00142 if (!ctx) {
00143 ossl_raise(eSSLError, "SSL_CTX_new:");
00144 }
00145 SSL_CTX_set_mode(ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
00146 SSL_CTX_set_options(ctx, SSL_OP_ALL);
00147 return Data_Wrap_Struct(klass, 0, ossl_sslctx_free, ctx);
00148 }
00149
00150 static VALUE
00151 ossl_sslctx_set_ssl_version(VALUE self, VALUE ssl_method)
00152 {
00153 SSL_METHOD *method = NULL;
00154 const char *s;
00155 int i;
00156
00157 SSL_CTX *ctx;
00158 if(TYPE(ssl_method) == T_SYMBOL)
00159 s = rb_id2name(SYM2ID(ssl_method));
00160 else
00161 s = StringValuePtr(ssl_method);
00162 for (i = 0; i < numberof(ossl_ssl_method_tab); i++) {
00163 if (strcmp(ossl_ssl_method_tab[i].name, s) == 0) {
00164 method = ossl_ssl_method_tab[i].func();
00165 break;
00166 }
00167 }
00168 if (!method) {
00169 ossl_raise(rb_eArgError, "unknown SSL method `%s'.", s);
00170 }
00171 Data_Get_Struct(self, SSL_CTX, ctx);
00172 if (SSL_CTX_set_ssl_version(ctx, method) != 1) {
00173 ossl_raise(eSSLError, "SSL_CTX_set_ssl_version:");
00174 }
00175
00176 return ssl_method;
00177 }
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187 static VALUE
00188 ossl_sslctx_initialize(int argc, VALUE *argv, VALUE self)
00189 {
00190 VALUE ssl_method;
00191 int i;
00192
00193 for(i = 0; i < numberof(ossl_sslctx_attrs); i++){
00194 char buf[32];
00195 snprintf(buf, sizeof(buf), "@%s", ossl_sslctx_attrs[i]);
00196 rb_iv_set(self, buf, Qnil);
00197 }
00198 if (rb_scan_args(argc, argv, "01", &ssl_method) == 0){
00199 return self;
00200 }
00201 ossl_sslctx_set_ssl_version(self, ssl_method);
00202
00203 return self;
00204 }
00205
00206 static VALUE
00207 ossl_call_client_cert_cb(VALUE obj)
00208 {
00209 VALUE cb, ary, cert, key;
00210 SSL *ssl;
00211
00212 Data_Get_Struct(obj, SSL, ssl);
00213 cb = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_client_cert_cb_idx);
00214 if (NIL_P(cb)) return Qfalse;
00215 ary = rb_funcall(cb, rb_intern("call"), 1, obj);
00216 Check_Type(ary, T_ARRAY);
00217 GetX509CertPtr(cert = rb_ary_entry(ary, 0));
00218 GetPKeyPtr(key = rb_ary_entry(ary, 1));
00219 ossl_ssl_set_x509(obj, cert);
00220 ossl_ssl_set_key(obj, key);
00221
00222 return Qtrue;
00223 }
00224
00225 static int
00226 ossl_client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
00227 {
00228 VALUE obj;
00229 int status, success;
00230
00231 obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
00232 success = rb_protect((VALUE(*)_((VALUE)))ossl_call_client_cert_cb,
00233 obj, &status);
00234 if (status || !success) return 0;
00235 *x509 = DupX509CertPtr(ossl_ssl_get_x509(obj));
00236 *pkey = DupPKeyPtr(ossl_ssl_get_key(obj));
00237
00238 return 1;
00239 }
00240
00241 #if !defined(OPENSSL_NO_DH)
00242 static VALUE
00243 ossl_call_tmp_dh_callback(VALUE *args)
00244 {
00245 SSL *ssl;
00246 VALUE cb, dh;
00247 EVP_PKEY *pkey;
00248
00249 Data_Get_Struct(args[0], SSL, ssl);
00250 cb = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_tmp_dh_callback_idx);
00251 if (NIL_P(cb)) return Qfalse;
00252 dh = rb_funcall(cb, rb_intern("call"), 3, args[0], args[1], args[2]);
00253 pkey = GetPKeyPtr(dh);
00254 if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DH) return Qfalse;
00255 ossl_ssl_set_tmp_dh(args[0], dh);
00256
00257 return Qtrue;
00258 }
00259
00260 static DH*
00261 ossl_tmp_dh_callback(SSL *ssl, int is_export, int keylength)
00262 {
00263 VALUE args[3];
00264 int status, success;
00265
00266 args[0] = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
00267 args[1] = INT2FIX(is_export);
00268 args[2] = INT2FIX(keylength);
00269 success = rb_protect((VALUE(*)_((VALUE)))ossl_call_tmp_dh_callback,
00270 (VALUE)args, &status);
00271 if (status || !success) return NULL;
00272
00273 return GetPKeyPtr(ossl_ssl_get_tmp_dh(args[0]))->pkey.dh;
00274 }
00275
00276 static DH*
00277 ossl_default_tmp_dh_callback(SSL *ssl, int is_export, int keylength)
00278 {
00279 rb_warning("using default DH parameters.");
00280
00281 switch(keylength){
00282 case 512:
00283 return OSSL_DEFAULT_DH_512;
00284 case 1024:
00285 return OSSL_DEFAULT_DH_1024;
00286 }
00287 return NULL;
00288 }
00289 #endif
00290
00291 static int
00292 ossl_ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
00293 {
00294 VALUE cb;
00295 SSL *ssl;
00296
00297 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
00298 cb = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_vcb_idx);
00299 X509_STORE_CTX_set_ex_data(ctx, ossl_verify_cb_idx, (void*)cb);
00300 return ossl_verify_cb(preverify_ok, ctx);
00301 }
00302
00303 static VALUE
00304 ossl_call_session_get_cb(VALUE ary)
00305 {
00306 VALUE ssl_obj, sslctx_obj, cb;
00307
00308 Check_Type(ary, T_ARRAY);
00309 ssl_obj = rb_ary_entry(ary, 0);
00310
00311 sslctx_obj = rb_iv_get(ssl_obj, "@context");
00312 if (NIL_P(sslctx_obj)) return Qnil;
00313 cb = rb_iv_get(sslctx_obj, "@session_get_cb");
00314 if (NIL_P(cb)) return Qnil;
00315
00316 return rb_funcall(cb, rb_intern("call"), 1, ary);
00317 }
00318
00319
00320 static SSL_SESSION *
00321 ossl_sslctx_session_get_cb(SSL *ssl, unsigned char *buf, int len, int *copy)
00322 {
00323 VALUE ary, ssl_obj, ret_obj;
00324 SSL_SESSION *sess;
00325 void *ptr;
00326 int state = 0;
00327
00328 OSSL_Debug("SSL SESSION get callback entered");
00329 if ((ptr = SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx)) == NULL)
00330 return NULL;
00331 ssl_obj = (VALUE)ptr;
00332 ary = rb_ary_new2(2);
00333 rb_ary_push(ary, ssl_obj);
00334 rb_ary_push(ary, rb_str_new((const char *)buf, len));
00335
00336 ret_obj = rb_protect((VALUE(*)_((VALUE)))ossl_call_session_get_cb, ary, &state);
00337 if (state) {
00338 rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(state));
00339 return NULL;
00340 }
00341 if (!rb_obj_is_instance_of(ret_obj, cSSLSession))
00342 return NULL;
00343
00344 SafeGetSSLSession(ret_obj, sess);
00345 *copy = 1;
00346
00347 return sess;
00348 }
00349
00350 static VALUE
00351 ossl_call_session_new_cb(VALUE ary)
00352 {
00353 VALUE ssl_obj, sslctx_obj, cb;
00354
00355 Check_Type(ary, T_ARRAY);
00356 ssl_obj = rb_ary_entry(ary, 0);
00357
00358 sslctx_obj = rb_iv_get(ssl_obj, "@context");
00359 if (NIL_P(sslctx_obj)) return Qnil;
00360 cb = rb_iv_get(sslctx_obj, "@session_new_cb");
00361 if (NIL_P(cb)) return Qnil;
00362
00363 return rb_funcall(cb, rb_intern("call"), 1, ary);
00364 }
00365
00366
00367 static int
00368 ossl_sslctx_session_new_cb(SSL *ssl, SSL_SESSION *sess)
00369 {
00370 VALUE ary, ssl_obj, sess_obj, ret_obj;
00371 void *ptr;
00372 int state = 0;
00373
00374 OSSL_Debug("SSL SESSION new callback entered");
00375
00376 if ((ptr = SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx)) == NULL)
00377 return 1;
00378 ssl_obj = (VALUE)ptr;
00379 sess_obj = rb_obj_alloc(cSSLSession);
00380 CRYPTO_add(&sess->references, 1, CRYPTO_LOCK_SSL_SESSION);
00381 DATA_PTR(sess_obj) = sess;
00382
00383 ary = rb_ary_new2(2);
00384 rb_ary_push(ary, ssl_obj);
00385 rb_ary_push(ary, sess_obj);
00386
00387 ret_obj = rb_protect((VALUE(*)_((VALUE)))ossl_call_session_new_cb, ary, &state);
00388 if (state) {
00389 rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(state));
00390 return 0;
00391 }
00392
00393 return RTEST(ret_obj) ? 1 : 0;
00394 }
00395
00396 #if 0
00397 static VALUE
00398 ossl_call_session_remove_cb(VALUE ary)
00399 {
00400 VALUE sslctx_obj, cb;
00401
00402 Check_Type(ary, T_ARRAY);
00403 sslctx_obj = rb_ary_entry(ary, 0);
00404
00405 cb = rb_iv_get(sslctx_obj, "@session_remove_cb");
00406 if (NIL_P(cb)) return Qnil;
00407
00408 return rb_funcall(cb, rb_intern("call"), 1, ary);
00409 }
00410 #endif
00411
00412 static void
00413 ossl_sslctx_session_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
00414 {
00415 VALUE ary, sslctx_obj, sess_obj, ret_obj;
00416 void *ptr;
00417 int state = 0;
00418
00419 OSSL_Debug("SSL SESSION remove callback entered");
00420
00421 if ((ptr = SSL_CTX_get_ex_data(ctx, ossl_ssl_ex_ptr_idx)) == NULL)
00422 return;
00423 sslctx_obj = (VALUE)ptr;
00424 sess_obj = rb_obj_alloc(cSSLSession);
00425 CRYPTO_add(&sess->references, 1, CRYPTO_LOCK_SSL_SESSION);
00426 DATA_PTR(sess_obj) = sess;
00427
00428 ary = rb_ary_new2(2);
00429 rb_ary_push(ary, sslctx_obj);
00430 rb_ary_push(ary, sess_obj);
00431
00432 ret_obj = rb_protect((VALUE(*)_((VALUE)))ossl_call_session_new_cb, ary, &state);
00433 if (state) {
00434
00435
00436
00437
00438
00439 }
00440 }
00441
00442 static VALUE
00443 ossl_sslctx_add_extra_chain_cert_i(VALUE i, VALUE arg)
00444 {
00445 X509 *x509;
00446 SSL_CTX *ctx;
00447
00448 Data_Get_Struct(arg, SSL_CTX, ctx);
00449 x509 = DupX509CertPtr(i);
00450 if(!SSL_CTX_add_extra_chain_cert(ctx, x509)){
00451 ossl_raise(eSSLError, NULL);
00452 }
00453
00454 return i;
00455 }
00456
00457 static VALUE ossl_sslctx_setup(VALUE self);
00458
00459 #ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
00460 static VALUE
00461 ossl_call_servername_cb(VALUE ary)
00462 {
00463 VALUE ssl_obj, sslctx_obj, cb, ret_obj;
00464
00465 Check_Type(ary, T_ARRAY);
00466 ssl_obj = rb_ary_entry(ary, 0);
00467
00468 sslctx_obj = rb_iv_get(ssl_obj, "@context");
00469 if (NIL_P(sslctx_obj)) return Qnil;
00470 cb = rb_iv_get(sslctx_obj, "@servername_cb");
00471 if (NIL_P(cb)) return Qnil;
00472
00473 ret_obj = rb_funcall(cb, rb_intern("call"), 1, ary);
00474 if (rb_obj_is_kind_of(ret_obj, cSSLContext)) {
00475 SSL *ssl;
00476 SSL_CTX *ctx2;
00477
00478 ossl_sslctx_setup(ret_obj);
00479 Data_Get_Struct(ssl_obj, SSL, ssl);
00480 Data_Get_Struct(ret_obj, SSL_CTX, ctx2);
00481 SSL_set_SSL_CTX(ssl, ctx2);
00482 } else if (!NIL_P(ret_obj)) {
00483 rb_raise(rb_eArgError, "servername_cb must return an OpenSSL::SSL::SSLContext object or nil");
00484 }
00485
00486 return ret_obj;
00487 }
00488
00489 static int
00490 ssl_servername_cb(SSL *ssl, int *ad, void *arg)
00491 {
00492 VALUE ary, ssl_obj, ret_obj;
00493 void *ptr;
00494 int state = 0;
00495 const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
00496
00497 if (!servername)
00498 return SSL_TLSEXT_ERR_OK;
00499
00500 if ((ptr = SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx)) == NULL)
00501 return SSL_TLSEXT_ERR_ALERT_FATAL;
00502 ssl_obj = (VALUE)ptr;
00503 ary = rb_ary_new2(2);
00504 rb_ary_push(ary, ssl_obj);
00505 rb_ary_push(ary, rb_str_new2(servername));
00506
00507 ret_obj = rb_protect((VALUE(*)_((VALUE)))ossl_call_servername_cb, ary, &state);
00508 if (state) {
00509 rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(state));
00510 return SSL_TLSEXT_ERR_ALERT_FATAL;
00511 }
00512
00513 return SSL_TLSEXT_ERR_OK;
00514 }
00515 #endif
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525 static VALUE
00526 ossl_sslctx_setup(VALUE self)
00527 {
00528 SSL_CTX *ctx;
00529 X509 *cert = NULL, *client_ca = NULL;
00530 X509_STORE *store;
00531 EVP_PKEY *key = NULL;
00532 char *ca_path = NULL, *ca_file = NULL;
00533 int i, verify_mode;
00534 VALUE val;
00535
00536 if(OBJ_FROZEN(self)) return Qnil;
00537 Data_Get_Struct(self, SSL_CTX, ctx);
00538
00539 #if !defined(OPENSSL_NO_DH)
00540 if (RTEST(ossl_sslctx_get_tmp_dh_cb(self))){
00541 SSL_CTX_set_tmp_dh_callback(ctx, ossl_tmp_dh_callback);
00542 }
00543 else{
00544 SSL_CTX_set_tmp_dh_callback(ctx, ossl_default_tmp_dh_callback);
00545 }
00546 #endif
00547 SSL_CTX_set_ex_data(ctx, ossl_ssl_ex_ptr_idx, (void*)self);
00548
00549 val = ossl_sslctx_get_cert_store(self);
00550 if(!NIL_P(val)){
00551
00552
00553
00554
00555
00556
00557 store = GetX509StorePtr(val);
00558 SSL_CTX_set_cert_store(ctx, store);
00559 SSL_CTX_set_ex_data(ctx, ossl_ssl_ex_store_p, (void*)1);
00560 }
00561
00562 val = ossl_sslctx_get_extra_cert(self);
00563 if(!NIL_P(val)){
00564 rb_block_call(val, rb_intern("each"), 0, 0, ossl_sslctx_add_extra_chain_cert_i, self);
00565 }
00566
00567
00568 val = ossl_sslctx_get_cert(self);
00569 cert = NIL_P(val) ? NULL : GetX509CertPtr(val);
00570 val = ossl_sslctx_get_key(self);
00571 key = NIL_P(val) ? NULL : GetPKeyPtr(val);
00572 if (cert && key) {
00573 if (!SSL_CTX_use_certificate(ctx, cert)) {
00574
00575 ossl_raise(eSSLError, "SSL_CTX_use_certificate:");
00576 }
00577 if (!SSL_CTX_use_PrivateKey(ctx, key)) {
00578
00579 ossl_raise(eSSLError, "SSL_CTX_use_PrivateKey:");
00580 }
00581 if (!SSL_CTX_check_private_key(ctx)) {
00582 ossl_raise(eSSLError, "SSL_CTX_check_private_key:");
00583 }
00584 }
00585
00586 val = ossl_sslctx_get_client_ca(self);
00587 if(!NIL_P(val)){
00588 if(TYPE(val) == T_ARRAY){
00589 for(i = 0; i < RARRAY_LEN(val); i++){
00590 client_ca = GetX509CertPtr(RARRAY_PTR(val)[i]);
00591 if (!SSL_CTX_add_client_CA(ctx, client_ca)){
00592
00593 ossl_raise(eSSLError, "SSL_CTX_add_client_CA");
00594 }
00595 }
00596 }
00597 else{
00598 client_ca = GetX509CertPtr(val);
00599 if (!SSL_CTX_add_client_CA(ctx, client_ca)){
00600
00601 ossl_raise(eSSLError, "SSL_CTX_add_client_CA");
00602 }
00603 }
00604 }
00605
00606 val = ossl_sslctx_get_ca_file(self);
00607 ca_file = NIL_P(val) ? NULL : StringValuePtr(val);
00608 val = ossl_sslctx_get_ca_path(self);
00609 ca_path = NIL_P(val) ? NULL : StringValuePtr(val);
00610 if(ca_file || ca_path){
00611 if (!SSL_CTX_load_verify_locations(ctx, ca_file, ca_path))
00612 rb_warning("can't set verify locations");
00613 }
00614
00615 val = ossl_sslctx_get_verify_mode(self);
00616 verify_mode = NIL_P(val) ? SSL_VERIFY_NONE : NUM2INT(val);
00617 SSL_CTX_set_verify(ctx, verify_mode, ossl_ssl_verify_callback);
00618 if (RTEST(ossl_sslctx_get_client_cert_cb(self)))
00619 SSL_CTX_set_client_cert_cb(ctx, ossl_client_cert_cb);
00620
00621 val = ossl_sslctx_get_timeout(self);
00622 if(!NIL_P(val)) SSL_CTX_set_timeout(ctx, NUM2LONG(val));
00623
00624 val = ossl_sslctx_get_verify_dep(self);
00625 if(!NIL_P(val)) SSL_CTX_set_verify_depth(ctx, NUM2LONG(val));
00626
00627 val = ossl_sslctx_get_options(self);
00628 if(!NIL_P(val)) SSL_CTX_set_options(ctx, NUM2LONG(val));
00629 rb_obj_freeze(self);
00630
00631 val = ossl_sslctx_get_sess_id_ctx(self);
00632 if (!NIL_P(val)){
00633 StringValue(val);
00634 if (!SSL_CTX_set_session_id_context(ctx, (unsigned char *)RSTRING_PTR(val),
00635 RSTRING_LEN(val))){
00636 ossl_raise(eSSLError, "SSL_CTX_set_session_id_context:");
00637 }
00638 }
00639
00640 if (RTEST(rb_iv_get(self, "@session_get_cb"))) {
00641 SSL_CTX_sess_set_get_cb(ctx, ossl_sslctx_session_get_cb);
00642 OSSL_Debug("SSL SESSION get callback added");
00643 }
00644 if (RTEST(rb_iv_get(self, "@session_new_cb"))) {
00645 SSL_CTX_sess_set_new_cb(ctx, ossl_sslctx_session_new_cb);
00646 OSSL_Debug("SSL SESSION new callback added");
00647 }
00648 if (RTEST(rb_iv_get(self, "@session_remove_cb"))) {
00649 SSL_CTX_sess_set_remove_cb(ctx, ossl_sslctx_session_remove_cb);
00650 OSSL_Debug("SSL SESSION remove callback added");
00651 }
00652
00653 #ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
00654 val = rb_iv_get(self, "@servername_cb");
00655 if (!NIL_P(val)) {
00656 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb);
00657 OSSL_Debug("SSL TLSEXT servername callback added");
00658 }
00659 #endif
00660
00661 return Qtrue;
00662 }
00663
00664 static VALUE
00665 ossl_ssl_cipher_to_ary(SSL_CIPHER *cipher)
00666 {
00667 VALUE ary;
00668 int bits, alg_bits;
00669
00670 ary = rb_ary_new2(4);
00671 rb_ary_push(ary, rb_str_new2(SSL_CIPHER_get_name(cipher)));
00672 rb_ary_push(ary, rb_str_new2(SSL_CIPHER_get_version(cipher)));
00673 bits = SSL_CIPHER_get_bits(cipher, &alg_bits);
00674 rb_ary_push(ary, INT2FIX(bits));
00675 rb_ary_push(ary, INT2FIX(alg_bits));
00676
00677 return ary;
00678 }
00679
00680
00681
00682
00683
00684 static VALUE
00685 ossl_sslctx_get_ciphers(VALUE self)
00686 {
00687 SSL_CTX *ctx;
00688 STACK_OF(SSL_CIPHER) *ciphers;
00689 SSL_CIPHER *cipher;
00690 VALUE ary;
00691 int i, num;
00692
00693 Data_Get_Struct(self, SSL_CTX, ctx);
00694 if(!ctx){
00695 rb_warning("SSL_CTX is not initialized.");
00696 return Qnil;
00697 }
00698 ciphers = ctx->cipher_list;
00699
00700 if (!ciphers)
00701 return rb_ary_new();
00702
00703 num = sk_num((STACK*)ciphers);
00704 ary = rb_ary_new2(num);
00705 for(i = 0; i < num; i++){
00706 cipher = (SSL_CIPHER*)sk_value((STACK*)ciphers, i);
00707 rb_ary_push(ary, ossl_ssl_cipher_to_ary(cipher));
00708 }
00709 return ary;
00710 }
00711
00712
00713
00714
00715
00716
00717
00718 static VALUE
00719 ossl_sslctx_set_ciphers(VALUE self, VALUE v)
00720 {
00721 SSL_CTX *ctx;
00722 VALUE str, elem;
00723 int i;
00724
00725 rb_check_frozen(self);
00726 if (NIL_P(v))
00727 return v;
00728 else if (TYPE(v) == T_ARRAY) {
00729 str = rb_str_new(0, 0);
00730 for (i = 0; i < RARRAY_LEN(v); i++) {
00731 elem = rb_ary_entry(v, i);
00732 if (TYPE(elem) == T_ARRAY) elem = rb_ary_entry(elem, 0);
00733 elem = rb_String(elem);
00734 rb_str_append(str, elem);
00735 if (i < RARRAY_LEN(v)-1) rb_str_cat2(str, ":");
00736 }
00737 } else {
00738 str = v;
00739 StringValue(str);
00740 }
00741
00742 Data_Get_Struct(self, SSL_CTX, ctx);
00743 if(!ctx){
00744 ossl_raise(eSSLError, "SSL_CTX is not initialized.");
00745 return Qnil;
00746 }
00747 if (!SSL_CTX_set_cipher_list(ctx, RSTRING_PTR(str))) {
00748 ossl_raise(eSSLError, "SSL_CTX_set_cipher_list:");
00749 }
00750
00751 return v;
00752 }
00753
00754
00755
00756
00757
00758
00759
00760 static VALUE
00761 ossl_sslctx_session_add(VALUE self, VALUE arg)
00762 {
00763 SSL_CTX *ctx;
00764 SSL_SESSION *sess;
00765
00766 Data_Get_Struct(self, SSL_CTX, ctx);
00767 SafeGetSSLSession(arg, sess);
00768
00769 return SSL_CTX_add_session(ctx, sess) == 1 ? Qtrue : Qfalse;
00770 }
00771
00772
00773
00774
00775
00776
00777 static VALUE
00778 ossl_sslctx_session_remove(VALUE self, VALUE arg)
00779 {
00780 SSL_CTX *ctx;
00781 SSL_SESSION *sess;
00782
00783 Data_Get_Struct(self, SSL_CTX, ctx);
00784 SafeGetSSLSession(arg, sess);
00785
00786 return SSL_CTX_remove_session(ctx, sess) == 1 ? Qtrue : Qfalse;
00787 }
00788
00789
00790
00791
00792
00793
00794 static VALUE
00795 ossl_sslctx_get_session_cache_mode(VALUE self)
00796 {
00797 SSL_CTX *ctx;
00798
00799 Data_Get_Struct(self, SSL_CTX, ctx);
00800
00801 return LONG2NUM(SSL_CTX_get_session_cache_mode(ctx));
00802 }
00803
00804
00805
00806
00807
00808
00809 static VALUE
00810 ossl_sslctx_set_session_cache_mode(VALUE self, VALUE arg)
00811 {
00812 SSL_CTX *ctx;
00813
00814 Data_Get_Struct(self, SSL_CTX, ctx);
00815
00816 SSL_CTX_set_session_cache_mode(ctx, NUM2LONG(arg));
00817
00818 return arg;
00819 }
00820
00821
00822
00823
00824
00825
00826 static VALUE
00827 ossl_sslctx_get_session_cache_size(VALUE self)
00828 {
00829 SSL_CTX *ctx;
00830
00831 Data_Get_Struct(self, SSL_CTX, ctx);
00832
00833 return LONG2NUM(SSL_CTX_sess_get_cache_size(ctx));
00834 }
00835
00836
00837
00838
00839
00840
00841 static VALUE
00842 ossl_sslctx_set_session_cache_size(VALUE self, VALUE arg)
00843 {
00844 SSL_CTX *ctx;
00845
00846 Data_Get_Struct(self, SSL_CTX, ctx);
00847
00848 SSL_CTX_sess_set_cache_size(ctx, NUM2LONG(arg));
00849
00850 return arg;
00851 }
00852
00853
00854
00855
00856
00857
00858 static VALUE
00859 ossl_sslctx_get_session_cache_stats(VALUE self)
00860 {
00861 SSL_CTX *ctx;
00862 VALUE hash;
00863
00864 Data_Get_Struct(self, SSL_CTX, ctx);
00865
00866 hash = rb_hash_new();
00867 rb_hash_aset(hash, ID2SYM(rb_intern("cache_num")), LONG2NUM(SSL_CTX_sess_number(ctx)));
00868 rb_hash_aset(hash, ID2SYM(rb_intern("connect")), LONG2NUM(SSL_CTX_sess_connect(ctx)));
00869 rb_hash_aset(hash, ID2SYM(rb_intern("connect_good")), LONG2NUM(SSL_CTX_sess_connect_good(ctx)));
00870 rb_hash_aset(hash, ID2SYM(rb_intern("connect_renegotiate")), LONG2NUM(SSL_CTX_sess_connect_renegotiate(ctx)));
00871 rb_hash_aset(hash, ID2SYM(rb_intern("accept")), LONG2NUM(SSL_CTX_sess_accept(ctx)));
00872 rb_hash_aset(hash, ID2SYM(rb_intern("accept_good")), LONG2NUM(SSL_CTX_sess_accept_good(ctx)));
00873 rb_hash_aset(hash, ID2SYM(rb_intern("accept_renegotiate")), LONG2NUM(SSL_CTX_sess_accept_renegotiate(ctx)));
00874 rb_hash_aset(hash, ID2SYM(rb_intern("cache_hits")), LONG2NUM(SSL_CTX_sess_hits(ctx)));
00875 rb_hash_aset(hash, ID2SYM(rb_intern("cb_hits")), LONG2NUM(SSL_CTX_sess_cb_hits(ctx)));
00876 rb_hash_aset(hash, ID2SYM(rb_intern("cache_misses")), LONG2NUM(SSL_CTX_sess_misses(ctx)));
00877 rb_hash_aset(hash, ID2SYM(rb_intern("cache_full")), LONG2NUM(SSL_CTX_sess_cache_full(ctx)));
00878 rb_hash_aset(hash, ID2SYM(rb_intern("timeouts")), LONG2NUM(SSL_CTX_sess_timeouts(ctx)));
00879
00880 return hash;
00881 }
00882
00883
00884
00885
00886
00887
00888
00889 static VALUE
00890 ossl_sslctx_flush_sessions(int argc, VALUE *argv, VALUE self)
00891 {
00892 VALUE arg1;
00893 SSL_CTX *ctx;
00894 time_t tm = 0;
00895
00896 rb_scan_args(argc, argv, "01", &arg1);
00897
00898 Data_Get_Struct(self, SSL_CTX, ctx);
00899
00900 if (NIL_P(arg1)) {
00901 tm = time(0);
00902 } else if (rb_obj_is_instance_of(arg1, rb_cTime)) {
00903 tm = NUM2LONG(rb_funcall(arg1, rb_intern("to_i"), 0));
00904 } else {
00905 rb_raise(rb_eArgError, "arg must be Time or nil");
00906 }
00907
00908 SSL_CTX_flush_sessions(ctx, (long)tm);
00909
00910 return self;
00911 }
00912
00913
00914
00915
00916 static void
00917 ossl_ssl_shutdown(SSL *ssl)
00918 {
00919 if (ssl) {
00920 SSL_shutdown(ssl);
00921 SSL_clear(ssl);
00922 }
00923 }
00924
00925 static void
00926 ossl_ssl_free(SSL *ssl)
00927 {
00928 ossl_ssl_shutdown(ssl);
00929 SSL_free(ssl);
00930 }
00931
00932 static VALUE
00933 ossl_ssl_s_alloc(VALUE klass)
00934 {
00935 return Data_Wrap_Struct(klass, 0, ossl_ssl_free, NULL);
00936 }
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952 static VALUE
00953 ossl_ssl_initialize(int argc, VALUE *argv, VALUE self)
00954 {
00955 VALUE io, ctx;
00956
00957 if (rb_scan_args(argc, argv, "11", &io, &ctx) == 1) {
00958 ctx = rb_funcall(cSSLContext, rb_intern("new"), 0);
00959 }
00960 OSSL_Check_Kind(ctx, cSSLContext);
00961 Check_Type(io, T_FILE);
00962 ossl_ssl_set_io(self, io);
00963 ossl_ssl_set_ctx(self, ctx);
00964 ossl_ssl_set_sync_close(self, Qfalse);
00965 ossl_sslctx_setup(ctx);
00966
00967 rb_iv_set(self, "@hostname", Qnil);
00968
00969 rb_call_super(0, 0);
00970
00971 return self;
00972 }
00973
00974 static VALUE
00975 ossl_ssl_setup(VALUE self)
00976 {
00977 VALUE io, v_ctx, cb;
00978 SSL_CTX *ctx;
00979 SSL *ssl;
00980 rb_io_t *fptr;
00981
00982 Data_Get_Struct(self, SSL, ssl);
00983 if(!ssl){
00984 #ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
00985 VALUE hostname = rb_iv_get(self, "@hostname");
00986 #endif
00987
00988 v_ctx = ossl_ssl_get_ctx(self);
00989 Data_Get_Struct(v_ctx, SSL_CTX, ctx);
00990
00991 ssl = SSL_new(ctx);
00992 if (!ssl) {
00993 ossl_raise(eSSLError, "SSL_new:");
00994 }
00995 DATA_PTR(self) = ssl;
00996
00997 #ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
00998 if (!NIL_P(hostname)) {
00999 if (SSL_set_tlsext_host_name(ssl, StringValuePtr(hostname)) != 1)
01000 ossl_raise(eSSLError, "SSL_set_tlsext_host_name:");
01001 }
01002 #endif
01003 io = ossl_ssl_get_io(self);
01004 GetOpenFile(io, fptr);
01005 rb_io_check_readable(fptr);
01006 rb_io_check_writable(fptr);
01007 SSL_set_fd(ssl, TO_SOCKET(FPTR_TO_FD(fptr)));
01008 SSL_set_ex_data(ssl, ossl_ssl_ex_ptr_idx, (void*)self);
01009 cb = ossl_sslctx_get_verify_cb(v_ctx);
01010 SSL_set_ex_data(ssl, ossl_ssl_ex_vcb_idx, (void*)cb);
01011 cb = ossl_sslctx_get_client_cert_cb(v_ctx);
01012 SSL_set_ex_data(ssl, ossl_ssl_ex_client_cert_cb_idx, (void*)cb);
01013 cb = ossl_sslctx_get_tmp_dh_cb(v_ctx);
01014 SSL_set_ex_data(ssl, ossl_ssl_ex_tmp_dh_callback_idx, (void*)cb);
01015 }
01016
01017 return Qtrue;
01018 }
01019
01020 #ifdef _WIN32
01021 #define ssl_get_error(ssl, ret) (errno = WSAGetLastError(), SSL_get_error(ssl, ret))
01022 #else
01023 #define ssl_get_error(ssl, ret) SSL_get_error(ssl, ret)
01024 #endif
01025
01026 static void
01027 write_would_block(int nonblock)
01028 {
01029 if (nonblock) {
01030 VALUE exc = ossl_exc_new(eSSLError, "write would block");
01031 rb_extend_object(exc, rb_mWaitWritable);
01032 rb_exc_raise(exc);
01033 }
01034 }
01035
01036 static void
01037 read_would_block(int nonblock)
01038 {
01039 if (nonblock) {
01040 VALUE exc = ossl_exc_new(eSSLError, "read would block");
01041 rb_extend_object(exc, rb_mWaitReadable);
01042 rb_exc_raise(exc);
01043 }
01044 }
01045
01046 static VALUE
01047 ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, int nonblock)
01048 {
01049 SSL *ssl;
01050 rb_io_t *fptr;
01051 int ret, ret2;
01052 VALUE cb_state;
01053
01054 rb_ivar_set(self, ID_callback_state, Qnil);
01055
01056 Data_Get_Struct(self, SSL, ssl);
01057 GetOpenFile(ossl_ssl_get_io(self), fptr);
01058 for(;;){
01059 ret = func(ssl);
01060
01061 cb_state = rb_ivar_get(self, ID_callback_state);
01062 if (!NIL_P(cb_state))
01063 rb_jump_tag(NUM2INT(cb_state));
01064
01065 if (ret > 0)
01066 break;
01067
01068 switch((ret2 = ssl_get_error(ssl, ret))){
01069 case SSL_ERROR_WANT_WRITE:
01070 write_would_block(nonblock);
01071 rb_io_wait_writable(FPTR_TO_FD(fptr));
01072 continue;
01073 case SSL_ERROR_WANT_READ:
01074 read_would_block(nonblock);
01075 rb_io_wait_readable(FPTR_TO_FD(fptr));
01076 continue;
01077 case SSL_ERROR_SYSCALL:
01078 if (errno) rb_sys_fail(funcname);
01079 ossl_raise(eSSLError, "%s SYSCALL returned=%d errno=%d state=%s", funcname, ret2, errno, SSL_state_string_long(ssl));
01080 default:
01081 ossl_raise(eSSLError, "%s returned=%d errno=%d state=%s", funcname, ret2, errno, SSL_state_string_long(ssl));
01082 }
01083 }
01084
01085 return self;
01086 }
01087
01088
01089
01090
01091
01092 static VALUE
01093 ossl_ssl_connect(VALUE self)
01094 {
01095 ossl_ssl_setup(self);
01096 return ossl_start_ssl(self, SSL_connect, "SSL_connect", 0);
01097 }
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117 static VALUE
01118 ossl_ssl_connect_nonblock(VALUE self)
01119 {
01120 ossl_ssl_setup(self);
01121 return ossl_start_ssl(self, SSL_connect, "SSL_connect", 1);
01122 }
01123
01124
01125
01126
01127
01128 static VALUE
01129 ossl_ssl_accept(VALUE self)
01130 {
01131 ossl_ssl_setup(self);
01132 return ossl_start_ssl(self, SSL_accept, "SSL_accept", 0);
01133 }
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153 static VALUE
01154 ossl_ssl_accept_nonblock(VALUE self)
01155 {
01156 ossl_ssl_setup(self);
01157 return ossl_start_ssl(self, SSL_accept, "SSL_accept", 1);
01158 }
01159
01160 static VALUE
01161 ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
01162 {
01163 SSL *ssl;
01164 int ilen, nread = 0;
01165 VALUE len, str;
01166 rb_io_t *fptr;
01167
01168 rb_scan_args(argc, argv, "11", &len, &str);
01169 ilen = NUM2INT(len);
01170 if(NIL_P(str)) str = rb_str_new(0, ilen);
01171 else{
01172 StringValue(str);
01173 rb_str_modify(str);
01174 rb_str_resize(str, ilen);
01175 }
01176 if(ilen == 0) return str;
01177
01178 Data_Get_Struct(self, SSL, ssl);
01179 GetOpenFile(ossl_ssl_get_io(self), fptr);
01180 if (ssl) {
01181 if(!nonblock && SSL_pending(ssl) <= 0)
01182 rb_thread_wait_fd(FPTR_TO_FD(fptr));
01183 for (;;){
01184 nread = SSL_read(ssl, RSTRING_PTR(str), RSTRING_LEN(str));
01185 switch(ssl_get_error(ssl, nread)){
01186 case SSL_ERROR_NONE:
01187 goto end;
01188 case SSL_ERROR_ZERO_RETURN:
01189 rb_eof_error();
01190 case SSL_ERROR_WANT_WRITE:
01191 write_would_block(nonblock);
01192 rb_io_wait_writable(FPTR_TO_FD(fptr));
01193 continue;
01194 case SSL_ERROR_WANT_READ:
01195 read_would_block(nonblock);
01196 rb_io_wait_readable(FPTR_TO_FD(fptr));
01197 continue;
01198 case SSL_ERROR_SYSCALL:
01199 if(ERR_peek_error() == 0 && nread == 0) rb_eof_error();
01200 rb_sys_fail(0);
01201 default:
01202 ossl_raise(eSSLError, "SSL_read:");
01203 }
01204 }
01205 }
01206 else {
01207 ID meth = nonblock ? rb_intern("read_nonblock") : rb_intern("sysread");
01208 rb_warning("SSL session is not started yet.");
01209 return rb_funcall(ossl_ssl_get_io(self), meth, 2, len, str);
01210 }
01211
01212 end:
01213 rb_str_set_len(str, nread);
01214 OBJ_TAINT(str);
01215
01216 return str;
01217 }
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229 static VALUE
01230 ossl_ssl_read(int argc, VALUE *argv, VALUE self)
01231 {
01232 return ossl_ssl_read_internal(argc, argv, self, 0);
01233 }
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244 static VALUE
01245 ossl_ssl_read_nonblock(int argc, VALUE *argv, VALUE self)
01246 {
01247 return ossl_ssl_read_internal(argc, argv, self, 1);
01248 }
01249
01250 static VALUE
01251 ossl_ssl_write_internal(VALUE self, VALUE str, int nonblock)
01252 {
01253 SSL *ssl;
01254 int nwrite = 0;
01255 rb_io_t *fptr;
01256
01257 StringValue(str);
01258 Data_Get_Struct(self, SSL, ssl);
01259 GetOpenFile(ossl_ssl_get_io(self), fptr);
01260
01261 if (ssl) {
01262 for (;;){
01263 nwrite = SSL_write(ssl, RSTRING_PTR(str), RSTRING_LEN(str));
01264 switch(ssl_get_error(ssl, nwrite)){
01265 case SSL_ERROR_NONE:
01266 goto end;
01267 case SSL_ERROR_WANT_WRITE:
01268 write_would_block(nonblock);
01269 rb_io_wait_writable(FPTR_TO_FD(fptr));
01270 continue;
01271 case SSL_ERROR_WANT_READ:
01272 read_would_block(nonblock);
01273 rb_io_wait_readable(FPTR_TO_FD(fptr));
01274 continue;
01275 case SSL_ERROR_SYSCALL:
01276 if (errno) rb_sys_fail(0);
01277 default:
01278 ossl_raise(eSSLError, "SSL_write:");
01279 }
01280 }
01281 }
01282 else {
01283 ID id_syswrite = rb_intern("syswrite");
01284 rb_warning("SSL session is not started yet.");
01285 return rb_funcall(ossl_ssl_get_io(self), id_syswrite, 1, str);
01286 }
01287
01288 end:
01289 return INT2NUM(nwrite);
01290 }
01291
01292
01293
01294
01295
01296 static VALUE
01297 ossl_ssl_write(VALUE self, VALUE str)
01298 {
01299 return ossl_ssl_write_internal(self, str, 0);
01300 }
01301
01302
01303
01304
01305
01306 static VALUE
01307 ossl_ssl_write_nonblock(VALUE self, VALUE str)
01308 {
01309 return ossl_ssl_write_internal(self, str, 1);
01310 }
01311
01312
01313
01314
01315
01316 static VALUE
01317 ossl_ssl_close(VALUE self)
01318 {
01319 SSL *ssl;
01320
01321 Data_Get_Struct(self, SSL, ssl);
01322 ossl_ssl_shutdown(ssl);
01323 if (RTEST(ossl_ssl_get_sync_close(self)))
01324 rb_funcall(ossl_ssl_get_io(self), rb_intern("close"), 0);
01325
01326 return Qnil;
01327 }
01328
01329
01330
01331
01332
01333 static VALUE
01334 ossl_ssl_get_cert(VALUE self)
01335 {
01336 SSL *ssl;
01337 X509 *cert = NULL;
01338
01339 Data_Get_Struct(self, SSL, ssl);
01340 if (ssl) {
01341 rb_warning("SSL session is not started yet.");
01342 return Qnil;
01343 }
01344
01345
01346
01347
01348
01349 cert = SSL_get_certificate(ssl);
01350
01351 if (!cert) {
01352 return Qnil;
01353 }
01354 return ossl_x509_new(cert);
01355 }
01356
01357
01358
01359
01360
01361 static VALUE
01362 ossl_ssl_get_peer_cert(VALUE self)
01363 {
01364 SSL *ssl;
01365 X509 *cert = NULL;
01366 VALUE obj;
01367
01368 Data_Get_Struct(self, SSL, ssl);
01369
01370 if (!ssl){
01371 rb_warning("SSL session is not started yet.");
01372 return Qnil;
01373 }
01374
01375 cert = SSL_get_peer_certificate(ssl);
01376
01377 if (!cert) {
01378 return Qnil;
01379 }
01380 obj = ossl_x509_new(cert);
01381 X509_free(cert);
01382
01383 return obj;
01384 }
01385
01386
01387
01388
01389
01390 static VALUE
01391 ossl_ssl_get_peer_cert_chain(VALUE self)
01392 {
01393 SSL *ssl;
01394 STACK_OF(X509) *chain;
01395 X509 *cert;
01396 VALUE ary;
01397 int i, num;
01398
01399 Data_Get_Struct(self, SSL, ssl);
01400 if(!ssl){
01401 rb_warning("SSL session is not started yet.");
01402 return Qnil;
01403 }
01404 chain = SSL_get_peer_cert_chain(ssl);
01405 if(!chain) return Qnil;
01406 num = sk_X509_num(chain);
01407 ary = rb_ary_new2(num);
01408 for (i = 0; i < num; i++){
01409 cert = sk_X509_value(chain, i);
01410 rb_ary_push(ary, ossl_x509_new(cert));
01411 }
01412
01413 return ary;
01414 }
01415
01416
01417
01418
01419
01420 static VALUE
01421 ossl_ssl_get_cipher(VALUE self)
01422 {
01423 SSL *ssl;
01424 SSL_CIPHER *cipher;
01425
01426 Data_Get_Struct(self, SSL, ssl);
01427 if (!ssl) {
01428 rb_warning("SSL session is not started yet.");
01429 return Qnil;
01430 }
01431 cipher = (SSL_CIPHER *)SSL_get_current_cipher(ssl);
01432
01433 return ossl_ssl_cipher_to_ary(cipher);
01434 }
01435
01436
01437
01438
01439
01440 static VALUE
01441 ossl_ssl_get_state(VALUE self)
01442 {
01443 SSL *ssl;
01444 VALUE ret;
01445
01446 Data_Get_Struct(self, SSL, ssl);
01447 if (!ssl) {
01448 rb_warning("SSL session is not started yet.");
01449 return Qnil;
01450 }
01451 ret = rb_str_new2(SSL_state_string(ssl));
01452 if (ruby_verbose) {
01453 rb_str_cat2(ret, ": ");
01454 rb_str_cat2(ret, SSL_state_string_long(ssl));
01455 }
01456 return ret;
01457 }
01458
01459
01460
01461
01462
01463 static VALUE
01464 ossl_ssl_pending(VALUE self)
01465 {
01466 SSL *ssl;
01467
01468 Data_Get_Struct(self, SSL, ssl);
01469 if (!ssl) {
01470 rb_warning("SSL session is not started yet.");
01471 return Qnil;
01472 }
01473
01474 return INT2NUM(SSL_pending(ssl));
01475 }
01476
01477
01478
01479
01480
01481
01482 static VALUE
01483 ossl_ssl_session_reused(VALUE self)
01484 {
01485 SSL *ssl;
01486
01487 Data_Get_Struct(self, SSL, ssl);
01488 if (!ssl) {
01489 rb_warning("SSL session is not started yet.");
01490 return Qnil;
01491 }
01492
01493 switch(SSL_session_reused(ssl)) {
01494 case 1: return Qtrue;
01495 case 0: return Qfalse;
01496 default: ossl_raise(eSSLError, "SSL_session_reused");
01497 }
01498 }
01499
01500
01501
01502
01503
01504
01505 static VALUE
01506 ossl_ssl_set_session(VALUE self, VALUE arg1)
01507 {
01508 SSL *ssl;
01509 SSL_SESSION *sess;
01510
01511
01512 ossl_ssl_setup(self);
01513
01514 Data_Get_Struct(self, SSL, ssl);
01515 if (!ssl) {
01516 rb_warning("SSL session is not started yet.");
01517 return Qnil;
01518 }
01519
01520 SafeGetSSLSession(arg1, sess);
01521
01522 if (SSL_set_session(ssl, sess) != 1)
01523 ossl_raise(eSSLError, "SSL_set_session");
01524
01525 return arg1;
01526 }
01527
01528 static VALUE
01529 ossl_ssl_get_verify_result(VALUE self)
01530 {
01531 SSL *ssl;
01532
01533 Data_Get_Struct(self, SSL, ssl);
01534 if (!ssl) {
01535 rb_warning("SSL session is not started yet.");
01536 return Qnil;
01537 }
01538
01539 return INT2FIX(SSL_get_verify_result(ssl));
01540 }
01541
01542 void
01543 Init_ossl_ssl()
01544 {
01545 int i;
01546 VALUE ary;
01547
01548 #if 0
01549 mOSSL = rb_define_module("OpenSSL");
01550 #endif
01551
01552 ID_callback_state = rb_intern("@callback_state");
01553
01554 ossl_ssl_ex_vcb_idx = SSL_get_ex_new_index(0,(void *)"ossl_ssl_ex_vcb_idx",0,0,0);
01555 ossl_ssl_ex_store_p = SSL_get_ex_new_index(0,(void *)"ossl_ssl_ex_store_p",0,0,0);
01556 ossl_ssl_ex_ptr_idx = SSL_get_ex_new_index(0,(void *)"ossl_ssl_ex_ptr_idx",0,0,0);
01557 ossl_ssl_ex_client_cert_cb_idx =
01558 SSL_get_ex_new_index(0,(void *)"ossl_ssl_ex_client_cert_cb_idx",0,0,0);
01559 ossl_ssl_ex_tmp_dh_callback_idx =
01560 SSL_get_ex_new_index(0,(void *)"ossl_ssl_ex_tmp_dh_callback_idx",0,0,0);
01561
01562 mSSL = rb_define_module_under(mOSSL, "SSL");
01563 eSSLError = rb_define_class_under(mSSL, "SSLError", eOSSLError);
01564
01565 Init_ossl_ssl_session();
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575 cSSLContext = rb_define_class_under(mSSL, "SSLContext", rb_cObject);
01576 rb_define_alloc_func(cSSLContext, ossl_sslctx_s_alloc);
01577 for(i = 0; i < numberof(ossl_sslctx_attrs); i++)
01578 rb_attr(cSSLContext, rb_intern(ossl_sslctx_attrs[i]), 1, 1, Qfalse);
01579 rb_define_alias(cSSLContext, "ssl_timeout", "timeout");
01580 rb_define_alias(cSSLContext, "ssl_timeout=", "timeout=");
01581 rb_define_method(cSSLContext, "initialize", ossl_sslctx_initialize, -1);
01582 rb_define_method(cSSLContext, "ssl_version=", ossl_sslctx_set_ssl_version, 1);
01583 rb_define_method(cSSLContext, "ciphers", ossl_sslctx_get_ciphers, 0);
01584 rb_define_method(cSSLContext, "ciphers=", ossl_sslctx_set_ciphers, 1);
01585
01586 rb_define_method(cSSLContext, "setup", ossl_sslctx_setup, 0);
01587
01588
01589 rb_define_const(cSSLContext, "SESSION_CACHE_OFF", LONG2FIX(SSL_SESS_CACHE_OFF));
01590 rb_define_const(cSSLContext, "SESSION_CACHE_CLIENT", LONG2FIX(SSL_SESS_CACHE_CLIENT));
01591 rb_define_const(cSSLContext, "SESSION_CACHE_SERVER", LONG2FIX(SSL_SESS_CACHE_SERVER));
01592 rb_define_const(cSSLContext, "SESSION_CACHE_BOTH", LONG2FIX(SSL_SESS_CACHE_BOTH));
01593 rb_define_const(cSSLContext, "SESSION_CACHE_NO_AUTO_CLEAR", LONG2FIX(SSL_SESS_CACHE_NO_AUTO_CLEAR));
01594 rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL_LOOKUP", LONG2FIX(SSL_SESS_CACHE_NO_INTERNAL_LOOKUP));
01595 rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL_STORE", LONG2FIX(SSL_SESS_CACHE_NO_INTERNAL_STORE));
01596 rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL", LONG2FIX(SSL_SESS_CACHE_NO_INTERNAL));
01597 rb_define_method(cSSLContext, "session_add", ossl_sslctx_session_add, 1);
01598 rb_define_method(cSSLContext, "session_remove", ossl_sslctx_session_remove, 1);
01599 rb_define_method(cSSLContext, "session_cache_mode", ossl_sslctx_get_session_cache_mode, 0);
01600 rb_define_method(cSSLContext, "session_cache_mode=", ossl_sslctx_set_session_cache_mode, 1);
01601 rb_define_method(cSSLContext, "session_cache_size", ossl_sslctx_get_session_cache_size, 0);
01602 rb_define_method(cSSLContext, "session_cache_size=", ossl_sslctx_set_session_cache_size, 1);
01603 rb_define_method(cSSLContext, "session_cache_stats", ossl_sslctx_get_session_cache_stats, 0);
01604 rb_define_method(cSSLContext, "flush_sessions", ossl_sslctx_flush_sessions, -1);
01605
01606 ary = rb_ary_new2(numberof(ossl_ssl_method_tab));
01607 for (i = 0; i < numberof(ossl_ssl_method_tab); i++) {
01608 rb_ary_push(ary, ID2SYM(rb_intern(ossl_ssl_method_tab[i].name)));
01609 }
01610 rb_obj_freeze(ary);
01611
01612 rb_define_const(cSSLContext, "METHODS", ary);
01613
01614
01615
01616
01617
01618
01619
01620 cSSLSocket = rb_define_class_under(mSSL, "SSLSocket", rb_cObject);
01621 rb_define_alloc_func(cSSLSocket, ossl_ssl_s_alloc);
01622 for(i = 0; i < numberof(ossl_ssl_attr_readers); i++)
01623 rb_attr(cSSLSocket, rb_intern(ossl_ssl_attr_readers[i]), 1, 0, Qfalse);
01624 for(i = 0; i < numberof(ossl_ssl_attrs); i++)
01625 rb_attr(cSSLSocket, rb_intern(ossl_ssl_attrs[i]), 1, 1, Qfalse);
01626 rb_define_alias(cSSLSocket, "to_io", "io");
01627 rb_define_method(cSSLSocket, "initialize", ossl_ssl_initialize, -1);
01628 rb_define_method(cSSLSocket, "connect", ossl_ssl_connect, 0);
01629 rb_define_method(cSSLSocket, "connect_nonblock", ossl_ssl_connect_nonblock, 0);
01630 rb_define_method(cSSLSocket, "accept", ossl_ssl_accept, 0);
01631 rb_define_method(cSSLSocket, "accept_nonblock", ossl_ssl_accept_nonblock, 0);
01632 rb_define_method(cSSLSocket, "sysread", ossl_ssl_read, -1);
01633 rb_define_private_method(cSSLSocket, "sysread_nonblock", ossl_ssl_read_nonblock, -1);
01634 rb_define_method(cSSLSocket, "syswrite", ossl_ssl_write, 1);
01635 rb_define_private_method(cSSLSocket, "syswrite_nonblock", ossl_ssl_write_nonblock, 1);
01636 rb_define_method(cSSLSocket, "sysclose", ossl_ssl_close, 0);
01637 rb_define_method(cSSLSocket, "cert", ossl_ssl_get_cert, 0);
01638 rb_define_method(cSSLSocket, "peer_cert", ossl_ssl_get_peer_cert, 0);
01639 rb_define_method(cSSLSocket, "peer_cert_chain", ossl_ssl_get_peer_cert_chain, 0);
01640 rb_define_method(cSSLSocket, "cipher", ossl_ssl_get_cipher, 0);
01641 rb_define_method(cSSLSocket, "state", ossl_ssl_get_state, 0);
01642 rb_define_method(cSSLSocket, "pending", ossl_ssl_pending, 0);
01643 rb_define_method(cSSLSocket, "session_reused?", ossl_ssl_session_reused, 0);
01644 rb_define_method(cSSLSocket, "session=", ossl_ssl_set_session, 1);
01645 rb_define_method(cSSLSocket, "verify_result", ossl_ssl_get_verify_result, 0);
01646
01647 #define ossl_ssl_def_const(x) rb_define_const(mSSL, #x, INT2NUM(SSL_##x))
01648
01649 ossl_ssl_def_const(VERIFY_NONE);
01650 ossl_ssl_def_const(VERIFY_PEER);
01651 ossl_ssl_def_const(VERIFY_FAIL_IF_NO_PEER_CERT);
01652 ossl_ssl_def_const(VERIFY_CLIENT_ONCE);
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665 ossl_ssl_def_const(OP_ALL);
01666 #if defined(SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION)
01667 ossl_ssl_def_const(OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
01668 #endif
01669 #if defined(SSL_OP_SINGLE_ECDH_USE)
01670 ossl_ssl_def_const(OP_SINGLE_ECDH_USE);
01671 #endif
01672 ossl_ssl_def_const(OP_SINGLE_DH_USE);
01673 ossl_ssl_def_const(OP_EPHEMERAL_RSA);
01674 #if defined(SSL_OP_CIPHER_SERVER_PREFERENCE)
01675 ossl_ssl_def_const(OP_CIPHER_SERVER_PREFERENCE);
01676 #endif
01677 ossl_ssl_def_const(OP_TLS_ROLLBACK_BUG);
01678 ossl_ssl_def_const(OP_NO_SSLv2);
01679 ossl_ssl_def_const(OP_NO_SSLv3);
01680 ossl_ssl_def_const(OP_NO_TLSv1);
01681 #if defined(SSL_OP_NO_TICKET)
01682 ossl_ssl_def_const(OP_NO_TICKET);
01683 #endif
01684 ossl_ssl_def_const(OP_PKCS1_CHECK_1);
01685 ossl_ssl_def_const(OP_PKCS1_CHECK_2);
01686 ossl_ssl_def_const(OP_NETSCAPE_CA_DN_BUG);
01687 ossl_ssl_def_const(OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG);
01688 }
01689