• 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 27976 2010-05-23 12:18:51Z 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 = 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 

Generated on Wed Sep 8 2010 09:55:21 for Ruby by  doxygen 1.7.1