Exemple #1
0
/*
 * initialize ssl methods
 */
static void
init_ssl_methods(void)
{
	LM_DBG("entered\n");

	ssl_methods[TLS_USE_TLSv1_cli-1] = (SSL_METHOD*)TLSv1_client_method();
	ssl_methods[TLS_USE_TLSv1_srv-1] = (SSL_METHOD*)TLSv1_server_method();
	ssl_methods[TLS_USE_TLSv1-1] = (SSL_METHOD*)TLSv1_method();

	ssl_methods[TLS_USE_SSLv23_cli-1] = (SSL_METHOD*)SSLv23_client_method();
	ssl_methods[TLS_USE_SSLv23_srv-1] = (SSL_METHOD*)SSLv23_server_method();
	ssl_methods[TLS_USE_SSLv23-1] = (SSL_METHOD*)SSLv23_method();

#if OPENSSL_VERSION_NUMBER >= 0x10001000L
	ssl_methods[TLS_USE_TLSv1_2_cli-1] = (SSL_METHOD*)TLSv1_2_client_method();
	ssl_methods[TLS_USE_TLSv1_2_srv-1] = (SSL_METHOD*)TLSv1_2_server_method();
	ssl_methods[TLS_USE_TLSv1_2-1] = (SSL_METHOD*)TLSv1_2_method();
#endif
}
Exemple #2
0
/*
  Initializes SSL and allocate global
  context SSL_context

  SYNOPSIS
    my_ssl_start
      mysql        connection handle

  RETURN VALUES
    0  success
    1  error
*/
int my_ssl_start(MYSQL *mysql)
{
  int rc= 0;
  DBUG_ENTER("my_ssl_start");
  /* lock mutex to prevent multiple initialization */
  pthread_mutex_lock(&LOCK_ssl_config);
  if (!my_ssl_initialized)
  {
#if OPENSSL_VERSION_NUMBER < 0x10100000
    if (ssl_crypto_init())
      goto end;
#endif
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
    OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL);
#else
    SSL_library_init();
#if SSLEAY_VERSION_NUMBER >= 0x00907000L
    OPENSSL_config(NULL);
#endif
#endif

    /* load errors */
    SSL_load_error_strings();
    /* digests and ciphers */
    OpenSSL_add_all_algorithms();

#if OPENSSL_VERSION_NUMBER >= 0x10100000L
    if (!(SSL_context= SSL_CTX_new(TLS_client_method())))
#else
    if (!(SSL_context= SSL_CTX_new(TLSv1_client_method())))
#endif
    {
      my_SSL_error(mysql);
      rc= 1;
      goto end;
    }
    my_ssl_initialized= TRUE;
  }
end:
  pthread_mutex_unlock(&LOCK_ssl_config);
  DBUG_RETURN(rc);
}
Exemple #3
0
void
_lm_ssl_initialize (LmSSL *ssl) 
{
    static gboolean initialized = FALSE;
    /*const char *cert_file = NULL;*/

    if (!initialized) {
        SSL_library_init();
        /* FIXME: Is this needed when we are not in debug? */
        SSL_load_error_strings();
        initialized = TRUE;
    }

    ssl->ssl_method = TLSv1_client_method();
    if (ssl->ssl_method == NULL) {
        g_warning ("TLSv1_client_method() == NULL");
        abort();
    }
    ssl->ssl_ctx = SSL_CTX_new(ssl->ssl_method);
    if (ssl->ssl_ctx == NULL) {
        g_warning ("SSL_CTX_new() == NULL");
        abort();
    }

    /* Set the NO_TICKET option on the context to allow for talk to Google Talk 
     * which apparently seems to be having a problem handling empty session 
     * tickets due to a bug in Java.
     *
     * See http://twistedmatrix.com/trac/ticket/3463 and
     * Loudmouth [#28].
     */
    SSL_CTX_set_options (ssl->ssl_ctx, SSL_OP_NO_TICKET);

    /*if (access("/etc/ssl/cert.pem", R_OK) == 0)
      cert_file = "/etc/ssl/cert.pem";
      if (!SSL_CTX_load_verify_locations(ssl->ssl_ctx,
      cert_file, "/etc/ssl/certs")) {
      g_warning("SSL_CTX_load_verify_locations() failed");
      }*/
    SSL_CTX_set_default_verify_paths (ssl->ssl_ctx);
    SSL_CTX_set_verify (ssl->ssl_ctx, SSL_VERIFY_PEER, ssl_verify_cb);
}
Exemple #4
0
// Establish a connection using an SSL layer
connection *sslConnect (void)
{
  connection *c;

  c = malloc (sizeof (connection));
  c->sslHandle = NULL;
  c->sslContext = NULL;

  c->socket = tcpConnect ();
  if (c->socket)
    {
      // Register the error strings for libcrypto & libssl
      SSL_load_error_strings ();
      // Register the available ciphers and digests
      SSL_library_init ();
 //     SSL_CTX_set_verify( tlsctx, SSL_VERIFY_PEER, verify_callback );
      // New context saying we are a client, and using SSL 2 or 3
    c->sslContext = SSL_CTX_new (TLSv1_client_method ());
   //   c->sslContext = SSL_CTX_new (TLSv1_client_method());
      if (c->sslContext == NULL)
        ERR_print_errors_fp (stderr);

      // Create an SSL struct for the connection
      c->sslHandle = SSL_new (c->sslContext);
      if (c->sslHandle == NULL)
        ERR_print_errors_fp (stderr);

      // Connect the SSL struct to our connection
      if (!SSL_set_fd (c->sslHandle, c->socket))
        ERR_print_errors_fp (stderr);

      // Initiate SSL handshake
      if (SSL_connect (c->sslHandle) != 1)
        ERR_print_errors_fp (stderr);
    }
  else
    {
      perror ("Connect failed");
    }

  return c;
}
Exemple #5
0
SSL*
imap_create_ssl(void)
{
  SSL *ssl;

  g_mutex_lock(&global_tls_lock);
  if(!global_ssl_context) {
    /* Initialize OpenSSL library, follow "Network Security with
       OpenSSL", ISBN 0-596-00270-X, guidelines. Example 4-2. */
    imaptls_thread_setup();
    SSL_library_init();
    SSL_load_error_strings();
#if 0
    global_ssl_context = SSL_CTX_new (TLSv1_client_method ());
#else
    /* Note: SSLv23_client_method() actually enables *all* protocols, including
     * SSLv(2|3) and TLSv1.(0|1|2), so we must switch all unsafe ones off */
    global_ssl_context = SSL_CTX_new (SSLv23_client_method ());
#ifdef ENABLE_SSL3
    SSL_CTX_set_options(global_ssl_context, SSL_OP_ALL|SSL_OP_NO_SSLv2);
#else
    SSL_CTX_set_options(global_ssl_context, SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3);
#endif
#endif
    /* no client certificate password support yet
     * SSL_CTX_set_default_passwd_cb (ctx, ctx_password_cb);
     * SSL_CTX_set_default_passwd_cb_userdata (ctx, ctx_password_cb_arg); 
     */

    /* Load the trusted CAs here. We just trust the system CA for the
       moment but we could try to be compatible with libESMTP in this
       respect.
    */
   SSL_CTX_set_default_verify_paths (global_ssl_context);
  }
  g_mutex_unlock(&global_tls_lock);

  ssl = SSL_new(global_ssl_context);

  /* setup client certificates here */
  return ssl;
}
Exemple #6
0
/*
 * initialize ssl methods 
 */
