15 #if defined(HAVE_UNISTD_H)
19 #define numberof(ary) (int)(sizeof(ary)/sizeof((ary)[0]))
22 # define TO_SOCKET(s) _get_osfhandle(s)
24 # define TO_SOCKET(s) (s)
32 #define ossl_sslctx_set_cert(o,v) rb_iv_set((o),"@cert",(v))
33 #define ossl_sslctx_set_key(o,v) rb_iv_set((o),"@key",(v))
34 #define ossl_sslctx_set_client_ca(o,v) rb_iv_set((o),"@client_ca",(v))
35 #define ossl_sslctx_set_ca_file(o,v) rb_iv_set((o),"@ca_file",(v))
36 #define ossl_sslctx_set_ca_path(o,v) rb_iv_set((o),"@ca_path",(v))
37 #define ossl_sslctx_set_timeout(o,v) rb_iv_set((o),"@timeout",(v))
38 #define ossl_sslctx_set_verify_mode(o,v) rb_iv_set((o),"@verify_mode",(v))
39 #define ossl_sslctx_set_verify_dep(o,v) rb_iv_set((o),"@verify_depth",(v))
40 #define ossl_sslctx_set_verify_cb(o,v) rb_iv_set((o),"@verify_callback",(v))
41 #define ossl_sslctx_set_options(o,v) rb_iv_set((o),"@options",(v))
42 #define ossl_sslctx_set_cert_store(o,v) rb_iv_set((o),"@cert_store",(v))
43 #define ossl_sslctx_set_extra_cert(o,v) rb_iv_set((o),"@extra_chain_cert",(v))
44 #define ossl_sslctx_set_client_cert_cb(o,v) rb_iv_set((o),"@client_cert_cb",(v))
45 #define ossl_sslctx_set_tmp_dh_cb(o,v) rb_iv_set((o),"@tmp_dh_callback",(v))
46 #define ossl_sslctx_set_sess_id_ctx(o, v) rb_iv_get((o),"@session_id_context"(v))
48 #define ossl_sslctx_get_cert(o) rb_iv_get((o),"@cert")
49 #define ossl_sslctx_get_key(o) rb_iv_get((o),"@key")
50 #define ossl_sslctx_get_client_ca(o) rb_iv_get((o),"@client_ca")
51 #define ossl_sslctx_get_ca_file(o) rb_iv_get((o),"@ca_file")
52 #define ossl_sslctx_get_ca_path(o) rb_iv_get((o),"@ca_path")
53 #define ossl_sslctx_get_timeout(o) rb_iv_get((o),"@timeout")
54 #define ossl_sslctx_get_verify_mode(o) rb_iv_get((o),"@verify_mode")
55 #define ossl_sslctx_get_verify_dep(o) rb_iv_get((o),"@verify_depth")
56 #define ossl_sslctx_get_verify_cb(o) rb_iv_get((o),"@verify_callback")
57 #define ossl_sslctx_get_options(o) rb_iv_get((o),"@options")
58 #define ossl_sslctx_get_cert_store(o) rb_iv_get((o),"@cert_store")
59 #define ossl_sslctx_get_extra_cert(o) rb_iv_get((o),"@extra_chain_cert")
60 #define ossl_sslctx_get_client_cert_cb(o) rb_iv_get((o),"@client_cert_cb")
61 #define ossl_sslctx_get_tmp_dh_cb(o) rb_iv_get((o),"@tmp_dh_callback")
62 #define ossl_sslctx_get_sess_id_ctx(o) rb_iv_get((o),"@session_id_context")
65 "cert",
"key",
"client_ca",
"ca_file",
"ca_path",
66 "timeout",
"verify_mode",
"verify_depth",
67 "verify_callback",
"options",
"cert_store",
"extra_chain_cert",
68 "client_cert_cb",
"tmp_dh_callback",
"session_id_context",
69 "session_get_cb",
"session_new_cb",
"session_remove_cb",
70 #ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
75 #define ossl_ssl_get_io(o) rb_iv_get((o),"@io")
76 #define ossl_ssl_get_ctx(o) rb_iv_get((o),"@context")
77 #define ossl_ssl_get_sync_close(o) rb_iv_get((o),"@sync_close")
78 #define ossl_ssl_get_x509(o) rb_iv_get((o),"@x509")
79 #define ossl_ssl_get_key(o) rb_iv_get((o),"@key")
80 #define ossl_ssl_get_tmp_dh(o) rb_iv_get((o),"@tmp_dh")
82 #define ossl_ssl_set_io(o,v) rb_iv_set((o),"@io",(v))
83 #define ossl_ssl_set_ctx(o,v) rb_iv_set((o),"@context",(v))
84 #define ossl_ssl_set_sync_close(o,v) rb_iv_set((o),"@sync_close",(v))
85 #define ossl_ssl_set_x509(o,v) rb_iv_set((o),"@x509",(v))
86 #define ossl_ssl_set_key(o,v) rb_iv_set((o),"@key",(v))
87 #define ossl_ssl_set_tmp_dh(o,v) rb_iv_set((o),"@tmp_dh",(v))
91 #ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
104 SSL_METHOD *(*func)(void);
106 #define OSSL_SSL_METHOD_ENTRY(name) { #name, (SSL_METHOD *(*)(void))name##_method }
110 #if defined(HAVE_SSLV2_METHOD) && defined(HAVE_SSLV2_SERVER_METHOD) && \
111 defined(HAVE_SSLV2_CLIENT_METHOD)
122 #undef OSSL_SSL_METHOD_ENTRY
135 ctx->cert_store =
NULL;
143 long mode = SSL_MODE_ENABLE_PARTIAL_WRITE;
145 #ifdef SSL_MODE_RELEASE_BUFFERS
146 mode |= SSL_MODE_RELEASE_BUFFERS;
149 ctx = SSL_CTX_new(SSLv23_method());
153 SSL_CTX_set_mode(ctx, mode);
167 SSL_METHOD *method =
NULL;
186 if (SSL_CTX_set_ssl_version(ctx, method) != 1) {
247 if (!
RTEST(success))
return 0;
254 #if !defined(OPENSSL_NO_DH)
267 if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DH)
return Qfalse;
309 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
318 VALUE ssl_obj, sslctx_obj, cb;
323 sslctx_obj =
rb_iv_get(ssl_obj,
"@context");
325 cb =
rb_iv_get(sslctx_obj,
"@session_get_cb");
335 VALUE ary, ssl_obj, ret_obj;
340 OSSL_Debug(
"SSL SESSION get callback entered");
343 ssl_obj = (
VALUE)ptr;
365 VALUE ssl_obj, sslctx_obj, cb;
370 sslctx_obj =
rb_iv_get(ssl_obj,
"@context");
372 cb =
rb_iv_get(sslctx_obj,
"@session_new_cb");
382 VALUE ary, ssl_obj, sess_obj, ret_obj;
386 OSSL_Debug(
"SSL SESSION new callback entered");
390 ssl_obj = (
VALUE)ptr;
392 CRYPTO_add(&sess->references, 1, CRYPTO_LOCK_SSL_SESSION);
417 VALUE sslctx_obj, cb;
422 cb =
rb_iv_get(sslctx_obj,
"@session_remove_cb");
431 VALUE ary, sslctx_obj, sess_obj, ret_obj;
435 OSSL_Debug(
"SSL SESSION remove callback entered");
439 sslctx_obj = (
VALUE)ptr;
441 CRYPTO_add(&sess->references, 1, CRYPTO_LOCK_SSL_SESSION);
466 if(!SSL_CTX_add_extra_chain_cert(ctx, x509)){
475 #ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
477 ossl_call_servername_cb(
VALUE ary)
479 VALUE ssl_obj, sslctx_obj, cb, ret_obj;
484 sslctx_obj =
rb_iv_get(ssl_obj,
"@context");
486 cb =
rb_iv_get(sslctx_obj,
"@servername_cb");
497 SSL_set_SSL_CTX(ssl, ctx2);
498 }
else if (!
NIL_P(ret_obj)) {
506 ssl_servername_cb(SSL *ssl,
int *ad,
void *
arg)
508 VALUE ary, ssl_obj, ret_obj;
511 const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
514 return SSL_TLSEXT_ERR_OK;
517 return SSL_TLSEXT_ERR_ALERT_FATAL;
518 ssl_obj = (
VALUE)ptr;
526 return SSL_TLSEXT_ERR_ALERT_FATAL;
529 return SSL_TLSEXT_ERR_OK;
546 X509 *cert =
NULL, *client_ca =
NULL;
549 char *ca_path =
NULL, *ca_file =
NULL;
556 #if !defined(OPENSSL_NO_DH)
575 SSL_CTX_set_cert_store(ctx, store);
590 if (!SSL_CTX_use_certificate(ctx, cert)) {
594 if (!SSL_CTX_use_PrivateKey(ctx, key)) {
598 if (!SSL_CTX_check_private_key(ctx)) {
608 if (!SSL_CTX_add_client_CA(ctx, client_ca)){
616 if (!SSL_CTX_add_client_CA(ctx, client_ca)){
627 if(ca_file || ca_path){
628 if (!SSL_CTX_load_verify_locations(ctx, ca_file, ca_path))
633 verify_mode =
NIL_P(val) ? SSL_VERIFY_NONE :
NUM2INT(val);
642 if(!
NIL_P(val)) SSL_CTX_set_verify_depth(ctx,
NUM2INT(val));
646 SSL_CTX_set_options(ctx,
NUM2LONG(val));
649 SSL_CTX_set_options(ctx, SSL_OP_ALL);
656 if (!SSL_CTX_set_session_id_context(ctx, (
unsigned char *)
RSTRING_PTR(val),
672 OSSL_Debug(
"SSL SESSION remove callback added");
675 #ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
678 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb);
679 OSSL_Debug(
"SSL TLSEXT servername callback added");
695 bits = SSL_CIPHER_get_bits(cipher, &alg_bits);
722 ciphers = ctx->cipher_list;
727 num = sk_SSL_CIPHER_num(ciphers);
729 for(i = 0; i < num; i++){
730 cipher = sk_SSL_CIPHER_value(ciphers, i);
777 if (!SSL_CTX_set_cipher_list(ctx,
RSTRING_PTR(str))) {
800 return SSL_CTX_add_session(ctx, sess) == 1 ?
Qtrue :
Qfalse;
818 return SSL_CTX_remove_session(ctx, sess) == 1 ?
Qtrue :
Qfalse;
834 return LONG2NUM(SSL_CTX_get_session_cache_mode(ctx));
852 SSL_CTX_set_session_cache_mode(ctx,
NUM2LONG(arg));
871 return LONG2NUM(SSL_CTX_sess_get_cache_size(ctx));
888 SSL_CTX_sess_set_cache_size(ctx,
NUM2LONG(arg));
966 SSL_CTX_flush_sessions(ctx, (
long)tm);
982 for (i = 0; i < 4; ++
i) {
987 if (rc = SSL_shutdown(ssl))
1048 VALUE io, v_ctx, cb;
1055 #ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
1068 #ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
1069 if (!
NIL_P(hostname)) {
1070 if (SSL_set_tlsext_host_name(ssl,
StringValuePtr(hostname)) != 1)
1092 #define ssl_get_error(ssl, ret) (errno = rb_w32_map_errno(WSAGetLastError()), SSL_get_error((ssl), (ret)))
1094 #define ssl_get_error(ssl, ret) SSL_get_error((ssl), (ret))
1133 if (!
NIL_P(cb_state))
1140 case SSL_ERROR_WANT_WRITE:
1144 case SSL_ERROR_WANT_READ:
1148 case SSL_ERROR_SYSCALL:
1150 ossl_raise(
eSSLError,
"%s SYSCALL returned=%d errno=%d state=%s", funcname, ret2,
errno, SSL_state_string_long(ssl));
1241 int ilen, nread = 0;
1253 if(ilen == 0)
return str;
1258 if(!nonblock && SSL_pending(ssl) <= 0)
1263 case SSL_ERROR_NONE:
1265 case SSL_ERROR_ZERO_RETURN:
1267 case SSL_ERROR_WANT_WRITE:
1271 case SSL_ERROR_WANT_READ:
1275 case SSL_ERROR_SYSCALL:
1276 if(ERR_peek_error() == 0 && nread == 0)
rb_eof_error();
1284 ID meth = nonblock ?
rb_intern(
"read_nonblock") : rb_intern(
"sysread");
1285 rb_warning(
"SSL session is not started yet.");
1343 case SSL_ERROR_NONE:
1345 case SSL_ERROR_WANT_WRITE:
1349 case SSL_ERROR_WANT_READ:
1353 case SSL_ERROR_SYSCALL:
1362 rb_warning(
"SSL session is not started yet.");
1435 rb_warning(
"SSL session is not started yet.");
1443 cert = SSL_get_certificate(ssl);
1467 rb_warning(
"SSL session is not started yet.");
1471 cert = SSL_get_peer_certificate(ssl);
1499 rb_warning(
"SSL session is not started yet.");
1502 chain = SSL_get_peer_cert_chain(ssl);
1503 if(!chain)
return Qnil;
1504 num = sk_X509_num(chain);
1506 for (i = 0; i < num; i++){
1507 cert = sk_X509_value(chain, i);
1528 rb_warning(
"SSL session is not started yet.");
1531 cipher = (SSL_CIPHER *)SSL_get_current_cipher(ssl);
1550 rb_warning(
"SSL session is not started yet.");
1574 rb_warning(
"SSL session is not started yet.");
1578 return INT2NUM(SSL_pending(ssl));
1594 rb_warning(
"SSL session is not started yet.");
1598 switch(SSL_session_reused(ssl)) {
1599 case 1:
return Qtrue;
1622 rb_warning(
"SSL session is not started yet.");
1628 if (SSL_set_session(ssl, sess) != 1)
1650 rb_warning(
"SSL session is not started yet.");
1654 return INT2FIX(SSL_get_verify_result(ssl));
1676 rb_warning(
"SSL session is not started yet.");
1680 ca = SSL_get_client_CA_list(ssl);
1700 SSL_get_ex_new_index(0,(
void *)
"ossl_ssl_ex_client_cert_cb_idx",0,0,0);
1702 SSL_get_ex_new_index(0,(
void *)
"ossl_ssl_ex_tmp_dh_callback_idx",0,0,0);
1853 #ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
1973 #define ossl_ssl_def_const(x) rb_define_const(mSSL, #x, INT2NUM(SSL_##x))
1994 #if defined(SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION)
1997 #if defined(SSL_OP_SINGLE_ECDH_USE)
2002 #if defined(SSL_OP_CIPHER_SERVER_PREFERENCE)
2009 #if defined(SSL_OP_NO_TICKET)
2012 #if defined(SSL_OP_NO_COMPRESSION)