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 ossl_ssl_shutdown(ssl);
00999 SSL_free(ssl);
01000 }
01001
01002 static VALUE
01003 ossl_ssl_s_alloc(VALUE klass)
01004 {
01005 return Data_Wrap_Struct(klass, 0, ossl_ssl_free, NULL);
01006 }
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024 static VALUE
01025 ossl_ssl_initialize(int argc, VALUE *argv, VALUE self)
01026 {
01027 VALUE io, ctx;
01028
01029 if (rb_scan_args(argc, argv, "11", &io, &ctx) == 1) {
01030 ctx = rb_funcall(cSSLContext, rb_intern("new"), 0);
01031 }
01032 OSSL_Check_Kind(ctx, cSSLContext);
01033 Check_Type(io, T_FILE);
01034 ossl_ssl_set_io(self, io);
01035 ossl_ssl_set_ctx(self, ctx);
01036 ossl_ssl_set_sync_close(self, Qfalse);
01037 ossl_sslctx_setup(ctx);
01038
01039 rb_iv_set(self, "@hostname", Qnil);
01040
01041 rb_call_super(0, 0);
01042
01043 return self;
01044 }
01045
01046 static VALUE
01047 ossl_ssl_setup(VALUE self)
01048 {
01049 VALUE io, v_ctx, cb;
01050 SSL_CTX *ctx;
01051 SSL *ssl;
01052 rb_io_t *fptr;
01053
01054 Data_Get_Struct(self, SSL, ssl);
01055 if(!ssl){
01056 #ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
01057 VALUE hostname = rb_iv_get(self, "@hostname");
01058 #endif
01059
01060 v_ctx = ossl_ssl_get_ctx(self);
01061 Data_Get_Struct(v_ctx, SSL_CTX, ctx);
01062
01063 ssl = SSL_new(ctx);
01064 if (!ssl) {
01065 ossl_raise(eSSLError, "SSL_new:");
01066 }
01067 DATA_PTR(self) = ssl;
01068
01069 #ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
01070 if (!NIL_P(hostname)) {
01071 if (SSL_set_tlsext_host_name(ssl, StringValuePtr(hostname)) != 1)
01072 ossl_raise(eSSLError, "SSL_set_tlsext_host_name:");
01073 }
01074 #endif
01075 io = ossl_ssl_get_io(self);
01076 GetOpenFile(io, fptr);
01077 rb_io_check_readable(fptr);
01078 rb_io_check_writable(fptr);
01079 SSL_set_fd(ssl, TO_SOCKET(FPTR_TO_FD(fptr)));
01080 SSL_set_ex_data(ssl, ossl_ssl_ex_ptr_idx, (void*)self);
01081 cb = ossl_sslctx_get_verify_cb(v_ctx);
01082 SSL_set_ex_data(ssl, ossl_ssl_ex_vcb_idx, (void*)cb);
01083 cb = ossl_sslctx_get_client_cert_cb(v_ctx);
01084 SSL_set_ex_data(ssl, ossl_ssl_ex_client_cert_cb_idx, (void*)cb);
01085 cb = ossl_sslctx_get_tmp_dh_cb(v_ctx);
01086 SSL_set_ex_data(ssl, ossl_ssl_ex_tmp_dh_callback_idx, (void*)cb);
01087 }
01088
01089 return Qtrue;
01090 }
01091
01092 #ifdef _WIN32
01093 #define ssl_get_error(ssl, ret) (errno = rb_w32_map_errno(WSAGetLastError()), SSL_get_error((ssl), (ret)))
01094 #else
01095 #define ssl_get_error(ssl, ret) SSL_get_error((ssl), (ret))
01096 #endif
01097
01098 static void
01099 write_would_block(int nonblock)
01100 {
01101 if (nonblock) {
01102 VALUE exc = ossl_exc_new(eSSLError, "write would block");
01103 rb_extend_object(exc, rb_mWaitWritable);
01104 rb_exc_raise(exc);
01105 }
01106 }
01107
01108 static void
01109 read_would_block(int nonblock)
01110 {
01111 if (nonblock) {
01112 VALUE exc = ossl_exc_new(eSSLError, "read would block");
01113 rb_extend_object(exc, rb_mWaitReadable);
01114 rb_exc_raise(exc);
01115 }
01116 }
01117
01118 static VALUE
01119 ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, int nonblock)
01120 {
01121 SSL *ssl;
01122 rb_io_t *fptr;
01123 int ret, ret2;
01124 VALUE cb_state;
01125
01126 rb_ivar_set(self, ID_callback_state, Qnil);
01127
01128 Data_Get_Struct(self, SSL, ssl);
01129 GetOpenFile(ossl_ssl_get_io(self), fptr);
01130 for(;;){
01131 ret = func(ssl);
01132
01133 cb_state = rb_ivar_get(self, ID_callback_state);
01134 if (!NIL_P(cb_state))
01135 rb_jump_tag(NUM2INT(cb_state));
01136
01137 if (ret > 0)
01138 break;
01139
01140 switch((ret2 = ssl_get_error(ssl, ret))){
01141 case SSL_ERROR_WANT_WRITE:
01142 write_would_block(nonblock);
01143 rb_io_wait_writable(FPTR_TO_FD(fptr));
01144 continue;
01145 case SSL_ERROR_WANT_READ:
01146 read_would_block(nonblock);
01147 rb_io_wait_readable(FPTR_TO_FD(fptr));
01148 continue;
01149 case SSL_ERROR_SYSCALL:
01150 if (errno) rb_sys_fail(funcname);
01151 ossl_raise(eSSLError, "%s SYSCALL returned=%d errno=%d state=%s", funcname, ret2, errno, SSL_state_string_long(ssl));
01152 default:
01153 ossl_raise(eSSLError, "%s returned=%d errno=%d state=%s", funcname, ret2, errno, SSL_state_string_long(ssl));
01154 }
01155 }
01156
01157 return self;
01158 }
01159
01160
01161
01162
01163
01164
01165
01166
01167 static VALUE
01168 ossl_ssl_connect(VALUE self)
01169 {
01170 ossl_ssl_setup(self);
01171 return ossl_start_ssl(self, SSL_connect, "SSL_connect", 0);
01172 }
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192 static VALUE
01193 ossl_ssl_connect_nonblock(VALUE self)
01194 {
01195 ossl_ssl_setup(self);
01196 return ossl_start_ssl(self, SSL_connect, "SSL_connect", 1);
01197 }
01198
01199
01200
01201
01202
01203
01204
01205
01206 static VALUE
01207 ossl_ssl_accept(VALUE self)
01208 {
01209 ossl_ssl_setup(self);
01210 return ossl_start_ssl(self, SSL_accept, "SSL_accept", 0);
01211 }
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231 static VALUE
01232 ossl_ssl_accept_nonblock(VALUE self)
01233 {
01234 ossl_ssl_setup(self);
01235 return ossl_start_ssl(self, SSL_accept, "SSL_accept", 1);
01236 }
01237
01238 static VALUE
01239 ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
01240 {
01241 SSL *ssl;
01242 int ilen, nread = 0;
01243 VALUE len, str;
01244 rb_io_t *fptr;
01245
01246 rb_scan_args(argc, argv, "11", &len, &str);
01247 ilen = NUM2INT(len);
01248 if(NIL_P(str)) str = rb_str_new(0, ilen);
01249 else{
01250 StringValue(str);
01251 rb_str_modify(str);
01252 rb_str_resize(str, ilen);
01253 }
01254 if(ilen == 0) return str;
01255
01256 Data_Get_Struct(self, SSL, ssl);
01257 GetOpenFile(ossl_ssl_get_io(self), fptr);
01258 if (ssl) {
01259 if(!nonblock && SSL_pending(ssl) <= 0)
01260 rb_thread_wait_fd(FPTR_TO_FD(fptr));
01261 for (;;){
01262 nread = SSL_read(ssl, RSTRING_PTR(str), RSTRING_LENINT(str));
01263 switch(ssl_get_error(ssl, nread)){
01264 case SSL_ERROR_NONE:
01265 goto end;
01266 case SSL_ERROR_ZERO_RETURN:
01267 rb_eof_error();
01268 case SSL_ERROR_WANT_WRITE:
01269 write_would_block(nonblock);
01270 rb_io_wait_writable(FPTR_TO_FD(fptr));
01271 continue;
01272 case SSL_ERROR_WANT_READ:
01273 read_would_block(nonblock);
01274 rb_io_wait_readable(FPTR_TO_FD(fptr));
01275 continue;
01276 case SSL_ERROR_SYSCALL:
01277 if(ERR_peek_error() == 0 && nread == 0) rb_eof_error();
01278 rb_sys_fail(0);
01279 default:
01280 ossl_raise(eSSLError, "SSL_read:");
01281 }
01282 }
01283 }
01284 else {
01285 ID meth = nonblock ? rb_intern("read_nonblock") : rb_intern("sysread");
01286 rb_warning("SSL session is not started yet.");
01287 return rb_funcall(ossl_ssl_get_io(self), meth, 2, len, str);
01288 }
01289
01290 end:
01291 rb_str_set_len(str, nread);
01292 OBJ_TAINT(str);
01293
01294 return str;
01295 }
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306 static VALUE
01307 ossl_ssl_read(int argc, VALUE *argv, VALUE self)
01308 {
01309 return ossl_ssl_read_internal(argc, argv, self, 0);
01310 }
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323 static VALUE
01324 ossl_ssl_read_nonblock(int argc, VALUE *argv, VALUE self)
01325 {
01326 return ossl_ssl_read_internal(argc, argv, self, 1);
01327 }
01328
01329 static VALUE
01330 ossl_ssl_write_internal(VALUE self, VALUE str, int nonblock)
01331 {
01332 SSL *ssl;
01333 int nwrite = 0;
01334 rb_io_t *fptr;
01335
01336 StringValue(str);
01337 Data_Get_Struct(self, SSL, ssl);
01338 GetOpenFile(ossl_ssl_get_io(self), fptr);
01339
01340 if (ssl) {
01341 for (;;){
01342 nwrite = SSL_write(ssl, RSTRING_PTR(str), RSTRING_LENINT(str));
01343 switch(ssl_get_error(ssl, nwrite)){
01344 case SSL_ERROR_NONE:
01345 goto end;
01346 case SSL_ERROR_WANT_WRITE:
01347 write_would_block(nonblock);
01348 rb_io_wait_writable(FPTR_TO_FD(fptr));
01349 continue;
01350 case SSL_ERROR_WANT_READ:
01351 read_would_block(nonblock);
01352 rb_io_wait_readable(FPTR_TO_FD(fptr));
01353 continue;
01354 case SSL_ERROR_SYSCALL:
01355 if (errno) rb_sys_fail(0);
01356 default:
01357 ossl_raise(eSSLError, "SSL_write:");
01358 }
01359 }
01360 }
01361 else {
01362 ID id_syswrite = rb_intern("syswrite");
01363 rb_warning("SSL session is not started yet.");
01364 return rb_funcall(ossl_ssl_get_io(self), id_syswrite, 1, str);
01365 }
01366
01367 end:
01368 return INT2NUM(nwrite);
01369 }
01370
01371
01372
01373
01374
01375
01376
01377 static VALUE
01378 ossl_ssl_write(VALUE self, VALUE str)
01379 {
01380 return ossl_ssl_write_internal(self, str, 0);
01381 }
01382
01383
01384
01385
01386
01387
01388
01389
01390 static VALUE
01391 ossl_ssl_write_nonblock(VALUE self, VALUE str)
01392 {
01393 return ossl_ssl_write_internal(self, str, 1);
01394 }
01395
01396
01397
01398
01399
01400
01401
01402 static VALUE
01403 ossl_ssl_close(VALUE self)
01404 {
01405 SSL *ssl;
01406
01407 Data_Get_Struct(self, SSL, ssl);
01408 ossl_ssl_shutdown(ssl);
01409 if (RTEST(ossl_ssl_get_sync_close(self)))
01410 rb_funcall(ossl_ssl_get_io(self), rb_intern("close"), 0);
01411
01412 return Qnil;
01413 }
01414
01415
01416
01417
01418
01419
01420
01421 static VALUE
01422 ossl_ssl_get_cert(VALUE self)
01423 {
01424 SSL *ssl;
01425 X509 *cert = NULL;
01426
01427 Data_Get_Struct(self, SSL, ssl);
01428 if (!ssl) {
01429 rb_warning("SSL session is not started yet.");
01430 return Qnil;
01431 }
01432
01433
01434
01435
01436
01437 cert = SSL_get_certificate(ssl);
01438
01439 if (!cert) {
01440 return Qnil;
01441 }
01442 return ossl_x509_new(cert);
01443 }
01444
01445
01446
01447
01448
01449
01450
01451 static VALUE
01452 ossl_ssl_get_peer_cert(VALUE self)
01453 {
01454 SSL *ssl;
01455 X509 *cert = NULL;
01456 VALUE obj;
01457
01458 Data_Get_Struct(self, SSL, ssl);
01459
01460 if (!ssl){
01461 rb_warning("SSL session is not started yet.");
01462 return Qnil;
01463 }
01464
01465 cert = SSL_get_peer_certificate(ssl);
01466
01467 if (!cert) {
01468 return Qnil;
01469 }
01470 obj = ossl_x509_new(cert);
01471 X509_free(cert);
01472
01473 return obj;
01474 }
01475
01476
01477
01478
01479
01480
01481
01482 static VALUE
01483 ossl_ssl_get_peer_cert_chain(VALUE self)
01484 {
01485 SSL *ssl;
01486 STACK_OF(X509) *chain;
01487 X509 *cert;
01488 VALUE ary;
01489 int i, num;
01490
01491 Data_Get_Struct(self, SSL, ssl);
01492 if(!ssl){
01493 rb_warning("SSL session is not started yet.");
01494 return Qnil;
01495 }
01496 chain = SSL_get_peer_cert_chain(ssl);
01497 if(!chain) return Qnil;
01498 num = sk_X509_num(chain);
01499 ary = rb_ary_new2(num);
01500 for (i = 0; i < num; i++){
01501 cert = sk_X509_value(chain, i);
01502 rb_ary_push(ary, ossl_x509_new(cert));
01503 }
01504
01505 return ary;
01506 }
01507
01508
01509
01510
01511
01512
01513
01514 static VALUE
01515 ossl_ssl_get_cipher(VALUE self)
01516 {
01517 SSL *ssl;
01518 SSL_CIPHER *cipher;
01519
01520 Data_Get_Struct(self, SSL, ssl);
01521 if (!ssl) {
01522 rb_warning("SSL session is not started yet.");
01523 return Qnil;
01524 }
01525 cipher = (SSL_CIPHER *)SSL_get_current_cipher(ssl);
01526
01527 return ossl_ssl_cipher_to_ary(cipher);
01528 }
01529
01530
01531
01532
01533
01534
01535
01536 static VALUE
01537 ossl_ssl_get_state(VALUE self)
01538 {
01539 SSL *ssl;
01540 VALUE ret;
01541
01542 Data_Get_Struct(self, SSL, ssl);
01543 if (!ssl) {
01544 rb_warning("SSL session is not started yet.");
01545 return Qnil;
01546 }
01547 ret = rb_str_new2(SSL_state_string(ssl));
01548 if (ruby_verbose) {
01549 rb_str_cat2(ret, ": ");
01550 rb_str_cat2(ret, SSL_state_string_long(ssl));
01551 }
01552 return ret;
01553 }
01554
01555
01556
01557
01558
01559
01560
01561 static VALUE
01562 ossl_ssl_pending(VALUE self)
01563 {
01564 SSL *ssl;
01565
01566 Data_Get_Struct(self, SSL, ssl);
01567 if (!ssl) {
01568 rb_warning("SSL session is not started yet.");
01569 return Qnil;
01570 }
01571
01572 return INT2NUM(SSL_pending(ssl));
01573 }
01574
01575
01576
01577
01578
01579
01580
01581 static VALUE
01582 ossl_ssl_session_reused(VALUE self)
01583 {
01584 SSL *ssl;
01585
01586 Data_Get_Struct(self, SSL, ssl);
01587 if (!ssl) {
01588 rb_warning("SSL session is not started yet.");
01589 return Qnil;
01590 }
01591
01592 switch(SSL_session_reused(ssl)) {
01593 case 1: return Qtrue;
01594 case 0: return Qfalse;
01595 default: ossl_raise(eSSLError, "SSL_session_reused");
01596 }
01597 }
01598
01599
01600
01601
01602
01603
01604
01605 static VALUE
01606 ossl_ssl_set_session(VALUE self, VALUE arg1)
01607 {
01608 SSL *ssl;
01609 SSL_SESSION *sess;
01610
01611
01612 ossl_ssl_setup(self);
01613
01614 Data_Get_Struct(self, SSL, ssl);
01615 if (!ssl) {
01616 rb_warning("SSL session is not started yet.");
01617 return Qnil;
01618 }
01619
01620 SafeGetSSLSession(arg1, sess);
01621
01622 if (SSL_set_session(ssl, sess) != 1)
01623 ossl_raise(eSSLError, "SSL_set_session");
01624
01625 return arg1;
01626 }
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637 static VALUE
01638 ossl_ssl_get_verify_result(VALUE self)
01639 {
01640 SSL *ssl;
01641
01642 Data_Get_Struct(self, SSL, ssl);
01643 if (!ssl) {
01644 rb_warning("SSL session is not started yet.");
01645 return Qnil;
01646 }
01647
01648 return INT2FIX(SSL_get_verify_result(ssl));
01649 }
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662 static VALUE
01663 ossl_ssl_get_client_ca_list(VALUE self)
01664 {
01665 SSL *ssl;
01666 STACK_OF(X509_NAME) *ca;
01667
01668 Data_Get_Struct(self, SSL, ssl);
01669 if (!ssl) {
01670 rb_warning("SSL session is not started yet.");
01671 return Qnil;
01672 }
01673
01674 ca = SSL_get_client_CA_list(ssl);
01675 return ossl_x509name_sk2ary(ca);
01676 }
01677
01678 void
01679 Init_ossl_ssl()
01680 {
01681 int i;
01682 VALUE ary;
01683
01684 #if 0
01685 mOSSL = rb_define_module("OpenSSL");
01686 #endif
01687
01688 ID_callback_state = rb_intern("@callback_state");
01689
01690 ossl_ssl_ex_vcb_idx = SSL_get_ex_new_index(0,(void *)"ossl_ssl_ex_vcb_idx",0,0,0);
01691 ossl_ssl_ex_store_p = SSL_get_ex_new_index(0,(void *)"ossl_ssl_ex_store_p",0,0,0);
01692 ossl_ssl_ex_ptr_idx = SSL_get_ex_new_index(0,(void *)"ossl_ssl_ex_ptr_idx",0,0,0);
01693 ossl_ssl_ex_client_cert_cb_idx =
01694 SSL_get_ex_new_index(0,(void *)"ossl_ssl_ex_client_cert_cb_idx",0,0,0);
01695 ossl_ssl_ex_tmp_dh_callback_idx =
01696 SSL_get_ex_new_index(0,(void *)"ossl_ssl_ex_tmp_dh_callback_idx",0,0,0);
01697
01698 mSSL = rb_define_module_under(mOSSL, "SSL");
01699 eSSLError = rb_define_class_under(mSSL, "SSLError", eOSSLError);
01700
01701 Init_ossl_ssl_session();
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715
01716
01717 cSSLContext = rb_define_class_under(mSSL, "SSLContext", rb_cObject);
01718 rb_define_alloc_func(cSSLContext, ossl_sslctx_s_alloc);
01719
01720
01721
01722
01723 rb_attr(cSSLContext, rb_intern("cert"), 1, 1, Qfalse);
01724
01725
01726
01727
01728 rb_attr(cSSLContext, rb_intern("key"), 1, 1, Qfalse);
01729
01730
01731
01732
01733 rb_attr(cSSLContext, rb_intern("client_ca"), 1, 1, Qfalse);
01734
01735
01736
01737
01738 rb_attr(cSSLContext, rb_intern("ca_file"), 1, 1, Qfalse);
01739
01740
01741
01742
01743
01744
01745 rb_attr(cSSLContext, rb_intern("ca_path"), 1, 1, Qfalse);
01746
01747
01748
01749
01750 rb_attr(cSSLContext, rb_intern("timeout"), 1, 1, Qfalse);
01751
01752
01753
01754
01755
01756
01757
01758 rb_attr(cSSLContext, rb_intern("verify_mode"), 1, 1, Qfalse);
01759
01760
01761
01762
01763 rb_attr(cSSLContext, rb_intern("verify_depth"), 1, 1, Qfalse);
01764
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776 rb_attr(cSSLContext, rb_intern("verify_callback"), 1, 1, Qfalse);
01777
01778
01779
01780
01781 rb_attr(cSSLContext, rb_intern("options"), 1, 1, Qfalse);
01782
01783
01784
01785
01786 rb_attr(cSSLContext, rb_intern("cert_store"), 1, 1, Qfalse);
01787
01788
01789
01790
01791
01792 rb_attr(cSSLContext, rb_intern("extra_chain_cert"), 1, 1, Qfalse);
01793
01794
01795
01796
01797
01798
01799
01800
01801
01802 rb_attr(cSSLContext, rb_intern("client_cert_cb"), 1, 1, Qfalse);
01803
01804
01805
01806
01807
01808
01809
01810
01811
01812
01813
01814 rb_attr(cSSLContext, rb_intern("tmp_dh_callback"), 1, 1, Qfalse);
01815
01816
01817
01818
01819
01820
01821 rb_attr(cSSLContext, rb_intern("session_id_context"), 1, 1, Qfalse);
01822
01823
01824
01825
01826
01827
01828
01829
01830 rb_attr(cSSLContext, rb_intern("session_get_cb"), 1, 1, Qfalse);
01831
01832
01833
01834
01835
01836
01837
01838 rb_attr(cSSLContext, rb_intern("session_new_cb"), 1, 1, Qfalse);
01839
01840
01841
01842
01843
01844
01845 rb_attr(cSSLContext, rb_intern("session_remove_cb"), 1, 1, Qfalse);
01846
01847 #ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
01848
01849
01850
01851
01852
01853
01854
01855 rb_attr(cSSLContext, rb_intern("servername_cb"), 1, 1, Qfalse);
01856 #endif
01857
01858 rb_define_alias(cSSLContext, "ssl_timeout", "timeout");
01859 rb_define_alias(cSSLContext, "ssl_timeout=", "timeout=");
01860 rb_define_method(cSSLContext, "initialize", ossl_sslctx_initialize, -1);
01861 rb_define_method(cSSLContext, "ssl_version=", ossl_sslctx_set_ssl_version, 1);
01862 rb_define_method(cSSLContext, "ciphers", ossl_sslctx_get_ciphers, 0);
01863 rb_define_method(cSSLContext, "ciphers=", ossl_sslctx_set_ciphers, 1);
01864
01865 rb_define_method(cSSLContext, "setup", ossl_sslctx_setup, 0);
01866
01867
01868
01869
01870
01871 rb_define_const(cSSLContext, "SESSION_CACHE_OFF", LONG2FIX(SSL_SESS_CACHE_OFF));
01872
01873
01874
01875
01876 rb_define_const(cSSLContext, "SESSION_CACHE_CLIENT", LONG2FIX(SSL_SESS_CACHE_CLIENT));
01877
01878
01879
01880
01881 rb_define_const(cSSLContext, "SESSION_CACHE_SERVER", LONG2FIX(SSL_SESS_CACHE_SERVER));
01882
01883
01884
01885
01886 rb_define_const(cSSLContext, "SESSION_CACHE_BOTH", LONG2FIX(SSL_SESS_CACHE_BOTH));
01887
01888
01889
01890
01891
01892
01893
01894 rb_define_const(cSSLContext, "SESSION_CACHE_NO_AUTO_CLEAR", LONG2FIX(SSL_SESS_CACHE_NO_AUTO_CLEAR));
01895
01896
01897
01898
01899
01900
01901
01902 rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL_LOOKUP", LONG2FIX(SSL_SESS_CACHE_NO_INTERNAL_LOOKUP));
01903
01904
01905
01906
01907 rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL_STORE", LONG2FIX(SSL_SESS_CACHE_NO_INTERNAL_STORE));
01908
01909
01910
01911
01912
01913 rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL", LONG2FIX(SSL_SESS_CACHE_NO_INTERNAL));
01914
01915 rb_define_method(cSSLContext, "session_add", ossl_sslctx_session_add, 1);
01916 rb_define_method(cSSLContext, "session_remove", ossl_sslctx_session_remove, 1);
01917 rb_define_method(cSSLContext, "session_cache_mode", ossl_sslctx_get_session_cache_mode, 0);
01918 rb_define_method(cSSLContext, "session_cache_mode=", ossl_sslctx_set_session_cache_mode, 1);
01919 rb_define_method(cSSLContext, "session_cache_size", ossl_sslctx_get_session_cache_size, 0);
01920 rb_define_method(cSSLContext, "session_cache_size=", ossl_sslctx_set_session_cache_size, 1);
01921 rb_define_method(cSSLContext, "session_cache_stats", ossl_sslctx_get_session_cache_stats, 0);
01922 rb_define_method(cSSLContext, "flush_sessions", ossl_sslctx_flush_sessions, -1);
01923
01924 ary = rb_ary_new2(numberof(ossl_ssl_method_tab));
01925 for (i = 0; i < numberof(ossl_ssl_method_tab); i++) {
01926 rb_ary_push(ary, ID2SYM(rb_intern(ossl_ssl_method_tab[i].name)));
01927 }
01928 rb_obj_freeze(ary);
01929
01930 rb_define_const(cSSLContext, "METHODS", ary);
01931
01932
01933
01934
01935
01936
01937
01938
01939 cSSLSocket = rb_define_class_under(mSSL, "SSLSocket", rb_cObject);
01940 rb_define_alloc_func(cSSLSocket, ossl_ssl_s_alloc);
01941 for(i = 0; i < numberof(ossl_ssl_attr_readers); i++)
01942 rb_attr(cSSLSocket, rb_intern(ossl_ssl_attr_readers[i]), 1, 0, Qfalse);
01943 for(i = 0; i < numberof(ossl_ssl_attrs); i++)
01944 rb_attr(cSSLSocket, rb_intern(ossl_ssl_attrs[i]), 1, 1, Qfalse);
01945 rb_define_alias(cSSLSocket, "to_io", "io");
01946 rb_define_method(cSSLSocket, "initialize", ossl_ssl_initialize, -1);
01947 rb_define_method(cSSLSocket, "connect", ossl_ssl_connect, 0);
01948 rb_define_method(cSSLSocket, "connect_nonblock", ossl_ssl_connect_nonblock, 0);
01949 rb_define_method(cSSLSocket, "accept", ossl_ssl_accept, 0);
01950 rb_define_method(cSSLSocket, "accept_nonblock", ossl_ssl_accept_nonblock, 0);
01951 rb_define_method(cSSLSocket, "sysread", ossl_ssl_read, -1);
01952 rb_define_private_method(cSSLSocket, "sysread_nonblock", ossl_ssl_read_nonblock, -1);
01953 rb_define_method(cSSLSocket, "syswrite", ossl_ssl_write, 1);
01954 rb_define_private_method(cSSLSocket, "syswrite_nonblock", ossl_ssl_write_nonblock, 1);
01955 rb_define_method(cSSLSocket, "sysclose", ossl_ssl_close, 0);
01956 rb_define_method(cSSLSocket, "cert", ossl_ssl_get_cert, 0);
01957 rb_define_method(cSSLSocket, "peer_cert", ossl_ssl_get_peer_cert, 0);
01958 rb_define_method(cSSLSocket, "peer_cert_chain", ossl_ssl_get_peer_cert_chain, 0);
01959 rb_define_method(cSSLSocket, "cipher", ossl_ssl_get_cipher, 0);
01960 rb_define_method(cSSLSocket, "state", ossl_ssl_get_state, 0);
01961 rb_define_method(cSSLSocket, "pending", ossl_ssl_pending, 0);
01962 rb_define_method(cSSLSocket, "session_reused?", ossl_ssl_session_reused, 0);
01963 rb_define_method(cSSLSocket, "session=", ossl_ssl_set_session, 1);
01964 rb_define_method(cSSLSocket, "verify_result", ossl_ssl_get_verify_result, 0);
01965 rb_define_method(cSSLSocket, "client_ca", ossl_ssl_get_client_ca_list, 0);
01966
01967 #define ossl_ssl_def_const(x) rb_define_const(mSSL, #x, INT2NUM(SSL_##x))
01968
01969 ossl_ssl_def_const(VERIFY_NONE);
01970 ossl_ssl_def_const(VERIFY_PEER);
01971 ossl_ssl_def_const(VERIFY_FAIL_IF_NO_PEER_CERT);
01972 ossl_ssl_def_const(VERIFY_CLIENT_ONCE);
01973
01974
01975
01976
01977 ossl_ssl_def_const(OP_MICROSOFT_SESS_ID_BUG);
01978 ossl_ssl_def_const(OP_NETSCAPE_CHALLENGE_BUG);
01979 ossl_ssl_def_const(OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG);
01980 ossl_ssl_def_const(OP_SSLREF2_REUSE_CERT_TYPE_BUG);
01981 ossl_ssl_def_const(OP_MICROSOFT_BIG_SSLV3_BUFFER);
01982 ossl_ssl_def_const(OP_MSIE_SSLV2_RSA_PADDING);
01983 ossl_ssl_def_const(OP_SSLEAY_080_CLIENT_DH_BUG);
01984 ossl_ssl_def_const(OP_TLS_D5_BUG);
01985 ossl_ssl_def_const(OP_TLS_BLOCK_PADDING_BUG);
01986 ossl_ssl_def_const(OP_DONT_INSERT_EMPTY_FRAGMENTS);
01987 ossl_ssl_def_const(OP_ALL);
01988 #if defined(SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION)
01989 ossl_ssl_def_const(OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
01990 #endif
01991 #if defined(SSL_OP_SINGLE_ECDH_USE)
01992 ossl_ssl_def_const(OP_SINGLE_ECDH_USE);
01993 #endif
01994 ossl_ssl_def_const(OP_SINGLE_DH_USE);
01995 ossl_ssl_def_const(OP_EPHEMERAL_RSA);
01996 #if defined(SSL_OP_CIPHER_SERVER_PREFERENCE)
01997 ossl_ssl_def_const(OP_CIPHER_SERVER_PREFERENCE);
01998 #endif
01999 ossl_ssl_def_const(OP_TLS_ROLLBACK_BUG);
02000 ossl_ssl_def_const(OP_NO_SSLv2);
02001 ossl_ssl_def_const(OP_NO_SSLv3);
02002 ossl_ssl_def_const(OP_NO_TLSv1);
02003 #if defined(SSL_OP_NO_TICKET)
02004 ossl_ssl_def_const(OP_NO_TICKET);
02005 #endif
02006 #if defined(SSL_OP_NO_COMPRESSION)
02007 ossl_ssl_def_const(OP_NO_COMPRESSION);
02008 #endif
02009 ossl_ssl_def_const(OP_PKCS1_CHECK_1);
02010 ossl_ssl_def_const(OP_PKCS1_CHECK_2);
02011 ossl_ssl_def_const(OP_NETSCAPE_CA_DN_BUG);
02012 ossl_ssl_def_const(OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG);
02013 }
02014