static void
init_ssl_methods(void)
{
	DBG("init_methods: Entered\n");
	ssl_methods[TLS_USE_SSLv2_cli - 1] = SSLv2_client_method();
	ssl_methods[TLS_USE_SSLv2_srv - 1] = SSLv2_server_method();
	ssl_methods[TLS_USE_SSLv2 - 1] = SSLv2_method();
	
	ssl_methods[TLS_USE_SSLv3_cli - 1] = SSLv3_client_method();
	ssl_methods[TLS_USE_SSLv3_srv - 1] = SSLv3_server_method();
	ssl_methods[TLS_USE_SSLv3 - 1] = SSLv3_method();
	
	ssl_methods[TLS_USE_TLSv1_cli - 1] = TLSv1_client_method();
	ssl_methods[TLS_USE_TLSv1_srv - 1] = TLSv1_server_method();
	ssl_methods[TLS_USE_TLSv1 - 1] = TLSv1_method();
	
	ssl_methods[TLS_USE_SSLv23_cli - 1] = SSLv23_client_method();
	ssl_methods[TLS_USE_SSLv23_srv - 1] = SSLv23_server_method();
	ssl_methods[TLS_USE_SSLv23 - 1] = SSLv23_method();
}
Exemple #7
0
SSL_CTX *cr_ssl_context_cli(void)
{
	const SSL_METHOD *meth;
	SSL_CTX *ssl;
	
	/* loading ssl features */

	SSL_load_error_strings();
	OpenSSL_add_all_algorithms();

	SSL_library_init();	
	/* creat a TLSv1 method instance */
	meth = TLSv1_client_method();

	ssl = SSL_CTX_new(meth);
	if(!ssl) {
		ERR_print_errors_fp(stderr);
		return NULL;
	}
	return ssl;
}
void TLSConnectionPrivate::OnConnect(uv_connect_t *connect, int status) {
	TLSConnectionPrivate *cp = static_cast<TLSConnectionPrivate *>(connect->data);
	assert(cp->state_ == TLS_CONNECTION_STATE_PRE_CONNECT);

	// Unable to connect.
	if (status == -1) {
		cp->ShutdownError(UVUtils::ErrorFromLastUVError(cp->loop_));
		return;
	}

	// Begin reading the incoming stream of data.
	int err = uv_read_start(connect->handle, TLSConnectionPrivate::AllocCallback, TLSConnectionPrivate::OnRead);
	if (err != UV_OK) {
		cp->ShutdownError(UVUtils::ErrorFromLastUVError(cp->loop_));
		return;
	}

	// Set up the OpenSSL context
	const SSL_METHOD *meth = TLSv1_client_method();
	cp->ctx_ = SSL_CTX_new(meth);

	SSL_CTX_set_verify(cp->ctx_, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
	SSL_CTX_set_cert_verify_callback(cp->ctx_, TLSConnectionPrivate::SSLVerifyCallback, cp);

	cp->ssl_ = SSL_new(cp->ctx_);
	SSL_set_connect_state(cp->ssl_);
	cp->bio_ = BIO_new(UVBioState::GetMethod());
	cp->biostate_ = new UVBioState(connect);
	cp->bio_->ptr = cp->biostate_;
	SSL_set_bio(cp->ssl_, cp->bio_, cp->bio_);

	// Set an empty X509_STORE as our SSL_CTX cert store.
	// The default store should be empty as well, but let's
	// make sure.
	X509_STORE *store = X509_STORE_new();
	SSL_CTX_set_cert_store(cp->ctx_, store);

	cp->state_ = TLS_CONNECTION_STATE_STARVED_SSL_CONNECT;
	cp->HandleStarvedConnectState();
}
Exemple #9
0
/**
 * Get internal ssl method ID
 * @param SSL method pointer
 * @return Internal ID or 0 if unknown
 */
uint_fast8_t get_ssl_method_id(const SSL_METHOD *method)
{
#ifndef OPENSSL_NO_SSL2
	if (method == SSLv2_client_method())
		return ssl_v2;
#endif // #ifndef OPENSSL_NO_SSL2
	if (method == SSLv3_client_method())
		return ssl_v3;

	if (method == TLSv1_client_method())
		return tls_v10;

#if OPENSSL_VERSION_NUMBER >= 0x1000008fL || OPENSSL_VERSION_NUMBER >= 0x1000100fL
	if (method == TLSv1_1_client_method())
		return tls_v11;

	if (method == TLSv1_2_client_method())
		return tls_v12;
#endif // #if OPENSSL_VERSION_NUMBER >= 0x1000008fL || OPENSSL_VERSION_NUMBER >= 0x1000100fL

	return 0;
}
Exemple #10
0
/**
 * Get a ssl method pointer by internal ID
 * @param id Internal ID
 * @return SSL method pointer
 */
const SSL_METHOD *get_ssl_method_by_id(uint_fast8_t id)
{
#ifndef OPENSSL_NO_SSL2
	if (id == ssl_v2)
		return SSLv2_client_method();
#endif // #ifndef OPENSSL_NO_SSL2
	if (id == ssl_v3)
		return SSLv3_client_method();

	if (id == tls_v10)
		return TLSv1_client_method();

#if OPENSSL_VERSION_NUMBER >= 0x1000008fL || OPENSSL_VERSION_NUMBER >= 0x1000100fL
	if (id == tls_v11)
		return TLSv1_1_client_method();

	if (id == tls_v12)
		return TLSv1_2_client_method();
#endif // #if OPENSSL_VERSION_NUMBER >= 0x1000008fL || OPENSSL_VERSION_NUMBER >= 0x1000100fL

	return NULL;
}
Exemple #11
0
/*
 * Negotiate SSL on the socket
 */
static DWORD negotiate_ssl(Remote *remote)
{
	DWORD hres = ERROR_SUCCESS;
	SOCKET fd = remote_get_fd(remote);
    DWORD ret;
	
	SSL_load_error_strings();
	SSL_library_init();

	remote->meth = TLSv1_client_method();

	remote->ctx  = SSL_CTX_new(remote->meth);
	SSL_CTX_set_mode(remote->ctx, SSL_MODE_AUTO_RETRY);

	remote->ssl  = SSL_new(remote->ctx);
	SSL_set_verify(remote->ssl, SSL_VERIFY_NONE, NULL);
	    if (SSL_set_fd(remote->ssl, remote->fd) == 0) {
		    perror("set fd failed");
		    exit(1);
	    }
	    

	    if ((ret = SSL_connect(remote->ssl)) != 1) {
		    printf("connect failed %d\n", SSL_get_error(remote->ssl, ret));
		    exit(1);
	    }
	dprintf("Sending a HTTP GET request to the remote side...");
	if((ret = SSL_write(remote->ssl, "GET / HTTP/1.0\r\n\r\n", 18)) <= 0) {
		dprintf("SSL write failed during negotiation with return: %d (%d)", ret, 
			SSL_get_error(remote->ssl, ret));
	}

	dprintf("Completed writing the HTTP GET request: %d", ret);
	
	if(ret < 0)
		ExitThread(0);

	return(0);
}
Exemple #12
0
int _tmain(int argc, _TCHAR* argv[])
{
	WSADATA wsaData = {0};
	WSAStartup(MAKEWORD(2, 2), &wsaData);
	SSLeay_add_all_algorithms();
	pthread_t pid;
	
	ERR_load_BIO_strings();
	SSL_library_init(); 
	SSL_load_error_strings();

	SSL *ssl = NULL;
	SSL_CTX *ctx = NULL;
	//这里要注意是client
	ctx = SSL_CTX_new(TLSv1_client_method());
	if (ctx == NULL)
	{
		printf("ssl ctx new eer\n");
		exit(-1);
	}

	transf_lock_cs = (pthread_mutex_t *)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
	transf_lock_count = (long *)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
	for (int i = 0; i < CRYPTO_num_locks(); i++)
	{
		transf_lock_count[i] = 0;
		pthread_mutex_init(&(transf_lock_cs[i]), NULL);
	}
	CRYPTO_set_id_callback((unsigned long(*)())transf_pthreads_thread_id);
	CRYPTO_set_locking_callback(transf_client_locking_callback);
	pthread_create(&pid, NULL, tcp_forwardlistenthread, ctx);

	pthread_join(pid, NULL);
	system("pause");
	getchar();
	SSL_CTX_free(ctx);
	WSACleanup();
	return 0;
}
Exemple #13
0
int tls_connect(rdpTls* tls, BIO *underlying)
{
	int options = 0;

	/**
	 * SSL_OP_NO_COMPRESSION:
	 *
	 * The Microsoft RDP server does not advertise support
	 * for TLS compression, but alternative servers may support it.
	 * This was observed between early versions of the FreeRDP server
	 * and the FreeRDP client, and caused major performance issues,
	 * which is why we're disabling it.
	 */
#ifdef SSL_OP_NO_COMPRESSION
	options |= SSL_OP_NO_COMPRESSION;
#endif

	/**
	 * SSL_OP_TLS_BLOCK_PADDING_BUG:
	 *
	 * The Microsoft RDP server does *not* support TLS padding.
	 * It absolutely needs to be disabled otherwise it won't work.
	 */
	options |= SSL_OP_TLS_BLOCK_PADDING_BUG;

	/**
	 * SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS:
	 *
	 * Just like TLS padding, the Microsoft RDP server does not
	 * support empty fragments. This needs to be disabled.
	 */
	options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;

	if (!tls_prepare(tls, underlying, TLSv1_client_method(), options, TRUE))
		return FALSE;

	return tls_do_handshake(tls, TRUE);
}
Exemple #14
0
const SSL_METHOD * hb_ssl_method_id_to_ptr( int n )
{
   const SSL_METHOD * p;

   switch( n )
   {
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
      case HB_SSL_CTX_NEW_METHOD_TLS:           p = TLS_method();           break;
      case HB_SSL_CTX_NEW_METHOD_TLS_SERVER:    p = TLS_server_method();    break;
      case HB_SSL_CTX_NEW_METHOD_TLS_CLIENT:    p = TLS_client_method();    break;
#else
      case HB_SSL_CTX_NEW_METHOD_TLSV1:         p = TLSv1_method();         break;
      case HB_SSL_CTX_NEW_METHOD_TLSV1_SERVER:  p = TLSv1_server_method();  break;
      case HB_SSL_CTX_NEW_METHOD_TLSV1_CLIENT:  p = TLSv1_client_method();  break;
      case HB_SSL_CTX_NEW_METHOD_TLS:           p = SSLv23_method();        break;
      case HB_SSL_CTX_NEW_METHOD_TLS_SERVER:    p = SSLv23_server_method(); break;
      case HB_SSL_CTX_NEW_METHOD_TLS_CLIENT:    p = SSLv23_client_method(); break;
#endif
      default: p = SSLv23_method();
   }

   return p;
}
Exemple #15
0
SSL *ssl_client_connect(const char *host, const char *port){
    SSL_METHOD *my_ssl_method;
    SSL_CTX *my_ssl_ctx;
    SSL *my_ssl;
    BIO *my_bio;
    char *host_port;
    
    host_port = w_malloc(strlen(host) + strlen(port) + 2);
    sprintf(host_port, "%s: %s", port, port);
    my_ssl_method = TLSv1_client_method();
    
    if ((my_ssl_ctx = SSL_CTX_new(my_ssl_method)) == NULL)
	return NULL;
    if ((my_ssl = SSL_new(my_ssl_ctx)) == NULL){
	SSL_CTX_free(my_ssl_ctx);
	return NULL;
    }
    if ((my_bio = BIO_new_connect(host_port)) == NULL){
	SSL_free(my_ssl);
	w_free(host_port);
	return NULL;
    }
    if (BIO_do_connect(my_bio) <= 0){
	SSL_free(my_ssl);
	BIO_free(my_bio);
	w_free(host_port);
	return NULL;
    }
    SSL_set_bio(my_ssl, my_bio, my_bio);
    if (SSL_connect(my_ssl) <= 0){
	SSL_free(my_ssl);
	w_free(host_port);
	return NULL;
    }
    w_free(host_port);
    return my_ssl;
}
Exemple #16
0
static int
tls_sc_create(lua_State *L) {
  tls_sc_t *ctx;
  const char *method_string = lua_tostring(L, 1);
  const SSL_METHOD *method = SSLv23_method();

  if (method_string) {
    if (strcmp(method_string, "SSLv3_method") == 0) {
      method = SSLv3_method();
    } else if (strcmp(method_string, "SSLv3_server_method") == 0) {
      method = SSLv3_server_method();
    } else if (strcmp(method_string, "SSLv3_client_method") == 0) {
      method = SSLv3_client_method();
    } else if (strcmp(method_string, "SSLv23_method") == 0) {
      method = SSLv23_method();
    } else if (strcmp(method_string, "SSLv23_server_method") == 0) {
      method = SSLv23_server_method();
    } else if (strcmp(method_string, "SSLv23_client_method") == 0) {
      method = SSLv23_client_method();
    } else if (strcmp(method_string, "TLSv1_method") == 0) {
      method = TLSv1_method();
    } else if (strcmp(method_string, "TLSv1_server_method") == 0) {
      method = TLSv1_server_method();
    } else if (strcmp(method_string, "TLSv1_client_method") == 0) {
      method = TLSv1_client_method();
    } else {
      return luaL_error(L, "method not supported: %s", method_string);
    }
  }

  ctx = newSC(L);
  ctx->ctx = SSL_CTX_new(method);
  /* TODO: customize Session cache */
  SSL_CTX_set_session_cache_mode(ctx->ctx, SSL_SESS_CACHE_SERVER);

  return 1;
}
Exemple #17
0
bool SSLSocket::setupCrypto(SSLSocket *session /* = NULL */) {
  if (m_data->m_handle) {
    raise_warning("SSL/TLS already set-up for this stream");
    return false;
  }

  /* need to do slightly different things, based on client/server method,
   * so lets remember which method was selected */
#if OPENSSL_VERSION_NUMBER < 0x00909000L
  SSL_METHOD *smethod;
#else
  const SSL_METHOD *smethod;
#endif
  switch (m_data->m_method) {
  case CryptoMethod::ClientSSLv23:
    m_data->m_client = true;
    smethod = SSLv23_client_method();
    break;
  case CryptoMethod::ClientSSLv3:
    m_data->m_client = true;
    smethod = SSLv3_client_method();
    break;
  case CryptoMethod::ClientTLS:
    m_data->m_client = true;
    smethod = TLSv1_client_method();
    break;
  case CryptoMethod::ServerSSLv23:
    m_data->m_client = false;
    smethod = SSLv23_server_method();
    break;
  case CryptoMethod::ServerSSLv3:
    m_data->m_client = false;
    smethod = SSLv3_server_method();
    break;

  /* SSLv2 protocol might be disabled in the OpenSSL library */
#ifndef OPENSSL_NO_SSL2
  case CryptoMethod::ClientSSLv2:
    m_data->m_client = true;
    smethod = SSLv2_client_method();
    break;
  case CryptoMethod::ServerSSLv2:
    m_data->m_client = false;
    smethod = SSLv2_server_method();
    break;
#else
  case CryptoMethod::ClientSSLv2:
  case CryptoMethod::ServerSSLv2:
    raise_warning("OpenSSL library does not support SSL2 protocol");
    return false;
  break;
#endif

  case CryptoMethod::ServerTLS:
    m_data->m_client = false;
    smethod = TLSv1_server_method();
    break;
  default:
    return false;
  }

  SSL_CTX *ctx = SSL_CTX_new(smethod);
  if (ctx == nullptr) {
    raise_warning("failed to create an SSL context");
    return false;
  }

  SSL_CTX_set_options(ctx, SSL_OP_ALL);
  m_data->m_handle = createSSL(ctx);
  if (m_data->m_handle == nullptr) {
    raise_warning("failed to create an SSL handle");
    SSL_CTX_free(ctx);
    return false;
  }

  if (!SSL_set_fd(m_data->m_handle, getFd())) {
    handleError(0, true);
  }
  if (session) {
    SSL_copy_session_id(m_data->m_handle, session->m_data->m_handle);
  }
  return true;
}
Exemple #18
0
int openconnect_open_https(struct openconnect_info *vpninfo)
{
	method_const SSL_METHOD *ssl3_method;
	SSL *https_ssl;
	BIO *https_bio;
	int ssl_sock;
	int err;

	if (vpninfo->https_ssl)
		return 0;

	if (vpninfo->peer_cert) {
		X509_free(vpninfo->peer_cert);
		vpninfo->peer_cert = NULL;
	}

	ssl_sock = connect_https_socket(vpninfo);
	if (ssl_sock < 0)
		return ssl_sock;

	ssl3_method = TLSv1_client_method();
	if (!vpninfo->https_ctx) {
		vpninfo->https_ctx = SSL_CTX_new(ssl3_method);

		/* Some servers (or their firewalls) really don't like seeing
		   extensions. */
#ifdef SSL_OP_NO_TICKET
		SSL_CTX_set_options(vpninfo->https_ctx, SSL_OP_NO_TICKET);
#endif

		if (vpninfo->cert) {
			err = load_certificate(vpninfo);
			if (err) {
				vpn_progress(vpninfo, PRG_ERR,
					     _("Loading certificate failed. Aborting.\n"));
				SSL_CTX_free(vpninfo->https_ctx);
				vpninfo->https_ctx = NULL;
				close(ssl_sock);
				return err;
			}
			check_certificate_expiry(vpninfo);
		}

		/* We just want to do:
		   SSL_CTX_set_purpose(vpninfo->https_ctx, X509_PURPOSE_ANY);
		   ... but it doesn't work with OpenSSL < 0.9.8k because of
		   problems with inheritance (fixed in v1.1.4.6 of
		   crypto/x509/x509_vpm.c) so we have to play silly buggers
		   instead. This trick doesn't work _either_ in < 0.9.7 but
		   I don't know of _any_ workaround which will, and can't
		   be bothered to find out either. */
#if OPENSSL_VERSION_NUMBER >= 0x00908000
		SSL_CTX_set_cert_verify_callback(vpninfo->https_ctx,
						 ssl_app_verify_callback, NULL);
#endif
		SSL_CTX_set_default_verify_paths(vpninfo->https_ctx);

#ifdef ANDROID_KEYSTORE
		if (vpninfo->cafile && !strncmp(vpninfo->cafile, "keystore:", 9)) {
			STACK_OF(X509_INFO) *stack;
			X509_STORE *store;
			X509_INFO *info;
			BIO *b = BIO_from_keystore(vpninfo, vpninfo->cafile);

			if (!b) {
				SSL_CTX_free(vpninfo->https_ctx);
				vpninfo->https_ctx = NULL;
				close(ssl_sock);
				return -EINVAL;
			}

			stack = PEM_X509_INFO_read_bio(b, NULL, NULL, NULL);
			BIO_free(b);

			if (!stack) {
				vpn_progress(vpninfo, PRG_ERR,
					     _("Failed to read certs from CA file '%s'\n"),
					     vpninfo->cafile);
				openconnect_report_ssl_errors(vpninfo);
				SSL_CTX_free(vpninfo->https_ctx);
				vpninfo->https_ctx = NULL;
				close(ssl_sock);
				return -ENOENT;
			}

			store = SSL_CTX_get_cert_store(vpninfo->https_ctx);

			while ((info = sk_X509_INFO_pop(stack))) {
				if (info->x509)
					X509_STORE_add_cert(store, info->x509);
				if (info->crl)
					X509_STORE_add_crl(store, info->crl);
				X509_INFO_free(info);
			}
			sk_X509_INFO_free(stack);
		} else
#endif
		if (vpninfo->cafile) {
			if (!SSL_CTX_load_verify_locations(vpninfo->https_ctx, vpninfo->cafile, NULL)) {
				vpn_progress(vpninfo, PRG_ERR,
					     _("Failed to open CA file '%s'\n"),
					     vpninfo->cafile);
				openconnect_report_ssl_errors(vpninfo);
				SSL_CTX_free(vpninfo->https_ctx);
				vpninfo->https_ctx = NULL;
				close(ssl_sock);
				return -EINVAL;
			}
		}

	}
	https_ssl = SSL_new(vpninfo->https_ctx);
	workaround_openssl_certchain_bug(vpninfo, https_ssl);

	https_bio = BIO_new_socket(ssl_sock, BIO_NOCLOSE);
	BIO_set_nbio(https_bio, 1);
	SSL_set_bio(https_ssl, https_bio, https_bio);

	vpn_progress(vpninfo, PRG_INFO, _("SSL negotiation with %s\n"),
		     vpninfo->hostname);

	while ((err = SSL_connect(https_ssl)) <= 0) {
		fd_set wr_set, rd_set;
		int maxfd = ssl_sock;

		FD_ZERO(&wr_set);
		FD_ZERO(&rd_set);

		err = SSL_get_error(https_ssl, err);
		if (err == SSL_ERROR_WANT_READ)
			FD_SET(ssl_sock, &rd_set);
		else if (err == SSL_ERROR_WANT_WRITE)
			FD_SET(ssl_sock, &wr_set);
		else {
			vpn_progress(vpninfo, PRG_ERR, _("SSL connection failure\n"));
			openconnect_report_ssl_errors(vpninfo);
			SSL_free(https_ssl);
			close(ssl_sock);
			return -EINVAL;
		}

		cmd_fd_set(vpninfo, &rd_set, &maxfd);
		select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
		if (is_cancel_pending(vpninfo, &rd_set)) {
			vpn_progress(vpninfo, PRG_ERR, _("SSL connection cancelled\n"));
			SSL_free(https_ssl);
			close(ssl_sock);
			return -EINVAL;
		}
	}

	if (verify_peer(vpninfo, https_ssl)) {
		SSL_free(https_ssl);
		close(ssl_sock);
		return -EINVAL;
	}

	vpninfo->ssl_fd = ssl_sock;
	vpninfo->https_ssl = https_ssl;

	/* Stash this now, because it might not be available later if the
	   server has disconnected. */
	vpninfo->peer_cert = SSL_get_peer_certificate(vpninfo->https_ssl);

	vpn_progress(vpninfo, PRG_INFO, _("Connected to HTTPS on %s\n"),
		     vpninfo->hostname);

	return 0;
}
Exemple #19
0
/* Create a socket and connect it to 'ip' on port 'port'.
 * Returns -1 on failure (ip is NULL, socket creation/connection error)
 * Returns sock number on success.
 */
int _mosquitto_socket_connect(struct mosquitto *mosq, const char *host, uint16_t port, const char *bind_address, bool blocking)
{
	mosq_sock_t sock = INVALID_SOCKET;
	int rc;
#ifdef WITH_TLS
	int ret;
	BIO *bio;
#endif

	if(!mosq || !host || !port) return MOSQ_ERR_INVAL;

	rc = _mosquitto_try_connect(mosq, host, port, &sock, bind_address, blocking);
	if(rc > 0) return rc;

#ifdef WITH_TLS
	if(mosq->tls_cafile || mosq->tls_capath || mosq->tls_psk){
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
		if(!mosq->tls_version || !strcmp(mosq->tls_version, "tlsv1.2")){
			mosq->ssl_ctx = SSL_CTX_new(TLSv1_2_client_method());
		}else if(!strcmp(mosq->tls_version, "tlsv1.1")){
			mosq->ssl_ctx = SSL_CTX_new(TLSv1_1_client_method());
		}else if(!strcmp(mosq->tls_version, "tlsv1")){
			mosq->ssl_ctx = SSL_CTX_new(TLSv1_client_method());
		}else{
			_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Protocol %s not supported.", mosq->tls_version);
			COMPAT_CLOSE(sock);
			return MOSQ_ERR_INVAL;
		}
#else
		if(!mosq->tls_version || !strcmp(mosq->tls_version, "tlsv1")){
			mosq->ssl_ctx = SSL_CTX_new(TLSv1_client_method());
		}else{
			_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Protocol %s not supported.", mosq->tls_version);
			COMPAT_CLOSE(sock);
			return MOSQ_ERR_INVAL;
		}
#endif
		if(!mosq->ssl_ctx){
			_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to create TLS context.");
			COMPAT_CLOSE(sock);
			return MOSQ_ERR_TLS;
		}

#if OPENSSL_VERSION_NUMBER >= 0x10000000
		/* Disable compression */
		SSL_CTX_set_options(mosq->ssl_ctx, SSL_OP_NO_COMPRESSION);
#endif
#ifdef SSL_MODE_RELEASE_BUFFERS
			/* Use even less memory per SSL connection. */
			SSL_CTX_set_mode(mosq->ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
#endif

		if(mosq->tls_ciphers){
			ret = SSL_CTX_set_cipher_list(mosq->ssl_ctx, mosq->tls_ciphers);
			if(ret == 0){
				_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to set TLS ciphers. Check cipher list \"%s\".", mosq->tls_ciphers);
				COMPAT_CLOSE(sock);
				return MOSQ_ERR_TLS;
			}
		}
		if(mosq->tls_cafile || mosq->tls_capath){
			ret = SSL_CTX_load_verify_locations(mosq->ssl_ctx, mosq->tls_cafile, mosq->tls_capath);
			if(ret == 0){
#ifdef WITH_BROKER
				if(mosq->tls_cafile && mosq->tls_capath){
					_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check bridge_cafile \"%s\" and bridge_capath \"%s\".", mosq->tls_cafile, mosq->tls_capath);
				}else if(mosq->tls_cafile){
					_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check bridge_cafile \"%s\".", mosq->tls_cafile);
				}else{
					_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check bridge_capath \"%s\".", mosq->tls_capath);
				}
#else
				if(mosq->tls_cafile && mosq->tls_capath){
					_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check cafile \"%s\" and capath \"%s\".", mosq->tls_cafile, mosq->tls_capath);
				}else if(mosq->tls_cafile){
					_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check cafile \"%s\".", mosq->tls_cafile);
				}else{
					_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load CA certificates, check capath \"%s\".", mosq->tls_capath);
				}
