Exemplo n.º 1
1
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;
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
0
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.");
  }
}
Exemplo n.º 6
0
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);
  }
}
Exemplo n.º 7
0
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;
}
Exemplo n.º 8
0
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;
}
Exemplo n.º 9
0
const char *
rb_get_ssl_strerror(rb_fde_t *F)
{
	return get_ssl_error(F->ssl_errno);
}
Exemplo n.º 10
0
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;
}
Exemplo n.º 11
0
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;
}
Exemplo n.º 12
0
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;
}
Exemplo n.º 13
0
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;
}
Exemplo n.º 14
0
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;
}