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