#endif
				COMPAT_CLOSE(sock);
				return MOSQ_ERR_TLS;
			}
			if(mosq->tls_cert_reqs == 0){
				SSL_CTX_set_verify(mosq->ssl_ctx, SSL_VERIFY_NONE, NULL);
			}else{
				SSL_CTX_set_verify(mosq->ssl_ctx, SSL_VERIFY_PEER, _mosquitto_server_certificate_verify);
			}

			if(mosq->tls_pw_callback){
				SSL_CTX_set_default_passwd_cb(mosq->ssl_ctx, mosq->tls_pw_callback);
				SSL_CTX_set_default_passwd_cb_userdata(mosq->ssl_ctx, mosq);
			}

			if(mosq->tls_certfile){
				ret = SSL_CTX_use_certificate_chain_file(mosq->ssl_ctx, mosq->tls_certfile);
				if(ret != 1){
#ifdef WITH_BROKER
					_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load client certificate, check bridge_certfile \"%s\".", mosq->tls_certfile);
#else
					_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load client certificate \"%s\".", mosq->tls_certfile);
#endif
					COMPAT_CLOSE(sock);
					return MOSQ_ERR_TLS;
				}
			}
			if(mosq->tls_keyfile){
				ret = SSL_CTX_use_PrivateKey_file(mosq->ssl_ctx, mosq->tls_keyfile, SSL_FILETYPE_PEM);
				if(ret != 1){
#ifdef WITH_BROKER
					_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load client key file, check bridge_keyfile \"%s\".", mosq->tls_keyfile);
#else
					_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to load client key file \"%s\".", mosq->tls_keyfile);
#endif
					COMPAT_CLOSE(sock);
					return MOSQ_ERR_TLS;
				}
				ret = SSL_CTX_check_private_key(mosq->ssl_ctx);
				if(ret != 1){
					_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Client certificate/key are inconsistent.");
					COMPAT_CLOSE(sock);
					return MOSQ_ERR_TLS;
				}
			}
#ifdef REAL_WITH_TLS_PSK
		}else if(mosq->tls_psk){
			SSL_CTX_set_psk_client_callback(mosq->ssl_ctx, psk_client_callback);
#endif
		}

		mosq->ssl = SSL_new(mosq->ssl_ctx);
		if(!mosq->ssl){
			COMPAT_CLOSE(sock);
			return MOSQ_ERR_TLS;
		}
		SSL_set_ex_data(mosq->ssl, tls_ex_index_mosq, mosq);
		bio = BIO_new_socket(sock, BIO_NOCLOSE);
		if(!bio){
			COMPAT_CLOSE(sock);
			return MOSQ_ERR_TLS;
		}
		SSL_set_bio(mosq->ssl, bio, bio);

		mosq->sock = sock;
		if(mosquitto__socket_connect_tls(mosq)){
			return MOSQ_ERR_TLS;
		}

	}
#endif

	mosq->sock = sock;

	return rc;
}
Exemple #20
0
boolean tls_connect(rdpTls* tls)
{
	CryptoCert cert;
	int connection_status;

	tls->ctx = SSL_CTX_new(TLSv1_client_method());

	if (tls->ctx == NULL)
	{
		printf("SSL_CTX_new failed\n");
		return false;
	}

	/*
	 * This is necessary, because the Microsoft TLS implementation is not perfect.
	 * SSL_OP_ALL enables a couple of workarounds for buggy TLS implementations,
	 * but the most important workaround being SSL_OP_TLS_BLOCK_PADDING_BUG.
	 * As the size of the encrypted payload may give hints about its contents,
	 * block padding is normally used, but the Microsoft TLS implementation
	 * won't recognize it and will disconnect you after sending a TLS alert.
	 */
	SSL_CTX_set_options(tls->ctx, SSL_OP_ALL);

	tls->ssl = SSL_new(tls->ctx);

	if (tls->ssl == NULL)
	{
		SSL_CTX_free(tls->ctx);
		printf("SSL_new failed\n");
		return false;
	}

	if (SSL_set_fd(tls->ssl, tls->sockfd) < 1)
	{
		SSL_free(tls->ssl);
		SSL_CTX_free(tls->ctx);
		printf("SSL_set_fd failed\n");
		return false;
	}

	connection_status = SSL_connect(tls->ssl);

	if (connection_status <= 0)
	{
		if (tls_print_error("SSL_connect", tls->ssl, connection_status))
		{
			SSL_free(tls->ssl);
			SSL_CTX_free(tls->ctx);
			return false;
		}
	}

	cert = tls_get_certificate(tls);

	if (cert == NULL)
	{
		printf("tls_connect: tls_get_certificate failed to return the server certificate.\n");
		return false;
	}

	if (!crypto_cert_get_public_key(cert, &tls->public_key))
	{
		printf("tls_connect: crypto_cert_get_public_key failed to return the server public key.\n");
		return false;
	}

	if (!tls_verify_certificate(tls, cert, tls->settings->hostname))
		tls_disconnect(tls);

	tls_free_certificate(cert);

	return true;
}
Exemple #21
0
boolean tls_connect(rdpTls* tls)
{
	CryptoCert cert;
	long options = 0;
	int connection_status;

	tls->ctx = SSL_CTX_new(TLSv1_client_method());

	if (tls->ctx == NULL)
	{
		printf("SSL_CTX_new failed\n");
		return false;
	}

	/**
	 * SSL_OP_NO_COMPRESSION:
	 *
	 * The Microsoft RDP server does not advertise support
	 * for TLS compression, but alternative servers may support it.
	 * This was observed between early versions of the FreeRDP server
	 * and the FreeRDP client, and caused major performance issues,
	 * which is why we're disabling it.
	 */
#ifdef SSL_OP_NO_COMPRESSION
	options |= SSL_OP_NO_COMPRESSION;
#endif
	 
	/**
	 * SSL_OP_TLS_BLOCK_PADDING_BUG:
	 *
	 * The Microsoft RDP server does *not* support TLS padding.
	 * It absolutely needs to be disabled otherwise it won't work.
	 */
	options |= SSL_OP_TLS_BLOCK_PADDING_BUG;

	/**
	 * SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS:
	 *
	 * Just like TLS padding, the Microsoft RDP server does not
	 * support empty fragments. This needs to be disabled.
	 */
	options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;

	SSL_CTX_set_options(tls->ctx, options);

	tls->ssl = SSL_new(tls->ctx);

	if (tls->ssl == NULL)
	{
		printf("SSL_new failed\n");
		return false;
	}

	if (SSL_set_fd(tls->ssl, tls->sockfd) < 1)
	{
		printf("SSL_set_fd failed\n");
		return false;
	}

	connection_status = SSL_connect(tls->ssl);

	if (connection_status <= 0)
	{
		if (tls_print_error("SSL_connect", tls->ssl, connection_status))
		{
			return false;
		}
	}

	cert = tls_get_certificate(tls, true);

	if (cert == NULL)
	{
		printf("tls_connect: tls_get_certificate failed to return the server certificate.\n");
		return false;
	}

	if (!crypto_cert_get_public_key(cert, &tls->public_key))
	{
		printf("tls_connect: crypto_cert_get_public_key failed to return the server public key.\n");
		tls_free_certificate(cert) ;
		return false;
	}

	if (!tls_verify_certificate(tls, cert, tls->settings->hostname))
	{
		printf("tls_connect: certificate not trusted, aborting.\n");
		tls_disconnect(tls);
		tls_free_certificate(cert);
		return false;
	}

	tls_free_certificate(cert);

	return true;
}
Exemple #22
0
BOOL tls_connect(rdpTls* tls)
{
	CryptoCert cert;
	long options = 0;
	int connection_status;
	char *hostname;

	tls->ctx = SSL_CTX_new(TLSv1_client_method());

	if (tls->ctx == NULL)
	{
		fprintf(stderr, "SSL_CTX_new failed\n");
		return FALSE;
	}

	//SSL_CTX_set_mode(tls->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE);

	/**
	 * SSL_OP_NO_COMPRESSION:
	 *
	 * The Microsoft RDP server does not advertise support
	 * for TLS compression, but alternative servers may support it.
	 * This was observed between early versions of the FreeRDP server
	 * and the FreeRDP client, and caused major performance issues,
	 * which is why we're disabling it.
	 */
#ifdef SSL_OP_NO_COMPRESSION
	options |= SSL_OP_NO_COMPRESSION;
#endif
	 
	/**
	 * SSL_OP_TLS_BLOCK_PADDING_BUG:
	 *
	 * The Microsoft RDP server does *not* support TLS padding.
	 * It absolutely needs to be disabled otherwise it won't work.
	 */
	options |= SSL_OP_TLS_BLOCK_PADDING_BUG;

	/**
	 * SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS:
	 *
	 * Just like TLS padding, the Microsoft RDP server does not
	 * support empty fragments. This needs to be disabled.
	 */
	options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;

	SSL_CTX_set_options(tls->ctx, options);

	tls->ssl = SSL_new(tls->ctx);

	if (tls->ssl == NULL)
	{
		fprintf(stderr, "SSL_new failed\n");
		return FALSE;
	}

	if (SSL_set_fd(tls->ssl, tls->sockfd) < 1)
	{
		fprintf(stderr, "SSL_set_fd failed\n");
		return FALSE;
	}

	connection_status = SSL_connect(tls->ssl);

	if (connection_status <= 0)
	{
		if (tls_print_error("SSL_connect", tls->ssl, connection_status))
		{
			return FALSE;
		}
	}

	cert = tls_get_certificate(tls, TRUE);

	if (cert == NULL)
	{
		fprintf(stderr, "tls_connect: tls_get_certificate failed to return the server certificate.\n");
		return FALSE;
	}

	tls->Bindings = tls_get_channel_bindings(cert->px509);

	if (!crypto_cert_get_public_key(cert, &tls->PublicKey, &tls->PublicKeyLength))
	{
		fprintf(stderr, "tls_connect: crypto_cert_get_public_key failed to return the server public key.\n");
		tls_free_certificate(cert);
		return FALSE;
	}

	if (tls->settings->GatewayUsageMethod)
		hostname = tls->settings->GatewayHostname;
	else
		hostname = tls->settings->ServerHostname;

	if (!tls_verify_certificate(tls, cert, hostname))
	{
		fprintf(stderr, "tls_connect: certificate not trusted, aborting.\n");
		tls_disconnect(tls);
		tls_free_certificate(cert);
		return FALSE;
	}

	tls_free_certificate(cert);

	return TRUE;
}
Exemple #23
0
static struct mailstream_ssl_data * tls_data_new(int fd, time_t timeout,
  void (* callback)(struct mailstream_ssl_context * ssl_context, void * cb_data), void * cb_data)
{
  return ssl_data_new_full(fd, timeout, TLSv1_client_method(), callback, cb_data);
}
Exemple #24
0
/**
 * Run SSL handshake and store the resulting time value in the
 * 'time_map'.
 *
 * @param time_map where to store the current time
 */
