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

Generated on Thu Sep 8 2011 03:50:35 for Ruby by  doxygen 1.7.1