aboutsummaryrefslogtreecommitdiffstats
path: root/ext/openssl/ossl_ssl.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/openssl/ossl_ssl.c')
-rw-r--r--ext/openssl/ossl_ssl.c413
1 files changed, 141 insertions, 272 deletions
diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c
index ed10bb14..3e6e1646 100644
--- a/ext/openssl/ossl_ssl.c
+++ b/ext/openssl/ossl_ssl.c
@@ -1,5 +1,4 @@
/*
- * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2000-2002 GOTOU Yuuzou <gotoyuzo@notwork.org>
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
@@ -29,6 +28,7 @@
} while (0)
VALUE mSSL;
+VALUE mSSLExtConfig;
VALUE eSSLError;
VALUE cSSLContext;
VALUE cSSLSocket;
@@ -45,11 +45,9 @@ static VALUE eSSLErrorWaitWritable;
#define ossl_sslctx_set_verify_mode(o,v) rb_iv_set((o),"@verify_mode",(v))
#define ossl_sslctx_set_verify_dep(o,v) rb_iv_set((o),"@verify_depth",(v))
#define ossl_sslctx_set_verify_cb(o,v) rb_iv_set((o),"@verify_callback",(v))
-#define ossl_sslctx_set_options(o,v) rb_iv_set((o),"@options",(v))
#define ossl_sslctx_set_cert_store(o,v) rb_iv_set((o),"@cert_store",(v))
#define ossl_sslctx_set_extra_cert(o,v) rb_iv_set((o),"@extra_chain_cert",(v))
#define ossl_sslctx_set_client_cert_cb(o,v) rb_iv_set((o),"@client_cert_cb",(v))
-#define ossl_sslctx_set_tmp_dh_cb(o,v) rb_iv_set((o),"@tmp_dh_callback",(v))
#define ossl_sslctx_set_sess_id_ctx(o, v) rb_iv_set((o),"@session_id_context",(v))
#define ossl_sslctx_get_cert(o) rb_iv_get((o),"@cert")
@@ -61,54 +59,22 @@ static VALUE eSSLErrorWaitWritable;
#define ossl_sslctx_get_verify_mode(o) rb_iv_get((o),"@verify_mode")
#define ossl_sslctx_get_verify_dep(o) rb_iv_get((o),"@verify_depth")
#define ossl_sslctx_get_verify_cb(o) rb_iv_get((o),"@verify_callback")
-#define ossl_sslctx_get_options(o) rb_iv_get((o),"@options")
#define ossl_sslctx_get_cert_store(o) rb_iv_get((o),"@cert_store")
#define ossl_sslctx_get_extra_cert(o) rb_iv_get((o),"@extra_chain_cert")
#define ossl_sslctx_get_client_cert_cb(o) rb_iv_get((o),"@client_cert_cb")
#define ossl_sslctx_get_tmp_ecdh_cb(o) rb_iv_get((o),"@tmp_ecdh_callback")
-#define ossl_sslctx_get_tmp_dh_cb(o) rb_iv_get((o),"@tmp_dh_callback")
#define ossl_sslctx_get_sess_id_ctx(o) rb_iv_get((o),"@session_id_context")
-static const char *ossl_sslctx_attrs[] = {
- "cert", "key", "client_ca", "ca_file", "ca_path",
- "timeout", "verify_mode", "verify_depth", "renegotiation_cb",
- "verify_callback", "options", "cert_store", "extra_chain_cert",
- "client_cert_cb", "tmp_dh_callback", "session_id_context",
- "session_get_cb", "session_new_cb", "session_remove_cb",
- "tmp_ecdh_callback",
-#ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
- "servername_cb",
-#endif
-#ifdef HAVE_OPENSSL_NPN_NEGOTIATED
- "npn_protocols",
- "npn_select_cb",
-#endif
-};
-
#define ossl_ssl_get_io(o) rb_iv_get((o),"@io")
#define ossl_ssl_get_ctx(o) rb_iv_get((o),"@context")
-#define ossl_ssl_get_sync_close(o) rb_iv_get((o),"@sync_close")
#define ossl_ssl_get_x509(o) rb_iv_get((o),"@x509")
#define ossl_ssl_get_key(o) rb_iv_get((o),"@key")
-#define ossl_ssl_get_tmp_dh(o) rb_iv_get((o),"@tmp_dh")
-#define ossl_ssl_get_tmp_ecdh(o) rb_iv_get((o),"@tmp_ecdh")
-#define ossl_ssl_set_io(o,v) rb_iv_set((o),"@io",(v))
-#define ossl_ssl_set_ctx(o,v) rb_iv_set((o),"@context",(v))
-#define ossl_ssl_set_sync_close(o,v) rb_iv_set((o),"@sync_close",(v))
#define ossl_ssl_set_x509(o,v) rb_iv_set((o),"@x509",(v))
#define ossl_ssl_set_key(o,v) rb_iv_set((o),"@key",(v))
#define ossl_ssl_set_tmp_dh(o,v) rb_iv_set((o),"@tmp_dh",(v))
#define ossl_ssl_set_tmp_ecdh(o,v) rb_iv_set((o),"@tmp_ecdh",(v))
-static const char *ossl_ssl_attr_readers[] = { "io", "context", };
-static const char *ossl_ssl_attrs[] = {
-#ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
- "hostname",
-#endif
- "sync_close",
-};
-
ID ID_callback_state;
static VALUE sym_exception, sym_wait_readable, sym_wait_writable;
@@ -142,9 +108,12 @@ static const struct {
OSSL_SSL_METHOD_ENTRY(SSLv2_server),
OSSL_SSL_METHOD_ENTRY(SSLv2_client),
#endif
+#if defined(HAVE_SSLV3_METHOD) && defined(HAVE_SSLV3_SERVER_METHOD) && \
+ defined(HAVE_SSLV3_CLIENT_METHOD)
OSSL_SSL_METHOD_ENTRY(SSLv3),
OSSL_SSL_METHOD_ENTRY(SSLv3_server),
OSSL_SSL_METHOD_ENTRY(SSLv3_client),
+#endif
OSSL_SSL_METHOD_ENTRY(SSLv23),
OSSL_SSL_METHOD_ENTRY(SSLv23_server),
OSSL_SSL_METHOD_ENTRY(SSLv23_client),
@@ -154,9 +123,6 @@ static const struct {
int ossl_ssl_ex_vcb_idx;
int ossl_ssl_ex_store_p;
int ossl_ssl_ex_ptr_idx;
-int ossl_ssl_ex_client_cert_cb_idx;
-int ossl_ssl_ex_tmp_dh_callback_idx;
-int ossl_ssl_ex_tmp_ecdh_callback_idx;
static void
ossl_sslctx_free(void *ptr)
@@ -193,6 +159,8 @@ ossl_sslctx_s_alloc(VALUE klass)
}
SSL_CTX_set_mode(ctx, mode);
RTYPEDDATA_DATA(obj) = ctx;
+ SSL_CTX_set_ex_data(ctx, ossl_ssl_ex_ptr_idx, (void*)obj);
+
return obj;
}
@@ -208,13 +176,13 @@ ossl_sslctx_set_ssl_version(VALUE self, VALUE ssl_method)
{
SSL_METHOD *method = NULL;
const char *s;
+ VALUE m = ssl_method;
int i;
SSL_CTX *ctx;
if (RB_TYPE_P(ssl_method, T_SYMBOL))
- s = rb_id2name(SYM2ID(ssl_method));
- else
- s = StringValuePtr(ssl_method);
+ m = rb_sym2str(ssl_method);
+ s = StringValueCStr(m);
for (i = 0; i < numberof(ossl_ssl_method_tab); i++) {
if (strcmp(ossl_ssl_method_tab[i].name, s) == 0) {
method = ossl_ssl_method_tab[i].func();
@@ -222,7 +190,7 @@ ossl_sslctx_set_ssl_version(VALUE self, VALUE ssl_method)
}
}
if (!method) {
- ossl_raise(rb_eArgError, "unknown SSL method `%s'.", s);
+ ossl_raise(rb_eArgError, "unknown SSL method `%"PRIsVALUE"'.", m);
}
GetSSLCTX(self, ctx);
if (SSL_CTX_set_ssl_version(ctx, method) != 1) {
@@ -232,41 +200,12 @@ ossl_sslctx_set_ssl_version(VALUE self, VALUE ssl_method)
return ssl_method;
}
-/*
- * call-seq:
- * SSLContext.new => ctx
- * SSLContext.new(:TLSv1) => ctx
- * SSLContext.new("SSLv23_client") => ctx
- *
- * You can get a list of valid methods with OpenSSL::SSL::SSLContext::METHODS
- */
-static VALUE
-ossl_sslctx_initialize(int argc, VALUE *argv, VALUE self)
-{
- VALUE ssl_method;
- int i;
-
- for(i = 0; i < numberof(ossl_sslctx_attrs); i++){
- char buf[32];
- snprintf(buf, sizeof(buf), "@%s", ossl_sslctx_attrs[i]);
- rb_iv_set(self, buf, Qnil);
- }
- if (rb_scan_args(argc, argv, "01", &ssl_method) == 0){
- return self;
- }
- ossl_sslctx_set_ssl_version(self, ssl_method);
-
- return self;
-}
-
static VALUE
ossl_call_client_cert_cb(VALUE obj)
{
VALUE cb, ary, cert, key;
- SSL *ssl;
- GetSSL(obj, ssl);
- cb = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_client_cert_cb_idx);
+ cb = rb_funcall(obj, rb_intern("client_cert_cb"), 0);
if (NIL_P(cb)) return Qfalse;
ary = rb_funcall(cb, rb_intern("call"), 1, obj);
Check_Type(ary, T_ARRAY);
@@ -284,8 +223,7 @@ ossl_client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
VALUE obj, success;
obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
- success = rb_protect((VALUE(*)_((VALUE)))ossl_call_client_cert_cb,
- obj, NULL);
+ success = rb_protect(ossl_call_client_cert_cb, obj, NULL);
if (!RTEST(success)) return 0;
*x509 = DupX509CertPtr(ossl_ssl_get_x509(obj));
*pkey = DupPKeyPtr(ossl_ssl_get_key(obj));
@@ -295,50 +233,35 @@ ossl_client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
#if !defined(OPENSSL_NO_DH)
static VALUE
-ossl_call_tmp_dh_callback(VALUE *args)
+ossl_call_tmp_dh_callback(VALUE args)
{
- SSL *ssl;
VALUE cb, dh;
EVP_PKEY *pkey;
- GetSSL(args[0], ssl);
- cb = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_tmp_dh_callback_idx);
+ cb = rb_funcall(rb_ary_entry(args, 0), rb_intern("tmp_dh_callback"), 0);
+
if (NIL_P(cb)) return Qfalse;
- dh = rb_funcall(cb, rb_intern("call"), 3, args[0], args[1], args[2]);
+ dh = rb_apply(cb, rb_intern("call"), args);
pkey = GetPKeyPtr(dh);
if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DH) return Qfalse;
- ossl_ssl_set_tmp_dh(args[0], dh);
- return Qtrue;
+ return dh;
}
static DH*
ossl_tmp_dh_callback(SSL *ssl, int is_export, int keylength)
{
- VALUE args[3], success;
+ VALUE args, dh, rb_ssl;
- args[0] = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
- args[1] = INT2FIX(is_export);
- args[2] = INT2FIX(keylength);
- success = rb_protect((VALUE(*)_((VALUE)))ossl_call_tmp_dh_callback,
- (VALUE)args, NULL);
- if (!RTEST(success)) return NULL;
+ rb_ssl = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
- return GetPKeyPtr(ossl_ssl_get_tmp_dh(args[0]))->pkey.dh;
-}
+ args = rb_ary_new_from_args(3, rb_ssl, INT2FIX(is_export), INT2FIX(keylength));
-static DH*
-ossl_default_tmp_dh_callback(SSL *ssl, int is_export, int keylength)
-{
- rb_warning("using default DH parameters.");
+ dh = rb_protect(ossl_call_tmp_dh_callback, args, NULL);
+ if (!RTEST(dh)) return NULL;
+ ossl_ssl_set_tmp_dh(rb_ssl, dh);
- switch(keylength){
- case 512:
- return OSSL_DEFAULT_DH_512;
- case 1024:
- return OSSL_DEFAULT_DH_1024;
- }
- return NULL;
+ return GetPKeyPtr(dh)->pkey.dh;
}
#endif /* OPENSSL_NO_DH */
@@ -346,34 +269,33 @@ ossl_default_tmp_dh_callback(SSL *ssl, int is_export, int keylength)
static VALUE
ossl_call_tmp_ecdh_callback(VALUE args)
{
- SSL *ssl;
VALUE cb, ecdh;
EVP_PKEY *pkey;
- GetSSL(rb_ary_entry(args, 0), ssl);
- cb = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_tmp_ecdh_callback_idx);
+ cb = rb_funcall(rb_ary_entry(args, 0), rb_intern("tmp_ecdh_callback"), 0);
+
if (NIL_P(cb)) return Qfalse;
ecdh = rb_apply(cb, rb_intern("call"), args);
pkey = GetPKeyPtr(ecdh);
if (EVP_PKEY_type(pkey->type) != EVP_PKEY_EC) return Qfalse;
- ossl_ssl_set_tmp_ecdh(rb_ary_entry(args, 0), ecdh);
- return Qtrue;
+ return ecdh;
}
static EC_KEY*
ossl_tmp_ecdh_callback(SSL *ssl, int is_export, int keylength)
{
- VALUE args, success, rb_ssl;
+ VALUE args, ecdh, rb_ssl;
rb_ssl = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
args = rb_ary_new_from_args(3, rb_ssl, INT2FIX(is_export), INT2FIX(keylength));
- success = rb_protect(ossl_call_tmp_ecdh_callback, args, NULL);
- if (!RTEST(success)) return NULL;
+ ecdh = rb_protect(ossl_call_tmp_ecdh_callback, args, NULL);
+ if (!RTEST(ecdh)) return NULL;
+ ossl_ssl_set_tmp_ecdh(rb_ssl, ecdh);
- return GetPKeyPtr(ossl_ssl_get_tmp_ecdh(rb_ssl))->pkey.ec;
+ return GetPKeyPtr(ecdh)->pkey.ec;
}
#endif
@@ -392,14 +314,12 @@ ossl_ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
static VALUE
ossl_call_session_get_cb(VALUE ary)
{
- VALUE ssl_obj, sslctx_obj, cb;
+ VALUE ssl_obj, cb;
Check_Type(ary, T_ARRAY);
ssl_obj = rb_ary_entry(ary, 0);
- sslctx_obj = rb_iv_get(ssl_obj, "@context");
- if (NIL_P(sslctx_obj)) return Qnil;
- cb = rb_iv_get(sslctx_obj, "@session_get_cb");
+ cb = rb_funcall(ssl_obj, rb_intern("session_get_cb"), 0);
if (NIL_P(cb)) return Qnil;
return rb_funcall(cb, rb_intern("call"), 1, ary);
@@ -422,7 +342,7 @@ ossl_sslctx_session_get_cb(SSL *ssl, unsigned char *buf, int len, int *copy)
rb_ary_push(ary, ssl_obj);
rb_ary_push(ary, rb_str_new((const char *)buf, len));
- ret_obj = rb_protect((VALUE(*)_((VALUE)))ossl_call_session_get_cb, ary, &state);
+ ret_obj = rb_protect(ossl_call_session_get_cb, ary, &state);
if (state) {
rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(state));
return NULL;
@@ -439,14 +359,12 @@ ossl_sslctx_session_get_cb(SSL *ssl, unsigned char *buf, int len, int *copy)
static VALUE
ossl_call_session_new_cb(VALUE ary)
{
- VALUE ssl_obj, sslctx_obj, cb;
+ VALUE ssl_obj, cb;
Check_Type(ary, T_ARRAY);
ssl_obj = rb_ary_entry(ary, 0);
- sslctx_obj = rb_iv_get(ssl_obj, "@context");
- if (NIL_P(sslctx_obj)) return Qnil;
- cb = rb_iv_get(sslctx_obj, "@session_new_cb");
+ cb = rb_funcall(ssl_obj, rb_intern("session_new_cb"), 0);
if (NIL_P(cb)) return Qnil;
return rb_funcall(cb, rb_intern("call"), 1, ary);
@@ -473,7 +391,7 @@ ossl_sslctx_session_new_cb(SSL *ssl, SSL_SESSION *sess)
rb_ary_push(ary, ssl_obj);
rb_ary_push(ary, sess_obj);
- rb_protect((VALUE(*)_((VALUE)))ossl_call_session_new_cb, ary, &state);
+ rb_protect(ossl_call_session_new_cb, ary, &state);
if (state) {
rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(state));
}
@@ -572,6 +490,7 @@ ossl_call_servername_cb(VALUE ary)
GetSSL(ssl_obj, ssl);
GetSSLCTX(ret_obj, ctx2);
SSL_set_SSL_CTX(ssl, ctx2);
+ rb_iv_set(ssl_obj, "@context", ret_obj);
} else if (!NIL_P(ret_obj)) {
ossl_raise(rb_eArgError, "servername_cb must return an OpenSSL::SSL::SSLContext object or nil");
}
@@ -728,6 +647,39 @@ ssl_info_cb(const SSL *ssl, int where, int val)
}
/*
+ * Gets various OpenSSL options.
+ */
+static VALUE
+ossl_sslctx_get_options(VALUE self)
+{
+ SSL_CTX *ctx;
+ GetSSLCTX(self, ctx);
+ return LONG2NUM(SSL_CTX_get_options(ctx));
+}
+
+/*
+ * Sets various OpenSSL options.
+ */
+static VALUE
+ossl_sslctx_set_options(VALUE self, VALUE options)
+{
+ SSL_CTX *ctx;
+
+ rb_check_frozen(self);
+ GetSSLCTX(self, ctx);
+
+ SSL_CTX_clear_options(ctx, SSL_CTX_get_options(ctx));
+
+ if (NIL_P(options)) {
+ SSL_CTX_set_options(ctx, SSL_OP_ALL);
+ } else {
+ SSL_CTX_set_options(ctx, NUM2LONG(options));
+ }
+
+ return self;
+}
+
+/*
* call-seq:
* ctx.setup => Qtrue # first time
* ctx.setup => nil # thereafter
@@ -751,12 +703,7 @@ ossl_sslctx_setup(VALUE self)
GetSSLCTX(self, ctx);
#if !defined(OPENSSL_NO_DH)
- if (RTEST(ossl_sslctx_get_tmp_dh_cb(self))){
- SSL_CTX_set_tmp_dh_callback(ctx, ossl_tmp_dh_callback);
- }
- else{
- SSL_CTX_set_tmp_dh_callback(ctx, ossl_default_tmp_dh_callback);
- }
+ SSL_CTX_set_tmp_dh_callback(ctx, ossl_tmp_dh_callback);
#endif
#if !defined(OPENSSL_NO_EC)
@@ -765,8 +712,6 @@ ossl_sslctx_setup(VALUE self)
}
#endif
- SSL_CTX_set_ex_data(ctx, ossl_ssl_ex_ptr_idx, (void*)self);
-
val = ossl_sslctx_get_cert_store(self);
if(!NIL_P(val)){
/*
@@ -845,13 +790,6 @@ ossl_sslctx_setup(VALUE self)
val = ossl_sslctx_get_verify_dep(self);
if(!NIL_P(val)) SSL_CTX_set_verify_depth(ctx, NUM2INT(val));
- val = ossl_sslctx_get_options(self);
- if(!NIL_P(val)) {
- SSL_CTX_set_options(ctx, NUM2LONG(val));
- } else {
- SSL_CTX_set_options(ctx, SSL_OP_ALL);
- }
-
#ifdef HAVE_OPENSSL_NPN_NEGOTIATED
val = rb_iv_get(self, "@npn_protocols");
if (!NIL_P(val)) {
@@ -1242,44 +1180,6 @@ ossl_ssl_s_alloc(VALUE klass)
return TypedData_Wrap_Struct(klass, &ossl_ssl_type, NULL);
}
-/*
- * call-seq:
- * SSLSocket.new(io) => aSSLSocket
- * SSLSocket.new(io, ctx) => aSSLSocket
- *
- * Creates a new SSL socket from +io+ which must be a real ruby object (not an
- * IO-like object that responds to read/write).
- *
- * If +ctx+ is provided the SSL Sockets initial params will be taken from
- * the context.
- *
- * The OpenSSL::Buffering module provides additional IO methods.
- *
- * This method will freeze the SSLContext if one is provided;
- * however, session management is still allowed in the frozen SSLContext.
- */
-static VALUE
-ossl_ssl_initialize(int argc, VALUE *argv, VALUE self)
-{
- VALUE io, ctx;
-
- if (rb_scan_args(argc, argv, "11", &io, &ctx) == 1) {
- ctx = rb_funcall(cSSLContext, rb_intern("new"), 0);
- }
- OSSL_Check_Kind(ctx, cSSLContext);
- Check_Type(io, T_FILE);
- ossl_ssl_set_io(self, io);
- ossl_ssl_set_ctx(self, ctx);
- ossl_ssl_set_sync_close(self, Qfalse);
- ossl_sslctx_setup(ctx);
-
- rb_iv_set(self, "@hostname", Qnil);
-
- rb_call_super(0, 0);
-
- return self;
-}
-
static VALUE
ossl_ssl_setup(VALUE self)
{
@@ -1317,12 +1217,6 @@ ossl_ssl_setup(VALUE self)
SSL_set_ex_data(ssl, ossl_ssl_ex_ptr_idx, (void*)self);
cb = ossl_sslctx_get_verify_cb(v_ctx);
SSL_set_ex_data(ssl, ossl_ssl_ex_vcb_idx, (void*)cb);
- cb = ossl_sslctx_get_client_cert_cb(v_ctx);
- SSL_set_ex_data(ssl, ossl_ssl_ex_client_cert_cb_idx, (void*)cb);
- cb = ossl_sslctx_get_tmp_dh_cb(v_ctx);
- SSL_set_ex_data(ssl, ossl_ssl_ex_tmp_dh_callback_idx, (void*)cb);
- cb = ossl_sslctx_get_tmp_ecdh_cb(v_ctx);
- SSL_set_ex_data(ssl, ossl_ssl_ex_tmp_ecdh_callback_idx, (void*)cb);
SSL_set_info_callback(ssl, ssl_info_cb);
}
@@ -1362,14 +1256,23 @@ read_would_block(int nonblock)
}
}
+static int
+no_exception_p(VALUE opts)
+{
+ if (RB_TYPE_P(opts, T_HASH) &&
+ rb_hash_lookup2(opts, sym_exception, Qundef) == Qfalse)
+ return 1;
+ return 0;
+}
+
static VALUE
-ossl_start_ssl(VALUE self, int (*func)(), const char *funcname,
- int nonblock, int no_exception)
+ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, VALUE opts)
{
SSL *ssl;
rb_io_t *fptr;
int ret, ret2;
VALUE cb_state;
+ int nonblock = opts != Qfalse;
rb_ivar_set(self, ID_callback_state, Qnil);
@@ -1388,12 +1291,12 @@ ossl_start_ssl(VALUE self, int (*func)(), const char *funcname,
switch((ret2 = ssl_get_error(ssl, ret))){
case SSL_ERROR_WANT_WRITE:
- if (no_exception) { return sym_wait_writable; }
+ if (no_exception_p(opts)) { return sym_wait_writable; }
write_would_block(nonblock);
rb_io_wait_writable(FPTR_TO_FD(fptr));
continue;
case SSL_ERROR_WANT_READ:
- if (no_exception) { return sym_wait_readable; }
+ if (no_exception_p(opts)) { return sym_wait_readable; }
read_would_block(nonblock);
rb_io_wait_readable(FPTR_TO_FD(fptr));
continue;
@@ -1419,15 +1322,8 @@ static VALUE
ossl_ssl_connect(VALUE self)
{
ossl_ssl_setup(self);
- return ossl_start_ssl(self, SSL_connect, "SSL_connect", 0, 0);
-}
-static int
-get_no_exception(VALUE opts)
-{
- if (!NIL_P(opts) && Qfalse == rb_hash_lookup2(opts, sym_exception, Qundef))
- return 1;
- return 0;
+ return ossl_start_ssl(self, SSL_connect, "SSL_connect", Qfalse);
}
/*
@@ -1455,14 +1351,12 @@ get_no_exception(VALUE opts)
static VALUE
ossl_ssl_connect_nonblock(int argc, VALUE *argv, VALUE self)
{
- int no_exception;
- VALUE opts = Qnil;
-
+ VALUE opts;
rb_scan_args(argc, argv, "0:", &opts);
- no_exception = get_no_exception(opts);
ossl_ssl_setup(self);
- return ossl_start_ssl(self, SSL_connect, "SSL_connect", 1, no_exception);
+
+ return ossl_start_ssl(self, SSL_connect, "SSL_connect", opts);
}
/*
@@ -1476,7 +1370,8 @@ static VALUE
ossl_ssl_accept(VALUE self)
{
ossl_ssl_setup(self);
- return ossl_start_ssl(self, SSL_accept, "SSL_accept", 0, 0);
+
+ return ossl_start_ssl(self, SSL_accept, "SSL_accept", Qfalse);
}
/*
@@ -1504,14 +1399,12 @@ ossl_ssl_accept(VALUE self)
static VALUE
ossl_ssl_accept_nonblock(int argc, VALUE *argv, VALUE self)
{
- int no_exception;
- VALUE opts = Qnil;
+ VALUE opts;
rb_scan_args(argc, argv, "0:", &opts);
- no_exception = get_no_exception(opts);
-
ossl_ssl_setup(self);
- return ossl_start_ssl(self, SSL_accept, "SSL_accept", 1, no_exception);
+
+ return ossl_start_ssl(self, SSL_accept, "SSL_accept", opts);
}
static VALUE
@@ -1519,13 +1412,15 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
{
SSL *ssl;
int ilen, nread = 0;
- int no_exception;
VALUE len, str;
rb_io_t *fptr;
VALUE opts = Qnil;
- rb_scan_args(argc, argv, "11:", &len, &str, &opts);
- no_exception = get_no_exception(opts);
+ if (nonblock) {
+ rb_scan_args(argc, argv, "11:", &len, &str, &opts);
+ } else {
+ rb_scan_args(argc, argv, "11", &len, &str);
+ }
ilen = NUM2INT(len);
if(NIL_P(str)) str = rb_str_new(0, ilen);
@@ -1547,21 +1442,21 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
case SSL_ERROR_NONE:
goto end;
case SSL_ERROR_ZERO_RETURN:
- if (no_exception) { return Qnil; }
+ if (no_exception_p(opts)) { return Qnil; }
rb_eof_error();
case SSL_ERROR_WANT_WRITE:
- if (no_exception) { return sym_wait_writable; }
+ if (no_exception_p(opts)) { return sym_wait_writable; }
write_would_block(nonblock);
rb_io_wait_writable(FPTR_TO_FD(fptr));
continue;
case SSL_ERROR_WANT_READ:
- if (no_exception) { return sym_wait_readable; }
+ if (no_exception_p(opts)) { return sym_wait_readable; }
read_would_block(nonblock);
rb_io_wait_readable(FPTR_TO_FD(fptr));
continue;
case SSL_ERROR_SYSCALL:
if(ERR_peek_error() == 0 && nread == 0) {
- if (no_exception) { return Qnil; }
+ if (no_exception_p(opts)) { return Qnil; }
rb_eof_error();
}
rb_sys_fail(0);
@@ -1621,11 +1516,12 @@ ossl_ssl_read_nonblock(int argc, VALUE *argv, VALUE self)
}
static VALUE
-ossl_ssl_write_internal(VALUE self, VALUE str, int nonblock, int no_exception)
+ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts)
{
SSL *ssl;
int nwrite = 0;
rb_io_t *fptr;
+ int nonblock = opts != Qfalse;
StringValue(str);
GetSSL(self, ssl);
@@ -1638,12 +1534,12 @@ ossl_ssl_write_internal(VALUE self, VALUE str, int nonblock, int no_exception)
case SSL_ERROR_NONE:
goto end;
case SSL_ERROR_WANT_WRITE:
- if (no_exception) { return sym_wait_writable; }
+ if (no_exception_p(opts)) { return sym_wait_writable; }
write_would_block(nonblock);
rb_io_wait_writable(FPTR_TO_FD(fptr));
continue;
case SSL_ERROR_WANT_READ:
- if (no_exception) { return sym_wait_readable; }
+ if (no_exception_p(opts)) { return sym_wait_readable; }
read_would_block(nonblock);
rb_io_wait_readable(FPTR_TO_FD(fptr));
continue;
@@ -1673,7 +1569,7 @@ ossl_ssl_write_internal(VALUE self, VALUE str, int nonblock, int no_exception)
static VALUE
ossl_ssl_write(VALUE self, VALUE str)
{
- return ossl_ssl_write_internal(self, str, 0, 0);
+ return ossl_ssl_write_internal(self, str, Qfalse);
}
/*
@@ -1686,43 +1582,34 @@ ossl_ssl_write(VALUE self, VALUE str)
static VALUE
ossl_ssl_write_nonblock(int argc, VALUE *argv, VALUE self)
{
- VALUE str;
- VALUE opts = Qnil;
- int no_exception;
+ VALUE str, opts;
rb_scan_args(argc, argv, "1:", &str, &opts);
- no_exception = get_no_exception(opts);
- return ossl_ssl_write_internal(self, str, 1, no_exception);
+ return ossl_ssl_write_internal(self, str, opts);
}
/*
* call-seq:
- * ssl.sysclose => nil
+ * ssl.stop => nil
*
- * Shuts down the SSL connection and prepares it for another connection.
+ * Stops the SSL connection and prepares it for another connection.
*/
static VALUE
-ossl_ssl_close(VALUE self)
+ossl_ssl_stop(VALUE self)
{
SSL *ssl;
- VALUE io;
/* ossl_ssl_data_get_struct() is not usable here because it may return
* from this function; */
GetSSL(self, ssl);
- io = ossl_ssl_get_io(self);
- if (!RTEST(rb_funcall(io, rb_intern("closed?"), 0))) {
- if (ssl) {
- ossl_ssl_shutdown(ssl);
- SSL_free(ssl);
- }
- DATA_PTR(self) = NULL;
- if (RTEST(ossl_ssl_get_sync_close(self)))
- rb_funcall(io, rb_intern("close"), 0);
+ if (ssl) {
+ ossl_ssl_shutdown(ssl);
+ SSL_free(ssl);
}
+ DATA_PTR(self) = NULL;
return Qnil;
}
@@ -1994,7 +1881,9 @@ ossl_ssl_npn_protocol(VALUE self)
else
return rb_str_new((const char *) out, outlen);
}
+# endif
+# ifdef HAVE_SSL_CTX_SET_ALPN_SELECT_CB
/*
* call-seq:
* ssl.alpn_protocol => String
@@ -2035,12 +1924,6 @@ Init_ossl_ssl(void)
ossl_ssl_ex_vcb_idx = SSL_get_ex_new_index(0,(void *)"ossl_ssl_ex_vcb_idx",0,0,0);
ossl_ssl_ex_store_p = SSL_get_ex_new_index(0,(void *)"ossl_ssl_ex_store_p",0,0,0);
ossl_ssl_ex_ptr_idx = SSL_get_ex_new_index(0,(void *)"ossl_ssl_ex_ptr_idx",0,0,0);
- ossl_ssl_ex_client_cert_cb_idx =
- SSL_get_ex_new_index(0,(void *)"ossl_ssl_ex_client_cert_cb_idx",0,0,0);
- ossl_ssl_ex_tmp_dh_callback_idx =
- SSL_get_ex_new_index(0,(void *)"ossl_ssl_ex_tmp_dh_callback_idx",0,0,0);
- ossl_ssl_ex_tmp_ecdh_callback_idx =
- SSL_get_ex_new_index(0,(void *)"ossl_ssl_ex_tmp_ecdh_callback_idx",0,0,0);
/* Document-module: OpenSSL::SSL
*
@@ -2050,6 +1933,17 @@ Init_ossl_ssl(void)
* of SSLContext to set up connections.
*/
mSSL = rb_define_module_under(mOSSL, "SSL");
+
+ /* Document-module: OpenSSL::ExtConfig
+ *
+ * This module contains configuration information about the SSL extension,
+ * for example if socket support is enabled, or the host name TLS extension
+ * is enabled. Constants in this module will always be defined, but contain
+ * `true` or `false` values depending on the configuration of your OpenSSL
+ * installation.
+ */
+ mSSLExtConfig = rb_define_module_under(mOSSL, "ExtConfig");
+
/* Document-class: OpenSSL::SSL::SSLError
*
* Generic error class raised by SSLSocket and SSLContext.
@@ -2138,11 +2032,6 @@ Init_ossl_ssl(void)
rb_attr(cSSLContext, rb_intern("verify_callback"), 1, 1, Qfalse);
/*
- * Sets various OpenSSL options.
- */
- rb_attr(cSSLContext, rb_intern("options"), 1, 1, Qfalse);
-
- /*
* An OpenSSL::X509::Store used for certificate verification
*/
rb_attr(cSSLContext, rb_intern("cert_store"), 1, 1, Qfalse);
@@ -2175,18 +2064,6 @@ Init_ossl_ssl(void)
*/
rb_attr(cSSLContext, rb_intern("tmp_ecdh_callback"), 1, 1, Qfalse);
- /*
- * A callback invoked when DH parameters are required.
- *
- * The callback is invoked with the Session for the key exchange, an
- * flag indicating the use of an export cipher and the keylength
- * required.
- *
- * The callback must return an OpenSSL::PKey::DH instance of the correct
- * key length.
- */
- rb_attr(cSSLContext, rb_intern("tmp_dh_callback"), 1, 1, Qfalse);
-
/*
* Sets the context in which a session can be reused. This allows
* sessions for multiple applications to be distinguished, for example, by
@@ -2219,15 +2096,11 @@ Init_ossl_ssl(void)
rb_attr(cSSLContext, rb_intern("session_remove_cb"), 1, 1, Qfalse);
#ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
- /*
- * A callback invoked at connect time to distinguish between multiple
- * server names.
- *
- * The callback is invoked with an SSLSocket and a server name. The
- * callback must return an SSLContext for the server name or nil.
- */
- rb_attr(cSSLContext, rb_intern("servername_cb"), 1, 1, Qfalse);
+ rb_define_const(mSSLExtConfig, "HAVE_TLSEXT_HOST_NAME", Qtrue);
+#else
+ rb_define_const(mSSLExtConfig, "HAVE_TLSEXT_HOST_NAME", Qfalse);
#endif
+
/*
* A callback invoked whenever a new handshake is initiated. May be used
* to disable renegotiation entirely.
@@ -2316,7 +2189,6 @@ Init_ossl_ssl(void)
rb_define_alias(cSSLContext, "ssl_timeout", "timeout");
rb_define_alias(cSSLContext, "ssl_timeout=", "timeout=");
- rb_define_method(cSSLContext, "initialize", ossl_sslctx_initialize, -1);
rb_define_method(cSSLContext, "ssl_version=", ossl_sslctx_set_ssl_version, 1);
rb_define_method(cSSLContext, "ciphers", ossl_sslctx_get_ciphers, 0);
rb_define_method(cSSLContext, "ciphers=", ossl_sslctx_set_ciphers, 1);
@@ -2378,6 +2250,8 @@ Init_ossl_ssl(void)
rb_define_method(cSSLContext, "session_cache_size=", ossl_sslctx_set_session_cache_size, 1);
rb_define_method(cSSLContext, "session_cache_stats", ossl_sslctx_get_session_cache_stats, 0);
rb_define_method(cSSLContext, "flush_sessions", ossl_sslctx_flush_sessions, -1);
+ rb_define_method(cSSLContext, "options", ossl_sslctx_get_options, 0);
+ rb_define_method(cSSLContext, "options=", ossl_sslctx_set_options, 1);
ary = rb_ary_new2(numberof(ossl_ssl_method_tab));
for (i = 0; i < numberof(ossl_ssl_method_tab); i++) {
@@ -2396,15 +2270,10 @@ Init_ossl_ssl(void)
*/
cSSLSocket = rb_define_class_under(mSSL, "SSLSocket", rb_cObject);
#ifdef OPENSSL_NO_SOCK
- rb_define_method(cSSLSocket, "initialize", rb_notimplement, -1);
+ rb_define_const(mSSLExtConfig, "OPENSSL_NO_SOCK", Qtrue);
#else
+ rb_define_const(mSSLExtConfig, "OPENSSL_NO_SOCK", Qfalse);
rb_define_alloc_func(cSSLSocket, ossl_ssl_s_alloc);
- for(i = 0; i < numberof(ossl_ssl_attr_readers); i++)
- rb_attr(cSSLSocket, rb_intern(ossl_ssl_attr_readers[i]), 1, 0, Qfalse);
- for(i = 0; i < numberof(ossl_ssl_attrs); i++)
- rb_attr(cSSLSocket, rb_intern(ossl_ssl_attrs[i]), 1, 1, Qfalse);
- rb_define_alias(cSSLSocket, "to_io", "io");
- rb_define_method(cSSLSocket, "initialize", ossl_ssl_initialize, -1);
rb_define_method(cSSLSocket, "connect", ossl_ssl_connect, 0);
rb_define_method(cSSLSocket, "connect_nonblock", ossl_ssl_connect_nonblock, -1);
rb_define_method(cSSLSocket, "accept", ossl_ssl_accept, 0);
@@ -2413,7 +2282,7 @@ Init_ossl_ssl(void)
rb_define_private_method(cSSLSocket, "sysread_nonblock", ossl_ssl_read_nonblock, -1);
rb_define_method(cSSLSocket, "syswrite", ossl_ssl_write, 1);
rb_define_private_method(cSSLSocket, "syswrite_nonblock", ossl_ssl_write_nonblock, -1);
- rb_define_method(cSSLSocket, "sysclose", ossl_ssl_close, 0);
+ rb_define_private_method(cSSLSocket, "stop", ossl_ssl_stop, 0);
rb_define_method(cSSLSocket, "cert", ossl_ssl_get_cert, 0);
rb_define_method(cSSLSocket, "peer_cert", ossl_ssl_get_peer_cert, 0);
rb_define_method(cSSLSocket, "peer_cert_chain", ossl_ssl_get_peer_cert_chain, 0);
@@ -2434,7 +2303,7 @@ Init_ossl_ssl(void)
# endif
#endif
-#define ossl_ssl_def_const(x) rb_define_const(mSSL, #x, INT2NUM(SSL_##x))
+#define ossl_ssl_def_const(x) rb_define_const(mSSL, #x, LONG2NUM(SSL_##x))
ossl_ssl_def_const(VERIFY_NONE);
ossl_ssl_def_const(VERIFY_PEER);