static void
run_ssl (uint32_t *time_map)
{
  BIO *s_bio;
  BIO *c_bio;
  SSL_CTX *ctx;
  SSL *ssl;

  SSL_load_error_strings();
  SSL_library_init();

  ctx = NULL;
  if (0 == strcmp("sslv23", protocol))
  {
    verb ("V: using SSLv23_client_method()\n");
    ctx = SSL_CTX_new(SSLv23_client_method());
  } else if (0 == strcmp("sslv3", protocol))
  {
    verb ("V: using SSLv3_client_method()\n");
    ctx = SSL_CTX_new(SSLv3_client_method());
  } else if (0 == strcmp("tlsv1", protocol))
  {
    verb ("V: using TLSv1_client_method()\n");
    ctx = SSL_CTX_new(TLSv1_client_method());
  } else
    die("Unsupported protocol `%s'\n", protocol);

  if (ctx == NULL)
    die("OpenSSL failed to support protocol `%s'\n", protocol);

  if (ca_racket)
  {
    // For google specifically:
    // SSL_CTX_load_verify_locations(ctx, "/etc/ssl/certs/Equifax_Secure_CA.pem", NULL);
    if (1 != SSL_CTX_load_verify_locations(ctx, NULL, "/etc/ssl/certs/"))
      fprintf(stderr, "SSL_CTX_load_verify_locations failed\n");
  }

  if (NULL == (s_bio = BIO_new_ssl_connect(ctx)))
    die ("SSL BIO setup failed\n");
  BIO_get_ssl(s_bio, &ssl);
  if (NULL == ssl)
    die ("SSL setup failed\n");
  SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
  if ( (1 != BIO_set_conn_hostname(s_bio, host)) ||
       (1 != BIO_set_conn_port(s_bio, port)) )
    die ("Failed to initialize connection to `%s:%s'\n", host, port);

  if (NULL == (c_bio = BIO_new_fp(stdout, BIO_NOCLOSE)))
    die ("FIXME: error message");

  // This should run in seccomp
  // eg:     prctl(PR_SET_SECCOMP, 1);
  if (1 != BIO_do_connect(s_bio)) // XXX TODO: BIO_should_retry() later?
    die ("SSL connection failed\n");    
  if (1 != BIO_do_handshake(s_bio))
    die ("SSL handshake failed\n");
  // Verify the peer certificate against the CA certs on the local system
  if (ca_racket) {
    X509 *x509;
    long ssl_verify_result;

    if (NULL == (x509 = SSL_get_peer_certificate(ssl)) )
      die ("Getting SSL certificate failed\n");

    // In theory, we verify that the cert is valid
    ssl_verify_result = SSL_get_verify_result(ssl);
    switch (ssl_verify_result)
    {
    case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
    case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
      die ("SSL certificate is self signed\n");
    case X509_V_OK:
      verb ("V: SSL certificate verification passed\n");
      break;
    default:
      die ("SSL certification verification error: %ld\n", 
	   ssl_verify_result);
    }
  } else {
    verb ("V: Certificate verification skipped!\n");
  }

  // from /usr/include/openssl/ssl3.h
  //  ssl->s3->server_random is an unsigned char of 32 bytes
  memcpy(time_map, ssl->s3->server_random, sizeof (uint32_t));  
}
Exemple #25
0
int main(int argc, char **argv)
{
	int port = 0;
	int messagenumber = 5;
	char local_addr[256];
	int c;
	int mclient = 1;
	char peer_address[129] = "\0";
	int peer_port = PEER_DEFAULT_PORT;

	char rest_api_separator = ':';
	int use_null_cipher=0;

	set_logfile("stdout");

	set_execdir();

	set_system_parameters(0);

	ns_bzero(local_addr, sizeof(local_addr));

	while ((c = getopt(argc, argv, "d:p:l:n:L:m:e:r:u:w:i:k:z:W:C:E:F:vsyhcxXgtTSAPDNOUHMRIGB")) != -1) {
		switch (c){
		case 'B':
			random_disconnect = 1;
			break;
		case 'G':
			extra_requests = 1;
			break;
		case 'F':
			STRCPY(cipher_suite,optarg);
			break;
		case 'I':
			no_permissions = 1;
			break;
		case 'M':
			mobility = 1;
			break;
		case 'H':
			shatype = SHATYPE_SHA256;
			break;
		case 'E':
		{
			char* fn = find_config_file(optarg,1);
			if(!fn) {
				fprintf(stderr,"ERROR: file %s not found\n",optarg);
				exit(-1);
			}
			STRCPY(ca_cert_file,fn);
		}
			break;
		case 'O':
			dos = 1;
			break;
		case 'C':
			rest_api_separator=*optarg;
			break;
		case 'D':
			mandatory_channel_padding = 1;
			break;
		case 'N':
			negative_test = 1;
			break;
		case 'R':
			negative_protocol_test = 1;
			break;
		case 'z':
			RTP_PACKET_INTERVAL = atoi(optarg);
			break;
		case 'A':
			use_short_term = 1;
			break;
		case 'u':
			STRCPY(g_uname, optarg);
			break;
		case 'w':
			STRCPY(g_upwd, optarg);
			break;
		case 'g':
			dont_fragment = 1;
			break;
		case 'd':
			STRCPY(client_ifname, optarg);
			break;
		case 'x':
			default_address_family = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6;
			break;
		case 'X':
			default_address_family = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4;
			break;
		case 'l':
			clmessage_length = atoi(optarg);
			break;
		case 's':
			do_not_use_channel = 1;
			break;
		case 'n':
			messagenumber = atoi(optarg);
			break;
		case 'p':
			port = atoi(optarg);
			break;
		case 'L':
			STRCPY(local_addr, optarg);
			break;
		case 'e':
			STRCPY(peer_address, optarg);
			break;
		case 'r':
			peer_port = atoi(optarg);
			break;
		case 'v':
			clnet_verbose = TURN_VERBOSE_NORMAL;
			break;
		case 'h':
			hang_on = 1;
			break;
		case 'c':
			no_rtcp = 1;
			break;
		case 'm':
			mclient = atoi(optarg);
			break;
		case 'y':
			c2c = 1;
			break;
		case 't':
			use_tcp = 1;
			break;
		case 'P':
			passive_tcp = 1;
			/* implies 'T': */
			/* no break */
		case 'T':
			relay_transport = STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE;
			break;
		case 'U':
		  use_null_cipher = 1;
		  /* implies 'S' */
		  /* no break */
		case 'S':
			use_secure = 1;
			break;
		case 'W':
			g_use_auth_secret_with_timestamp = 1;
			STRCPY(g_auth_secret,optarg);
			break;
		case 'i':
		{
			char* fn = find_config_file(optarg,1);
			if(!fn) {
				fprintf(stderr,"ERROR: file %s not found\n",optarg);
				exit(-1);
			}
			STRCPY(cert_file,fn);
			free(fn);
		}
			break;
		case 'k':
		{
			char* fn = find_config_file(optarg,1);
			if(!fn) {
				fprintf(stderr,"ERROR: file %s not found\n",optarg);
				exit(-1);
			}
			STRCPY(pkey_file,fn);
			free(fn);
		}
			break;
		default:
			fprintf(stderr, "%s\n", Usage);
			exit(1);
		}
	}

	if(g_use_auth_secret_with_timestamp) {

		if(use_short_term) {
			fprintf(stderr,"ERROR: You cannot use authentication secret (REST API) with short-term credentials mechanism.\n");
			exit(-1);
		}
		{
			char new_uname[1025];
			const unsigned long exp_time = 3600 * 24; /* one day */
			if(g_uname[0]) {
			  snprintf(new_uname,sizeof(new_uname),"%lu%c%s",(unsigned long)time(NULL) + exp_time,rest_api_separator, (char*)g_uname);
			} else {
			  snprintf(new_uname,sizeof(new_uname),"%lu", (unsigned long)time(NULL) + exp_time);
			}
			STRCPY(g_uname,new_uname);
		}
		{
			u08bits hmac[MAXSHASIZE];
			unsigned int hmac_len;

			switch(shatype) {
			case SHATYPE_SHA256:
				hmac_len = SHA256SIZEBYTES;
				break;
			default:
				hmac_len = SHA1SIZEBYTES;
			};

			hmac[0]=0;

			if(stun_calculate_hmac(g_uname, strlen((char*)g_uname), (u08bits*)g_auth_secret, strlen(g_auth_secret), hmac, &hmac_len, shatype)>=0) {
				size_t pwd_length = 0;
				char *pwd = base64_encode(hmac,hmac_len,&pwd_length);

				if(pwd) {
					if(pwd_length>0) {
						ns_bcopy(pwd,g_upwd,pwd_length);
						g_upwd[pwd_length]=0;
					}
				}
				free(pwd);
			}
		}
	}

	if(is_TCP_relay()) {
		dont_fragment = 0;
		no_rtcp = 1;
		c2c = 1;
		use_tcp = 1;
		do_not_use_channel = 1;
	}

	if(port == 0) {
		if(use_secure)
			port = DEFAULT_STUN_TLS_PORT;
		else
			port = DEFAULT_STUN_PORT;
	}

	if (clmessage_length < (int) sizeof(message_info))
		clmessage_length = (int) sizeof(message_info);

	const int max_header = 100;
	if(clmessage_length > (int)(STUN_BUFFER_SIZE-max_header)) {
		fprintf(stderr,"Message length was corrected to %d\n",(STUN_BUFFER_SIZE-max_header));
		clmessage_length = (int)(STUN_BUFFER_SIZE-max_header);
	}

	if (optind >= argc) {
		fprintf(stderr, "%s\n", Usage);
		exit(-1);
	}

	if (!c2c) {
		if (make_ioa_addr((const u08bits*) peer_address, peer_port, &peer_addr) < 0)
			return -1;
		if(peer_addr.ss.sa_family == AF_INET6)
			default_address_family = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6;

	}

	/* SSL Init ==>> */

	if(use_secure) {

		SSL_load_error_strings();
		OpenSSL_add_ssl_algorithms();

		const char *csuite = "ALL"; //"AES256-SHA" "DH"
		if(use_null_cipher)
			csuite = "eNULL";
		else if(cipher_suite[0])
			csuite=cipher_suite;

		if(use_tcp) {
		  root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(SSLv23_client_method());
		  SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite);
		  root_tls_ctx_num++;
		  root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(SSLv3_client_method());
		  SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite);
		  root_tls_ctx_num++;
		  root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(TLSv1_client_method());
		  SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite);
		  root_tls_ctx_num++;
