コード例 #1
0
/* This should exactly match openssl's SSL_set_fd except for using my BIO */
static int
my_SSL_set_fd(Port *port, int fd)
{
	int			ret = 0;
	BIO		   *bio = NULL;

	bio = BIO_new(my_BIO_s_socket());

	if (bio == NULL)
	{
		SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB);
		goto err;
	}
	/* Use 'ptr' to store pointer to PGconn */
	bio->ptr = port;

	BIO_set_fd(bio, fd, BIO_NOCLOSE);
	SSL_set_bio(port->ssl, bio, bio);
	ret = 1;
err:
	return ret;
}
コード例 #2
0
  bool OpenSSLBase::init( const std::string& clientKey,
                          const std::string& clientCerts,
                          const StringList& cacerts )
  {
    if( m_initLib )
      SSL_library_init();

    SSL_COMP_add_compression_method( 193, COMP_zlib() );

    OpenSSL_add_all_algorithms();

    if( !setType() ) //inits m_ctx
      return false;

    setClientCert( clientKey, clientCerts );
    setCACerts( cacerts );

    if( !SSL_CTX_set_cipher_list( m_ctx, "HIGH:MEDIUM:AES:@STRENGTH" ) )
      return false;

    m_ssl = SSL_new( m_ctx );
    if( !m_ssl )
      return false;

    if( !BIO_new_bio_pair( &m_ibio, 0, &m_nbio, 0 ) )
      return false;

    SSL_set_bio( m_ssl, m_ibio, m_ibio );
    SSL_set_mode( m_ssl, SSL_MODE_AUTO_RETRY | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE );

    ERR_load_crypto_strings();
    SSL_load_error_strings();

    if( !privateInit() )
      return false;

    m_valid = true;
    return true;
  }
