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