#if defined(SSL_TXT_TLSV1_1)
		  root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(TLSv1_1_client_method());
		  SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite);
		  root_tls_ctx_num++;
#if defined(SSL_TXT_TLSV1_2)
		  root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(TLSv1_2_client_method());
		  SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite);
		  root_tls_ctx_num++;
#endif
#endif
		} else {
#if defined(TURN_NO_DTLS)
		  fprintf(stderr,"ERROR: DTLS is not supported.\n");
		  exit(-1);
#else
		  if(OPENSSL_VERSION_NUMBER < 0x10000000L) {
		  	TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "WARNING: OpenSSL version is rather old, DTLS may not be working correctly.\n");
		  }
		  root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(DTLSv1_client_method());
		  SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite);
		  root_tls_ctx_num++;
#endif
		}

		int sslind = 0;
		for(sslind = 0; sslind<root_tls_ctx_num; sslind++) {

			if(cert_file[0]) {
				if (!SSL_CTX_use_certificate_chain_file(root_tls_ctx[sslind], cert_file)) {
					TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "\nERROR: no certificate found!\n");
					exit(-1);
				}
			}

			if (!SSL_CTX_use_PrivateKey_file(root_tls_ctx[sslind], pkey_file,
						SSL_FILETYPE_PEM)) {
				TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "\nERROR: no private key found!\n");
				exit(-1);
			}

			if(cert_file[0]) {
				if (!SSL_CTX_check_private_key(root_tls_ctx[sslind])) {
					TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "\nERROR: invalid private key!\n");
					exit(-1);
				}
			}

			if (ca_cert_file[0]) {
				if (!SSL_CTX_load_verify_locations(root_tls_ctx[sslind], ca_cert_file, NULL )) {
					TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,
							"ERROR: cannot load CA from file: %s\n",
							ca_cert_file);
				}

				/* Set to require peer (client) certificate verification */
				SSL_CTX_set_verify(root_tls_ctx[sslind], SSL_VERIFY_PEER, NULL );

				/* Set the verification depth to 9 */
				SSL_CTX_set_verify_depth(root_tls_ctx[sslind], 9);
			} else {
				SSL_CTX_set_verify(root_tls_ctx[sslind], SSL_VERIFY_NONE, NULL );
			}

			if(!use_tcp)
				SSL_CTX_set_read_ahead(root_tls_ctx[sslind], 1);
		}
	}

	start_mclient(argv[optind], port, client_ifname, local_addr, messagenumber, mclient);

	return 0;
}
Exemple #26
0
HTTPScode
https_init(const char *useragent, const char *cafile, const char *proxy)
{
        X509_STORE *store;
        X509 *cert;
        BIO *bio;
        char *p;
        
        if ((ctx = calloc(1, sizeof(*ctx))) == NULL ||
            (ctx->useragent = strdup(useragent)) == NULL) {
                ctx->errstr = strerror(errno);
                return (HTTPS_ERR_SYSTEM);
        }
        /* Initialize SSL context */
        SSL_library_init();
        SSL_load_error_strings();
        OpenSSL_add_ssl_algorithms();

        /* XXX - ape openssl s_client -rand for testing on ancient systems */
        if (!RAND_status()) {
                if ((p = getenv("RANDFILE")) != NULL) {
                        RAND_load_file(p, 8192);
                } else {
                        ctx->errstr = "No /dev/random, EGD, or $RANDFILE";
                        return (HTTPS_ERR_LIB);
                }
        }
        if ((ctx->ssl_ctx = SSL_CTX_new(TLSv1_client_method())) == NULL) {
                ctx->errstr = _SSL_strerror();
                return (HTTPS_ERR_LIB);
        }
        /* Set up our CA cert */
        if (cafile == NULL) {
                /* Load default CA cert from memory */
                if ((bio = BIO_new_mem_buf((void *)CACERT_PEM, -1)) == NULL ||
                    (store = SSL_CTX_get_cert_store(ctx->ssl_ctx)) == NULL) {
                        ctx->errstr = _SSL_strerror();
                        return (HTTPS_ERR_LIB);
                }
                while ((cert = PEM_read_bio_X509(bio, NULL, 0, NULL)) != NULL) {
                        X509_STORE_add_cert(store, cert);
                        X509_free(cert);
                }
                BIO_free_all(bio);
                SSL_CTX_set_verify(ctx->ssl_ctx, SSL_VERIFY_PEER, NULL);
        } else if (cafile[0] == '\0') {                
                /* Skip verification */
                SSL_CTX_set_verify(ctx->ssl_ctx, SSL_VERIFY_NONE, NULL);
        } else {
                /* Load CA cert from file */
                if (!SSL_CTX_load_verify_locations(ctx->ssl_ctx,
                        cafile, NULL)) {
                        SSL_CTX_free(ctx->ssl_ctx);
                        ctx->errstr = _SSL_strerror();
                        return (HTTPS_ERR_CLIENT);
                }
                SSL_CTX_set_verify(ctx->ssl_ctx, SSL_VERIFY_PEER, NULL);
        }
        /* Save our proxy config if any */
        if ((p = getenv("http_proxy")) != NULL ||
            (p = (char *)proxy) != NULL) {
                if (strstr(p, "://") != NULL) {
                        if (strncmp(p, "http://", 7) != 0) {
                                ctx->errstr = "http_proxy must be HTTP";
                                return (HTTPS_ERR_CLIENT);
                        }
                        p += 7;
                }
                p = strdup(p);
                
                if ((ctx->proxy = strchr(p, '@')) != NULL) {
                        *ctx->proxy++ = '\0';
                        ctx->proxy_auth = p;
                } else {
                        ctx->proxy = p;
                }
                strtok(ctx->proxy, "/");
                
                if ((ctx->proxy_port = strchr(ctx->proxy, ':')) != NULL) {
                        *ctx->proxy_port++ = '\0';
                } else {
                        ctx->proxy_port = "80";
                }
        }
        /* Set HTTP parser callbacks */
        ctx->parse_settings.on_body = __on_body;
        ctx->parse_settings.on_message_complete = __on_message_complete;

        signal(SIGPIPE, SIG_IGN);
        
        return (0);
}
Exemple #27
0
/*
 * This function loads all the client/CA certificates and CRLs. Setup the TLS
 * layer and do all necessary magic.
 */
static CURLcode
cyassl_connect_step1(struct connectdata *conn,
                     int sockindex)
{
  struct SessionHandle *data = conn->data;
  struct ssl_connect_data* conssl = &conn->ssl[sockindex];
  SSL_METHOD* req_method = NULL;
  void* ssl_sessionid = NULL;
  curl_socket_t sockfd = conn->sock[sockindex];

  if(conssl->state == ssl_connection_complete)
    return CURLE_OK;

  /* CyaSSL doesn't support SSLv2 */
  if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
    failf(data, "CyaSSL does not support SSLv2");
    return CURLE_SSL_CONNECT_ERROR;
  }

  /* check to see if we've been told to use an explicit SSL/TLS version */
  switch(data->set.ssl.version) {
  default:
  case CURL_SSLVERSION_DEFAULT:
  case CURL_SSLVERSION_TLSv1:
    infof(data, "CyaSSL cannot be configured to use TLS 1.0-1.2, "
          "TLS 1.0 is used exclusively\n");
    req_method = TLSv1_client_method();
    break;
  case CURL_SSLVERSION_TLSv1_0:
    req_method = TLSv1_client_method();
    break;
  case CURL_SSLVERSION_TLSv1_1:
    req_method = TLSv1_1_client_method();
    break;
  case CURL_SSLVERSION_TLSv1_2:
    req_method = TLSv1_2_client_method();
    break;
  case CURL_SSLVERSION_SSLv3:
    req_method = SSLv3_client_method();
    break;
  }

  if(!req_method) {
    failf(data, "SSL: couldn't create a method!");
    return CURLE_OUT_OF_MEMORY;
  }

  if(conssl->ctx)
    SSL_CTX_free(conssl->ctx);
  conssl->ctx = SSL_CTX_new(req_method);

  if(!conssl->ctx) {
    failf(data, "SSL: couldn't create a context!");
    return CURLE_OUT_OF_MEMORY;
  }

#ifndef NO_FILESYSTEM
  /* load trusted cacert */
  if(data->set.str[STRING_SSL_CAFILE]) {
    if(!SSL_CTX_load_verify_locations(conssl->ctx,
                                      data->set.str[STRING_SSL_CAFILE],
                                      data->set.str[STRING_SSL_CAPATH])) {
      if(data->set.ssl.verifypeer) {
        /* Fail if we insist on successfully verifying the server. */
        failf(data,"error setting certificate verify locations:\n"
              "  CAfile: %s\n  CApath: %s",
              data->set.str[STRING_SSL_CAFILE]?
              data->set.str[STRING_SSL_CAFILE]: "none",
              data->set.str[STRING_SSL_CAPATH]?
              data->set.str[STRING_SSL_CAPATH] : "none");
        return CURLE_SSL_CACERT_BADFILE;
      }
      else {
        /* Just continue with a warning if no strict certificate
           verification is required. */
        infof(data, "error setting certificate verify locations,"
              " continuing anyway:\n");
      }
    }
    else {
      /* Everything is fine. */
      infof(data, "successfully set certificate verify locations:\n");
    }
    infof(data,
          "  CAfile: %s\n"
          "  CApath: %s\n",
          data->set.str[STRING_SSL_CAFILE] ? data->set.str[STRING_SSL_CAFILE]:
          "none",
          data->set.str[STRING_SSL_CAPATH] ? data->set.str[STRING_SSL_CAPATH]:
          "none");
  }

  /* Load the client certificate, and private key */
  if(data->set.str[STRING_CERT] && data->set.str[STRING_KEY]) {
    int file_type = do_file_type(data->set.str[STRING_CERT_TYPE]);

    if(SSL_CTX_use_certificate_file(conssl->ctx, data->set.str[STRING_CERT],
                                     file_type) != 1) {
      failf(data, "unable to use client certificate (no key or wrong pass"
            " phrase?)");
      return CURLE_SSL_CONNECT_ERROR;
    }

    file_type = do_file_type(data->set.str[STRING_KEY_TYPE]);
    if(SSL_CTX_use_PrivateKey_file(conssl->ctx, data->set.str[STRING_KEY],
                                    file_type) != 1) {
      failf(data, "unable to set private key");
      return CURLE_SSL_CONNECT_ERROR;
    }
  }
#else
  if(CyaSSL_no_filesystem_verify(conssl->ctx)!= SSL_SUCCESS) {
    return CURLE_SSL_CONNECT_ERROR;
  }