コード例 #3
0
e_TlsError TlsInitHandshake(t_TlsConnection *p_TlsConnection)
{
    DEBUG_LOG_PRINT_LEV2(("TlsInitHandshake : handle %d : Entry\n" , p_TlsConnection->handle ));

    p_TlsConnection->p_BIO =
 //        BIO_new_socket(
         BIO_new_fd(
         p_TlsConnection->socket,
            BIO_NOCLOSE);

      if(p_TlsConnection->p_BIO == NULL)
      {
         DEBUG_LOG_PRINT_LEV2(("ERROR failed to create SSL BIO on socket\n" ));
         if(p_TlsConnection->socket)   close(p_TlsConnection->socket);
         return K_TLS_ERROR_BIO_INIT;
      }

    // Prepare for SSL layer
     p_TlsConnection->p_SSL = SSL_new(gp_SSL_CTX);
     if(p_TlsConnection->p_SSL == NULL)
     {
        DEBUG_LOG_PRINT_LEV2(("ERROR failed to create SSL structure for SSL connection\n" ));
        BIO_free(p_TlsConnection->p_BIO);
        p_TlsConnection->p_BIO = NULL;
        return K_TLS_ERROR_SSL_INIT;
     }

     SSL_set_bio(
        p_TlsConnection->p_SSL,
        p_TlsConnection->p_BIO,
        p_TlsConnection->p_BIO);
     SSL_set_mode(p_TlsConnection->p_SSL, SSL_MODE_AUTO_RETRY);

     TlsTransitionState(p_TlsConnection , K_TLS_STATE_HANDSHAKE_IN_PROGRESS);

     DEBUG_LOG_PRINT_LEV2(("TlsInitHandshake : Exit\n"));

     return TlsDoHandshake( p_TlsConnection );
}
コード例 #4
0
ファイル: mssl.c プロジェクト: CCbird/httping
int connect_ssl(int fd, SSL_CTX *client_ctx, SSL **ssl_h, BIO **s_bio, double timeout, double *ssl_handshake)
{
	int dummy = -1;
	double dstart = get_ts();

	struct timeval tv;
	tv.tv_sec  = (long)(timeout / 1000.0);
	tv.tv_usec = (long)(timeout * 1000.0) % 1000000;

	*ssl_handshake = -1.0;

	if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof tv) == -1)
	{
		set_error(gettext("problem setting receive timeout (%s)"), strerror(errno));
		return -1;
	}

	if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof tv) == -1)
	{
		set_error(gettext("problem setting transmit timeout (%s)"), strerror(errno));
		return -1;
	}

	*ssl_h = SSL_new(client_ctx);

	*s_bio = BIO_new_socket(fd, BIO_NOCLOSE);
	SSL_set_bio(*ssl_h, *s_bio, *s_bio);

	dummy = SSL_connect(*ssl_h);
	if (dummy <= 0)
	{
		set_error(gettext("problem starting SSL connection: %d"), SSL_get_error(*ssl_h, dummy));
		return -1;
	}

	*ssl_handshake = get_ts() - dstart;

	return 0;
}
コード例 #5
0
int openssl_connect(git_stream *stream)
{
	int ret;
	BIO *bio;
	openssl_stream *st = (openssl_stream *) stream;

	if ((ret = git_stream_connect(st->io)) < 0)
		return ret;

	bio = BIO_new(&git_stream_bio_method);
	GITERR_CHECK_ALLOC(bio);
	bio->ptr = st->io;

	SSL_set_bio(st->ssl, bio, bio);
	/* specify the host in case SNI is needed */
	SSL_set_tlsext_host_name(st->ssl, st->host);

	if ((ret = SSL_connect(st->ssl)) <= 0)
		return ssl_set_error(st->ssl, ret);

	return verify_server_cert(st->ssl, st->host);
}
コード例 #6
0
ファイル: socket.c プロジェクト: deweerdt/h2o
static void setup_bio(h2o_socket_t *sock)
{
    static BIO_METHOD *bio_methods = NULL;
    if (bio_methods == NULL) {
        static pthread_mutex_t init_lock = PTHREAD_MUTEX_INITIALIZER;
        pthread_mutex_lock(&init_lock);
        if (bio_methods == NULL) {
            BIO_METHOD *biom = BIO_meth_new(BIO_TYPE_FD, "h2o_socket");
            BIO_meth_set_write(biom, write_bio);
            BIO_meth_set_read(biom, read_bio);
            BIO_meth_set_puts(biom, puts_bio);
            BIO_meth_set_ctrl(biom, ctrl_bio);
            __sync_synchronize();
            bio_methods = biom;
        }
    }

    BIO *bio = BIO_new(bio_methods);
    BIO_set_data(bio, sock);
    BIO_set_init(bio, 1);
    SSL_set_bio(sock->ssl->ssl, bio, bio);
}
コード例 #7
0
ファイル: basesslprotocol.cpp プロジェクト: OpenQCam/qcam
bool BaseSSLProtocol::Initialize(Variant &parameters) {
	//1. Initialize the SSL library
	if (!_libraryInitialized) {
		//3. This is the first time we use the library. So we have to
		//initialize it first
		SSL_library_init();

		//init readable error messages
		SSL_load_error_strings();
		ERR_load_SSL_strings();
		ERR_load_CRYPTO_strings();
		ERR_load_crypto_strings();
		OpenSSL_add_all_algorithms();
		OpenSSL_add_all_ciphers();
		OpenSSL_add_all_digests();

		//initialize the random numbers generator
		InitRandGenerator();
		_libraryInitialized = true;
	}

	//2. Initialize the global context
	if (!InitGlobalContext(parameters)) {
		FATAL("Unable to initialize global context");
		return false;
	}

	//3. create connection SSL context
	_pSSL = SSL_new(_pGlobalSSLContext);
	if (_pSSL == NULL) {
		FATAL("Unable to create SSL connection context");
		return false;
	}

	//4. setup the I/O buffers
	SSL_set_bio(_pSSL, BIO_new(BIO_s_mem()), BIO_new(BIO_s_mem()));

	return DoHandshake();
}
コード例 #8
0
ファイル: IoSecureServer.c プロジェクト: ADTSH/io
IoSecureSocket *IoSecureServer_dtlsWrap(IoSecureServer *self, IoObject *locals, IoMessage *msg)
{
	SSL_CTX *ctx = OCTX(self);
	IoSocket *sock = IoObject_getSlot_(self, IOSYMBOL("socket"));
	IoIPAddress *ioip = IoMessage_locals_addressArgAt_(msg, locals, 0);
	IPAddress *ip = IoIPAddress_rawIPAddress(ioip);
	struct sockaddr *addr = IPAddress_sockaddr(ip);
	IoNumber *port = IoObject_getSlot_(sock, IOSYMBOL("port"));
	int fd = IoSocket_rawDescriptor(sock);
	SSL *ssl = SSL_new(ctx);
	BIO *rbio = BIO_new(BIO_s_mem());
	BIO_set_mem_eof_return(rbio, -1);
	BIO *wbio = BIO_new_dgram(fd, BIO_NOCLOSE);
	BIO_dgram_set_peer(wbio, addr);
	SSL_set_bio(ssl, rbio, wbio);
	SSL_set_accept_state(ssl);
	set_nonblocking(wbio);
	SSL_set_mode(ssl, SSL_MODE_ENABLE_PARTIAL_WRITE |
		SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
	IoSecureSocket *ssock = IoSecureSocket_newWithSSL_IP_(IoObject_state(self), ssl, ioip);
	return ssock;
}
コード例 #9
0
CONN *establish_connection(char *addr, char *port)
{
    // Blank connection structure
    CONN *conn = malloc(sizeof (CONN));
    // Initialise connection
    init_conn(conn);
    // Load certificates
    load_certs(conn);
    // Create new SSL structure
    conn->ssl = SSL_new(conn->ctx);
    
    struct addrinfo hints, *res;
    
    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    
    getaddrinfo(addr, port, &hints, &res);
    
    conn->sd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
    
    // Connect to server
    if(connect(conn->sd, res->ai_addr, res->ai_addrlen) != 0) {
        perror("connection");
    }
    
    // Set BIO into SSL structure
    conn->bio = BIO_new_socket(conn->sd, BIO_NOCLOSE);
    SSL_set_bio(conn->ssl, conn->bio, conn->bio);
    
    // Perform handshake
    if(SSL_connect(conn->ssl) != 1) {
        perror("handshake\n");
    }
    
    printf("Connection Established\n");
    return conn;
}
コード例 #10
0
ファイル: server.c プロジェクト: zr139898/sample_app
int main(int argc, char * argv[]) {
    BIO * acc, * client;
    THREAD_TYPE tid;
    SSL * ssl;
    SSL_CTX * ctx;

    init_OpenSSL();
    seed_prng();

    ctx = setup_server_ctx();
    
    acc = BIO_new_accept(PORT);
    if (!acc)
        int_error("Error creating server socket");
    if (BIO_do_accept(acc) <= 0)
        int_error("Error binding server socket");
    // BIO_do_accept() will block and wait for a remote connection.
    while (1) {
        if (BIO_do_accept(acc) <= 0)
            int_error("Error accepting connection");
        // get the client BIO
        client = BIO_pop(acc);
        if (!(ssl = SSL_new(ctx)))
            int_error("Error creating SSL context");
        SSL_set_accept_state(ssl);
        SSL_set_bio(ssl, client, client);
        // create a new thread to handle the new connection,
        // The thread will call do_server_loop with the client BIO.
        // THREAD_CREATE(tid, entry, arg);
        // tid is the id of the new thread.
        // server_thread is the function defined above, which will call
        // do_server_loop() with the client BIO.
        THREAD_CREATE(tid, server_thread, ssl);
    }
    SSL_CTX_free(ctx);
    BIO_free(acc);
    return 0;
}
コード例 #11
0
ファイル: SSLSocket.cpp プロジェクト: coredumped/X-VR2
void SSLSocket::attach() {
    ssl_internal_stack *stack;
    if(idata != 0) {
        stack = (ssl_internal_stack *)idata;
        delete stack;
    }
    stack = new ssl_internal_stack();
    stack->ssl = SSL_new((SSL_CTX *)ctx.getInternal());
    stack->sbio=BIO_new_socket(tsock,BIO_NOCLOSE);
    if(stack->sbio == 0x00)
        throw SSLSocketAddIOFailure();
    SSL_set_bio(stack->ssl, stack->sbio, stack->sbio);
    if(SSL_connect(stack->ssl) <= 0)
        throw SSLConnectFailed();
    //Verify certificate now
    int vres;
    if((vres = SSL_get_verify_result(stack->ssl)) != X509_V_OK) {
#ifdef USE_DEBUG
        ::X509 *x5;
        x5 = SSL_get_peer_certificate(stack->ssl);
        X509 cert(x5);
        X509_free(x5);
#endif
        switch(vres) {
        case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
            throw X509IssuerCertificateNotFound();
        case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
            throw X509UnableToDecryptCertificate();
        case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
#ifdef USE_DEBUG
            debugmsg(this, "Certificate not found locally.\n");
#endif
            throw CertificateIssuerNotFoundLocally();
        default:
            throw SSLInvalidCertificate();
        }
    }
}
コード例 #12
0
ファイル: SSLSocket.C プロジェクト: AlvaroVega/TIDorbC
//
// Constructor
//
SSLSocket::SSLSocket(const char* host, in_port_t port,
                     const InetAddress& localAddr, in_port_t localPort,
                     SSLContext* context)
  throw(IOException, SystemException)
  : Socket(host, port, localAddr, localPort), _context(context), _session(NULL)
{
  // TODO: check if context is != NULL

  /* Connect the SSL socket */
  _ssl  = SSL_new(_context->_ctx);
  _sbio = BIO_new_socket(_impl->_fd, BIO_NOCLOSE);
  SSL_set_bio(_ssl, _sbio, _sbio);

  //SSL_set_connect_state(_ssl);

  // Verify certificate
  if (SSL_get_verify_result(_ssl) != X509_V_OK) {
    throw IOException("SSLSocket: Certificate doesn't verified");
  }

  _session_creation = true;
  _use_client_mode = true;
}
コード例 #13
0
ファイル: 12334.c プロジェクト: 0x24bin/exploit-database
/* ssl_connect_to
 * establish ssl connection over tcp connection
 */
SSL *ssl_connect_to(int s) {
   SSL *ssl;
   SSL_CTX *ctx;
   BIO *sbio;
   SSL_METHOD *meth;

   CRYPTO_malloc_init();
   SSL_load_error_strings();
   SSL_library_init();

   // meth = TLSv1_client_method();
   meth = SSLv23_client_method();
   ctx = SSL_CTX_new(meth);
   ssl = SSL_new(ctx);
   sbio = BIO_new_socket(s, BIO_NOCLOSE);
   SSL_set_bio(ssl, sbio, sbio);

   if (SSL_connect(ssl) <= 0) {
      return NULL;
   }

   return ssl;
}
コード例 #14
0
ファイル: tls_udp.c プロジェクト: anchowee/traversal_server
static struct tls_conn *conn_alloc(struct tls_sock *ts, const struct sa *peer)
{
	struct tls_conn *tc;

	tc = mem_zalloc(sizeof(*tc), conn_destructor);
	if (!tc)
		return NULL;

	tc->ssl = SSL_new(ts->tls->ctx);
	if (!tc->ssl)
		goto error;

	tc->sbio_in = BIO_new(BIO_s_mem());
	if (!tc->sbio_in)
		goto error;

	tc->sbio_out = BIO_new(&bio_udp_send);
	if (!tc->sbio_out) {
		BIO_free(tc->sbio_in);
		goto error;
	}
	tc->sbio_out->ptr = tc;

	SSL_set_bio(tc->ssl, tc->sbio_in, tc->sbio_out);

	tmr_init(&tc->tmr);

	tc->peer = *peer;
	tc->ts   = ts;

	hash_append(ts->ht_conn, sa_hash(peer, SA_ALL), &tc->he, tc);

	return tc;

 error:
	return mem_deref(tc);
}
コード例 #15
0
ファイル: server3.c プロジェクト: iloveloveyou/chirico
int main(int argc, char *argv[])
{
    BIO     *acc, *client;
    SSL     *ssl;
    SSL_CTX *ctx;
    THREAD_TYPE tid;

    init_OpenSSL(  );
    seed_prng();

 
    ctx = setup_server_ctx(  );
 
    acc = BIO_new_accept(PORT);
    if (!acc)
        int_error("Error creating server socket");
 
    if (BIO_do_accept(acc) <= 0)
        int_error("Error binding server socket");
 
    while(1)
    {
        if (BIO_do_accept(acc) <= 0)
            int_error("Error accepting connection");
 
        client = BIO_pop(acc);
        if (!(ssl = SSL_new(ctx)))
        int_error("Error creating SSL context");
        SSL_set_accept_state(ssl);
        SSL_set_bio(ssl, client, client);
        THREAD_CREATE(tid, (void *)server_thread, ssl);
    }
 
    SSL_CTX_free(ctx);
    BIO_free(acc);
    return 0;
}
コード例 #16
0
ファイル: auth_client.c プロジェクト: Maihj/secure_cs
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;
}
コード例 #17
0
static int dtls_connect (void)
{
	struct timeval timeout;
	fd_set wfd;
	int width = 0;
	struct sockaddr peer;
	int peerlen = sizeof (struct sockaddr);

	ssl = SSL_new (ctx);
   if (DTLS1_VERSION == SSL_version (ssl))
      fprintf (stderr, "%s: %s(): Yes: DTLS1_VERSION CLIENT\n", __FILE__, __func__);
	sbio = BIO_new_dgram (udpsock, BIO_NOCLOSE);
	if (getsockname (udpsock, &peer, (socklen_t *)&peerlen) < 0)
	{
		dtls_report_err ("%s: %s(): getsockname FAILED: %s\n", __FILE__, __func__, strerror (errno));
		shutdown (udpsock, SHUT_RDWR);
		return -1;
	}
	BIO_ctrl_set_connected (sbio, 1, &peer);
	timeout.tv_sec = 10;
	timeout.tv_usec = 0;
	BIO_ctrl (sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0, &timeout);
	BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL);
	SSL_set_bio (ssl, sbio, sbio);
	SSL_set_connect_state (ssl);
   fprintf (stderr, "%s: %s(): Am now here @ %d\n", __FILE__, __func__, __LINE__);
	width = SSL_get_fd (ssl) + 1;
	FD_ZERO (&wfd);
	FD_SET (SSL_get_fd (ssl), &wfd);
	timeout.tv_sec = 10;
	timeout.tv_usec = 0;
	if (select (width, NULL, &wfd, NULL, &timeout) < 0)
	{
		return 1;
	}
	return 0;
}	
コード例 #18
0
ファイル: ssl.c プロジェクト: FPiriz/uperf
static int
protocol_ssl_connect(protocol_t * p, void *options)
{
	BIO *sbio;
	int status;

	ssl_private_t *ssl_p = (ssl_private_t *) p->_protocol_p;
	flowop_options_t *flowop_options = (flowop_options_t *) options;

	uperf_debug("ssl - Connecting to %s:%d\n", p->host, p->port);

	status = generic_connect(p, IPPROTO_TCP);
	if (status == UPERF_SUCCESS)
		set_tcp_options(p->fd, flowop_options);

	if (flowop_options && (strcmp(flowop_options->engine, ""))) {
		status = load_engine(flowop_options->engine);
		if (status == -1) {
			uperf_info(
"ssl - Engine %s does NOT exist! Using the default OpenSSL softtoken",
			flowop_options->engine);
		}
	}
	if ((ssl_p->ssl = SSL_new(ctx)) == NULL) {
		ulog_err("Error initializng SSL");
		return (-1);
	}
	sbio = BIO_new_socket(p->fd, BIO_NOCLOSE);
	SSL_set_bio(ssl_p->ssl, sbio, sbio);

	status = SSL_connect(ssl_p->ssl);
	if (status <= 0) {
		uperf_log_msg(UPERF_LOG_ERROR, 0, "ssl connect error");
		return (-1);
	}
	return (0);
}
コード例 #19
0
ファイル: server.cpp プロジェクト: Mandragorian/netSSL
int main(int argc, char *argv[])
{
	BIO *acc, *client;
	SSL *ssl;
	SSL_CTX *ctx;
	THREAD_TYPE tid;
	void* (*func)(void*) = &server_thread;


	std::cout << "before init\n";
	init_OpenSSL();
	//seed_prng();
	std::cout << "after init\n";

	ctx = setup_server_ctx();

	acc = BIO_new_accept(PORT);
	if(!acc)
		int_error("Error creating socket");
	if(BIO_do_accept(acc) <= 0)
		int_error("Error binding socket");

	for(;;)
	{
		if(BIO_do_accept(acc) <= 0)
			int_error("Error accepting connection");

		client = BIO_pop(acc);
		if(!(ssl = SSL_new(ctx)))
			int_error("Error creating ssl object");
		SSL_set_bio(ssl,client,client);
		THREAD_CREATE(tid,func,ssl);
	}
	BIO_free(acc);
	SSL_CTX_free(ctx);
	return 0;
}
コード例 #20
0
static void
gst_dtls_connection_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
{
  GstDtlsConnection *self = GST_DTLS_CONNECTION (object);
  GstDtlsAgent *agent;
  GstDtlsConnectionPrivate *priv = self->priv;
  SSL_CTX *ssl_context;

  switch (prop_id) {
    case PROP_AGENT:
      g_return_if_fail (!priv->ssl);
      agent = GST_DTLS_AGENT (g_value_get_object (value));
      g_return_if_fail (GST_IS_DTLS_AGENT (agent));

      ssl_context = _gst_dtls_agent_peek_context (agent);

      priv->ssl = SSL_new (ssl_context);
      g_return_if_fail (priv->ssl);

      priv->bio = BIO_new (BIO_s_gst_dtls_connection ());
      g_return_if_fail (priv->bio);

      BIO_set_data (priv->bio, self);
      SSL_set_bio (priv->ssl, priv->bio, priv->bio);

      SSL_set_verify (priv->ssl,
          SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
          openssl_verify_callback);
      SSL_set_ex_data (priv->ssl, connection_ex_index, self);

      log_state (self, "connection created");
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
  }
}
コード例 #21
0
ファイル: client.c プロジェクト: yku/openssl_example
int main(int argc, char **argv)
{
    BIO *conn;
    SSL *ssl;
    SSL_CTX *ctx;

    init_openssl();
    seed_prng(64);

    ctx = setup_client_ctx();

    conn = BIO_new_connect(SERVER ":" PORT);
    if(!conn)
        log_err("Failed create bio connection");

    if(BIO_do_connect(conn) <= 0)
        log_err("Failed connecting to remote host");

    if(!(ssl = SSL_new(ctx)))
        log_err("Error creating an SSL context.");
    SSL_set_bio(ssl, conn, conn);
    if(SSL_connect(ssl) <= 0)
        log_err("Error connecting SSL object.");

    fprintf(stderr, "Connection opened\n");
    if(do_client(ssl))
        SSL_shutdown(ssl);
    else
        SSL_clear(ssl);
    fprintf(stderr, "Connection closed\n");

    //BIO_free(conn);
    SSL_free(ssl);
    SSL_CTX_free(ctx);
    return 0;
}
コード例 #22
0
ファイル: Connection.cpp プロジェクト: 3Nigma/frayon
Connection::Connection(Context& ctx, std::ios& ios, OpenMode omode)
: _ios(&ios)
, _connected(false)
, _in(0)
, _out(0)
, _ssl(0)
{
    // Create the SSL objects
    _in  = BIO_new( BIO_s_mem() );
    _out = BIO_new( BIO_s_mem() );
    _ssl = SSL_new( ctx.impl()->ctx() );

    // Connect the BIO
    BIO_set_nbio(_in, 1);
    BIO_set_nbio(_out, 1);
    SSL_set_bio(_ssl, _in, _out);

    if(omode == Accept)
        SSL_set_accept_state(_ssl);
    else
        SSL_set_connect_state(_ssl);

    assert(_ssl);
}
コード例 #23
0
R_API RSocket *r_socket_accept(RSocket *s) {
	RSocket *sock;
	socklen_t salen = sizeof (s->sa);
	if (!s) return NULL;
	sock = R_NEW (RSocket);
	if (!sock) return NULL;
	//signal (SIGPIPE, SIG_DFL);
	sock->fd = accept (s->fd, (struct sockaddr *)&s->sa, &salen);
	if (sock->fd == -1) {
		r_sys_perror ("accept");
		free (sock);
		return NULL;
	}
#if HAVE_LIB_SSL
	sock->is_ssl = s->is_ssl;
	if (sock->is_ssl) {
		sock->sfd = NULL;
		sock->ctx = NULL;
		sock->bio = NULL;
		BIO *sbio = BIO_new_socket (sock->fd, BIO_NOCLOSE);
		sock->sfd = SSL_new (s->ctx);
		SSL_set_bio (sock->sfd, sbio, sbio);
		if (SSL_accept (sock->sfd) <= 0) {
			r_socket_free (sock);
			return NULL;
		}
		sock->bio = BIO_new (BIO_f_buffer ());
		sbio = BIO_new (BIO_f_ssl ());
		BIO_set_ssl (sbio, sock->sfd, BIO_CLOSE);
		BIO_push (sock->bio, sbio);
	}
#else
	sock->is_ssl = 0;
#endif
	return sock;
}
コード例 #24
0
ファイル: ssl_common.c プロジェクト: Demotix/couchnode
/******************************************************************************
 ******************************************************************************
 ** Common Routines for lcbio_TABLE Emulation                                **
 ******************************************************************************
 ******************************************************************************/
