int sslsocket::recvsome(void* buff, int capacity) { ERR_clear_error(); // the SSL_read operation may fail because SSL handshake // is being done transparently and that requires IO on the socket // which cannot be completed at the time. This is indicated by // SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE. When this happens // we need to wait utill the condition can be satisfied on the // underlying socket object (can read/write) and then restart // the SSL operation with the *same* parameters. int recv = 0; do { const int ret = SSL_read(ssl_, buff, capacity); switch (SSL_get_error(ssl_, ret)) { case SSL_ERROR_NONE: recv += ret; break; case SSL_ERROR_WANT_WRITE: ssl_wait_write(); break; case SSL_ERROR_WANT_READ: ssl_wait_read(); break; // some I/O error occurred. The OpenSSL error queue may contain // more information. If the error queue is empty (i.e. ERR_get_error returns 0) // ret can be used to find more about the error. if ret == 0 an EOF was observed // that violates the protocol. if err == -1 the underlying BIO reported an I/O // error. case SSL_ERROR_SYSCALL: { const auto ssl_err = ERR_get_error(); if (ssl_err == 0) { if (ret == 0) throw std::runtime_error("socket was closed unexpectedly"); const auto sock_err = get_last_socket_error(); if (sock_err != std::errc::operation_would_block) throw std::system_error(sock_err, "socket send"); } else { throw std::runtime_error(get_ssl_error(ssl_err)); } } break; // socket was closed. case SSL_ERROR_ZERO_RETURN: return 0; default: throw std::runtime_error("SSL_read"); } } while (!recv); return recv; }
int rb_init_ssl(void) { int ret = 1; char libratbox_data[] = "libratbox data"; SSL_load_error_strings(); SSL_library_init(); libratbox_index = SSL_get_ex_new_index(0, libratbox_data, NULL, NULL, NULL); ssl_server_ctx = SSL_CTX_new(SSLv23_server_method()); if(ssl_server_ctx == NULL) { rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL server context: %s", get_ssl_error(ERR_get_error())); ret = 0; } /* Disable SSLv2, make the client use our settings */ SSL_CTX_set_options(ssl_server_ctx, SSL_OP_NO_SSLv2 | SSL_OP_CIPHER_SERVER_PREFERENCE); SSL_CTX_set_verify(ssl_server_ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, verify_accept_all_cb); ssl_client_ctx = SSL_CTX_new(TLSv1_client_method()); if(ssl_client_ctx == NULL) { rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL client context: %s", get_ssl_error(ERR_get_error())); ret = 0; } return ret; }
int rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile) { DH *dh; unsigned long err; if(cert == NULL) { rb_lib_log("rb_setup_ssl_server: No certificate file"); return 0; } if(!SSL_CTX_use_certificate_chain_file(ssl_server_ctx, cert) || !SSL_CTX_use_certificate_chain_file(ssl_client_ctx, cert)) { err = ERR_get_error(); rb_lib_log("rb_setup_ssl_server: Error loading certificate file [%s]: %s", cert, get_ssl_error(err)); return 0; } if(keyfile == NULL) { rb_lib_log("rb_setup_ssl_server: No key file"); return 0; } if(!SSL_CTX_use_PrivateKey_file(ssl_server_ctx, keyfile, SSL_FILETYPE_PEM) || !SSL_CTX_use_PrivateKey_file(ssl_client_ctx, keyfile, SSL_FILETYPE_PEM)) { err = ERR_get_error(); rb_lib_log("rb_setup_ssl_server: Error loading keyfile [%s]: %s", keyfile, get_ssl_error(err)); return 0; } if(dhfile != NULL) { /* DH parameters aren't necessary, but they are nice..if they didn't pass one..that is their problem */ BIO *bio = BIO_new_file(dhfile, "r"); if(bio != NULL) { dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); if(dh == NULL) { err = ERR_get_error(); rb_lib_log ("rb_setup_ssl_server: Error loading DH params file [%s]: %s", dhfile, get_ssl_error(err)); BIO_free(bio); return 0; } BIO_free(bio); SSL_CTX_set_tmp_dh(ssl_server_ctx, dh); } else { err = ERR_get_error(); rb_lib_log("rb_setup_ssl_server: Error loading DH params file [%s]: %s", dhfile, get_ssl_error(err)); } } return 1; }
int rb_init_ssl(void) { int ret = 1; char libratbox_data[] = "libratbox data"; SSL_load_error_strings(); SSL_library_init(); libratbox_index = SSL_get_ex_new_index(0, libratbox_data, NULL, NULL, NULL); ssl_server_ctx = SSL_CTX_new(SSLv23_server_method()); if(ssl_server_ctx == NULL) { rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL server context: %s", get_ssl_error(ERR_get_error())); ret = 0; } /* Disable SSLv2, make the client use our settings */ SSL_CTX_set_options(ssl_server_ctx, SSL_OP_NO_SSLv2 | SSL_OP_CIPHER_SERVER_PREFERENCE #ifdef SSL_OP_SINGLE_DH_USE | SSL_OP_SINGLE_DH_USE #endif ); SSL_CTX_set_verify(ssl_server_ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, verify_accept_all_cb); SSL_CTX_set_session_id_context(ssl_server_ctx, (const unsigned char *)"libratbox", 9); SSL_CTX_set_cipher_list(ssl_server_ctx, "EECDH+HIGH:EDH+HIGH:HIGH:!aNULL"); /* Set ECDHE on OpenSSL 1.00+, but make sure it's actually available because redhat are dicks and bastardise their OpenSSL for stupid reasons... */ #if (OPENSSL_VERSION_NUMBER >= 0x10000000) && defined(NID_secp384r1) EC_KEY *key = EC_KEY_new_by_curve_name(NID_secp384r1); if (key) { SSL_CTX_set_tmp_ecdh(ssl_server_ctx, key); EC_KEY_free(key); } #ifdef SSL_OP_SINGLE_ECDH_USE SSL_CTX_set_options(ssl_server_ctx, SSL_OP_SINGLE_ECDH_USE); #endif #endif ssl_client_ctx = SSL_CTX_new(TLSv1_client_method()); if(ssl_client_ctx == NULL) { rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL client context: %s", get_ssl_error(ERR_get_error())); ret = 0; } return ret; }
void handle_auth(struct vsf_session* p_sess) { str_upper(&p_sess->ftp_arg_str); if (str_equal_text(&p_sess->ftp_arg_str, "TLS") || str_equal_text(&p_sess->ftp_arg_str, "TLS-C") || str_equal_text(&p_sess->ftp_arg_str, "SSL") || str_equal_text(&p_sess->ftp_arg_str, "TLS-P")) { vsf_cmdio_write(p_sess, FTP_AUTHOK, "Proceed with negotiation."); if (!ssl_session_init(p_sess)) { struct mystr err_str = INIT_MYSTR; str_alloc_text(&err_str, "Negotiation failed: "); str_append_text(&err_str, get_ssl_error()); vsf_cmdio_write_str(p_sess, FTP_TLS_FAIL, &err_str); vsf_sysutil_exit(0); } p_sess->control_use_ssl = 1; if (str_equal_text(&p_sess->ftp_arg_str, "SSL") || str_equal_text(&p_sess->ftp_arg_str, "TLS-P")) { p_sess->data_use_ssl = 1; } } else { vsf_cmdio_write(p_sess, FTP_BADAUTH, "Unknown AUTH type."); } }
static void maybe_log_ssl_error_state(struct vsf_session* p_sess, int ret) { if (tunable_debug_ssl) { str_alloc_text(&debug_str, "SSL ret: "); str_append_ulong(&debug_str, ret); str_append_text(&debug_str, ", SSL error: "); str_append_text(&debug_str, get_ssl_error()); str_append_text(&debug_str, ", errno: "); str_append_ulong(&debug_str, errno); vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str); } }
void ssl_control_handshake(struct vsf_session* p_sess) { if (!ssl_session_init(p_sess)) { struct mystr err_str = INIT_MYSTR; str_alloc_text(&err_str, "Negotiation failed: "); /* Technically, we shouldn't leak such detailed error messages. */ str_append_text(&err_str, get_ssl_error()); vsf_cmdio_write_str(p_sess, FTP_TLS_FAIL, &err_str); vsf_sysutil_exit(0); } p_sess->control_use_ssl = 1; }
static SSL* get_ssl(struct vsf_session* p_sess, int fd) { SSL* p_ssl = SSL_new(p_sess->p_ssl_ctx); if (p_ssl == NULL) { return NULL; } if (!SSL_set_fd(p_ssl, fd)) { SSL_free(p_ssl); return NULL; } if (SSL_accept(p_ssl) != 1) { die(get_ssl_error()); SSL_free(p_ssl); return NULL; } return p_ssl; }
const char * rb_get_ssl_strerror(rb_fde_t *F) { return get_ssl_error(F->ssl_errno); }
static SSL* get_ssl(struct vsf_session* p_sess, int fd) { SSL* p_ssl = SSL_new(p_sess->p_ssl_ctx); if (p_ssl == NULL) { if (tunable_debug_ssl) { str_alloc_text(&debug_str, "SSL_new failed"); vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str); } return NULL; } if (!SSL_set_fd(p_ssl, fd)) { if (tunable_debug_ssl) { str_alloc_text(&debug_str, "SSL_set_fd failed"); vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str); } SSL_free(p_ssl); return NULL; } int retval; if (p_sess->is_ssl_client) { /* Connect to a remote FXP server in SSL client mode */ retval = SSL_connect(p_ssl); str_alloc_text(&debug_str, "SSL_connect failed: "); } else { /* Accept a SSL connection from a client or remote FXP server */ retval = SSL_accept(p_ssl); str_alloc_text(&debug_str, "SSL_accept failed: "); } if (retval != 1) { const char* p_err = get_ssl_error(); if (tunable_debug_ssl) { str_append_text(&debug_str, p_err); vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str); } /* The RFC is quite clear that we can just close the control channel * here. */ die(p_err); } if (tunable_debug_ssl) { const char* p_ssl_version = SSL_get_cipher_version(p_ssl); SSL_CIPHER* p_ssl_cipher = SSL_get_current_cipher(p_ssl); const char* p_cipher_name = SSL_CIPHER_get_name(p_ssl_cipher); X509* p_ssl_cert = SSL_get_peer_certificate(p_ssl); int reused = SSL_session_reused(p_ssl); str_alloc_text(&debug_str, "SSL version: "); str_append_text(&debug_str, p_ssl_version); str_append_text(&debug_str, ", SSL cipher: "); str_append_text(&debug_str, p_cipher_name); if (reused) { str_append_text(&debug_str, ", reused"); } else { str_append_text(&debug_str, ", not reused"); } if (p_ssl_cert != NULL) { str_append_text(&debug_str, ", CERT PRESENTED"); X509_free(p_ssl_cert); } else { str_append_text(&debug_str, ", no cert"); } vsf_log_line(p_sess, kVSFLogEntryDebug, &debug_str); } return p_ssl; }
int rb_init_ssl(void) { int ret = 1; char libratbox_data[] = "libratbox data"; const char libratbox_ciphers[] = "kEECDH+HIGH:kEDH+HIGH:HIGH:!RC4:!aNULL"; SSL_load_error_strings(); SSL_library_init(); libratbox_index = SSL_get_ex_new_index(0, libratbox_data, NULL, NULL, NULL); #if defined(LIBRESSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x10100000L) ssl_server_ctx = SSL_CTX_new(SSLv23_server_method()); #else ssl_server_ctx = SSL_CTX_new(TLS_server_method()); #endif if(ssl_server_ctx == NULL) { rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL server context: %s", get_ssl_error(ERR_get_error())); ret = 0; } long server_options = SSL_CTX_get_options(ssl_server_ctx); #if defined(LIBRESSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x10100000L) server_options |= SSL_OP_NO_SSLv2; server_options |= SSL_OP_NO_SSLv3; #endif #ifdef SSL_OP_SINGLE_DH_USE server_options |= SSL_OP_SINGLE_DH_USE; #endif #ifdef SSL_OP_SINGLE_ECDH_USE server_options |= SSL_OP_SINGLE_ECDH_USE; #endif #ifdef SSL_OP_NO_TICKET server_options |= SSL_OP_NO_TICKET; #endif server_options |= SSL_OP_CIPHER_SERVER_PREFERENCE; SSL_CTX_set_options(ssl_server_ctx, server_options); SSL_CTX_set_verify(ssl_server_ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, verify_accept_all_cb); SSL_CTX_set_session_cache_mode(ssl_server_ctx, SSL_SESS_CACHE_OFF); SSL_CTX_set_cipher_list(ssl_server_ctx, libratbox_ciphers); /* Set ECDHE on OpenSSL 1.00+, but make sure it's actually available because redhat are dicks and bastardise their OpenSSL for stupid reasons... */ #if (OPENSSL_VERSION_NUMBER >= 0x10000000L) && defined(NID_secp384r1) EC_KEY *key = EC_KEY_new_by_curve_name(NID_secp384r1); if (key) { SSL_CTX_set_tmp_ecdh(ssl_server_ctx, key); EC_KEY_free(key); } #endif #if defined(LIBRESSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x10100000L) ssl_client_ctx = SSL_CTX_new(TLSv1_client_method()); #else ssl_client_ctx = SSL_CTX_new(TLS_client_method()); #endif if(ssl_client_ctx == NULL) { rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL client context: %s", get_ssl_error(ERR_get_error())); ret = 0; } #ifdef SSL_OP_NO_TICKET SSL_CTX_set_options(ssl_client_ctx, SSL_OP_NO_TICKET); #endif SSL_CTX_set_cipher_list(ssl_client_ctx, libratbox_ciphers); return ret; }
int sslsocket::sendsome(const void* buff, int len) { ERR_clear_error(); // the SSL_read operation may fail because SSL handshake // is being done transparently and that requires IO on the socket // which cannot be completed at the time. This is indicated by // SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE. When this happens // we need to wait utill the condition can be satisfied on the // underlying socket object (can read/write) and then restart // the SSL operation with the *same* parameters. int sent = 0; do { const int ret = SSL_write(ssl_, buff, len); switch (SSL_get_error(ssl_, ret)) { case SSL_ERROR_NONE: sent += ret; break; case SSL_ERROR_WANT_READ: ssl_wait_read(); break; case SSL_ERROR_WANT_WRITE: ssl_wait_write(); break; // some I/O error occurred. The OpenSSL error queue may contain // more information. If the error queue is empty (i.e. ERR_get_error returns 0) // ret can be used to find more about the error. if ret == 0 an EOF was observed // that violates the protocol. if err == -1 the underlying BIO reported an I/O // error. case SSL_ERROR_SYSCALL: { const auto ssl_err = ERR_get_error(); if (ssl_err == 0) { if (ret == 0) throw std::runtime_error("socket was closed unexpectedly"); const auto sock_err = get_last_socket_error(); if (sock_err != std::errc::operation_would_block) throw std::system_error(sock_err, "socket send"); } else { throw std::runtime_error(get_ssl_error(ssl_err)); } } break; default: throw std::runtime_error("SSL_write"); } } while (!sent); // on windows writeability is edge triggered, // i.e. the event is signaled once when the socket is writeable and a call // to send clears the signal. the signal remains cleared // untill send fails with WSAEWOULDBLOCK which will schedule // the event for signaling once the socket can write more. #if defined(WINDOWS_OS) // set the signal manually since the socket can write more, // so that we have the same semantics with linux. SetEvent(handle_); #endif return sent; }
int rb_setup_ssl_server(const char *certfile, const char *keyfile, const char *dhfile, const char *cipher_list) { const char librb_ciphers[] = "kEECDH+HIGH:kEDH+HIGH:HIGH:!aNULL"; #ifdef LRB_HAVE_TLS_SET_CURVES const char librb_curves[] = "P-521:P-384:P-256"; #endif if(certfile == NULL) { rb_lib_log("rb_setup_ssl_server: No certificate file"); return 0; } if(keyfile == NULL) keyfile = certfile; if(cipher_list == NULL) cipher_list = librb_ciphers; if (ssl_server_ctx) SSL_CTX_free(ssl_server_ctx); if (ssl_client_ctx) SSL_CTX_free(ssl_client_ctx); #ifdef LRB_HAVE_TLS_METHOD_API ssl_server_ctx = SSL_CTX_new(TLS_server_method()); ssl_client_ctx = SSL_CTX_new(TLS_client_method()); #else ssl_server_ctx = SSL_CTX_new(SSLv23_server_method()); ssl_client_ctx = SSL_CTX_new(SSLv23_client_method()); #endif if(ssl_server_ctx == NULL) { rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL server context: %s", get_ssl_error(ERR_get_error())); return 0; } if(ssl_client_ctx == NULL) { rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL client context: %s", get_ssl_error(ERR_get_error())); return 0; } #ifndef LRB_HAVE_TLS_METHOD_API SSL_CTX_set_options(ssl_server_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); SSL_CTX_set_options(ssl_client_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); #endif #ifdef SSL_OP_SINGLE_DH_USE SSL_CTX_set_options(ssl_server_ctx, SSL_OP_SINGLE_DH_USE); #endif #ifdef SSL_OP_SINGLE_ECDH_USE SSL_CTX_set_options(ssl_server_ctx, SSL_OP_SINGLE_ECDH_USE); #endif #ifdef SSL_OP_NO_TICKET SSL_CTX_set_options(ssl_server_ctx, SSL_OP_NO_TICKET); SSL_CTX_set_options(ssl_client_ctx, SSL_OP_NO_TICKET); #endif #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE SSL_CTX_set_options(ssl_server_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); #endif SSL_CTX_set_verify(ssl_server_ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, verify_accept_all_cb); SSL_CTX_set_session_cache_mode(ssl_server_ctx, SSL_SESS_CACHE_OFF); #ifdef LRB_HAVE_TLS_SET_CURVES SSL_CTX_set1_curves_list(ssl_server_ctx, librb_curves); #endif #ifdef LRB_HAVE_TLS_ECDH_AUTO SSL_CTX_set_ecdh_auto(ssl_server_ctx, 1); #endif /* * Set manual ECDHE curve on OpenSSL 1.0.0 & 1.0.1, but make sure it's actually available */ #if (OPENSSL_VERSION_NUMBER >= 0x10000000L) && (OPENSSL_VERSION_NUMBER < 0x10002000L) && !defined(OPENSSL_NO_ECDH) EC_KEY *key = EC_KEY_new_by_curve_name(NID_secp384r1); if (key) { SSL_CTX_set_tmp_ecdh(ssl_server_ctx, key); EC_KEY_free(key); } #endif SSL_CTX_set_cipher_list(ssl_server_ctx, cipher_list); SSL_CTX_set_cipher_list(ssl_client_ctx, cipher_list); if(!SSL_CTX_use_certificate_chain_file(ssl_server_ctx, certfile) || !SSL_CTX_use_certificate_chain_file(ssl_client_ctx, certfile)) { rb_lib_log("rb_setup_ssl_server: Error loading certificate file [%s]: %s", certfile, get_ssl_error(ERR_get_error())); return 0; } if(!SSL_CTX_use_PrivateKey_file(ssl_server_ctx, keyfile, SSL_FILETYPE_PEM) || !SSL_CTX_use_PrivateKey_file(ssl_client_ctx, keyfile, SSL_FILETYPE_PEM)) { rb_lib_log("rb_setup_ssl_server: Error loading keyfile [%s]: %s", keyfile, get_ssl_error(ERR_get_error())); return 0; } if(dhfile != NULL) { /* DH parameters aren't necessary, but they are nice..if they didn't pass one..that is their problem */ FILE *fp = fopen(dhfile, "r"); DH *dh = NULL; if(fp == NULL) { rb_lib_log("rb_setup_ssl_server: Error loading DH params file [%s]: %s", dhfile, strerror(errno)); } else if(PEM_read_DHparams(fp, &dh, NULL, NULL) == NULL) { rb_lib_log("rb_setup_ssl_server: Error loading DH params file [%s]: %s", dhfile, get_ssl_error(ERR_get_error())); fclose(fp); } else { SSL_CTX_set_tmp_dh(ssl_server_ctx, dh); DH_free(dh); fclose(fp); } } return 1; }
int rb_init_ssl(void) { int ret = 1; char librb_data[] = "librb data"; const char librb_ciphers[] = "kEECDH+HIGH:kEDH+HIGH:HIGH:!RC4:!aNULL"; SSL_load_error_strings(); SSL_library_init(); librb_index = SSL_get_ex_new_index(0, librb_data, NULL, NULL, NULL); #ifndef LRB_HAVE_TLS_METHOD_API ssl_server_ctx = SSL_CTX_new(SSLv23_server_method()); #else ssl_server_ctx = SSL_CTX_new(TLS_server_method()); #endif if(ssl_server_ctx == NULL) { rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL server context: %s", get_ssl_error(ERR_get_error())); ret = 0; } long server_options = SSL_CTX_get_options(ssl_server_ctx); #ifndef LRB_HAVE_TLS_METHOD_API server_options |= SSL_OP_NO_SSLv2; server_options |= SSL_OP_NO_SSLv3; #endif #ifdef SSL_OP_SINGLE_DH_USE server_options |= SSL_OP_SINGLE_DH_USE; #endif #ifdef SSL_OP_SINGLE_ECDH_USE server_options |= SSL_OP_SINGLE_ECDH_USE; #endif #ifdef SSL_OP_NO_TICKET server_options |= SSL_OP_NO_TICKET; #endif server_options |= SSL_OP_CIPHER_SERVER_PREFERENCE; SSL_CTX_set_options(ssl_server_ctx, server_options); SSL_CTX_set_verify(ssl_server_ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, verify_accept_all_cb); SSL_CTX_set_session_cache_mode(ssl_server_ctx, SSL_SESS_CACHE_OFF); SSL_CTX_set_cipher_list(ssl_server_ctx, librb_ciphers); /* Set ECDHE on OpenSSL 1.00+, but make sure it's actually available * (it's not by default on Solaris or Red Hat... f**k Red Hat and Oracle) */ #if (OPENSSL_VERSION_NUMBER >= 0x10000000L) && !defined(OPENSSL_NO_ECDH) EC_KEY *key = EC_KEY_new_by_curve_name(NID_secp384r1); if (key) { SSL_CTX_set_tmp_ecdh(ssl_server_ctx, key); EC_KEY_free(key); } #endif #ifndef LRB_HAVE_TLS_METHOD_API ssl_client_ctx = SSL_CTX_new(SSLv23_client_method()); #else ssl_client_ctx = SSL_CTX_new(TLS_client_method()); #endif if(ssl_client_ctx == NULL) { rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL client context: %s", get_ssl_error(ERR_get_error())); ret = 0; } #ifndef LRB_HAVE_TLS_METHOD_API SSL_CTX_set_options(ssl_client_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); #endif #ifdef SSL_OP_NO_TICKET SSL_CTX_set_options(ssl_client_ctx, SSL_OP_NO_TICKET); #endif SSL_CTX_set_cipher_list(ssl_client_ctx, librb_ciphers); return ret; }