#endif /* NO_FILESYSTEM */

  /* SSL always tries to verify the peer, this only says whether it should
   * fail to connect if the verification fails, or if it should continue
   * anyway. In the latter case the result of the verification is checked with
   * SSL_get_verify_result() below. */
  SSL_CTX_set_verify(conssl->ctx,
                     data->set.ssl.verifypeer?SSL_VERIFY_PEER:SSL_VERIFY_NONE,
                     NULL);

  /* Let's make an SSL structure */
  if(conssl->handle)
    SSL_free(conssl->handle);
  conssl->handle = SSL_new(conssl->ctx);
  if(!conssl->handle) {
    failf(data, "SSL: couldn't create a context (handle)!");
    return CURLE_OUT_OF_MEMORY;
  }

  /* Check if there's a cached ID we can/should use here! */
  if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)) {
    /* we got a session id, use it! */
    if(!SSL_set_session(conssl->handle, ssl_sessionid)) {
      failf(data, "SSL: SSL_set_session failed: %s",
            ERR_error_string(SSL_get_error(conssl->handle, 0),NULL));
      return CURLE_SSL_CONNECT_ERROR;
    }
    /* Informational message */
    infof (data, "SSL re-using session ID\n");
  }

  /* pass the raw socket into the SSL layer */
  if(!SSL_set_fd(conssl->handle, (int)sockfd)) {
    failf(data, "SSL: SSL_set_fd failed");
    return CURLE_SSL_CONNECT_ERROR;
  }

  conssl->connecting_state = ssl_connect_2;
  return CURLE_OK;
}
Exemple #28
0
bool
ssl_init ()
{
  SSL_METHOD *meth;

  if (ssl_ctx)
    /* The SSL has already been initialized. */
    return true;

  /* Init the PRNG.  If that fails, bail out.  */
  init_prng ();
  if (RAND_status () != 1)
    {
      logprintf (LOG_NOTQUIET,
                 _("Could not seed PRNG; consider using --random-file.\n"));
      goto error;
    }

  SSL_library_init ();
  SSL_load_error_strings ();
  SSLeay_add_all_algorithms ();
  SSLeay_add_ssl_algorithms ();

  switch (opt.secure_protocol)
    {
    case secure_protocol_auto:
      meth = SSLv23_client_method ();
      break;
    case secure_protocol_sslv2:
      meth = SSLv2_client_method ();
      break;
    case secure_protocol_sslv3:
      meth = SSLv3_client_method ();
      break;
    case secure_protocol_tlsv1:
      meth = TLSv1_client_method ();
      break;
    default:
      abort ();
    }

  ssl_ctx = SSL_CTX_new (meth);
  if (!ssl_ctx)
    goto error;

  SSL_CTX_set_default_verify_paths (ssl_ctx);
  SSL_CTX_load_verify_locations (ssl_ctx, opt.ca_cert, opt.ca_directory);

  /* SSL_VERIFY_NONE instructs OpenSSL not to abort SSL_connect if the
     certificate is invalid.  We verify the certificate separately in
     ssl_check_certificate, which provides much better diagnostics
     than examining the error stack after a failed SSL_connect.  */
  SSL_CTX_set_verify (ssl_ctx, SSL_VERIFY_NONE, NULL);

  if (opt.cert_file)
    if (SSL_CTX_use_certificate_file (ssl_ctx, opt.cert_file,
                                      key_type_to_ssl_type (opt.cert_type))
        != 1)
      goto error;
  if (opt.private_key)
    if (SSL_CTX_use_PrivateKey_file (ssl_ctx, opt.private_key,
                                     key_type_to_ssl_type (opt.private_key_type))
        != 1)
      goto error;

  /* Since fd_write unconditionally assumes partial writes (and
     handles them correctly), allow them in OpenSSL.  */
  SSL_CTX_set_mode (ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);

  /* The OpenSSL library can handle renegotiations automatically, so
     tell it to do so.  */
  SSL_CTX_set_mode (ssl_ctx, SSL_MODE_AUTO_RETRY);

  return true;

 error:
  if (ssl_ctx)
    SSL_CTX_free (ssl_ctx);
  print_errors ();
  return false;
}
Exemple #29
0
int MAIN(int argc, char **argv)
{
    int off=0;
    SSL *con=NULL,*con2=NULL;
    X509_STORE *store = NULL;
    int s,k,width,state=0;
    char *cbuf=NULL,*sbuf=NULL,*mbuf=NULL;
    int cbuf_len,cbuf_off;
    int sbuf_len,sbuf_off;
    fd_set readfds,writefds;
    short port=PORT;
    int full_log=1;
    char *host=SSL_HOST_NAME;
    char *cert_file=NULL,*key_file=NULL;
    int cert_format = FORMAT_PEM, key_format = FORMAT_PEM;
    char *passarg = NULL, *pass = NULL;
    X509 *cert = NULL;
    EVP_PKEY *key = NULL;
    char *CApath=NULL,*CAfile=NULL,*cipher=NULL;
    int reconnect=0,badop=0,verify=SSL_VERIFY_NONE,bugs=0;
    int crlf=0;
    int write_tty,read_tty,write_ssl,read_ssl,tty_on,ssl_pending;
    SSL_CTX *ctx=NULL;
    int ret=1,in_init=1,i,nbio_test=0;
    int starttls_proto = PROTO_OFF;
    int prexit = 0, vflags = 0;
    SSL_METHOD *meth=NULL;
#ifdef sock_type
#undef sock_type
#endif
    int sock_type=SOCK_STREAM;
    BIO *sbio;
    char *inrand=NULL;
    int mbuf_len=0;
#ifndef OPENSSL_NO_ENGINE
    char *engine_id=NULL;
    ENGINE *e=NULL;
#endif
#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE)
    struct timeval tv;
#endif

    struct sockaddr peer;
    int peerlen = sizeof(peer);
    int enable_timeouts = 0 ;
    long mtu = 0;

#if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3)
    meth=SSLv23_client_method();
#elif !defined(OPENSSL_NO_SSL3)
    meth=SSLv3_client_method();
#elif !defined(OPENSSL_NO_SSL2)
    meth=SSLv2_client_method();
#endif

    apps_startup();
    c_Pause=0;
    c_quiet=0;
    c_ign_eof=0;
    c_debug=0;
    c_msg=0;
    c_showcerts=0;

    if (bio_err == NULL)
        bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);

    if (!load_config(bio_err, NULL))
        goto end;

    if (	((cbuf=OPENSSL_malloc(BUFSIZZ)) == NULL) ||
            ((sbuf=OPENSSL_malloc(BUFSIZZ)) == NULL) ||
            ((mbuf=OPENSSL_malloc(BUFSIZZ)) == NULL))
    {
        BIO_printf(bio_err,"out of memory\n");
        goto end;
    }

    verify_depth=0;
    verify_error=X509_V_OK;
#ifdef FIONBIO
    c_nbio=0;
#endif

    argc--;
    argv++;
    while (argc >= 1)
    {
        if	(strcmp(*argv,"-host") == 0)
        {
            if (--argc < 1) goto bad;
            host= *(++argv);
        }
        else if	(strcmp(*argv,"-port") == 0)
        {
            if (--argc < 1) goto bad;
            port=atoi(*(++argv));
            if (port == 0) goto bad;
        }
        else if (strcmp(*argv,"-connect") == 0)
        {
            if (--argc < 1) goto bad;
            if (!extract_host_port(*(++argv),&host,NULL,&port))
                goto bad;
        }
        else if	(strcmp(*argv,"-verify") == 0)
        {
            verify=SSL_VERIFY_PEER;
            if (--argc < 1) goto bad;
            verify_depth=atoi(*(++argv));
            BIO_printf(bio_err,"verify depth is %d\n",verify_depth);
        }
        else if	(strcmp(*argv,"-cert") == 0)
        {
            if (--argc < 1) goto bad;
            cert_file= *(++argv);
        }
        else if	(strcmp(*argv,"-certform") == 0)
        {
            if (--argc < 1) goto bad;
            cert_format = str2fmt(*(++argv));
        }
        else if	(strcmp(*argv,"-crl_check") == 0)
            vflags |= X509_V_FLAG_CRL_CHECK;
        else if	(strcmp(*argv,"-crl_check_all") == 0)
            vflags |= X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL;
        else if	(strcmp(*argv,"-prexit") == 0)
            prexit=1;
        else if	(strcmp(*argv,"-crlf") == 0)
            crlf=1;
        else if	(strcmp(*argv,"-quiet") == 0)
        {
            c_quiet=1;
            c_ign_eof=1;
        }
        else if	(strcmp(*argv,"-ign_eof") == 0)
            c_ign_eof=1;
        else if	(strcmp(*argv,"-pause") == 0)
            c_Pause=1;
        else if	(strcmp(*argv,"-debug") == 0)
            c_debug=1;
#ifdef WATT32
        else if (strcmp(*argv,"-wdebug") == 0)
            dbug_init();
#endif
        else if	(strcmp(*argv,"-msg") == 0)
            c_msg=1;
        else if	(strcmp(*argv,"-showcerts") == 0)
            c_showcerts=1;
        else if	(strcmp(*argv,"-nbio_test") == 0)
            nbio_test=1;
        else if	(strcmp(*argv,"-state") == 0)
            state=1;
#ifndef OPENSSL_NO_SSL2
        else if	(strcmp(*argv,"-ssl2") == 0)
            meth=SSLv2_client_method();
#endif
#ifndef OPENSSL_NO_SSL3
        else if	(strcmp(*argv,"-ssl3") == 0)
            meth=SSLv3_client_method();
#endif
#ifndef OPENSSL_NO_TLS1
        else if	(strcmp(*argv,"-tls1") == 0)
            meth=TLSv1_client_method();
#endif
#ifndef OPENSSL_NO_DTLS1
        else if	(strcmp(*argv,"-dtls1") == 0)
        {
            meth=DTLSv1_client_method();
            sock_type=SOCK_DGRAM;
        }
        else if (strcmp(*argv,"-timeout") == 0)
            enable_timeouts=1;
        else if (strcmp(*argv,"-mtu") == 0)
        {
            if (--argc < 1) goto bad;
            mtu = atol(*(++argv));
        }
#endif
        else if (strcmp(*argv,"-bugs") == 0)
            bugs=1;
        else if	(strcmp(*argv,"-keyform") == 0)
        {
            if (--argc < 1) goto bad;
            key_format = str2fmt(*(++argv));
        }
        else if	(strcmp(*argv,"-pass") == 0)
        {
            if (--argc < 1) goto bad;
            passarg = *(++argv);
        }
        else if	(strcmp(*argv,"-key") == 0)
        {
            if (--argc < 1) goto bad;
            key_file= *(++argv);
        }
        else if	(strcmp(*argv,"-reconnect") == 0)
        {
            reconnect=5;
        }
        else if	(strcmp(*argv,"-CApath") == 0)
        {
            if (--argc < 1) goto bad;
            CApath= *(++argv);
        }
        else if	(strcmp(*argv,"-CAfile") == 0)
        {
            if (--argc < 1) goto bad;
            CAfile= *(++argv);
        }
        else if (strcmp(*argv,"-no_tls1") == 0)
            off|=SSL_OP_NO_TLSv1;
        else if (strcmp(*argv,"-no_ssl3") == 0)
            off|=SSL_OP_NO_SSLv3;
        else if (strcmp(*argv,"-no_ssl2") == 0)
            off|=SSL_OP_NO_SSLv2;
        else if (strcmp(*argv,"-serverpref") == 0)
            off|=SSL_OP_CIPHER_SERVER_PREFERENCE;
        else if	(strcmp(*argv,"-cipher") == 0)
        {
            if (--argc < 1) goto bad;
            cipher= *(++argv);
        }
#ifdef FIONBIO
        else if (strcmp(*argv,"-nbio") == 0)
        {
            c_nbio=1;
        }
#endif
        else if	(strcmp(*argv,"-starttls") == 0)
        {
            if (--argc < 1) goto bad;
            ++argv;
            if (strcmp(*argv,"smtp") == 0)
                starttls_proto = PROTO_SMTP;
            else if (strcmp(*argv,"pop3") == 0)
                starttls_proto = PROTO_POP3;
            else if (strcmp(*argv,"imap") == 0)
                starttls_proto = PROTO_IMAP;
            else if (strcmp(*argv,"ftp") == 0)
                starttls_proto = PROTO_FTP;
            else
                goto bad;
        }
#ifndef OPENSSL_NO_ENGINE
        else if	(strcmp(*argv,"-engine") == 0)
        {
            if (--argc < 1) goto bad;
            engine_id = *(++argv);
        }
#endif
        else if (strcmp(*argv,"-rand") == 0)
        {
            if (--argc < 1) goto bad;
            inrand= *(++argv);
        }
        else
        {
            BIO_printf(bio_err,"unknown option %s\n",*argv);
            badop=1;
            break;
        }
        argc--;
        argv++;
    }
    if (badop)
    {
bad:
        sc_usage();
        goto end;
    }

    OpenSSL_add_ssl_algorithms();
    SSL_load_error_strings();

#ifndef OPENSSL_NO_ENGINE
    e = setup_engine(bio_err, engine_id, 1);
#endif
    if (!app_passwd(bio_err, passarg, NULL, &pass, NULL))
    {
        BIO_printf(bio_err, "Error getting password\n");
        goto end;
    }

    if (key_file == NULL)
        key_file = cert_file;


    if (key_file)

    {

        key = load_key(bio_err, key_file, key_format, 0, pass, e,
                       "client certificate private key file");
        if (!key)
        {
            ERR_print_errors(bio_err);
            goto end;
        }

    }

    if (cert_file)

    {
        cert = load_cert(bio_err,cert_file,cert_format,
                         NULL, e, "client certificate file");

        if (!cert)
        {
            ERR_print_errors(bio_err);
            goto end;
        }
    }

    if (!app_RAND_load_file(NULL, bio_err, 1) && inrand == NULL
            && !RAND_status())
    {
        BIO_printf(bio_err,"warning, not much extra random data, consider using the -rand option\n");
    }
    if (inrand != NULL)
        BIO_printf(bio_err,"%ld semi-random bytes loaded\n",
                   app_RAND_load_files(inrand));

    if (bio_c_out == NULL)
    {
        if (c_quiet && !c_debug && !c_msg)
        {
            bio_c_out=BIO_new(BIO_s_null());
        }
        else
        {
            if (bio_c_out == NULL)
                bio_c_out=BIO_new_fp(stdout,BIO_NOCLOSE);
        }
    }

    ctx=SSL_CTX_new(meth);
    if (ctx == NULL)
    {
        ERR_print_errors(bio_err);
        goto end;
    }

    if (bugs)
        SSL_CTX_set_options(ctx,SSL_OP_ALL|off);
    else
        SSL_CTX_set_options(ctx,off);
    /* DTLS: partial reads end up discarding unread UDP bytes :-(
     * Setting read ahead solves this problem.
     */
    if (sock_type == SOCK_DGRAM) SSL_CTX_set_read_ahead(ctx, 1);

    if (state) SSL_CTX_set_info_callback(ctx,apps_ssl_info_callback);
    if (cipher != NULL)
        if(!SSL_CTX_set_cipher_list(ctx,cipher)) {
            BIO_printf(bio_err,"error setting cipher list\n");
            ERR_print_errors(bio_err);
            goto end;
        }
#if 0
        else
            SSL_CTX_set_cipher_list(ctx,getenv("SSL_CIPHER"));
#endif

    SSL_CTX_set_verify(ctx,verify,verify_callback);
    if (!set_cert_key_stuff(ctx,cert,key))
        goto end;

    if ((!SSL_CTX_load_verify_locations(ctx,CAfile,CApath)) ||
            (!SSL_CTX_set_default_verify_paths(ctx)))
    {
        /* BIO_printf(bio_err,"error setting default verify locations\n"); */
        ERR_print_errors(bio_err);
        /* goto end; */
    }

    store = SSL_CTX_get_cert_store(ctx);
    X509_STORE_set_flags(store, vflags);

    con=SSL_new(ctx);