void
iotssl_init_common(lcbio_XSSL *xs, lcbio_TABLE *orig, SSL_CTX *sctx)
{
    lcbio_TABLE *base = &xs->base_;
    xs->iops_dummy_ = calloc(1, sizeof(*xs->iops_dummy_));
    xs->iops_dummy_->v.v0.cookie = xs;
    xs->orig = orig;
    base->model = xs->orig->model;
    base->p = xs->iops_dummy_;
    base->refcount = 1;
    base->loop.start = loop_run;
    base->loop.stop = loop_stop;
    base->timer.create = create_timer;
    base->timer.destroy = destroy_timer;
    base->timer.schedule = schedule_timer;
    base->timer.cancel = cancel_timer;

    if (orig->model == LCB_IOMODEL_EVENT) {
        base->u_io.v0.ev.create = create_event;
        base->u_io.v0.ev.destroy = destroy_event;
    }

    lcbio_table_ref(xs->orig);

    xs->error = 0;
    xs->ssl = SSL_new(sctx);

    xs->rbio = BIO_new(BIO_s_mem());
    xs->wbio = BIO_new(BIO_s_mem());

    SSL_set_bio(xs->ssl, xs->rbio, xs->wbio);
    SSL_set_read_ahead(xs->ssl, 0);

    /* Indicate that we are a client */
    SSL_set_connect_state(xs->ssl);
}
コード例 #25
0
ファイル: sm.c プロジェクト: 119120119/node
int state_machine_set_SSL(state_machine_t * machine, SSL *ssl, int is_server)
{
    if (machine->ssl)
        /* Shouldn't ever be set twice */
        abort();
    machine->ssl = ssl;
    /* Create the BIOs to handle the dirty side of the SSL */
    if ((machine->bio_intossl = BIO_new(BIO_s_mem())) == NULL)
        abort();
    if ((machine->bio_fromssl = BIO_new(BIO_s_mem())) == NULL)
        abort();
    /* Hook up the BIOs on the dirty side of the SSL */
    SSL_set_bio(machine->ssl, machine->bio_intossl, machine->bio_fromssl);
    if (is_server)
        SSL_set_accept_state(machine->ssl);
    else
        SSL_set_connect_state(machine->ssl);
    /*
     * If we're the first one to generate traffic - do it now otherwise we go
     * into the next select empty-handed and our peer will not send data but
     * will similarly wait for us.
     */
    return state_machine_churn(machine);
}
コード例 #26
0
ファイル: qssl.cpp プロジェクト: tuxmaster/QSSL
void QFrankSSL::K_MitServerVerbunden()
{
	if(K_SSLStruktur==NULL)
	{
#ifndef QT_NO_DEBUG
		qWarning("QFrankSSL Verbindung mit dem Server hergestellt: Keine SSL Strukur");
#endif
		K_AllesZuruecksetzen();
		emit SSLFehler(K_KeineSSLStrukturText);
		return;
	}	
#ifndef QT_NO_DEBUG
	qDebug("QFrankSSL Verbindung mit dem Server hergestellt. Baue OpenSSL auf");
#endif
	K_Empfangspuffer=BIO_new(BIO_s_mem());
	K_Sendepuffer=BIO_new(BIO_s_mem());
	SSL_set_bio(K_SSLStruktur, K_Empfangspuffer, K_Sendepuffer);
	SSL_set_connect_state(K_SSLStruktur);
	K_Verbindungsstatus=QFrankSSL::VERBINDEN;
	// SSL Verbindung erstellen
	SSL_connect(K_SSLStruktur);
	if(K_MussWasGesendetWerden())
			K_DatenSenden();
}
コード例 #27
0
ファイル: client.c プロジェクト: 5ouya/raspC
int
lws_client_socket_service(struct lws_context *context, struct lws *wsi,
			  struct lws_pollfd *pollfd)
{
	struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
	char *p = (char *)&pt->serv_buf[0];
	char *sb = p;
	unsigned char c;
	int n, len;

