Ruby 1.9.2p136(2010-12-25revision30365)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# ext/openssl/ossl_ssl.c

Go to the documentation of this file.

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