#ifndef OPENSSL_NO_KRB5
    if (con  &&  (con->kssl_ctx = kssl_ctx_new()) != NULL)
    {
        kssl_ctx_setstring(con->kssl_ctx, KSSL_SERVER, host);
    }
#endif	/* OPENSSL_NO_KRB5  */
    /*	SSL_set_cipher_list(con,"RC4-MD5"); */

re_start:

    if (init_client(&s,host,port,sock_type) == 0)
    {
        BIO_printf(bio_err,"connect:errno=%d\n",get_last_socket_error());
        SHUTDOWN(s);
        goto end;
    }
    BIO_printf(bio_c_out,"CONNECTED(%08X)\n",s);

#ifdef FIONBIO
    if (c_nbio)
    {
        unsigned long l=1;
        BIO_printf(bio_c_out,"turning on non blocking io\n");
        if (BIO_socket_ioctl(s,FIONBIO,&l) < 0)
        {
            ERR_print_errors(bio_err);
            goto end;
        }
    }
#endif
    if (c_Pause & 0x01) con->debug=1;

    if ( SSL_version(con) == DTLS1_VERSION)
    {
        struct timeval timeout;

        sbio=BIO_new_dgram(s,BIO_NOCLOSE);
        if (getsockname(s, &peer, (void *)&peerlen) < 0)
        {
            BIO_printf(bio_err, "getsockname:errno=%d\n",
                       get_last_socket_error());
            SHUTDOWN(s);
            goto end;
        }

        (void)BIO_ctrl_set_connected(sbio, 1, &peer);

        if ( enable_timeouts)
        {
            timeout.tv_sec = 0;
            timeout.tv_usec = DGRAM_RCV_TIMEOUT;
            BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout);

            timeout.tv_sec = 0;
            timeout.tv_usec = DGRAM_SND_TIMEOUT;
            BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0, &timeout);
        }

        if ( mtu > 0)
        {
            SSL_set_options(con, SSL_OP_NO_QUERY_MTU);
            SSL_set_mtu(con, mtu);
        }
        else
            /* want to do MTU discovery */
            BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL);
    }
    else
        sbio=BIO_new_socket(s,BIO_NOCLOSE);



    if (nbio_test)
    {
        BIO *test;

        test=BIO_new(BIO_f_nbio_test());
        sbio=BIO_push(test,sbio);
    }

    if (c_debug)
    {
        con->debug=1;
        BIO_set_callback(sbio,bio_dump_callback);
        BIO_set_callback_arg(sbio,(char *)bio_c_out);
    }
    if (c_msg)
    {
        SSL_set_msg_callback(con, msg_cb);
        SSL_set_msg_callback_arg(con, bio_c_out);
    }

    SSL_set_bio(con,sbio,sbio);
    SSL_set_connect_state(con);

    /* ok, lets connect */
    width=SSL_get_fd(con)+1;

    read_tty=1;
    write_tty=0;
    tty_on=0;
    read_ssl=1;
    write_ssl=1;

    cbuf_len=0;
    cbuf_off=0;
    sbuf_len=0;
    sbuf_off=0;

    /* This is an ugly hack that does a lot of assumptions */
    /* We do have to handle multi-line responses which may come
       in a single packet or not. We therefore have to use
       BIO_gets() which does need a buffering BIO. So during
       the initial chitchat we do push a buffering BIO into the
       chain that is removed again later on to not disturb the
       rest of the s_client operation. */
    if (starttls_proto == PROTO_SMTP)
    {
        int foundit=0;
        BIO *fbio = BIO_new(BIO_f_buffer());
        BIO_push(fbio, sbio);
        /* wait for multi-line response to end from SMTP */
        do
        {
            mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ);
        }
        while (mbuf_len>3 && mbuf[3]=='-');
        /* STARTTLS command requires EHLO... */
        BIO_printf(fbio,"EHLO openssl.client.net\r\n");
        (void)BIO_flush(fbio);
        /* wait for multi-line response to end EHLO SMTP response */
        do
        {
            mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ);
            if (strstr(mbuf,"STARTTLS"))
                foundit=1;
        }
        while (mbuf_len>3 && mbuf[3]=='-');
        (void)BIO_flush(fbio);
        BIO_pop(fbio);
        BIO_free(fbio);
        if (!foundit)
            BIO_printf(bio_err,
                       "didn't found starttls in server response,"
                       " try anyway...\n");
        BIO_printf(sbio,"STARTTLS\r\n");
        BIO_read(sbio,sbuf,BUFSIZZ);
    }
    else if (starttls_proto == PROTO_POP3)
    {
        BIO_read(sbio,mbuf,BUFSIZZ);
        BIO_printf(sbio,"STLS\r\n");
        BIO_read(sbio,sbuf,BUFSIZZ);
    }
    else if (starttls_proto == PROTO_IMAP)
    {
        int foundit=0;
        BIO *fbio = BIO_new(BIO_f_buffer());
        BIO_push(fbio, sbio);
        BIO_gets(fbio,mbuf,BUFSIZZ);
        /* STARTTLS command requires CAPABILITY... */
        BIO_printf(fbio,". CAPABILITY\r\n");
        (void)BIO_flush(fbio);
        /* wait for multi-line CAPABILITY response */
        do
        {
            mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ);
            if (strstr(mbuf,"STARTTLS"))
                foundit=1;
        }
        while (mbuf_len>3 && mbuf[0]!='.');
        (void)BIO_flush(fbio);
        BIO_pop(fbio);
        BIO_free(fbio);
        if (!foundit)
            BIO_printf(bio_err,
                       "didn't found STARTTLS in server response,"
                       " try anyway...\n");
        BIO_printf(sbio,". STARTTLS\r\n");
        BIO_read(sbio,sbuf,BUFSIZZ);
    }
    else if (starttls_proto == PROTO_FTP)
    {
        BIO *fbio = BIO_new(BIO_f_buffer());
        BIO_push(fbio, sbio);
        /* wait for multi-line response to end from FTP */
        do
        {
            mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ);
        }
        while (mbuf_len>3 && mbuf[3]=='-');
        (void)BIO_flush(fbio);
        BIO_pop(fbio);
        BIO_free(fbio);
        BIO_printf(sbio,"AUTH TLS\r\n");
        BIO_read(sbio,sbuf,BUFSIZZ);
    }

    for (;;)
    {
        FD_ZERO(&readfds);
        FD_ZERO(&writefds);

        if (SSL_in_init(con) && !SSL_total_renegotiations(con))
        {
            in_init=1;
            tty_on=0;
        }
        else
        {
            tty_on=1;
            if (in_init)
            {
                in_init=0;
                print_stuff(bio_c_out,con,full_log);
                if (full_log > 0) full_log--;

                if (starttls_proto)
                {
                    BIO_printf(bio_err,"%s",mbuf);
                    /* We don't need to know any more */
                    starttls_proto = PROTO_OFF;
                }

                if (reconnect)
                {
                    reconnect--;
                    BIO_printf(bio_c_out,"drop connection and then reconnect\n");
                    SSL_shutdown(con);
                    SSL_set_connect_state(con);
                    SHUTDOWN(SSL_get_fd(con));
                    goto re_start;
                }
            }
        }

        ssl_pending = read_ssl && SSL_pending(con);

        if (!ssl_pending)
        {
#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_NETWARE)
            if (tty_on)
            {
                if (read_tty)  FD_SET(fileno(stdin),&readfds);
                if (write_tty) FD_SET(fileno(stdout),&writefds);
            }
            if (read_ssl)
                FD_SET(SSL_get_fd(con),&readfds);
            if (write_ssl)
                FD_SET(SSL_get_fd(con),&writefds);
#else
            if(!tty_on || !write_tty) {
                if (read_ssl)
                    FD_SET(SSL_get_fd(con),&readfds);
                if (write_ssl)
                    FD_SET(SSL_get_fd(con),&writefds);
            }
#endif
            /*			printf("mode tty(%d %d%d) ssl(%d%d)\n",
            				tty_on,read_tty,write_tty,read_ssl,write_ssl);*/

            /* Note: under VMS with SOCKETSHR the second parameter
             * is currently of type (int *) whereas under other
             * systems it is (void *) if you don't have a cast it
             * will choke the compiler: if you do have a cast then
             * you can either go for (int *) or (void *).
             */
#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS)
            /* Under Windows/DOS we make the assumption that we can
            * always write to the tty: therefore if we need to
            		 * write to the tty we just fall through. Otherwise
            		 * we timeout the select every second and see if there
            		 * are any keypresses. Note: this is a hack, in a proper
            		 * Windows application we wouldn't do this.
            		 */
            i=0;
            if(!write_tty) {
                if(read_tty) {
                    tv.tv_sec = 1;
                    tv.tv_usec = 0;
                    i=select(width,(void *)&readfds,(void *)&writefds,
                             NULL,&tv);
#if defined(OPENSSL_SYS_WINCE) || defined(OPENSSL_SYS_MSDOS)
                    if(!i && (!_kbhit() || !read_tty) ) continue;
#else
                    if(!i && (!((_kbhit()) || (WAIT_OBJECT_0 == WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE), 0))) || !read_tty) ) continue;
#endif
                } else 	i=select(width,(void *)&readfds,(void *)&writefds,
                                     NULL,NULL);
            }
#elif defined(OPENSSL_SYS_NETWARE)
            if(!write_tty) {
                if(read_tty) {
                    tv.tv_sec = 1;
                    tv.tv_usec = 0;
                    i=select(width,(void *)&readfds,(void *)&writefds,
                             NULL,&tv);
                } else 	i=select(width,(void *)&readfds,(void *)&writefds,
                                     NULL,NULL);
            }
#else
            i=select(width,(void *)&readfds,(void *)&writefds,
                     NULL,NULL);
#endif
            if ( i < 0)
            {
                BIO_printf(bio_err,"bad select %d\n",
                           get_last_socket_error());
                goto shut;
                /* goto end; */
            }
        }

        if (!ssl_pending && FD_ISSET(SSL_get_fd(con),&writefds))
        {
            k=SSL_write(con,&(cbuf[cbuf_off]),
                        (unsigned int)cbuf_len);
            switch (SSL_get_error(con,k))
            {
            case SSL_ERROR_NONE:
                cbuf_off+=k;
                cbuf_len-=k;
                if (k <= 0) goto end;
                /* we have done a  write(con,NULL,0); */
                if (cbuf_len <= 0)
                {
                    read_tty=1;
                    write_ssl=0;
                }
                else /* if (cbuf_len > 0) */
                {
                    read_tty=0;
                    write_ssl=1;
                }
                break;
            case SSL_ERROR_WANT_WRITE:
                BIO_printf(bio_c_out,"write W BLOCK\n");
                write_ssl=1;
                read_tty=0;
                break;
            case SSL_ERROR_WANT_READ:
                BIO_printf(bio_c_out,"write R BLOCK\n");
                write_tty=0;
                read_ssl=1;
                write_ssl=0;
                break;
            case SSL_ERROR_WANT_X509_LOOKUP:
                BIO_printf(bio_c_out,"write X BLOCK\n");
                break;
            case SSL_ERROR_ZERO_RETURN:
                if (cbuf_len != 0)
                {
                    BIO_printf(bio_c_out,"shutdown\n");
                    goto shut;
                }
                else
                {
                    read_tty=1;
                    write_ssl=0;
                    break;
                }

            case SSL_ERROR_SYSCALL:
                if ((k != 0) || (cbuf_len != 0))
                {
                    BIO_printf(bio_err,"write:errno=%d\n",
                               get_last_socket_error());
                    goto shut;
                }
                else
                {
                    read_tty=1;
                    write_ssl=0;
                }
                break;
            case SSL_ERROR_SSL:
                ERR_print_errors(bio_err);
                goto shut;
            }
        }
#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE)
        /* Assume Windows/DOS can always write */
        else if (!ssl_pending && write_tty)
#else
        else if (!ssl_pending && FD_ISSET(fileno(stdout),&writefds))
#endif
        {
#ifdef CHARSET_EBCDIC
            ascii2ebcdic(&(sbuf[sbuf_off]),&(sbuf[sbuf_off]),sbuf_len);
#endif
            i=write(fileno(stdout),&(sbuf[sbuf_off]),sbuf_len);

            if (i <= 0)
            {
                BIO_printf(bio_c_out,"DONE\n");
                goto shut;
                /* goto end; */
            }

            sbuf_len-=i;;
            sbuf_off+=i;
            if (sbuf_len <= 0)
            {
                read_ssl=1;
                write_tty=0;
            }
        }
        else if (ssl_pending || FD_ISSET(SSL_get_fd(con),&readfds))
        {
#ifdef RENEG
        { static int iiii; if (++iiii == 52) {
                    SSL_renegotiate(con);
                    iiii=0;
                }
            }
#endif
#if 1
            k=SSL_read(con,sbuf,1024 /* BUFSIZZ */ );
#else
            /* Demo for pending and peek :-) */
            k=SSL_read(con,sbuf,16);
            {   char zbuf[10240];
                printf("read=%d pending=%d peek=%d\n",k,SSL_pending(con),SSL_peek(con,zbuf,10240));
            }
#endif

            switch (SSL_get_error(con,k))
            {
            case SSL_ERROR_NONE:
                if (k <= 0)
                    goto end;
                sbuf_off=0;
                sbuf_len=k;

                read_ssl=0;
                write_tty=1;
                break;
            case SSL_ERROR_WANT_WRITE:
                BIO_printf(bio_c_out,"read W BLOCK\n");
                write_ssl=1;
                read_tty=0;
                break;
            case SSL_ERROR_WANT_READ:
                BIO_printf(bio_c_out,"read R BLOCK\n");
                write_tty=0;
                read_ssl=1;
                if ((read_tty == 0) && (write_ssl == 0))
                    write_ssl=1;
                break;
            case SSL_ERROR_WANT_X509_LOOKUP:
                BIO_printf(bio_c_out,"read X BLOCK\n");
                break;
            case SSL_ERROR_SYSCALL:
                BIO_printf(bio_err,"read:errno=%d\n",get_last_socket_error());
                goto shut;
            case SSL_ERROR_ZERO_RETURN:
                BIO_printf(bio_c_out,"closed\n");
                goto shut;
            case SSL_ERROR_SSL:
                ERR_print_errors(bio_err);
                goto shut;
                /* break; */
            }
        }

