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