	switch (wsi->mode) {

	case LWSCM_WSCL_WAITING_CONNECT:

		/*
		 * we are under PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE
		 * timeout protection set in client-handshake.c
		 */

		if (!lws_client_connect_2(wsi)) {
			/* closed */
			lwsl_client("closed\n");
			return -1;
		}

		/* either still pending connection, or changed mode */
		return 0;

	case LWSCM_WSCL_WAITING_PROXY_REPLY:

		/* handle proxy hung up on us */

		if (pollfd->revents & LWS_POLLHUP) {

			lwsl_warn("Proxy connection %p (fd=%d) dead\n",
				  (void *)wsi, pollfd->fd);

			lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
			return 0;
		}

		n = recv(wsi->sock, sb, LWS_MAX_SOCKET_IO_BUF, 0);
		if (n < 0) {
			if (LWS_ERRNO == LWS_EAGAIN) {
				lwsl_debug("Proxy read returned EAGAIN... retrying\n");
				return 0;
			}

			lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
			lwsl_err("ERROR reading from proxy socket\n");
			return 0;
		}

		pt->serv_buf[13] = '\0';
		if (strcmp(sb, "HTTP/1.0 200 ") &&
		    strcmp(sb, "HTTP/1.1 200 ")) {
			lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
			lwsl_err("ERROR proxy: %s\n", sb);
			return 0;
		}

		/* clear his proxy connection timeout */

		lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);