#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS)
#if defined(OPENSSL_SYS_WINCE) || defined(OPENSSL_SYS_MSDOS)
        else if (_kbhit())
#else
        else if ((_kbhit()) || (WAIT_OBJECT_0 == WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE), 0)))
#endif
#elif defined (OPENSSL_SYS_NETWARE)
        else if (_kbhit())
#else
        else if (FD_ISSET(fileno(stdin),&readfds))
#endif
        {
            if (crlf)
            {
                int j, lf_num;

                i=read(fileno(stdin),cbuf,BUFSIZZ/2);
                lf_num = 0;
                /* both loops are skipped when i <= 0 */
                for (j = 0; j < i; j++)
                    if (cbuf[j] == '\n')
                        lf_num++;
                for (j = i-1; j >= 0; j--)
                {
                    cbuf[j+lf_num] = cbuf[j];
                    if (cbuf[j] == '\n')
                    {
                        lf_num--;
                        i++;
                        cbuf[j+lf_num] = '\r';
                    }
                }
                assert(lf_num == 0);
            }
            else
                i=read(fileno(stdin),cbuf,BUFSIZZ);

            if ((!c_ign_eof) && ((i <= 0) || (cbuf[0] == 'Q')))
            {
                BIO_printf(bio_err,"DONE\n");
                goto shut;
            }

            if ((!c_ign_eof) && (cbuf[0] == 'R'))
            {
                BIO_printf(bio_err,"RENEGOTIATING\n");
                SSL_renegotiate(con);
                cbuf_len=0;
            }
            else
            {
                cbuf_len=i;
                cbuf_off=0;
#ifdef CHARSET_EBCDIC
                ebcdic2ascii(cbuf, cbuf, i);
#endif
            }

            write_ssl=1;
            read_tty=0;
        }
    }
shut:
    SSL_shutdown(con);
    SHUTDOWN(SSL_get_fd(con));
    ret=0;
end:
    if(prexit) print_stuff(bio_c_out,con,1);
    if (con != NULL) SSL_free(con);
    if (con2 != NULL) SSL_free(con2);
    if (ctx != NULL) SSL_CTX_free(ctx);
    if (cert)
        X509_free(cert);
    if (key)
        EVP_PKEY_free(key);
    if (pass)
        OPENSSL_free(pass);
    if (cbuf != NULL) {
        OPENSSL_cleanse(cbuf,BUFSIZZ);
        OPENSSL_free(cbuf);
    }
    if (sbuf != NULL) {
        OPENSSL_cleanse(sbuf,BUFSIZZ);
        OPENSSL_free(sbuf);
    }
    if (mbuf != NULL) {
        OPENSSL_cleanse(mbuf,BUFSIZZ);
        OPENSSL_free(mbuf);
    }
    if (bio_c_out != NULL)
    {
        BIO_free(bio_c_out);
        bio_c_out=NULL;
    }
    apps_shutdown();
    OPENSSL_EXIT(ret);
}
eventer_ssl_ctx_t *
eventer_ssl_ctx_new(eventer_ssl_orientation_t type,
                    const char *layer,
                    const char *certificate, const char *key,
                    const char *ca, const char *ciphers) {
  char ssl_ctx_key[SSL_CTX_KEYLEN];
  eventer_ssl_ctx_t *ctx;
  const char *layer_str;
  char *ctx_layer, *opts;
  char *opts_fallback = DEFAULT_OPTS_STRING;
  time_t now;
  ctx = calloc(1, sizeof(*ctx));
  if(!ctx) return NULL;

  layer_str = layer ? layer : DEFAULT_LAYER_STRING;
  ctx_layer = alloca(strlen(layer_str)+1);
  memcpy(ctx_layer, layer_str, strlen(layer_str)+1);
  opts = strchr(ctx_layer,':');
  if(opts) *opts++ = '\0';
  else {
    opts = alloca(strlen(opts_fallback)+1);
    memcpy(opts, opts_fallback, strlen(opts_fallback)+1);
  }

  now = time(NULL);
  ssl_ctx_key_write(ssl_ctx_key, sizeof(ssl_ctx_key),
                    type, layer, certificate, key, ca, ciphers);
  ctx->ssl_ctx_cn = ssl_ctx_cache_get(ssl_ctx_key);
  if(ctx->ssl_ctx_cn) {
    if(now - ctx->ssl_ctx_cn->creation_time > ssl_ctx_cache_expiry ||
       (now - ctx->ssl_ctx_cn->last_stat_time > ssl_ctx_cache_finfo_expiry &&
           (validate_finfo(&ctx->ssl_ctx_cn->cert_finfo, certificate) ||
            validate_finfo(&ctx->ssl_ctx_cn->key_finfo, key) ||
            validate_finfo(&ctx->ssl_ctx_cn->ca_finfo, ca) || 
            (ctx->ssl_ctx_cn->last_stat_time = now) == 0))) { /* assignment */
      ssl_ctx_cache_remove(ssl_ctx_key);
      ssl_ctx_cache_node_free(ctx->ssl_ctx_cn);
      ctx->ssl_ctx_cn = NULL;
    }
  }

  if(!ctx->ssl_ctx_cn) {
    char *part = NULL, *brkt = NULL;
    long ctx_options = 0;
    ssl_ctx_cache_node *existing_ctx_cn;
    ctx->ssl_ctx_cn = calloc(1, sizeof(*ctx->ssl_ctx_cn));
    ctx->ssl_ctx_cn->key = strdup(ssl_ctx_key);
    ctx->ssl_ctx_cn->refcnt = 1;
    ctx->ssl_ctx_cn->creation_time = now;
    ctx->ssl_ctx_cn->last_stat_time = now;
    populate_finfo(&ctx->ssl_ctx_cn->cert_finfo, certificate);
    populate_finfo(&ctx->ssl_ctx_cn->key_finfo, key);
    populate_finfo(&ctx->ssl_ctx_cn->ca_finfo, ca);
    ctx->ssl_ctx = NULL;
    if(0)
      ;
#if defined(SSL_TXT_SSLV3) && defined(HAVE_SSLV3_SERVER) && defined(HAVE_SSLV3_CLIENT)
    else if(layer && !strcasecmp(layer, SSL_TXT_SSLV3))
      ctx->ssl_ctx = SSL_CTX_new(type == SSL_SERVER ?
                                 SSLv3_server_method() : SSLv3_client_method());
#endif
#if defined(SSL_TXT_SSLV2) && defined(HAVE_SSLV2_SERVER) && defined(HAVE_SSLV2_CLIENT)
    else if(layer && !strcasecmp(layer, SSL_TXT_SSLV2))
      ctx->ssl_ctx = SSL_CTX_new(type == SSL_SERVER ?
                                 SSLv2_server_method() : SSLv2_client_method());
#endif
#if defined(SSL_TXT_TLSV1) && defined(HAVE_TLSV1_SERVER) && defined(HAVE_TLSV1_CLIENT)
    else if(layer && !strcasecmp(layer, SSL_TXT_TLSV1))
      ctx->ssl_ctx = SSL_CTX_new(type == SSL_SERVER ?
                                 TLSv1_server_method() : TLSv1_client_method());
#endif
#if defined(SSL_TXT_TLSV1_1) && defined(HAVE_TLSV1_1_SERVER) && defined(HAVE_TLSV1_1_CLIENT)
    else if(layer && !strcasecmp(layer, SSL_TXT_TLSV1_1))
      ctx->ssl_ctx = SSL_CTX_new(type == SSL_SERVER ?
                                 TLSv1_1_server_method() : TLSv1_1_client_method());
#endif
#if defined(SSL_TXT_TLSV1_2) && defined(HAVE_TLSV1_2_SERVER) && defined(HAVE_TLSV1_2_CLIENT)
    else if(layer && !strcasecmp(layer, SSL_TXT_TLSV1_2))
      ctx->ssl_ctx = SSL_CTX_new(type == SSL_SERVER ?
                                 TLSv1_2_server_method() : TLSv1_2_client_method());
#endif
    if(ctx->ssl_ctx == NULL)
      ctx->ssl_ctx = SSL_CTX_new(type == SSL_SERVER ?
                                 SSLv23_server_method() : SSLv23_client_method());
    if(!ctx->ssl_ctx) goto bail;

    for(part = strtok_r(opts, ",", &brkt);
        part;
        part = strtok_r(NULL, ",", &brkt)) {
      char *optname = part;
      int neg = 0;
      if(*optname == '!') neg = 1, optname++;

#define SETBITOPT(name, neg, opt) \
  if(!strcasecmp(optname, name)) { \
    if(neg) ctx_options &= ~(opt); \
    else    ctx_options |= (opt); \
  }

      SETBITOPT("all", neg, SSL_OP_ALL)
#ifdef SSL_TXT_SSLV2
      else SETBITOPT(SSL_TXT_SSLV2, !neg, SSL_OP_NO_SSLv2)
#endif
#ifdef SSL_TXT_SSLV3
      else SETBITOPT(SSL_TXT_SSLV3, !neg, SSL_OP_NO_SSLv3)
#endif
#ifdef SSL_TXT_TLSV1
      else SETBITOPT(SSL_TXT_TLSV1, !neg, SSL_OP_NO_TLSv1)
#endif
#ifdef SSL_TXT_TLSV1_1
      else SETBITOPT(SSL_TXT_TLSV1_1, !neg, SSL_OP_NO_TLSv1_1)
#endif
#ifdef SSL_TXT_TLSV1_2
      else SETBITOPT(SSL_TXT_TLSV1_2, !neg, SSL_OP_NO_TLSv1_2)
#endif
#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
      else SETBITOPT("cipher_server_preference", neg, SSL_OP_CIPHER_SERVER_PREFERENCE)
#endif
      else {
        mtevL(mtev_error, "SSL layer part '%s' not understood.\n", optname);
      }
    }

    if (type == SSL_SERVER)
      SSL_CTX_set_session_id_context(ctx->ssl_ctx,
              (unsigned char *)EVENTER_SSL_DATANAME,
              sizeof(EVENTER_SSL_DATANAME)-1);
#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
    ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
#endif
#ifdef SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
    ctx_options &= ~SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG;
#endif
#ifdef SSL_OP_NO_COMPRESSION
    ctx_options |= SSL_OP_NO_COMPRESSION;
#endif
#ifdef SSL_OP_NO_TICKET
    ctx_options |= SSL_OP_NO_TICKET;
#endif
#ifdef SSL_OP_SINGLE_DH_USE
    ctx_options |= SSL_OP_SINGLE_DH_USE;
#endif
#ifdef SSL_OP_SINGLE_ECDH_USE
    ctx_options |= SSL_OP_SINGLE_ECDH_USE;
#endif
    SSL_CTX_set_options(ctx->ssl_ctx, ctx_options);
#ifdef SSL_MODE_RELEASE_BUFFERS
    SSL_CTX_set_mode(ctx->ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
#endif
    if(certificate &&
       SSL_CTX_use_certificate_chain_file(ctx->ssl_ctx, certificate) != 1)
      goto bail;
    if(key &&
       SSL_CTX_use_RSAPrivateKey_file(ctx->ssl_ctx,key,
                                      SSL_FILETYPE_PEM) != 1)
      goto bail;
    if(ca) {
      STACK_OF(X509_NAME) *cert_stack;
      if(!SSL_CTX_load_verify_locations(ctx->ssl_ctx,ca,NULL) ||
         (cert_stack = SSL_load_client_CA_file(ca)) == NULL)
        goto bail;
      SSL_CTX_set_client_CA_list(ctx->ssl_ctx, cert_stack);
    }
    SSL_CTX_set_cipher_list(ctx->ssl_ctx, ciphers ? ciphers : "DEFAULT");
    SSL_CTX_set_verify(ctx->ssl_ctx, SSL_VERIFY_PEER, verify_cb);
#ifndef OPENSSL_NO_EC
#if defined(SSL_CTX_set_ecdh_auto)
    SSL_CTX_set_ecdh_auto(ctx->ssl_ctx, 1);
#elif defined(NID_X9_62_prime256v1)
    EC_KEY *ec_key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
    SSL_CTX_set_tmp_ecdh(ctx->ssl_ctx, ec_key);
    EC_KEY_free(ec_key);
#endif
#endif
    existing_ctx_cn = ssl_ctx_cache_set(ctx->ssl_ctx_cn);
    if(existing_ctx_cn != ctx->ssl_ctx_cn) {
      ssl_ctx_cache_node_free(ctx->ssl_ctx_cn);
      ctx->ssl_ctx_cn = existing_ctx_cn;
    }
  }