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