		/* fallthru */

	case LWSCM_WSCL_ISSUE_HANDSHAKE:

		/*
		 * we are under PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE
		 * timeout protection set in client-handshake.c
		 *
		 * take care of our lws_callback_on_writable
		 * happening at a time when there's no real connection yet
		 */
		if (lws_change_pollfd(wsi, LWS_POLLOUT, 0))
			return -1;
		lws_libev_io(wsi, LWS_EV_STOP | LWS_EV_WRITE);

#ifdef LWS_OPENSSL_SUPPORT
		/* we can retry this... just cook the SSL BIO the first time */

		if (wsi->use_ssl && !wsi->ssl) {
#if defined(CYASSL_SNI_HOST_NAME) || defined(WOLFSSL_SNI_HOST_NAME) || defined(SSL_CTRL_SET_TLSEXT_HOSTNAME)
			const char *hostname = lws_hdr_simple_ptr(wsi,
						_WSI_TOKEN_CLIENT_HOST);
#endif

			wsi->ssl = SSL_new(context->ssl_client_ctx);
#ifndef USE_WOLFSSL
			SSL_set_mode(wsi->ssl,
					SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
#endif
			/*
			 * use server name indication (SNI), if supported,
			 * when establishing connection
			 */
#ifdef USE_WOLFSSL
#ifdef USE_OLD_CYASSL
#ifdef CYASSL_SNI_HOST_NAME
			CyaSSL_UseSNI(wsi->ssl, CYASSL_SNI_HOST_NAME,
				hostname, strlen(hostname));
#endif
#else
#ifdef WOLFSSL_SNI_HOST_NAME
			wolfSSL_UseSNI(wsi->ssl, WOLFSSL_SNI_HOST_NAME,
				hostname, strlen(hostname));
#endif
#endif
#else
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
			SSL_set_tlsext_host_name(wsi->ssl, hostname);
#endif
#endif

#ifdef USE_WOLFSSL
			/*
			 * wolfSSL/CyaSSL does certificate verification differently
			 * from OpenSSL.
			 * If we should ignore the certificate, we need to set
			 * this before SSL_new and SSL_connect is called.
			 * Otherwise the connect will simply fail with error
			 * code -155
			 */
#ifdef USE_OLD_CYASSL
			if (wsi->use_ssl == 2)
				CyaSSL_set_verify(wsi->ssl,
							SSL_VERIFY_NONE, NULL);
#else
			if (wsi->use_ssl == 2)
				wolfSSL_set_verify(wsi->ssl,
							SSL_VERIFY_NONE, NULL);
#endif
#endif /* USE_WOLFSSL */

			wsi->client_bio =
				BIO_new_socket(wsi->sock, BIO_NOCLOSE);
			SSL_set_bio(wsi->ssl, wsi->client_bio, wsi->client_bio);

#ifdef USE_WOLFSSL
#ifdef USE_OLD_CYASSL
			CyaSSL_set_using_nonblock(wsi->ssl, 1);
#else
			wolfSSL_set_using_nonblock(wsi->ssl, 1);
#endif
#else
			BIO_set_nbio(wsi->client_bio, 1); /* nonblocking */
#endif

			SSL_set_ex_data(wsi->ssl,
					openssl_websocket_private_data_index,
								       context);
		}

		if (wsi->use_ssl) {
			lws_latency_pre(context, wsi);
			n = SSL_connect(wsi->ssl);
			lws_latency(context, wsi,
			  "SSL_connect LWSCM_WSCL_ISSUE_HANDSHAKE", n, n > 0);

			if (n < 0) {
				n = SSL_get_error(wsi->ssl, n);

				if (n == SSL_ERROR_WANT_READ)
					goto some_wait;

				if (n == SSL_ERROR_WANT_WRITE) {
					/*
					 * wants us to retry connect due to
					 * state of the underlying ssl layer...
					 * but since it may be stalled on
					 * blocked write, no incoming data may
					 * arrive to trigger the retry.
					 * Force (possibly many times if the SSL
					 * state persists in returning the
					 * condition code, but other sockets
					 * are getting serviced inbetweentimes)
					 * us to get called back when writable.
					 */
					lwsl_info("%s: WANT_WRITE... retrying\n", __func__);
					lws_callback_on_writable(wsi);
some_wait:
					wsi->mode = LWSCM_WSCL_WAITING_SSL;

					return 0; /* no error */
				}
				n = -1;
			}

			if (n <= 0) {
				/*
				 * retry if new data comes until we
				 * run into the connection timeout or win
				 */
				n = ERR_get_error();
				if (n != SSL_ERROR_NONE) {
					lwsl_err("SSL connect error %lu: %s\n",
						n, ERR_error_string(n, sb));
					return 0;
				}
			}
		} else
			wsi->ssl = NULL;

		/* fallthru */

	case LWSCM_WSCL_WAITING_SSL:

		if (wsi->use_ssl) {
			if (wsi->mode == LWSCM_WSCL_WAITING_SSL) {
				lws_latency_pre(context, wsi);
				n = SSL_connect(wsi->ssl);
				lws_latency(context, wsi,
					    "SSL_connect LWSCM_WSCL_WAITING_SSL",
					    n, n > 0);

				if (n < 0) {
					n = SSL_get_error(wsi->ssl, n);

					if (n == SSL_ERROR_WANT_READ)
						goto some_wait;

					if (n == SSL_ERROR_WANT_WRITE) {
						/*
						 * wants us to retry connect due to
						 * state of the underlying ssl layer...
						 * but since it may be stalled on
						 * blocked write, no incoming data may
						 * arrive to trigger the retry.
						 * Force (possibly many times if the SSL
						 * state persists in returning the
						 * condition code, but other sockets
						 * are getting serviced inbetweentimes)
						 * us to get called back when writable.
						 */
						lwsl_info("SSL_connect WANT_WRITE... retrying\n");
						lws_callback_on_writable(wsi);

						goto some_wait;
					}
					n = -1;
				}

				if (n <= 0) {
					/*
					 * retry if new data comes until we
					 * run into the connection timeout or win
					 */
					n = ERR_get_error();
					if (n != SSL_ERROR_NONE) {
						lwsl_err("SSL connect error %lu: %s\n",
							 n, ERR_error_string(n, sb));
						return 0;
					}
				}
			}

			#ifndef USE_WOLFSSL
			/*
			 * See comment above about wolfSSL certificate
			 * verification
			 */
			lws_latency_pre(context, wsi);
			n = SSL_get_verify_result(wsi->ssl);
			lws_latency(context, wsi,
				"SSL_get_verify_result LWS_CONNMODE..HANDSHAKE",
								      n, n > 0);

			if (n != X509_V_OK) {
				if ((n == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ||
				     n == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) && wsi->use_ssl == 2) {
					lwsl_notice("accepting self-signed certificate\n");
				} else {
					lwsl_err("server's cert didn't look good, X509_V_ERR = %d: %s\n",
						 n, ERR_error_string(n, sb));
					lws_close_free_wsi(wsi,
						LWS_CLOSE_STATUS_NOSTATUS);
					return 0;
				}
			}
#endif /* USE_WOLFSSL */
		} else
			wsi->ssl = NULL;
#endif

		wsi->mode = LWSCM_WSCL_ISSUE_HANDSHAKE2;
		lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND,
				AWAITING_TIMEOUT);

