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

Generated on Sat Jul 7 2012 15:29:11 for Ruby by  doxygen 1.7.1