		/* fallthru */

	case LWSCM_WSCL_ISSUE_HANDSHAKE2:
		p = lws_generate_client_handshake(wsi, p);
		if (p == NULL) {
			lwsl_err("Failed to generate handshake for client\n");
			lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
			return 0;
		}

		/* send our request to the server */

		lws_latency_pre(context, wsi);

		n = lws_ssl_capable_write(wsi, (unsigned char *)sb, p - sb);
		lws_latency(context, wsi, "send lws_issue_raw", n,
			    n == p - sb);
		switch (n) {
		case LWS_SSL_CAPABLE_ERROR:
			lwsl_debug("ERROR writing to client socket\n");
			lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
			return 0;
		case LWS_SSL_CAPABLE_MORE_SERVICE:
			lws_callback_on_writable(wsi);
			break;
		}

		wsi->u.hdr.parser_state = WSI_TOKEN_NAME_PART;
		wsi->u.hdr.lextable_pos = 0;
		wsi->mode = LWSCM_WSCL_WAITING_SERVER_REPLY;
		lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE,
				AWAITING_TIMEOUT);
		break;

	case LWSCM_WSCL_WAITING_SERVER_REPLY:

		/* handle server hung up on us */

		if (pollfd->revents & LWS_POLLHUP) {

			lwsl_debug("Server connection %p (fd=%d) dead\n",
				(void *)wsi, pollfd->fd);

			goto bail3;
		}

		if (!(pollfd->revents & LWS_POLLIN))
			break;

		/* interpret the server response */

		/*
		 *  HTTP/1.1 101 Switching Protocols
		 *  Upgrade: websocket
		 *  Connection: Upgrade
		 *  Sec-WebSocket-Accept: me89jWimTRKTWwrS3aRrL53YZSo=
		 *  Sec-WebSocket-Nonce: AQIDBAUGBwgJCgsMDQ4PEC==
		 *  Sec-WebSocket-Protocol: chat
		 */

		/*
		 * we have to take some care here to only take from the
		 * socket bytewise.  The browser may (and has been seen to
		 * in the case that onopen() performs websocket traffic)
		 * coalesce both handshake response and websocket traffic
		 * in one packet, since at that point the connection is
		 * definitively ready from browser pov.
		 */
		len = 1;
		while (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE &&
		       len > 0) {
			n = lws_ssl_capable_read(wsi, &c, 1);
			lws_latency(context, wsi, "send lws_issue_raw", n,
				    n == 1);
			switch (n) {
			case 0:
			case LWS_SSL_CAPABLE_ERROR:
				goto bail3;
			case LWS_SSL_CAPABLE_MORE_SERVICE:
				return 0;
			}

			if (lws_parse(wsi, c)) {
				lwsl_warn("problems parsing header\n");
				goto bail3;
			}
		}

		/*
		 * hs may also be coming in multiple packets, there is a 5-sec
		 * libwebsocket timeout still active here too, so if parsing did
		 * not complete just wait for next packet coming in this state
		 */

		if (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE)
			break;

		/*
		 * otherwise deal with the handshake.  If there's any
		 * packet traffic already arrived we'll trigger poll() again
		 * right away and deal with it that way
		 */

		return lws_client_interpret_server_handshake(wsi);

bail3:
		lwsl_info("closing conn at LWS_CONNMODE...SERVER_REPLY\n");
		lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
		return -1;

	case LWSCM_WSCL_WAITING_EXTENSION_CONNECT:
		lwsl_ext("LWSCM_WSCL_WAITING_EXTENSION_CONNECT\n");
		break;

	case LWSCM_WSCL_PENDING_CANDIDATE_CHILD:
		lwsl_ext("LWSCM_WSCL_PENDING_CANDIDATE_CHILD\n");
		break;
	default:
		break;
	}

	return 0;
}
コード例 #28
0
ファイル: iostream-openssl.c プロジェクト: bdraco/dovecot
static int
openssl_iostream_create(struct ssl_iostream_context *ctx, const char *source,
                        const struct ssl_iostream_settings *set,
                        struct istream **input, struct ostream **output,
                        struct ssl_iostream **iostream_r)
{
    struct ssl_iostream *ssl_io;
    SSL *ssl;
    BIO *bio_int, *bio_ext;
    int ret;

    ssl = SSL_new(ctx->ssl_ctx);
    if (ssl == NULL) {
        i_error("SSL_new() failed: %s", openssl_iostream_error());
        return -1;
    }

    /* BIO pairs use default buffer sizes (17 kB in OpenSSL 0.9.8e).
       Each of the BIOs have one "write buffer". BIO_write() copies data
       to them, while BIO_read() reads from the other BIO's write buffer
       into the given buffer. The bio_int is used by OpenSSL and bio_ext
       is used by this library. */
    if (BIO_new_bio_pair(&bio_int, 0, &bio_ext, 0) != 1) {
        i_error("BIO_new_bio_pair() failed: %s",
                openssl_iostream_error());
        SSL_free(ssl);
        return -1;
    }

    ssl_io = i_new(struct ssl_iostream, 1);
    ssl_io->refcount = 1;
    ssl_io->ctx = ctx;
    ssl_io->ssl = ssl;
    ssl_io->bio_ext = bio_ext;
    ssl_io->plain_input = *input;
    ssl_io->plain_output = *output;
    ssl_io->source = i_strdup(source);
    /* bio_int will be freed by SSL_free() */
    SSL_set_bio(ssl_io->ssl, bio_int, bio_int);
    SSL_set_ex_data(ssl_io->ssl, dovecot_ssl_extdata_index, ssl_io);

    T_BEGIN {
        ret = openssl_iostream_set(ssl_io, set);
    } T_END;
    if (ret < 0) {
        openssl_iostream_free(ssl_io);
        return -1;
    }

    o_stream_uncork(ssl_io->plain_output);

    *input = openssl_i_stream_create_ssl(ssl_io);
    *output = openssl_o_stream_create_ssl(ssl_io);
    i_stream_set_name(*input, t_strconcat("SSL ",
                                          i_stream_get_name(ssl_io->plain_input), NULL));
    o_stream_set_name(*output, t_strconcat("SSL ",
                                           o_stream_get_name(ssl_io->plain_output), NULL));

    if (ssl_io->plain_output->real_stream->error_handling_disabled)
        o_stream_set_no_error_handling(*output, TRUE);

    ssl_io->ssl_output = *output;
    *iostream_r = ssl_io;
    return 0;
}
コード例 #29
0
ファイル: s_client.c プロジェクト: peterlingoal/openssl
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);
}
コード例 #30
0
ファイル: anet.c プロジェクト: bbroerman30/ssl-redis
int anetSSLAccept( char *err, int fd, struct redisServer server, anetSSLConnection *ctn) {

  ctn->sd = -1;
  ctn->ctx = NULL;
  ctn->ssl = NULL;
  ctn->bio = NULL;
  ctn->conn_str = NULL;

  if( fd == -1 ) {
    return ANET_ERR;
  }
  ctn->sd = fd;

  // Create the SSL Context ( server method )
  SSL_CTX* ctx = SSL_CTX_new(TLSv1_1_server_method());
  ctn->ctx = ctx;

   /*
     You will need to generate certificates, the root certificate authority file, the private key file, and the random file yourself.
     Google will help. The openssl executable created when you compiled OpenSSL can do all this.
   */

    // Load trusted root authorities
    SSL_CTX_load_verify_locations(ctx, server.ssl_root_file, server.ssl_root_dir);

    // Sets the default certificate password callback function. Read more under the Certificate Verification section.
    if( NULL != server.ssl_srvr_cert_passwd ) {
      global_ssl_cert_password = server.ssl_srvr_cert_passwd;
      SSL_CTX_set_default_passwd_cb(ctx, password_callback);
    }

    // Sets the certificate file to be used.
    SSL_CTX_use_certificate_file(ctx, server.ssl_cert_file, SSL_FILETYPE_PEM);

    // Sets the private key file to be used.
    SSL_CTX_use_PrivateKey_file(ctx, server.ssl_pk_file, SSL_FILETYPE_PEM);

    // Set the maximum depth to be used verifying certificates
    // Due to a bug, this is not enforced. The verify callback must enforce it.
    SSL_CTX_set_verify_depth(ctx, 1);

    // Set the certificate verification callback.
    SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER /* | SSL_VERIFY_FAIL_IF_NO_PEER_CERT */, verify_callback);

    /*
      End certificate verification setup.
    */

    // We need to load the Diffie-Hellman key exchange parameters.
    // First load dh1024.pem (you DID create it, didn't you?)
    BIO* bio = BIO_new_file(server.ssl_dhk_file, "r");

    // Did we get a handle to the file?
    if (bio == NULL) {
      anetSetError(err, "SSL Accept: Couldn't open DH param file");
      anetCleanupSSL( ctn);
      return ANET_ERR;
    }

    // Read in the DH params.
    DH* ret = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);

    // Free up the BIO object.
    BIO_free(bio);

    // Set up our SSL_CTX to use the DH parameters.
    if (SSL_CTX_set_tmp_dh(ctx, ret) < 0) {
      anetSetError(err, "SSL Accept: Couldn't set DH parameters");
      anetCleanupSSL( ctn );
      return ANET_ERR;
    }

    // Now we need to generate a RSA key for use.
    // 1024-bit key. If you want to use something stronger, go ahead but it must be a power of 2. Upper limit should be 4096.
    RSA* rsa = RSA_generate_key(1024, RSA_F4, NULL, NULL);

    // Set up our SSL_CTX to use the generated RSA key.
    if (!SSL_CTX_set_tmp_rsa(ctx, rsa)) {
      anetSetError(err, "SSL Accept: Couldn't set RSA Key");
      anetCleanupSSL( ctn );
      return ANET_ERR;
    }

    // Free up the RSA structure.
    RSA_free(rsa);

    /*
      For some reason many tutorials don't include this...

      Servers must specify the ciphers they can use, to verify that both the client and the server can use the same cipher.
      If you don't do this, you'll get errors relating to "no shared ciphers" or "no common ciphers".

      Use all ciphers with the exception of: ones with anonymous Diffie-Hellman, low-strength ciphers, export ciphers, md5 hashing. Ordered from strongest to weakest.
      Note that as ciphers become broken, it will be necessary to change the available cipher list to remain secure.
    */

    if( NULL == server.ssl_srvr_cipher_list || 0 == strlen(server.ssl_srvr_cipher_list) )
        SSL_CTX_set_cipher_list(ctx, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
    else
    	SSL_CTX_set_cipher_list(ctx, server.ssl_srvr_cipher_list);

    // Set up our SSL object as before
    SSL* ssl = SSL_new(ctx);
    ctn->ssl = ssl;
    
    // Set up our BIO object to use the client socket
    BIO* sslclient = BIO_new_socket(fd, BIO_NOCLOSE);
    ctn->bio = sslclient;

    // Set up our SSL object to use the BIO.
    SSL_set_bio(ssl, sslclient, sslclient);

    // Do SSL handshaking.
    int r = SSL_accept(ssl);

    // Something failed. Print out all the error information, since all of it may be relevant to the problem.
    if (r != 1) {
      char error[65535];

      ERR_error_string_n(ERR_get_error(), error, 65535);

      anetSetError(err, "SSL Accept: Error %d - %s ", SSL_get_error(ssl, r), error );

      // We failed to accept this client connection.
      // Ideally here you'll drop the connection and continue on.
      anetCleanupSSL( ctn );
      return ANET_ERR;
    }

    /* Verify certificate */
    if (SSL_get_verify_result(ssl) != X509_V_OK) {
      anetSetError(err, "SSL Accept: Certificate failed verification!");
      // Ideally here you'll close this connection and continue on.
      anetCleanupSSL( ctn );
      return ANET_ERR;
    }

    return ANET_OK;
}