Ejemplo n.º 1
3
SSL_Connection *ssl_connect(const char *host, int port, const char *certfile, const char *keyfile, const char *capath) 
{
    int err;

    SSL_Connection *sslcon = NULL;
    sslcon = (SSL_Connection *)malloc(sizeof(SSL_Connection));
    if(sslcon == NULL)
    {
        log_error("Could not allocate memory for SSL Connection");
        return NULL;
    }

    /* Load encryption & hashing algorithms for the SSL program */
    SSL_library_init();
 
    /* Load the error strings for SSL & CRYPTO APIs */
    SSL_load_error_strings();
 
    /* Create an SSL_METHOD structure (choose an SSL/TLS protocol version) */
    sslcon->meth = SSLv3_method();
 
    /* Create an SSL_CTX structure */
    sslcon->ctx = SSL_CTX_new(sslcon->meth);                        
    if(!sslcon->ctx)
    {
        log_error("Could not get SSL Context\n");
        return NULL;
    }

    /* Load the CA from the Path */
    if(SSL_CTX_load_verify_locations(sslcon->ctx, NULL, capath) <= 0)
    {
        /* Handle failed load here */
        log_error("Failed to set CA location...\n");
        ERR_print_errors_fp(stderr);
        return NULL;
    }

    /* Load the client certificate into the SSL_CTX structure */
    if (SSL_CTX_use_certificate_file(sslcon->ctx, certfile, SSL_FILETYPE_PEM) <= 0) {
        log_error("Cannot use Certificate File\n");
        ERR_print_errors_fp(stderr);
        return NULL;
    }
 
    /* Load the private-key corresponding to the client certificate */
    if (SSL_CTX_use_PrivateKey_file(sslcon->ctx, keyfile, SSL_FILETYPE_PEM) <= 0) {
        log_error("Cannot use Private Key\n");
        ERR_print_errors_fp(stderr);
        return NULL;
    }
 
    /* Check if the client certificate and private-key matches */
    if (!SSL_CTX_check_private_key(sslcon->ctx)) {
        log_error("Private key does not match the certificate public key\n");
        return NULL;
    }
 
    /* Set up a TCP socket */
    sslcon->sock = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);       
    if(sslcon->sock == -1)
    {
        log_error("Could not get Socket\n");
		return NULL;
    }
 
    memset (&sslcon->server_addr, '\0', sizeof(sslcon->server_addr));
    sslcon->server_addr.sin_family      = AF_INET;
    sslcon->server_addr.sin_port        = htons(port);       /* Server Port number */
    sslcon->host_info = gethostbyname(host);
    if(sslcon->host_info)
    {
        /* Take the first IP */
        struct in_addr *address = (struct in_addr*)sslcon->host_info->h_addr_list[0];
        sslcon->server_addr.sin_addr.s_addr = inet_addr(inet_ntoa(*address)); /* Server IP */
    }
    else
    {
        log_error("Could not resolve hostname %s\n", host);
        return NULL;
    }

    /* Establish a TCP/IP connection to the SSL client */
    err = connect(sslcon->sock, (struct sockaddr*) &sslcon->server_addr, sizeof(sslcon->server_addr)); 
    if(err == -1)
    {
        log_error("Could not connect\n");
        return NULL;
    }    

    /* An SSL structure is created */
    sslcon->ssl = SSL_new(sslcon->ctx);
    if(!sslcon->ssl)
    {
        log_error("Could not get SSL Socket\n");
        return NULL;
    }    
 
    /* Assign the socket into the SSL structure (SSL and socket without BIO) */
    SSL_set_fd(sslcon->ssl, sslcon->sock);
 
    /* Perform SSL Handshake on the SSL client */
    err = SSL_connect(sslcon->ssl);
    if(err <= 0)
    {
        log_error("Could not connect to SSL Server\n");
        return NULL;
    }

    return sslcon;
}
Ejemplo n.º 2
0
HybridSslConnection*
hybrid_ssl_connect_with_fd(gint sk,    ssl_callback func, gpointer user_data)
{
    gint                 l;
    SSL                 *ssl;
    BIO                 *sbio;
    BIO                 *buf_io;
    BIO                 *ssl_bio;
    SSL_CTX             *ssl_ctx;
    HybridSslConnection *ssl_conn;

    SSL_load_error_strings();
    SSL_library_init();

    if (!(ssl_ctx = SSL_CTX_new(TLSv1_client_method()))) {

        hybrid_debug_error("ssl", "initialize SSL CTX: %s",
                           ERR_reason_error_string(ERR_get_error()));
        return NULL;
    }

    if (!(ssl = ssl_new_with_certs(ssl_ctx))) {
        return NULL;
    }

    if (!SSL_set_fd(ssl, sk)) {
        hybrid_debug_error("ssl", "add ssl to tcp socket:%s",
                           ERR_reason_error_string(ERR_get_error()));
        return NULL;
    }

    sbio = BIO_new(BIO_s_socket());
    BIO_set_fd(sbio, sk, BIO_NOCLOSE);
    SSL_set_bio(ssl, sbio, sbio);

    SSL_set_connect_state(ssl);

 reconnect:
    l = SSL_connect(ssl);

    switch (SSL_get_error(ssl, l)) {
    case SSL_ERROR_NONE:
        goto ssl_conn_sk_ok;
    case SSL_ERROR_WANT_WRITE:
    case SSL_ERROR_WANT_READ:
        usleep(100);
        goto reconnect;
    case SSL_ERROR_SYSCALL:
    case SSL_ERROR_WANT_X509_LOOKUP:
    case SSL_ERROR_ZERO_RETURN:
    case SSL_ERROR_SSL:
    default:
        hybrid_debug_error("ssl", "ssl hand-shake error:%s",
                           ERR_reason_error_string(ERR_get_error()));
        return NULL;
    }

ssl_conn_sk_ok:

    if (HYBRID_OK != ssl_verify_certs(ssl)) {
        return NULL;
    }

    SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);

    buf_io = BIO_new(BIO_f_buffer());
    ssl_bio = BIO_new(BIO_f_ssl());

    BIO_set_ssl(ssl_bio, ssl, BIO_NOCLOSE);
    BIO_push(buf_io, ssl_bio);

    ssl_conn = g_new0(HybridSslConnection, 1);

    ssl_conn->sk        = sk;
    ssl_conn->ssl       = ssl;
    ssl_conn->ssl_ctx   = ssl_ctx;
    ssl_conn->conn_cb   = func;
    ssl_conn->conn_data = user_data;
    ssl_conn->rbio      = buf_io;
    ssl_conn->wbio      = sbio;

    if (func) {
        func(ssl_conn, user_data);
    }

    return ssl_conn;
}
Ejemplo n.º 3
0
status_t SSO::SSLSend(const char *host, HTTPFormatter *send, HTTPFormatter **recv) {
	int err = B_OK;
	int sd;
	struct sockaddr_in sa;
	struct hostent *hp;
	SSL_CTX *ctx;
	SSL *ssl;
	char buffer[1024];
	SSL_METHOD *meth;

	SSL_load_error_strings();
	SSLeay_add_ssl_algorithms();
	meth = SSLv23_client_method();
	ctx = SSL_CTX_new (meth);
	CHK_NULL(ctx);
	SSL_CTX_set_options(ctx, SSL_OP_ALL);

	/* ----------------------------------------------- */
	/* Create a socket and connect to server using normal socket calls. */
	sd = socket (AF_INET, SOCK_STREAM, 0);
	CHK_ERR(sd, "socket");

	// clear sa
	memset (&sa, '\0', sizeof(sa));
	
	// get address
	if ((hp= gethostbyname(host)) == NULL) { 
		sa.sin_addr.s_addr = inet_addr (host);   /* Server IP */
	} else {
		memcpy((char *)&sa.sin_addr,hp->h_addr,hp->h_length); /* set address */
	};
	
	sa.sin_family = AF_INET;
	sa.sin_port = htons(443);    /* Server Port number */
	
	err = connect(sd, (struct sockaddr*) &sa, sizeof(sa));
	CHK_ERR(err, "connect");
	
	/* ----------------------------------------------- */
	/* Now we have TCP conncetion. Start SSL negotiation. */
  
	ssl = SSL_new (ctx);                         CHK_NULL(ssl);    
	if (SSL_set_fd(ssl, sd) == 0) {
		LOG(kProtocolName, liDebug, "C %lX: SSL Error setting fd", this);
		return -1;
	};
	
    SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL);
	SSL_set_connect_state(ssl);
	
	err = SSL_connect (ssl);
	CHK_SSL(err);
	
	/* --------------------------------------------------- */
	/* DATA EXCHANGE - Send a message and receive a reply. */

	err = SSL_write(ssl, send->Flatten(), send->Length());
	CHK_SSL(err);
	
	if (err <= 0) {
		LOG(kProtocolName, liDebug, "C %lX: SSL Error writing. Err: %ld", this, SSL_get_error(ssl, err));
	};
	
	BString data;
	int received = 0;
	while (err > 0) {
		err = SSL_read(ssl, buffer, sizeof(buffer));
		CHK_SSL(err);
		if (err > 0) {
			received += err;
			data.Append(buffer, err);
			memset(buffer, 0, sizeof(buffer));
		};
	};

	*recv = new HTTPFormatter(data.String(), data.Length());
	LOG(kProtocolName, liDebug, "C %lX: Got %d chars", this, received);
	SSL_shutdown (ssl);  /* send SSL/TLS close_notify */
	
	/* Clean up. */
	close (sd);
	SSL_free (ssl);
	SSL_CTX_free (ctx);
	
	return received;
};
Ejemplo n.º 4
0
Archivo: imap-send.c Proyecto: 0369/git
static int ssl_socket_connect(struct imap_socket *sock, int use_tls_only, int verify)
{
#if (OPENSSL_VERSION_NUMBER >= 0x10000000L)
	const SSL_METHOD *meth;
#else
	SSL_METHOD *meth;
#endif
	SSL_CTX *ctx;
	int ret;
	X509 *cert;

	SSL_library_init();
	SSL_load_error_strings();

	if (use_tls_only)
		meth = TLSv1_method();
	else
		meth = SSLv23_method();

	if (!meth) {
		ssl_socket_perror("SSLv23_method");
		return -1;
	}

	ctx = SSL_CTX_new(meth);

	if (verify)
		SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);

	if (!SSL_CTX_set_default_verify_paths(ctx)) {
		ssl_socket_perror("SSL_CTX_set_default_verify_paths");
		return -1;
	}
	sock->ssl = SSL_new(ctx);
	if (!sock->ssl) {
		ssl_socket_perror("SSL_new");
		return -1;
	}
	if (!SSL_set_rfd(sock->ssl, sock->fd[0])) {
		ssl_socket_perror("SSL_set_rfd");
		return -1;
	}
	if (!SSL_set_wfd(sock->ssl, sock->fd[1])) {
		ssl_socket_perror("SSL_set_wfd");
		return -1;
	}

#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
	/*
	 * SNI (RFC4366)
	 * OpenSSL does not document this function, but the implementation
	 * returns 1 on success, 0 on failure after calling SSLerr().
	 */
	ret = SSL_set_tlsext_host_name(sock->ssl, server.host);
	if (ret != 1)
		warning("SSL_set_tlsext_host_name(%s) failed.", server.host);
#endif

	ret = SSL_connect(sock->ssl);
	if (ret <= 0) {
		socket_perror("SSL_connect", sock, ret);
		return -1;
	}

	if (verify) {
		/* make sure the hostname matches that of the certificate */
		cert = SSL_get_peer_certificate(sock->ssl);
		if (!cert)
			return error("unable to get peer certificate.");
		if (verify_hostname(cert, server.host) < 0)
			return -1;
	}

	return 0;
}
Ejemplo n.º 5
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)
{
	int sock = INVALID_SOCKET;
#ifndef WIN32
	int opt;
#endif
	struct addrinfo hints;
	struct addrinfo *ainfo, *rp;
	int s;
#ifdef WIN32
	uint32_t val = 1;
#endif
#ifdef WITH_TLS
	int ret;
	BIO *bio;
#endif
    
	if(!mosq || !host || !port) return MOSQ_ERR_INVAL;
    
	memset(&hints, 0, sizeof(struct addrinfo));
	hints.ai_family = PF_UNSPEC;
	hints.ai_flags = AI_ADDRCONFIG;
	hints.ai_socktype = SOCK_STREAM;
    
	s = getaddrinfo(host, NULL, &hints, &ainfo);
	if(s) return MOSQ_ERR_UNKNOWN;
    
	for(rp = ainfo; rp != NULL; rp = rp->ai_next){
		sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
		if(sock == INVALID_SOCKET) continue;
		
		if(rp->ai_family == PF_INET){
			((struct sockaddr_in *)rp->ai_addr)->sin_port = htons(port);
		}else if(rp->ai_family == PF_INET6){
			((struct sockaddr_in6 *)rp->ai_addr)->sin6_port = htons(port);
		}else{
			continue;
		}
		if(connect(sock, rp->ai_addr, rp->ai_addrlen) != -1){
			break;
		}
        
#ifdef WIN32
		errno = WSAGetLastError();
#endif
		COMPAT_CLOSE(sock);
	}
	freeaddrinfo(ainfo);
	if(!rp){
		return MOSQ_ERR_ERRNO;
	}
    
	/* Set non-blocking */
#ifndef WIN32
	opt = fcntl(sock, F_GETFL, 0);
	if(opt == -1 || fcntl(sock, F_SETFL, opt | O_NONBLOCK) == -1){
#ifdef WITH_TLS
		if(mosq->ssl){
			SSL_shutdown(mosq->ssl);
			SSL_free(mosq->ssl);
			mosq->ssl = NULL;
		}
		if(mosq->ssl_ctx){
			SSL_CTX_free(mosq->ssl_ctx);
			mosq->ssl_ctx = NULL;
		}
#endif
		COMPAT_CLOSE(sock);
		return MOSQ_ERR_ERRNO;
	}
#else
	if(ioctlsocket(sock, FIONBIO, &val)){
		errno = WSAGetLastError();
#ifdef WITH_TLS
		if(mosq->ssl){
			SSL_shutdown(mosq->ssl);
			SSL_free(mosq->ssl);
			mosq->ssl = NULL;
		}
		if(mosq->ssl_ctx){
			SSL_CTX_free(mosq->ssl_ctx);
			mosq->ssl_ctx = NULL;
		}
#endif
		COMPAT_CLOSE(sock);
		return MOSQ_ERR_ERRNO;
	}
#endif
    
#ifdef WITH_TLS
	if(mosq->tls_cafile || mosq->tls_capath || mosq->tls_psk){
		if(!mosq->tls_version || !strcmp(mosq->tls_version, "tlsv1")){
			mosq->ssl_ctx = SSL_CTX_new(TLSv1_client_method());
			if(!mosq->ssl_ctx){
				_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to create TLS context.");
				COMPAT_CLOSE(sock);
				return MOSQ_ERR_TLS;
			}
		}else{
			COMPAT_CLOSE(sock);
			return MOSQ_ERR_INVAL;
		}
        
#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, NULL);
			}
            
			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_file(mosq->ssl_ctx, mosq->tls_certfile, SSL_FILETYPE_PEM);
				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 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);
        
		ret = SSL_connect(mosq->ssl);
		if(ret != 1){
			ret = SSL_get_error(mosq->ssl, ret);
			if(ret == SSL_ERROR_WANT_READ){
				mosq->want_read = true;
			}else if(ret == SSL_ERROR_WANT_WRITE){
				mosq->want_write = true;
			}else{
				COMPAT_CLOSE(sock);
				return MOSQ_ERR_TLS;
			}
		}
	}
#endif
    
	mosq->sock = sock;
    
	return MOSQ_ERR_SUCCESS;
}
Ejemplo n.º 6
0
BOOL CSSLTcpSocket::SSLConnect(LPCSTR pszTargetIP,USHORT nTargetPort)
{
	BOOL bRes = Connect(pszTargetIP,nTargetPort);
	int nRet = SSL_connect (m_ssl);
	return FALSE;
}
Ejemplo n.º 7
0
int main(int argc, char **argv)
{
    int c, test_config = 0;
#ifndef WIN32
    int gid = 0;
#endif

    int sock = 0, port = 1515, ret = 0;
    char *dir  = DEFAULTDIR;
    char *user = USER;
    char *group = GROUPGLOBAL;
    char *cfg = DEFAULTCPATH;
    char *manager = NULL;
    char *agentname = NULL;
    char lhostname[512 + 1];
    char buf[2048 +1];
    SSL_CTX *ctx;
    SSL *ssl;
    BIO *sbio;


    bio_err = 0;
    buf[2048] = '\0';


    /* Setting the name */
    OS_SetName(ARGV0);

    while((c = getopt(argc, argv, "Vdhu:g:D:c:m:p:A:")) != -1)
    {
        switch(c) {
        case 'V':
            print_version();
            break;
        case 'h':
            report_help();
            break;
        case 'd':
            nowDebug();
            break;
        case 'u':
            if(!optarg)
                ErrorExit("%s: -u needs an argument",ARGV0);
            user=optarg;
            break;
        case 'g':
            if(!optarg)
                ErrorExit("%s: -g needs an argument",ARGV0);
            group=optarg;
            break;
        case 'D':
            if(!optarg)
                ErrorExit("%s: -D needs an argument",ARGV0);
            dir=optarg;
            break;
        case 'c':
            if(!optarg)
                ErrorExit("%s: -c needs an argument",ARGV0);
            cfg = optarg;
            break;
        case 't':
            test_config = 1;
            break;
        case 'm':
            if(!optarg)
                ErrorExit("%s: -%c needs an argument",ARGV0, c);
            manager = optarg;
            break;
        case 'A':
            if(!optarg)
                ErrorExit("%s: -%c needs an argument",ARGV0, c);
            agentname = optarg;
            break;
        case 'p':
            if(!optarg)
                ErrorExit("%s: -%c needs an argument",ARGV0, c);
            port = atoi(optarg);
            if(port <= 0 || port >= 65536)
            {
                ErrorExit("%s: Invalid port: %s", ARGV0, optarg);
            }
            break;
        default:
            report_help();
            break;
        }
    }

    /* Starting daemon */
    debug1(STARTED_MSG,ARGV0);


#ifndef WIN32
    /* Check if the user/group given are valid */
    gid = Privsep_GetGroup(group);
    if(gid < 0)
        ErrorExit(USER_ERROR,ARGV0,user,group);



    /* Privilege separation */
    if(Privsep_SetGroup(gid) < 0)
        ErrorExit(SETGID_ERROR,ARGV0,group);



    /* Signal manipulation */
    StartSIG(ARGV0);



    /* Creating PID files */
    if(CreatePID(ARGV0, getpid()) < 0)
        ErrorExit(PID_ERROR,ARGV0);
#endif


    /* Start up message */
    verbose(STARTUP_MSG, ARGV0, (int)getpid());


    if(agentname == NULL)
    {
        lhostname[512] = '\0';
        if(gethostname(lhostname, 512 -1) != 0)
        {
            merror("%s: ERROR: Unable to extract hostname. Custom agent name not set.", ARGV0);
            exit(1);
        }
        agentname = lhostname;
    }



    /* Starting SSL */
    ctx = os_ssl_keys(1, NULL);
    if(!ctx)
    {
        merror("%s: ERROR: SSL error. Exiting.", ARGV0);
        exit(1);
    }

    if(!manager)
    {
        merror("%s: ERROR: Manager IP not set.", ARGV0);
        exit(1);
    }


    /* Check to see if manager is an IP */
    int is_ip = 1;
    struct sockaddr_in iptest;
    memset(&iptest, 0, sizeof(iptest));

    if(inet_pton(AF_INET, manager, &iptest.sin_addr) != 1)
        is_ip = 0;	/* This is not an IPv4 address */

    /* Not IPv4, IPv6 maybe? */
    if(is_ip == 0)
    {
        struct sockaddr_in6 iptest6;
        memset(&iptest6, 0, sizeof(iptest6));
        if(inet_pton(AF_INET6, manager, &iptest6.sin6_addr) != 1)
            is_ip = 0;
        else
            is_ip = 1;	/* This is an IPv6 address */
    }


    /* If it isn't an ip, try to resolve the IP */
    if(is_ip == 0)
    {
        char *ipaddress;
        ipaddress = OS_GetHost(manager, 3);
        if(ipaddress != NULL)
            strncpy(manager, ipaddress, 16);
        else
        {
            printf("Could not resolve hostname: %s\n", manager);
            return(1);
        }
    }


    /* Connecting via TCP */
    sock = OS_ConnectTCP(port, manager, 0);
    if(sock <= 0)
    {
        merror("%s: Unable to connect to %s:%d", ARGV0, manager, port);
        exit(1);
    }


    /* Connecting the SSL socket */
    ssl = SSL_new(ctx);
    sbio = BIO_new_socket(sock, BIO_NOCLOSE);
    SSL_set_bio(ssl, sbio, sbio);


    ret = SSL_connect(ssl);
    if(ret <= 0)
    {
        ERR_print_errors_fp(stderr);
        merror("%s: ERROR: SSL error (%d). Exiting.", ARGV0, ret);
        exit(1);
    }


    printf("INFO: Connected to %s:%d\n", manager, port);
    printf("INFO: Using agent name as: %s\n", agentname);


    snprintf(buf, 2048, "OSSEC A:'%s'\n", agentname);
    ret = SSL_write(ssl, buf, strlen(buf));
    if(ret < 0)
    {
        printf("SSL write error (unable to send message.)\n");
        ERR_print_errors_fp(stderr);
        exit(1);
    }

    printf("INFO: Send request to manager. Waiting for reply.\n");

    while(1)
    {
        ret = SSL_read(ssl,buf,sizeof(buf) -1);
        switch(SSL_get_error(ssl,ret))
        {
        case SSL_ERROR_NONE:
            buf[ret] = '\0';
            if(strncmp(buf, "ERROR", 5) == 0)
            {
                char *tmpstr;
                tmpstr = strchr(buf, '\n');
                if(tmpstr) *tmpstr = '\0';
                printf("%s (from manager)\n", buf);
            }
            else if(strncmp(buf, "OSSEC K:'",9) == 0)
            {
                char *key;
                char *tmpstr;
                char **entry;
                printf("INFO: Received response with agent key\n");

                key = buf;
                key += 9;
                tmpstr = strchr(key, '\'');
                if(!tmpstr)
                {
                    printf("ERROR: Invalid key received. Closing connection.\n");
                    exit(1);
                }
                *tmpstr = '\0';
                entry = OS_StrBreak(' ', key, 4);
                if(!OS_IsValidID(entry[0]) || !OS_IsValidName(entry[1]) ||
                        !OS_IsValidName(entry[2]) || !OS_IsValidName(entry[3]))
                {
                    printf("ERROR: Invalid key received (2). Closing connection.\n");
                    exit(1);
                }

                {
                    FILE *fp;
                    fp = fopen(KEYSFILE_PATH,"w");
                    if(!fp)
                    {
                        printf("ERROR: Unable to open key file: %s", KEYSFILE_PATH);
                        exit(1);
                    }
                    fprintf(fp, "%s\n", key);
                    fclose(fp);
                }
                printf("INFO: Valid key created. Finished.\n");
            }
            break;
        case SSL_ERROR_ZERO_RETURN:
        case SSL_ERROR_SYSCALL:
            printf("INFO: Connection closed.\n");
            exit(0);
            break;
        default:
            printf("ERROR: SSL read (unable to receive message)\n");
            exit(1);
            break;
        }

    }



    /* Shutdown the socket */
    SSL_CTX_free(ctx);
    close(sock);

    exit(0);
}
Ejemplo n.º 8
0
/* handle_connect_results assumes that select or poll have already shown the
 * descriptor to be active */
void handle_connect_result(struct npool *ms, struct nevent *nse, enum nse_status status) {
  int optval;
  socklen_t optlen = sizeof(int);
  struct niod *iod = nse->iod;
#if HAVE_OPENSSL
  int sslerr;
  int rc = 0;
  int sslconnect_inprogress = nse->type == NSE_TYPE_CONNECT_SSL && nse->iod &&
    (nse->sslinfo.ssl_desire == SSL_ERROR_WANT_READ ||
     nse->sslinfo.ssl_desire == SSL_ERROR_WANT_WRITE);
#else
  int sslconnect_inprogress = 0;
#endif

  if (status == NSE_STATUS_TIMEOUT || status == NSE_STATUS_CANCELLED) {
    nse->status = status;
    nse->event_done = 1;
  } else if (sslconnect_inprogress) {
    /* Do nothing */
  } else if (status == NSE_STATUS_SUCCESS) {
    /* First we want to determine whether the socket really is connected */
    if (getsockopt(iod->sd, SOL_SOCKET, SO_ERROR, (char *)&optval, &optlen) != 0)
      optval = socket_errno(); /* Stupid Solaris */

    switch (optval) {
      case 0:
        nse->status = NSE_STATUS_SUCCESS;
        break;
      /* EACCES can be caused by ICMPv6 dest-unreach-admin, or when a port is
         blocked by Windows Firewall (WSAEACCES). */
      case EACCES:
      case ECONNREFUSED:
      case EHOSTUNREACH:
      case ENETDOWN:
      case ENETUNREACH:
      case ENETRESET:
      case ECONNABORTED:
      case ETIMEDOUT:
      case EHOSTDOWN:
      case ECONNRESET:
#ifdef WIN32
      case WSAEADDRINUSE:
      case WSAEADDRNOTAVAIL:
#endif
#ifndef WIN32
      case EPIPE: /* Has been seen after connect on Linux. */
      case ENOPROTOOPT: /* Also seen on Linux, perhaps in response to protocol unreachable. */
#endif
        nse->status = NSE_STATUS_ERROR;
        nse->errnum = optval;
        break;

      default:
        /* I'd like for someone to report it */
        fatal("Strange connect error from %s (%d): %s",
              inet_ntop_ez(&iod->peer, iod->peerlen), optval,
              socket_strerror(optval));
    }

    /* Now special code for the SSL case where the TCP connection was successful. */
    if (nse->type == NSE_TYPE_CONNECT_SSL &&
        nse->status == NSE_STATUS_SUCCESS) {
#if HAVE_OPENSSL
      assert(ms->sslctx != NULL);
      /* Reuse iod->ssl if present. If set, this is the second try at connection
         without the SSL_OP_NO_SSLv2 option set. */
      if (iod->ssl == NULL) {
        iod->ssl = SSL_new(ms->sslctx);
        if (!iod->ssl)
          fatal("SSL_new failed: %s", ERR_error_string(ERR_get_error(), NULL));
      }

#if HAVE_SSL_SET_TLSEXT_HOST_NAME
      if (iod->hostname != NULL) {
        if (SSL_set_tlsext_host_name(iod->ssl, iod->hostname) != 1)
          fatal("SSL_set_tlsext_host_name failed: %s", ERR_error_string(ERR_get_error(), NULL));
      }
#endif

      /* Associate our new SSL with the connected socket.  It will inherit the
       * non-blocking nature of the sd */
      if (SSL_set_fd(iod->ssl, iod->sd) != 1)
        fatal("SSL_set_fd failed: %s", ERR_error_string(ERR_get_error(), NULL));

      /* Event not done -- need to do SSL connect below */
      nse->sslinfo.ssl_desire = SSL_ERROR_WANT_CONNECT;
#endif
    } else {
      /* This is not an SSL connect (in which case we are always done), or the
       * TCP connect() underlying the SSL failed (in which case we are also done */
      nse->event_done = 1;
    }
  } else {
    fatal("Unknown status (%d)", status);
  }

  /* At this point the TCP connection is done, whether successful or not.
   * Therefore decrease the read/write listen counts that were incremented in
   * nsp_add_event. In the SSL case, we may increase one of the counts depending
   * on whether SSL_connect returns an error of SSL_ERROR_WANT_READ or
   * SSL_ERROR_WANT_WRITE. In that case we will re-enter this function, but we
   * don't want to execute this block again. */
  if (iod->sd != -1 && !sslconnect_inprogress) {
    int ev = EV_NONE;

    ev |= socket_count_read_dec(iod);
    ev |= socket_count_write_dec(iod);
    ev |= EV_EXCEPT;
    update_events(iod, ms, EV_NONE, ev);
  }

#if HAVE_OPENSSL
  if (nse->type == NSE_TYPE_CONNECT_SSL && !nse->event_done) {
    /* Lets now start/continue/finish the connect! */
    if (iod->ssl_session) {
      rc = SSL_set_session(iod->ssl, iod->ssl_session);
      if (rc == 0)
        nsock_log_error(ms, "Uh-oh: SSL_set_session() failed - please tell [email protected]");
      iod->ssl_session = NULL; /* No need for this any more */
    }

    /* If this is a reinvocation of handle_connect_result, clear out the listen
     * bits that caused it, based on the previous SSL desire. */
    if (sslconnect_inprogress) {
      int ev;

      ev = socket_count_dec_ssl_desire(nse);
      update_events(iod, ms, EV_NONE, ev);
    }

    rc = SSL_connect(iod->ssl);
    if (rc == 1) {
      /* Woop!  Connect is done! */
      nse->event_done = 1;
      /* Check that certificate verification was okay, if requested. */
      if (nsi_ssl_post_connect_verify(iod)) {
        nse->status = NSE_STATUS_SUCCESS;
      } else {
        nsock_log_error(ms, "certificate verification error for EID %li: %s",
                        nse->id, ERR_error_string(ERR_get_error(), NULL));
        nse->status = NSE_STATUS_ERROR;
      }
    } else {
      long options = SSL_get_options(iod->ssl);

      sslerr = SSL_get_error(iod->ssl, rc);
      if (rc == -1 && sslerr == SSL_ERROR_WANT_READ) {
        nse->sslinfo.ssl_desire = sslerr;
        socket_count_read_inc(iod);
        update_events(iod, ms, EV_READ, EV_NONE);
      } else if (rc == -1 && sslerr == SSL_ERROR_WANT_WRITE) {
        nse->sslinfo.ssl_desire = sslerr;
        socket_count_write_inc(iod);
        update_events(iod, ms, EV_WRITE, EV_NONE);
      } else if (!(options & SSL_OP_NO_SSLv2)) {
        int saved_ev;

        /* SSLv3-only and TLSv1-only servers can't be connected to when the
         * SSL_OP_NO_SSLv2 option is not set, which is the case when the pool
         * was initialized with nsp_ssl_init_max_speed. Try reconnecting with
         * SSL_OP_NO_SSLv2. Never downgrade a NO_SSLv2 connection to one that
         * might use SSLv2. */
        nsock_log_info(ms, "EID %li reconnecting with SSL_OP_NO_SSLv2", nse->id);

        saved_ev = iod->watched_events;
        nsock_engine_iod_unregister(ms, iod);
        close(iod->sd);
        nsock_connect_internal(ms, nse, SOCK_STREAM, iod->lastproto, &iod->peer,
                               iod->peerlen, nsi_peerport(iod));
        nsock_engine_iod_register(ms, iod, saved_ev);

        SSL_clear(iod->ssl);
        if(!SSL_clear(iod->ssl))
           fatal("SSL_clear failed: %s", ERR_error_string(ERR_get_error(), NULL));

        SSL_set_options(iod->ssl, options | SSL_OP_NO_SSLv2);
        socket_count_read_inc(nse->iod);
        socket_count_write_inc(nse->iod);
        update_events(iod, ms, EV_READ|EV_WRITE, EV_NONE);
        nse->sslinfo.ssl_desire = SSL_ERROR_WANT_CONNECT;
      } else {
        nsock_log_info(ms, "EID %li %s",
                       nse->id, ERR_error_string(ERR_get_error(), NULL));
        nse->event_done = 1;
        nse->status = NSE_STATUS_ERROR;
        nse->errnum = EIO;
      }
    }
  }
#endif
}
Ejemplo n.º 9
0
int main(int argc, char **argv)
{
    int c;
    int sock = 0, portnum, ret = 0;
    char *host = NULL, *port = "443";
    SSL_CTX *ctx;
    SSL *ssl;
    SSL_METHOD *sslmeth;
    BIO *sbio;
    BIO *bio_err = 0;

    while ((c = getopt(argc, argv, "h:p:")) != -1) {
        switch (c) {
            case 'h':
                host = optarg;
                break;
            case 'p':
                portnum = atoi(optarg);
                if (portnum <= 0 || portnum >= 65536) {
                    exit(1);
                }
                port = optarg;
                break;
            default:
                exit(1);
                break;
        }
    }

    if (!bio_err) {
        SSL_library_init();
        SSL_load_error_strings();
        OpenSSL_add_all_algorithms();
        bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
    }

    sslmeth = SSLv23_method();
    ctx = SSL_CTX_new(sslmeth);
    if (!ctx) {
        printf("CTX ERROR\n");
        exit(1);
    }

    if (!host) {
        printf("ERROR - host not set.\n");
        exit(1);
    }

    /* Connect via TCP */
    sock = OS_ConnectTCP(port, host);
    if (sock <= 0) {
        printf("connect error\n");
        exit(1);
    }

    /* Connect the SSL socket */
    ssl = SSL_new(ctx);
    sbio = BIO_new_socket(sock, BIO_NOCLOSE);
    SSL_set_bio(ssl, sbio, sbio);
    ret = SSL_connect(ssl);
    if (ret <= 0) {
        printf("SSL connect error\n");
        ERR_print_errors_fp(stderr);
        exit(1);
    }

    printf("Connected!\n");

    ret = SSL_write(ssl, TEST, sizeof(TEST));
    if (ret < 0) {
        printf("SSL write error\n");
        ERR_print_errors_fp(stderr);
        exit(1);
    }

    while (1) {
        char buf[2048];
        ret = SSL_read(ssl, buf, sizeof(buf) - 1);
        printf("ret: %d\n", ret);
        switch (SSL_get_error(ssl, ret)) {
            case SSL_ERROR_NONE:
                buf[ret] = '\0';
                printf("no error: %s\n", buf);
                break;
            case SSL_ERROR_ZERO_RETURN:
                printf("no return\n");
                exit(1);
                break;
            case SSL_ERROR_SYSCALL:
                fprintf(stderr,
                        "SSL Error: Premature close\n");
                exit(1);
                break;
            default:
                printf("default error\n");
                exit(1);
                break;
        }

    }

    exit(0);
}
Ejemplo n.º 10
0
bool SSLSocket::enableCrypto(bool activate /* = true */) {
  if (activate && !m_data->m_ssl_active) {
    double timeout = m_data->m_connect_timeout;
    bool blocked = m_data->m_is_blocked;
    if (!m_data->m_state_set) {
      if (m_data->m_client) {
        SSL_set_connect_state(m_data->m_handle);
      } else {
        SSL_set_accept_state(m_data->m_handle);
      }
      m_data->m_state_set = true;
    }

    if (m_data->m_client && setBlocking(false)) {
      m_data->m_is_blocked = false;
    }

    int n;
    bool retry = true;
    do {
      if (m_data->m_client) {
        struct timeval tvs, tve;
        struct timezone tz;

        gettimeofday(&tvs, &tz);
        n = SSL_connect(m_data->m_handle);
        gettimeofday(&tve, &tz);

        timeout -= (tve.tv_sec + (double) tve.tv_usec / 1000000) -
          (tvs.tv_sec + (double) tvs.tv_usec / 1000000);
        if (timeout < 0) {
          raise_warning("SSL: connection timeout");
          return false;
        }
      } else {
        n = SSL_accept(m_data->m_handle);
      }

      if (n <= 0) {
        retry = handleError(n, true);
      } else {
        break;
      }
    } while (retry);

    if (m_data->m_client &&
        m_data->m_is_blocked != blocked &&
        setBlocking(blocked)) {
      m_data->m_is_blocked = blocked;
    }

    if (n == 1) {
      X509 *peer_cert = SSL_get_peer_certificate(m_data->m_handle);
      if (!applyVerificationPolicy(peer_cert)) {
        SSL_shutdown(m_data->m_handle);
      } else {
        m_data->m_ssl_active = true;

        /* allow the script to capture the peer cert
         * and/or the certificate chain */
        if (m_context[s_capture_peer_cert].toBoolean()) {
          m_context.set(s_peer_certificate,
                        Variant(req::make<Certificate>(peer_cert)));
          peer_cert = nullptr;
        }

        if (m_context[s_capture_peer_cert_chain].toBoolean()) {
          Array arr;
          STACK_OF(X509) *chain = SSL_get_peer_cert_chain(m_data->m_handle);
          if (chain) {
            for (int i = 0; i < sk_X509_num(chain); i++) {
              X509 *mycert = X509_dup(sk_X509_value(chain, i));
              arr.append(Variant(req::make<Certificate>(mycert)));
            }
          }
          m_context.set(s_peer_certificate_chain, arr);
        }
      }

      if (peer_cert) {
        X509_free(peer_cert);
      }
    } else  {
      n = errno == EAGAIN ? 0 : -1;
    }

    return n >= 0;

  } else if (!activate && m_data->m_ssl_active) {
    /* deactivate - common for server/client */
    SSL_shutdown(m_data->m_handle);
    m_data->m_ssl_active = false;
  }
  return true;
}
Ejemplo n.º 11
0
void _socket_handle(int fd, int type)
{
	sock *sock = fds[fd];
	if (sock == NULL)
	{
		return;
	}
	sock->flags |= SOCKET_INUSE;
#ifdef HAVE_SSL
	switch (sock->sslstate)
	{
		case SSL_OFF:
		case SSL_IDLE:
#endif
			if ((type & MONITOR_READ) && sock->read_handler)
			{
				sock->read_handler(sock);
			}
			if ((type & MONITOR_WRITE) && sock->write_handler)
			{
				sock->write_handler(sock);
			}
#ifdef HAVE_SSL
			break;
		case SSL_ACCEPT:
			if (_socket_checkssl(sock, SSL_accept(sock->ssl)) < 0)
			{
				type |= MONITOR_ERROR;
			}			
			break;
		case SSL_CONNECT:
			if (_socket_checkssl(sock, SSL_connect(sock->ssl)) < 0)
			{
				type |= MONITOR_ERROR;
			}
			break;
		case SSL_READ:
			if (sock->read_handler)
			{
				sock->read_handler(sock);
			}
			break;
		case SSL_WRITE:
			if (sock->write_handler)
			{
				sock->write_handler(sock);
			}
			break;
	}
#endif
	if ((type & MONITOR_ERROR) && sock->error_handler)
	{
		sock->error_handler(sock);
	}
	if (sock->flags & SOCKET_CLOSE)
	{
		_socket_free(sock);
	}
	else
	{
		sock->flags &= ~SOCKET_INUSE;
	}
}
Ejemplo n.º 12
0
int np_net_ssl_init_with_hostname_version_and_cert(int sd, char *host_name, int version, char *cert, char *privkey) {
	SSL_METHOD *method = NULL;

	switch (version) {
	case 0: /* Deafult to auto negotiation */
		method = SSLv23_client_method();
		break;
	case 1: /* TLSv1 protocol */
		method = TLSv1_client_method();
		break;
	case 2: /* SSLv2 protocol */
#if defined(USE_GNUTLS) || defined(OPENSSL_NO_SSL2)
		printf(("%s\n", _("CRITICAL - SSL protocol version 2 is not supported by your SSL library.")));
		return STATE_CRITICAL;
#else
		method = SSLv2_client_method();
#endif
		break;
	case 3: /* SSLv3 protocol */
		method = SSLv3_client_method();
		break;
	default: /* Unsupported */
		printf("%s\n", _("CRITICAL - Unsupported SSL protocol version."));
		return STATE_CRITICAL;
	}
	if (!initialized) {
		/* Initialize SSL context */
		SSLeay_add_ssl_algorithms();
		SSL_load_error_strings();
		OpenSSL_add_all_algorithms();
		initialized = 1;
	}
	if ((c = SSL_CTX_new(method)) == NULL) {
		printf("%s\n", _("CRITICAL - Cannot create SSL context."));
		return STATE_CRITICAL;
	}
	if (cert && privkey) {
		SSL_CTX_use_certificate_file(c, cert, SSL_FILETYPE_PEM);
		SSL_CTX_use_PrivateKey_file(c, privkey, SSL_FILETYPE_PEM);
		if (!SSL_CTX_check_private_key(c)) {
			printf ("%s\n", _("CRITICAL - Private key does not seem to match certificate!\n"));
			return STATE_CRITICAL;
		}
	}
#ifdef SSL_OP_NO_TICKET
	SSL_CTX_set_options(c, SSL_OP_NO_TICKET);
#endif
	SSL_CTX_set_mode(c, SSL_MODE_AUTO_RETRY);
	if ((s = SSL_new(c)) != NULL) {
#ifdef SSL_set_tlsext_host_name
		if (host_name != NULL)
			SSL_set_tlsext_host_name(s, host_name);
#endif
		SSL_set_fd(s, sd);
		if (SSL_connect(s) == 1) {
			return OK;
		} else {
			printf("%s\n", _("CRITICAL - Cannot make SSL connection."));
#  ifdef USE_OPENSSL /* XXX look into ERR_error_string */
			ERR_print_errors_fp(stdout);
#  endif /* USE_OPENSSL */
		}
	} else {
			printf("%s\n", _("CRITICAL - Cannot initiate SSL handshake."));
	}
	return STATE_CRITICAL;
}
Ejemplo n.º 13
0
// This test launches a gRPC server on a separate thread and then establishes a
// TLS handshake via a minimal TLS client. The TLS client has configurable (via
// alpn_list) ALPN settings and can probe at the supported ALPN preferences
// using this (via alpn_expected).
static bool server_ssl_test(const char *alpn_list[], unsigned int alpn_list_len,
                            const char *alpn_expected) {
  bool success = true;

  grpc_init();
  int port = grpc_pick_unused_port_or_die();
  gpr_event_init(&client_handshake_complete);

  // Launch the gRPC server thread.
  gpr_thd_options thdopt = gpr_thd_options_default();
  gpr_thd_id thdid;
  gpr_thd_options_set_joinable(&thdopt);
  GPR_ASSERT(gpr_thd_new(&thdid, server_thread, &port, &thdopt));

  SSL_load_error_strings();
  OpenSSL_add_ssl_algorithms();

  const SSL_METHOD *method = TLSv1_2_client_method();
  SSL_CTX *ctx = SSL_CTX_new(method);
  if (!ctx) {
    perror("Unable to create SSL context");
    ERR_print_errors_fp(stderr);
    abort();
  }

  // Load key pair.
  if (SSL_CTX_use_certificate_file(ctx, SSL_CERT_PATH, SSL_FILETYPE_PEM) < 0) {
    ERR_print_errors_fp(stderr);
    abort();
  }
  if (SSL_CTX_use_PrivateKey_file(ctx, SSL_KEY_PATH, SSL_FILETYPE_PEM) < 0) {
    ERR_print_errors_fp(stderr);
    abort();
  }

  // Set the cipher list to match the one expressed in
  // src/core/lib/tsi/ssl_transport_security.c.
  const char *cipher_list =
      "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-"
      "SHA384:ECDHE-RSA-AES256-GCM-SHA384";
  if (!SSL_CTX_set_cipher_list(ctx, cipher_list)) {
    ERR_print_errors_fp(stderr);
    gpr_log(GPR_ERROR, "Couldn't set server cipher list.");
    abort();
  }

  // Configure ALPN list the client will send to the server. This must match the
  // wire format, see documentation for SSL_CTX_set_alpn_protos.
  unsigned int alpn_protos_len = alpn_list_len;
  for (unsigned int i = 0; i < alpn_list_len; ++i) {
    alpn_protos_len += (unsigned int)strlen(alpn_list[i]);
  }
  unsigned char *alpn_protos = gpr_malloc(alpn_protos_len);
  unsigned char *p = alpn_protos;
  for (unsigned int i = 0; i < alpn_list_len; ++i) {
    const uint8_t len = (uint8_t)strlen(alpn_list[i]);
    *p++ = len;
    memcpy(p, alpn_list[i], len);
    p += len;
  }
  GPR_ASSERT(SSL_CTX_set_alpn_protos(ctx, alpn_protos, alpn_protos_len) == 0);

  // Try and connect to server. We allow a bounded number of retries as we might
  // be racing with the server setup on its separate thread.
  int retries = 10;
  int sock = -1;
  while (sock == -1 && retries-- > 0) {
    sock = create_socket(port);
    if (sock < 0) {
      sleep(1);
    }
  }
  GPR_ASSERT(sock > 0);
  gpr_log(GPR_INFO, "Connected to server on port %d", port);

  // Establish a SSL* and connect at SSL layer.
  SSL *ssl = SSL_new(ctx);
  GPR_ASSERT(ssl);
  SSL_set_fd(ssl, sock);
  if (SSL_connect(ssl) <= 0) {
    ERR_print_errors_fp(stderr);
    gpr_log(GPR_ERROR, "Handshake failed.");
    success = false;
  } else {
    gpr_log(GPR_INFO, "Handshake successful.");
    // Validate ALPN preferred by server matches alpn_expected.
    const unsigned char *alpn_selected;
    unsigned int alpn_selected_len;
    SSL_get0_alpn_selected(ssl, &alpn_selected, &alpn_selected_len);
    if (strlen(alpn_expected) != alpn_selected_len ||
        strncmp((const char *)alpn_selected, alpn_expected,
                alpn_selected_len) != 0) {
      gpr_log(GPR_ERROR, "Unexpected ALPN protocol preference");
      success = false;
    }
  }
  gpr_event_set(&client_handshake_complete, &client_handshake_complete);

  SSL_free(ssl);
  gpr_free(alpn_protos);
  SSL_CTX_free(ctx);
  EVP_cleanup();
  close(sock);

  gpr_thd_join(thdid);

  grpc_shutdown();

  return success;
}
Ejemplo n.º 14
0
static int
ssl23_get_server_hello(SSL *s)
{
	char buf[8];
	unsigned char *p;
	int i;
	int n;

	n = ssl23_read_bytes(s, 7);

	if (n != 7)
		return (n);
	p = s->packet;

	memcpy(buf, p, n);

	/* Old unsupported sslv2 handshake */
	if ((p[0] & 0x80) && (p[2] == SSL2_MT_SERVER_HELLO) &&
	    (p[5] == 0x00) && (p[6] == 0x02)) {
		SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,
		    SSL_R_UNSUPPORTED_PROTOCOL);
		goto err;
	}

	if (p[1] == SSL3_VERSION_MAJOR &&
	    p[2] <= TLS1_2_VERSION_MINOR &&
	    ((p[0] == SSL3_RT_HANDSHAKE && p[5] == SSL3_MT_SERVER_HELLO) ||
	    (p[0] == SSL3_RT_ALERT && p[3] == 0 && p[4] == 2))) {
		/* we have sslv3 or tls1 (server hello or alert) */

		if ((p[2] == SSL3_VERSION_MINOR) &&
		    !(s->options & SSL_OP_NO_SSLv3)) {
			s->version = SSL3_VERSION;
			s->method = SSLv3_client_method();
		} else if ((p[2] == TLS1_VERSION_MINOR) &&
		    !(s->options & SSL_OP_NO_TLSv1)) {
			s->version = TLS1_VERSION;
			s->method = TLSv1_client_method();
		} else if ((p[2] == TLS1_1_VERSION_MINOR) &&
		    !(s->options & SSL_OP_NO_TLSv1_1)) {
			s->version = TLS1_1_VERSION;
			s->method = TLSv1_1_client_method();
		} else if ((p[2] == TLS1_2_VERSION_MINOR) &&
		    !(s->options & SSL_OP_NO_TLSv1_2)) {
			s->version = TLS1_2_VERSION;
			s->method = TLSv1_2_client_method();
		} else {
			SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,
			    SSL_R_UNSUPPORTED_PROTOCOL);
			goto err;
		}

		if (p[0] == SSL3_RT_ALERT && p[5] != SSL3_AL_WARNING) {
			/* fatal alert */
			void (*cb)(const SSL *ssl, int type, int val) = NULL;
			int j;

			if (s->info_callback != NULL)
				cb = s->info_callback;
			else if (s->ctx->info_callback != NULL)
				cb = s->ctx->info_callback;

			i = p[5];
			if (cb != NULL) {
				j = (i << 8) | p[6];
				cb(s, SSL_CB_READ_ALERT, j);
			}

			if (s->msg_callback)
				s->msg_callback(0, s->version, SSL3_RT_ALERT,
				    p + 5, 2, s, s->msg_callback_arg);

			s->rwstate = SSL_NOTHING;
			SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,
			    SSL_AD_REASON_OFFSET + p[6]);
			goto err;
		}

		if (!ssl_init_wbio_buffer(s, 1))
			goto err;

		/* we are in this state */
		s->state = SSL3_ST_CR_SRVR_HELLO_A;

		/* put the 7 bytes we have read into the input buffer
		 * for SSLv3 */
		s->rstate = SSL_ST_READ_HEADER;
		s->packet_length = n;
		if (s->s3->rbuf.buf == NULL)
			if (!ssl3_setup_read_buffer(s))
				goto err;
		s->packet = &(s->s3->rbuf.buf[0]);
		memcpy(s->packet, buf, n);
		s->s3->rbuf.left = n;
		s->s3->rbuf.offset = 0;

		s->handshake_func = s->method->ssl_connect;
	} else {
		SSLerr(SSL_F_SSL23_GET_SERVER_HELLO, SSL_R_UNKNOWN_PROTOCOL);
		goto err;
	}
	s->init_num = 0;

	/*
	 * Since, if we are sending a ssl23 client hello, we are not
	 * reusing a session-id
	 */
	if (!ssl_get_new_session(s, 0))
		goto err;

	return (SSL_connect(s));
err:
	return (-1);
}
Ejemplo n.º 15
0
 int OpenSSLClient::handshakeFunction()
 {
   return SSL_connect( m_ssl );
 }
Ejemplo n.º 16
0
R_API int r_socket_connect (RSocket *s, const char *host, const char *port, int proto, int timeout) {
#if __WINDOWS__
	struct sockaddr_in sa;
	struct hostent *he;
	WSADATA wsadata;
	if (WSAStartup (MAKEWORD (1, 1), &wsadata) == SOCKET_ERROR) {
		eprintf ("Error creating socket.");
		return R_FALSE;
	}
	s->fd = socket (AF_INET, SOCK_STREAM, 0);
	if (s->fd == -1)
		return R_FALSE;

	memset (&sa, 0, sizeof(sa));
	sa.sin_family = AF_INET;
	he = (struct hostent *)gethostbyname (host);
	if (he == (struct hostent*)0) {
		close (s->fd);
		return R_FALSE;
	}

	sa.sin_addr = *((struct in_addr *)he->h_addr);

	s->port = r_socket_port_by_name (port);
	sa.sin_port = htons (s->port);
#warning TODO: implement connect timeout on w32
	if (connect (s->fd, (const struct sockaddr*)&sa, sizeof (struct sockaddr))) {
		close (s->fd);
		return R_FALSE;
	}
	return R_TRUE;
#elif __UNIX__
	if (!proto) proto = R_SOCKET_PROTO_TCP;
	int gai, ret;
	struct addrinfo hints, *res, *rp;
	signal (SIGPIPE, SIG_IGN);
	if (proto == R_SOCKET_PROTO_UNIX) {
		if (!r_socket_unix_connect (s, host))
			return R_FALSE;
	} else {
		memset (&hints, 0, sizeof (struct addrinfo));
		hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
		hints.ai_protocol = proto;
		gai = getaddrinfo (host, port, &hints, &res);
		if (gai != 0) {
			//eprintf ("Error in getaddrinfo: %s\n", gai_strerror (gai));
			return R_FALSE;
		}
		for (rp = res; rp != NULL; rp = rp->ai_next) {
			s->fd = socket (rp->ai_family, rp->ai_socktype, rp->ai_protocol);
			if (s->fd == -1)
				continue;
			if (timeout>0)
				r_socket_block_time (s, 1, timeout);
				//fcntl (s->fd, F_SETFL, O_NONBLOCK, 1);
			ret = connect (s->fd, rp->ai_addr, rp->ai_addrlen);
			if (ret<0) {
				close (s->fd);
				s->fd = -1;
				continue;
			}
			if (timeout<1) {
				if (ret == -1) {
					close (s->fd);
					s->fd = -1;
					return R_FALSE;
				}
				return R_TRUE;
			}
			if (timeout>0) {
				struct timeval tv;
				fd_set fdset, errset;
				FD_ZERO (&fdset);
				FD_SET (s->fd, &fdset);
				tv.tv_sec = 1; //timeout;
				tv.tv_usec = 0;

				if (r_socket_is_connected (s))
					return R_TRUE;
				if (select (s->fd + 1, NULL, NULL, &errset, &tv) == 1) {
					int so_error;
					socklen_t len = sizeof so_error;
					ret = getsockopt (s->fd, SOL_SOCKET,
						SO_ERROR, &so_error, &len);
			//		fcntl (s->fd, F_SETFL, O_NONBLOCK, 0);
//					r_socket_block_time (s, 0, 0);
					freeaddrinfo (res);
					return R_TRUE;
				} else {
	//				freeaddrinfo (res);
					close (s->fd);
					s->fd = -1;
					continue;
	//				return R_FALSE;
				}
			}
			close (s->fd);
			s->fd = -1;
		}
		freeaddrinfo (res);
		if (rp == NULL) {
			eprintf ("Could not resolve address '%s'\n", host);
			return R_FALSE;
		}
	}
#endif
#if HAVE_LIB_SSL
	if (s->is_ssl) {
		s->ctx = SSL_CTX_new (SSLv23_client_method ());
		if (s->ctx == NULL) {
			r_socket_free (s);
			return R_FALSE;
		}
		s->sfd = SSL_new (s->ctx);
		SSL_set_fd (s->sfd, s->fd);
		if (SSL_connect (s->sfd) != 1) {
			r_socket_free (s);
			return R_FALSE;
		}
	}
#endif
	return R_TRUE;
}
Ejemplo n.º 17
0
/* OS dependent */
Boolean rocs_socket_connect( iOSocket inst ) {
#ifdef __ROCS_SOCKET__
    iOSocketData o = Data(inst);
    struct sockaddr_in srvaddr;
    struct in_addr* addr = o->hostaddr;
    int rc = 0;

    if( o->sh == 0 )
        rocs_socket_create( o );

    if( o->sh == 0 )
        return False;

    if( !rocs_socket_resolveHost( o ) )
        return False;

    addr = o->hostaddr;

    memset( &srvaddr,0, sizeof( struct sockaddr_in ) );
    srvaddr.sin_family = AF_INET;
    srvaddr.sin_port   = htons( (u_short)o->port );
    srvaddr.sin_addr   = *addr;

    rc = connect( o->sh, (struct sockaddr *)&srvaddr, sizeof( struct sockaddr_in ) );

    if( rc == -1 ) {
        o->rc = WSAGetLastError();
        TraceOp.trc( name, TRCLEVEL_EXCEPTION, __LINE__, 9999, "connect(%s:%d) failed [%d]",
                     o->host, o->port , WSAGetLastError() );
        o->connected = False;
        return False;
    }
    o->connected = True;
    TraceOp.trc( name, TRCLEVEL_DEBUG, __LINE__, 9999, "socket connected." );

    if( o->ssl ) {
#ifdef __OPENSSL__
        SSL_METHOD* meth;
        X509*       server_cert;

        o->openssl_support = True;

        SSLeay_add_ssl_algorithms();
        meth = SSLv3_client_method();
        SSL_load_error_strings();
        o->ssl_ctx = SSL_CTX_new (meth);

        TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "OpenSSL support.(v%d)", meth->version );

        o->ssl_sh = SSL_new( o->ssl_ctx );
        if( o->ssl_sh != NULL ) {
            SSL_set_fd( o->ssl_sh, o->sh );
            rc = SSL_connect( o->ssl_sh );
            if( rc <= 0 ) {
                char err[256] = {'\0'};
                rc = ERR_peek_error();
                ERR_error_string_n( (unsigned long) rc, err, sizeof(err) );

                TraceOp.trc( name, TRCLEVEL_EXCEPTION, __LINE__, 9999, "SSL_connect() failed [%d] %s", rc, err );
                o->connected = False;
                o->openssl_support = False;
                return False;
            }

            /* Trace some info. */
            TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "SSL connection using %s", SSL_get_cipher( o->ssl_sh ) );

            server_cert = SSL_get_peer_certificate( o->ssl_sh );
            if( server_cert != NULL ) {
                char* sub = NULL;
                char* iss = NULL;

                sub = X509_NAME_oneline( X509_get_subject_name( server_cert ), 0, 0 );
                iss = X509_NAME_oneline( X509_get_issuer_name ( server_cert ), 0, 0 );

                TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999,
                             "SSL Server certificate subject = %s, issuer = %s", sub, iss );
                free( sub );
                free( iss );
            }

        }
#else
        TraceOp.trc( name, TRCLEVEL_EXCEPTION, __LINE__, 9999, "SSL requested but not supported! Compile with __OPENSSL__ defined." );
        return False;
#endif
    }

#endif
    return True;
}
void echoclient_test(void* args)
{
    SOCKET_T sockfd = 0;

    FILE* fin  = stdin;
    FILE* fout = stdout;

    int inCreated  = 0;
    int outCreated = 0;

    char send[1024];
    char reply[1024];

    SSL_METHOD* method = 0;
    SSL_CTX*    ctx    = 0;
    SSL*        ssl    = 0;

    int doDTLS = 0;
    int sendSz;
    int argc    = 0;
    char** argv = 0;

    ((func_args*)args)->return_code = -1; /* error state */
    argc = ((func_args*)args)->argc;
    argv = ((func_args*)args)->argv;

    if (argc >= 2) {
        fin  = fopen(argv[1], "r"); 
        inCreated = 1;
    }
    if (argc >= 3) {
        fout = fopen(argv[2], "w");
        outCreated = 1;
    }

    if (!fin)  err_sys("can't open input file");
    if (!fout) err_sys("can't open output file");

#ifdef CYASSL_DTLS
    doDTLS  = 1;
#endif

    tcp_connect(&sockfd, yasslIP, yasslPort, doDTLS);

#if defined(CYASSL_DTLS)
    method  = DTLSv1_client_method();
#elif  !defined(NO_TLS)
    method = CyaSSLv23_client_method();
#else
    method = SSLv3_client_method();
#endif
    ctx    = SSL_CTX_new(method);

#ifndef NO_FILESYSTEM
    if (SSL_CTX_load_verify_locations(ctx, caCert, 0) != SSL_SUCCESS)
        err_sys("can't load ca file, Please run from CyaSSL home dir");
    #ifdef HAVE_ECC
        if (SSL_CTX_load_verify_locations(ctx, eccCert, 0) != SSL_SUCCESS)
            err_sys("can't load ca file, Please run from CyaSSL home dir");
    #endif
#else
    load_buffer(ctx, caCert, CYASSL_CA);
#endif

#if defined(CYASSL_SNIFFER) && !defined(HAVE_NTRU) && !defined(HAVE_ECC)
    /* don't use EDH, can't sniff tmp keys */
    SSL_CTX_set_cipher_list(ctx, "AES256-SHA");
#endif

#ifdef OPENSSL_EXTRA
    SSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack);
#endif
    ssl = SSL_new(ctx);

    SSL_set_fd(ssl, sockfd);
#if defined(USE_WINDOWS_API) && defined(CYASSL_DTLS) && defined(NO_MAIN_DRIVER)
    /* let echoserver bind first, TODO: add Windows signal like pthreads does */
    Sleep(100);
#endif
    if (SSL_connect(ssl) != SSL_SUCCESS) err_sys("SSL_connect failed");

    while (fgets(send, sizeof(send), fin)) {

        sendSz = (int)strlen(send);

        if (SSL_write(ssl, send, sendSz) != sendSz)
            err_sys("SSL_write failed");

        if (strncmp(send, "quit", 4) == 0) {
            fputs("sending server shutdown command: quit!\n", fout);
            break;
        }

        if (strncmp(send, "break", 5) == 0) {
            fputs("sending server session close: break!\n", fout);
            break;
        }

        while (sendSz) {
            int got;
            if ( (got = SSL_read(ssl, reply, sizeof(reply))) > 0) {
                reply[got] = 0;
                fputs(reply, fout);
                sendSz -= got;
            }
            else
                break;
        }
    }

#ifdef CYASSL_DTLS
    strncpy(send, "break", 6);
    sendSz = (int)strlen(send);
    /* try to tell server done */
    SSL_write(ssl, send, sendSz);
#else
    SSL_shutdown(ssl);
#endif

    SSL_free(ssl);
    SSL_CTX_free(ctx);

    fflush(fout);
    if (inCreated)  fclose(fin);
    if (outCreated) fclose(fout);

    CloseSocket(sockfd);
    ((func_args*)args)->return_code = 0; 
}
Ejemplo n.º 19
0
static void handle_connect(int cnum, struct timeval* nowP, int double_check)
{
	int url_num;
	char buf[600];
	int bytes, r;

	url_num = connections[cnum].url_num;
	if (double_check)
	{
		/* Check to make sure the non-blocking connect succeeded. */
		int err, errlen;

		if (connect(connections[cnum].conn_fd,
		    (struct sockaddr*)&connections[cnum].sa, connections[cnum].sa_len)
		    < 0)
		{
			switch(errno)
			{
				case EISCONN:
				/* Ok! */
				break;
				case EINVAL:
					errlen = sizeof(err);
					if ( getsockopt( connections[cnum].conn_fd, SOL_SOCKET, SO_ERROR, (void*) &err, (socklen_t*)&errlen ) < 0 )
					{
						(void) fprintf(stderr, "%s: unknown connect error\n", urls[url_num].url_str );
					}
					else
					{
						(void) fprintf(stderr, "%s: %s\n", urls[url_num].url_str, strerror( err ));
					}
					close_connection( cnum );
				return;
				default:
					perror( urls[url_num].url_str );
					close_connection( cnum );
				return;
			}
		}
	}
#ifdef USE_SSL
	if ( urls[url_num].protocol == PROTO_HTTPS )
	{
		int flags;

		/* Make SSL connection. */
		if ( ssl_ctx == (SSL_CTX*) 0 )
		{
			SSL_load_error_strings();
			SSLeay_add_ssl_algorithms();
			ssl_ctx = SSL_CTX_new( SSLv23_client_method() );
			if ( cipher != (char*) 0 )
			{
				if ( ! SSL_CTX_set_cipher_list( ssl_ctx, cipher ) )
				{
					(void) fprintf(
						stderr, "%s: cannot set cipher list\n", argv0 );
					ERR_print_errors_fp( stderr );
					close_connection( cnum );
					return;
				}
			}
		}
		if ( ! RAND_status() )
		{
			unsigned char bytes[1024];
			int i;
			for ( i = 0; i < sizeof(bytes); ++i )
			bytes[i] = random() % 0xff;
			RAND_seed( bytes, sizeof(bytes) );
		}
		flags = fcntl( connections[cnum].conn_fd, F_GETFL, 0 );
		if ( flags != -1 )
		(void) fcntl(
			connections[cnum].conn_fd, F_SETFL, flags & ~ (int) O_NDELAY );
		connections[cnum].ssl = SSL_new( ssl_ctx );
		SSL_set_fd( connections[cnum].ssl, connections[cnum].conn_fd );
		r = SSL_connect( connections[cnum].ssl );
		if ( r <= 0 )
		{
			(void) fprintf(
				stderr, "%s: SSL connection failed - %d\n", argv0, r );
			ERR_print_errors_fp( stderr );
			close_connection( cnum );
			return;
		}
	}
#endif
	connections[cnum].did_connect = 1;

	/* Format the request. */
	if (do_proxy)
	{
#ifdef USE_SSL
		bytes = snprintf(
			buf, sizeof(buf), "GET %s://%.500s:%d%.500s HTTP/1.0\r\n",
			urls[url_num].protocol == PROTO_HTTPS ? "https" : "http",
			urls[url_num].hostname, (int) urls[url_num].port,
			urls[url_num].filename );
#else
		bytes = snprintf(buf, sizeof(buf),
		    "GET http://%.500s:%d%.500s HTTP/1.0\r\n", urls[url_num].hostname,
		    (int)urls[url_num].port, urls[url_num].filename);
#endif
	}
	else
	{
		bytes = snprintf(buf, sizeof(buf), "GET %.500s HTTP/1.0\r\n",
		    urls[url_num].filename);
	}
	bytes += snprintf(&buf[bytes], sizeof(buf) - bytes, "Host: %s\r\n",
	    urls[url_num].hostname);
	bytes += snprintf(&buf[bytes], sizeof(buf) - bytes, "User-Agent: %s\r\n",
	    VERSION);
	bytes += snprintf(&buf[bytes], sizeof(buf) - bytes, "\r\n");

	/* Send the request. */
	connections[cnum].request_at = *nowP;
#ifdef USE_SSL
	if ( urls[url_num].protocol == PROTO_HTTPS )
	r = SSL_write( connections[cnum].ssl, buf, bytes );
	else
	r = write( connections[cnum].conn_fd, buf, bytes );
#else
	r = write(connections[cnum].conn_fd, buf, bytes);
#endif

	if (r < 0)
	{
		perror(urls[url_num].url_str);
		close_connection(cnum);
		return;
	}
	connections[cnum].conn_state = CNST_HEADERS;
	connections[cnum].header_state = HDST_LINE1_PROTOCOL;
}
Ejemplo n.º 20
0
tcpcon_t *
tcp_connect(const char *hostname, int port, char *errbuf, size_t errbufsize,
	    int timeout, int ssl)
{
  struct hostent *hp;
  char *tmphstbuf;
  int fd, val, r, err, herr;
  const char *errtxt;
#if !defined(__APPLE__)
  struct hostent hostbuf;
  size_t hstbuflen;
  int res;
#endif
  struct sockaddr_in6 in6;
  struct sockaddr_in in;
  socklen_t errlen = sizeof(int);


  if(!strcmp(hostname, "localhost")) {
    if((fd = getstreamsocket(AF_INET, errbuf, errbufsize)) == -1)
      return NULL;

    memset(&in, 0, sizeof(in));
    in.sin_family = AF_INET;
    in.sin_port = htons(port);
    in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    r = connect(fd, (struct sockaddr *)&in, sizeof(struct sockaddr_in));
  } else {

#if defined(__APPLE__)
    herr = 0;
    tmphstbuf = NULL; /* free NULL is a nop */
    /* TODO: AF_INET6 */
    hp = gethostbyname(hostname);
    if(hp == NULL)
      herr = h_errno;
#else
    hstbuflen = 1024;
    tmphstbuf = malloc(hstbuflen);

    while((res = gethostbyname_r(hostname, &hostbuf, tmphstbuf, hstbuflen,
				 &hp, &herr)) == ERANGE) {
      hstbuflen *= 2;
      tmphstbuf = realloc(tmphstbuf, hstbuflen);
    }
#endif
    if(herr != 0) {
      switch(herr) {
      case HOST_NOT_FOUND:
	errtxt = "Unknown host";
	break;

      case NO_ADDRESS:
	errtxt = "The requested name is valid but does not have an IP address";
	break;
      
      case NO_RECOVERY:
	errtxt = "A non-recoverable name server error occurred";
	break;
      
      case TRY_AGAIN:
	errtxt = "A temporary error occurred on an authoritative name server";
	break;
      
      default:
	errtxt = "Unknown error";
	break;
      }

      snprintf(errbuf, errbufsize, "%s", errtxt);
      free(tmphstbuf);
      return NULL;
    } else if(hp == NULL) {
      snprintf(errbuf, errbufsize, "Resolver internal error");
      free(tmphstbuf);
      return NULL;
    }

    if((fd = getstreamsocket(hp->h_addrtype, errbuf, errbufsize)) == -1) {
      free(tmphstbuf);
      return NULL;
    }

    switch(hp->h_addrtype) {
    case AF_INET:
      memset(&in, 0, sizeof(in));
      in.sin_family = AF_INET;
      in.sin_port = htons(port);
      memcpy(&in.sin_addr, hp->h_addr_list[0], sizeof(struct in_addr));
      r = connect(fd, (struct sockaddr *)&in, sizeof(struct sockaddr_in));
      break;

    case AF_INET6:
      memset(&in6, 0, sizeof(in6));
      in6.sin6_family = AF_INET6;
      in6.sin6_port = htons(port);
      memcpy(&in6.sin6_addr, hp->h_addr_list[0], sizeof(struct in6_addr));
      r = connect(fd, (struct sockaddr *)&in, sizeof(struct sockaddr_in6));
      break;

    default:
      snprintf(errbuf, errbufsize, "Invalid protocol family");
      free(tmphstbuf);
      return NULL;
    }

    free(tmphstbuf);
  }
  if(r == -1) {
    if(errno == EINPROGRESS) {
      struct pollfd pfd;

      pfd.fd = fd;
      pfd.events = POLLOUT;
      pfd.revents = 0;

      r = poll(&pfd, 1, timeout);
      if(r == 0) {
	/* Timeout */
	snprintf(errbuf, errbufsize, "Connection attempt timed out");
	close(fd);
	return NULL;
      }
      
      if(r == -1) {
	snprintf(errbuf, errbufsize, "poll() error: %s", strerror(errno));
	close(fd);
	return NULL;
      }

      getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen);
    } else {
      err = errno;
    }
  } else {
    err = 0;
  }

  if(err != 0) {
    snprintf(errbuf, errbufsize, "%s", strerror(err));
    close(fd);
    return NULL;
  }
  
  fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_NONBLOCK);

  val = 1;
  setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));

  tcpcon_t *tc = calloc(1, sizeof(tcpcon_t));
  tc->fd = fd;
  htsbuf_queue_init(&tc->spill, 0);
  

  if(ssl) {
#if ENABLE_OPENSSL
    if(showtime_ssl_ctx != NULL) {
      char errmsg[120];

      if((tc->ssl = SSL_new(showtime_ssl_ctx)) == NULL) {
	ERR_error_string(ERR_get_error(), errmsg);
	snprintf(errbuf, errlen, "SSL: %s", errmsg);
	tcp_close(tc);
	return NULL;
      }
      if(SSL_set_fd(tc->ssl, tc->fd) == 0) {
	ERR_error_string(ERR_get_error(), errmsg);
	snprintf(errbuf, errlen, "SSL fd: %s", errmsg);
	tcp_close(tc);
	return NULL;
      }

      if(SSL_connect(tc->ssl) <= 0) {
	ERR_error_string(ERR_get_error(), errmsg);
	snprintf(errbuf, errlen, "SSL connect: %s", errmsg);
	tcp_close(tc);
	return NULL;
      }

      SSL_set_mode(tc->ssl, SSL_MODE_AUTO_RETRY);
      tc->read = ssl_read;
      tc->write = ssl_write;
    } else
#elif ENABLE_POLARSSL
    if(1) {
      tc->ssl = malloc(sizeof(ssl_context));
      if(ssl_init(tc->ssl)) {
	snprintf(errbuf, errlen, "SSL failed to initialize");
	close(fd);
	free(tc->ssl);
	free(tc);
	return NULL;
      }

      tc->ssn = malloc(sizeof(ssl_session));
      tc->hs = malloc(sizeof(havege_state));

      havege_init(tc->hs);
      memset(tc->ssn, 0, sizeof(ssl_session));


      ssl_set_endpoint(tc->ssl, SSL_IS_CLIENT );
      ssl_set_authmode(tc->ssl, SSL_VERIFY_NONE );

      ssl_set_rng(tc->ssl, havege_rand, tc->hs );
      ssl_set_bio(tc->ssl, net_recv, &tc->fd, net_send, &tc->fd);
      ssl_set_ciphers(tc->ssl, ssl_default_ciphers );
      ssl_set_session(tc->ssl, 1, 600, tc->ssn );
      
      tc->read = polarssl_read;
      tc->write = polarssl_write;
      
    } else
#endif
    {

      snprintf(errbuf, errlen, "SSL not supported");
      tcp_close(tc);
      return NULL;
    }
  } else {
    tc->read = tcp_read;
    tc->write = tcp_write;
  }

  return tc;
}
Ejemplo n.º 21
0
/*
 * Create an SSL connection, but does not ready any post-handshake
 * NewSessionTicket messages.
 * If |read| is set and we're using DTLS then we will attempt to SSL_read on
 * the connection once we've completed one half of it, to ensure any retransmits
 * get triggered.
 */
int create_bare_ssl_connection(SSL *serverssl, SSL *clientssl, int want,
                               int read)
{
    int retc = -1, rets = -1, err, abortctr = 0;
    int clienterr = 0, servererr = 0;
    int isdtls = SSL_is_dtls(serverssl);

    do {
        err = SSL_ERROR_WANT_WRITE;
        while (!clienterr && retc <= 0 && err == SSL_ERROR_WANT_WRITE) {
            retc = SSL_connect(clientssl);
            if (retc <= 0)
                err = SSL_get_error(clientssl, retc);
        }

        if (!clienterr && retc <= 0 && err != SSL_ERROR_WANT_READ) {
            TEST_info("SSL_connect() failed %d, %d", retc, err);
            clienterr = 1;
        }
        if (want != SSL_ERROR_NONE && err == want)
            return 0;

        err = SSL_ERROR_WANT_WRITE;
        while (!servererr && rets <= 0 && err == SSL_ERROR_WANT_WRITE) {
            rets = SSL_accept(serverssl);
            if (rets <= 0)
                err = SSL_get_error(serverssl, rets);
        }

        if (!servererr && rets <= 0
                && err != SSL_ERROR_WANT_READ
                && err != SSL_ERROR_WANT_X509_LOOKUP) {
            TEST_info("SSL_accept() failed %d, %d", rets, err);
            servererr = 1;
        }
        if (want != SSL_ERROR_NONE && err == want)
            return 0;
        if (clienterr && servererr)
            return 0;
        if (isdtls && read) {
            unsigned char buf[20];

            /* Trigger any retransmits that may be appropriate */
            if (rets > 0 && retc <= 0) {
                if (SSL_read(serverssl, buf, sizeof(buf)) > 0) {
                    /* We don't expect this to succeed! */
                    TEST_info("Unexpected SSL_read() success!");
                    return 0;
                }
            }
            if (retc > 0 && rets <= 0) {
                if (SSL_read(clientssl, buf, sizeof(buf)) > 0) {
                    /* We don't expect this to succeed! */
                    TEST_info("Unexpected SSL_read() success!");
                    return 0;
                }
            }
        }
        if (++abortctr == MAXLOOPS) {
            TEST_info("No progress made");
            return 0;
        }
        if (isdtls && abortctr <= 50 && (abortctr % 10) == 0) {
            /*
             * It looks like we're just spinning. Pause for a short period to
             * give the DTLS timer a chance to do something. We only do this for
             * the first few times to prevent hangs.
             */
            ossl_sleep(50);
        }
    } while (retc <=0 || rets <= 0);

    return 1;
}
Ejemplo n.º 22
0
gboolean
_lm_ssl_begin (LmSSL *ssl, gint fd, const gchar *server, GError **error)
{
    gint ssl_ret;
    GIOStatus status;
    LmSSLBase *base;

    base = LM_SSL_BASE(ssl);
    if (!ssl->ssl_ctx) {
        g_set_error (error,
                     LM_ERROR, LM_ERROR_CONNECTION_OPEN,
                     "No SSL Context for OpenSSL");
        return FALSE;
    }

    if (base->cipher_list) {
        SSL_CTX_set_cipher_list(ssl->ssl_ctx, base->cipher_list);
    }
    if (base->ca_path) {
        _lm_ssl_set_ca (ssl, base->ca_path);
    } else {
        SSL_CTX_set_default_verify_paths (ssl->ssl_ctx);
    }

    ssl->ssl = SSL_new(ssl->ssl_ctx);
    if (ssl->ssl == NULL) {
        g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SSL, "SSL_new() == NULL");
        g_set_error(error, LM_ERROR, LM_ERROR_CONNECTION_OPEN,
                    "SSL_new()");
        return FALSE;
    }

    if (!SSL_set_fd (ssl->ssl, fd)) {
        g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SSL, "SSL_set_fd() failed");
        g_set_error(error, LM_ERROR, LM_ERROR_CONNECTION_OPEN,
                    "SSL_set_fd()");
        return FALSE;
    }
    /*ssl->bio = BIO_new_socket (fd, BIO_NOCLOSE);
      if (ssl->bio == NULL) {
      g_warning("BIO_new_socket() failed");
      g_set_error(error, LM_ERROR, LM_ERROR_CONNECTION_OPEN,
      "BIO_new_socket()");
      return FALSE;
      }
      SSL_set_bio(ssl->ssl, ssl->bio, ssl->bio);*/

    do {
        ssl_ret = SSL_connect(ssl->ssl);
        if (ssl_ret <= 0) {
            status = ssl_io_status_from_return(ssl, ssl_ret);
            if (status != G_IO_STATUS_AGAIN) {
                ssl_print_state(ssl, "SSL_connect",
                                ssl_ret);
                g_set_error(error, LM_ERROR,
                            LM_ERROR_CONNECTION_OPEN,
                            "SSL_connect()");
                return FALSE;
            }

        }
    } while (ssl_ret <= 0);

    if (!ssl_verify_certificate (ssl, server)) {
        g_set_error (error, LM_ERROR, LM_ERROR_CONNECTION_OPEN,
                     "*** SSL certificate verification failed");
        return FALSE;
    }

    return TRUE;
}
Ejemplo n.º 23
0
int
lws_ssl_client_connect2(struct lws *wsi)
{
	struct lws_context *context = wsi->context;
	struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
	char *p = (char *)&pt->serv_buf[0];
	char *sb = p;
	int n;

	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) {
				wsi->mode = LWSCM_WSCL_WAITING_SSL;

				return 0; /* no error */
			}

			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);

				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;
			}
		}
	}

#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, x509: %s\n",
				 n, ERR_error_string(n, sb),  X509_verify_cert_error_string(n));
			lws_close_free_wsi(wsi,
				LWS_CLOSE_STATUS_NOSTATUS);
			return 0;
		}
	}
#endif /* USE_WOLFSSL */

	return 1;
}
netsnmp_transport *
netsnmp_tlstcp_open(netsnmp_transport *t)
{
    _netsnmpTLSBaseData *tlsdata;
    BIO *bio;
    SSL_CTX *ctx;
    SSL *ssl;
    int rc = 0;
    _netsnmp_verify_info *verify_info;

    netsnmp_assert_or_return(t != NULL, NULL);
    netsnmp_assert_or_return(t->data != NULL, NULL);
    netsnmp_assert_or_return(sizeof(_netsnmpTLSBaseData) == t->data_length,
                             NULL);

    tlsdata = t->data;
    
    if (tlsdata->flags & NETSNMP_TLSBASE_IS_CLIENT) {
        /* Is the client */

        /* RFC5953 Section 5.3.1:  Establishing a Session as a Client
         *    1)  The snmpTlstmSessionOpens counter is incremented.
         */
        snmp_increment_statistic(STAT_TLSTM_SNMPTLSTMSESSIONOPENS);

        /* RFC5953 Section 5.3.1:  Establishing a Session as a Client
          2)  The client selects the appropriate certificate and cipher_suites
              for the key agreement based on the tmSecurityName and the
              tmRequestedSecurityLevel for the session.  For sessions being
              established as a result of a SNMP-TARGET-MIB based operation, the
              certificate will potentially have been identified via the
              snmpTlstmParamsTable mapping and the cipher_suites will have to
              be taken from system-wide or implementation-specific
              configuration.  If no row in the snmpTlstmParamsTable exists then
              implementations MAY choose to establish the connection using a
              default client certificate available to the application.
              Otherwise, the certificate and appropriate cipher_suites will
              need to be passed to the openSession() ASI as supplemental
              information or configured through an implementation-dependent
              mechanism.  It is also implementation-dependent and possibly
              policy-dependent how tmRequestedSecurityLevel will be used to
              influence the security capabilities provided by the (D)TLS
              connection.  However this is done, the security capabilities
              provided by (D)TLS MUST be at least as high as the level of
              security indicated by the tmRequestedSecurityLevel parameter.
              The actual security level of the session is reported in the
              tmStateReference cache as tmSecurityLevel.  For (D)TLS to provide
              strong authentication, each principal acting as a command
              generator SHOULD have its own certificate.
        */
        /*
          Implementation notes: we do most of this in the
          sslctx_client_setup The transport should have been
          f_config()ed with the proper fingerprints to use (which is
          stored in tlsdata), or we'll use the default identity
          fingerprint if that can be found.
        */

        /* XXX: check securityLevel and ensure no NULL fingerprints are used */

        /* set up the needed SSL context */
        tlsdata->ssl_context = ctx =
            sslctx_client_setup(TLSv1_method(), tlsdata);
        if (!ctx) {
            snmp_log(LOG_ERR, "failed to create TLS context\n");
            return NULL;
        }

        /* RFC5953 Section 5.3.1:  Establishing a Session as a Client
           3)  Using the destTransportDomain and destTransportAddress values,
               the client will initiate the (D)TLS handshake protocol to
               establish session keys for message integrity and encryption.
        */
        /* Implementation note:
           The transport domain and address are pre-processed by this point
        */

        /* Create a BIO connection for it */
        DEBUGMSGTL(("tlstcp", "connecting to tlstcp %s\n",
		    tlsdata->addr_string));
        t->remote = (void *) strdup(tlsdata->addr_string);
        t->remote_length = strlen(tlsdata->addr_string) + 1;

        bio = BIO_new_connect(tlsdata->addr_string);

        /* RFC5953 Section 5.3.1:  Establishing a Session as a Client
           3) continued:
              If the attempt to establish a session is unsuccessful, then
              snmpTlstmSessionOpenErrors is incremented, an error indication is
              returned, and processing stops.
        */

        if (NULL == bio) {
            snmp_increment_statistic(STAT_TLSTM_SNMPTLSTMSESSIONOPENERRORS);
            snmp_log(LOG_ERR, "tlstcp: failed to create bio\n");
            _openssl_log_error(rc, NULL, "BIO creation");
            SNMP_FREE(tlsdata);
            SNMP_FREE(t);
            return NULL;
        }
            

        /* Tell the BIO to actually do the connection */
        if ((rc = BIO_do_connect(bio)) <= 0) {
            snmp_increment_statistic(STAT_TLSTM_SNMPTLSTMSESSIONOPENERRORS);
            snmp_log(LOG_ERR, "tlstcp: failed to connect to %s\n",
		     tlsdata->addr_string);
            _openssl_log_error(rc, NULL, "BIO_do_connect");
            BIO_free(bio);
            SNMP_FREE(tlsdata);
            SNMP_FREE(t);
            return NULL;
        }

        /* Create the SSL layer on top of the socket bio */
        ssl = tlsdata->ssl = SSL_new(ctx);
        if (NULL == ssl) {
            snmp_increment_statistic(STAT_TLSTM_SNMPTLSTMSESSIONOPENERRORS);
            snmp_log(LOG_ERR, "tlstcp: failed to create a SSL connection\n");
            BIO_free(bio);
            SNMP_FREE(tlsdata);
            SNMP_FREE(t);
            return NULL;
        }
        
        /* Bind the SSL layer to the BIO */ 
        SSL_set_bio(ssl, bio, bio);
        SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);

        verify_info = SNMP_MALLOC_TYPEDEF(_netsnmp_verify_info);
        if (NULL == verify_info) {
            snmp_increment_statistic(STAT_TLSTM_SNMPTLSTMSESSIONOPENERRORS);
            snmp_log(LOG_ERR, "tlstcp: failed to create a SSL connection\n");
            SSL_shutdown(ssl);
            BIO_free(bio);
            SNMP_FREE(tlsdata);
            SNMP_FREE(t);
            return NULL;
        }

        SSL_set_ex_data(ssl, tls_get_verify_info_index(), verify_info);

        /* Then have SSL do it's connection over the BIO */
        if ((rc = SSL_connect(ssl)) <= 0) {
            snmp_increment_statistic(STAT_TLSTM_SNMPTLSTMSESSIONOPENERRORS);
            snmp_log(LOG_ERR, "tlstcp: failed to ssl_connect\n");
            BIO_free(bio);
            SNMP_FREE(tlsdata);
            SNMP_FREE(t);
            return NULL;
        }

        /* RFC5953 Section 5.3.1: Establishing a Session as a Client
           3) continued:
              If the session failed to open because the presented
              server certificate was unknown or invalid then the
              snmpTlstmSessionUnknownServerCertificate or
              snmpTlstmSessionInvalidServerCertificates MUST be
              incremented and a snmpTlstmServerCertificateUnknown or
              snmpTlstmServerInvalidCertificate notification SHOULD be
              sent as appropriate.  Reasons for server certificate
              invalidation includes, but is not limited to,
              cryptographic validation failures and an unexpected
              presented certificate identity.
        */

        /* RFC5953 Section 5.3.1: Establishing a Session as a Client
           4)  The (D)TLS client MUST then verify that the (D)TLS server's
               presented certificate is the expected certificate.  The (D)TLS
               client MUST NOT transmit SNMP messages until the server
               certificate has been authenticated, the client certificate has
               been transmitted and the TLS connection has been fully
               established.

               If the connection is being established from configuration based
               on SNMP-TARGET-MIB configuration, then the snmpTlstmAddrTable
               DESCRIPTION clause describes how the verification is done (using
               either a certificate fingerprint, or an identity authenticated
               via certification path validation).

               If the connection is being established for reasons other than
               configuration found in the SNMP-TARGET-MIB then configuration and
               procedures outside the scope of this document should be followed.
               Configuration mechanisms SHOULD be similar in nature to those
               defined in the snmpTlstmAddrTable to ensure consistency across
               management configuration systems.  For example, a command-line
               tool for generating SNMP GETs might support specifying either the
               server's certificate fingerprint or the expected host name as a
               command line argument.
        */

        /* Implementation notes:
           - All remote certificate fingerprints are expected to be
             stored in the transport's config information.  This is
             true both for CLI clients and TARGET-MIB sessions.
           - netsnmp_tlsbase_verify_server_cert implements these checks
        */
        if (netsnmp_tlsbase_verify_server_cert(ssl, tlsdata) != SNMPERR_SUCCESS) {
            /* XXX: unknown vs invalid; two counters */
            snmp_increment_statistic(STAT_TLSTM_SNMPTLSTMSESSIONUNKNOWNSERVERCERTIFICATE);
            snmp_log(LOG_ERR, "tlstcp: failed to verify ssl certificate\n");
            SSL_shutdown(ssl);
            BIO_free(bio);
            SNMP_FREE(tlsdata);
            SNMP_FREE(t);
            return NULL;
        }

        /* RFC5953 Section 5.3.1: Establishing a Session as a Client
           5)  (D)TLS provides assurance that the authenticated identity has
               been signed by a trusted configured certification authority.  If
               verification of the server's certificate fails in any way (for
               example because of failures in cryptographic verification or the
               presented identity did not match the expected named entity) then
               the session establishment MUST fail, the
               snmpTlstmSessionInvalidServerCertificates object is incremented.
               If the session can not be opened for any reason at all, including
               cryptographic verification failures, then the
               snmpTlstmSessionOpenErrors counter is incremented and processing
               stops.

        */
        /* XXX: add snmpTlstmSessionInvalidServerCertificates on
           crypto failure */

        /* RFC5953 Section 5.3.1: Establishing a Session as a Client
           6)  The TLSTM-specific session identifier (tlstmSessionID) is set in
           the tmSessionID of the tmStateReference passed to the TLS
           Transport Model to indicate that the session has been established
           successfully and to point to a specific (D)TLS connection for
           future use.  The tlstmSessionID is also stored in the LCD for
           later lookup during processing of incoming messages
           (Section 5.1.2).
        */
        /* Implementation notes:
           - the tlsdata pointer is used as our session identifier, as
             noted in the netsnmp_tlstcp_recv() function comments.
        */

        t->sock = BIO_get_fd(bio, NULL);

    } else {
        /* Is the server */
        
        /* Create the socket bio */
        DEBUGMSGTL(("tlstcp", "listening on tlstcp port %s\n",
		    tlsdata->addr_string));
        tlsdata->accept_bio = BIO_new_accept(tlsdata->addr_string);
        t->local = (void *) strdup(tlsdata->addr_string);
        t->local_length = strlen(tlsdata->addr_string)+1;
        if (NULL == tlsdata->accept_bio) {
            SNMP_FREE(t);
            SNMP_FREE(tlsdata);
            snmp_log(LOG_ERR, "TLSTCP: Falied to create a accept BIO\n");
            return NULL;
        }

        /* openssl requires an initial accept to bind() the socket */
        if (BIO_do_accept(tlsdata->accept_bio) <= 0) {
	    _openssl_log_error(rc, tlsdata->ssl, "BIO_do__accept");
            SNMP_FREE(t);
            SNMP_FREE(tlsdata);
            snmp_log(LOG_ERR, "TLSTCP: Falied to do first accept on the TLS accept BIO\n");
            return NULL;
        }

        /* create the OpenSSL TLS context */
        tlsdata->ssl_context =
            sslctx_server_setup(TLSv1_method());

        t->sock = BIO_get_fd(tlsdata->accept_bio, NULL);
        t->flags |= NETSNMP_TRANSPORT_FLAG_LISTEN;
    }
    return t;
}
Ejemplo n.º 25
0
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;

#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,
				context->timeout_secs);

		/* 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,
				context->timeout_secs);
		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;
}
Ejemplo n.º 26
0
Archivo: tls.c Proyecto: yomei-o/msmtp
int tls_start(tls_t *tls, int fd, const char *hostname, int no_certcheck,
        tls_cert_info_t *tci, char **errstr)
{
#ifdef HAVE_LIBGNUTLS
    int error_code;

    gnutls_transport_set_ptr(tls->session, (gnutls_transport_ptr_t)fd);
    do
    {
        error_code = gnutls_handshake(tls->session);
    }
    while (error_code < 0 && gnutls_error_is_fatal(error_code) == 0);

    if (error_code != 0)
    {
        *errstr = xasprintf(_("TLS handshake failed: %s"),
                gnutls_strerror(error_code));
        gnutls_deinit(tls->session);
        gnutls_certificate_free_credentials(tls->cred);
        return TLS_EHANDSHAKE;
    }
    if (tci)
    {
        if ((error_code = tls_cert_info_get(tls, tci, errstr)) != TLS_EOK)
        {
            gnutls_deinit(tls->session);
            gnutls_certificate_free_credentials(tls->cred);
            return error_code;
        }
    }
    if (!no_certcheck)
    {
        if ((error_code = tls_check_cert(tls, hostname, errstr)) != TLS_EOK)
        {
            gnutls_deinit(tls->session);
            gnutls_certificate_free_credentials(tls->cred);
            return error_code;
        }
    }
    tls->is_active = 1;
    return TLS_EOK;
#endif /* HAVE_LIBGNUTLS */

#ifdef HAVE_LIBSSL
    int error_code;

    if (!SSL_set_fd(tls->ssl, fd))
    {
        *errstr = xasprintf(_("cannot set the file descriptor for TLS: %s"),
                ERR_error_string(ERR_get_error(), NULL));
        SSL_free(tls->ssl);
        SSL_CTX_free(tls->ssl_ctx);
        return TLS_ELIBFAILED;
    }
    if ((error_code = SSL_connect(tls->ssl)) < 1)
    {
        if (errno == EINTR
                && (SSL_get_error(tls->ssl, error_code) == SSL_ERROR_WANT_READ
                    || SSL_get_error(tls->ssl, error_code)
                    == SSL_ERROR_WANT_WRITE))
        {
            *errstr = xasprintf(_("operation aborted"));
        }
        else
        {
            *errstr = openssl_io_error(error_code,
                    SSL_get_error(tls->ssl, error_code),
                    _("TLS handshake failed"));
        }
        SSL_free(tls->ssl);
        SSL_CTX_free(tls->ssl_ctx);
        return TLS_EIO;
    }
    if (tci)
    {
        if ((error_code = tls_cert_info_get(tls, tci, errstr)) != TLS_EOK)
        {
            SSL_free(tls->ssl);
            SSL_CTX_free(tls->ssl_ctx);
            return error_code;
        }
    }
    if (!no_certcheck)
    {
        if ((error_code = tls_check_cert(tls, hostname, errstr)) != TLS_EOK)
        {
            SSL_free(tls->ssl);
            SSL_CTX_free(tls->ssl_ctx);
            return error_code;
        }
    }
    tls->is_active = 1;
    return TLS_EOK;
#endif /* HAVE_LIBSSL */
}
Ejemplo n.º 27
0
static struct mailstream_ssl_data * ssl_data_new_full(int fd, SSL_METHOD * method, void (* callback)(struct mailstream_ssl_context * ssl_context, void * cb_data), void * cb_data)
{
  struct mailstream_ssl_data * ssl_data;
  SSL * ssl_conn;
  int r;
  SSL_CTX * tmp_ctx;
  struct mailstream_cancel * cancel;
  struct mailstream_ssl_context * ssl_context = NULL;
  
  mailstream_ssl_init();
  
  tmp_ctx = SSL_CTX_new(method);
  if (tmp_ctx == NULL)
    goto err;
  
  if (callback != NULL) {
    ssl_context = mailstream_ssl_context_new(tmp_ctx, fd);
    callback(ssl_context, cb_data);
  }
  
  SSL_CTX_set_app_data(tmp_ctx, ssl_context);
  SSL_CTX_set_client_cert_cb(tmp_ctx, mailstream_openssl_client_cert_cb);
  ssl_conn = (SSL *) SSL_new(tmp_ctx);
  if (ssl_conn == NULL)
    goto free_ctx;
  
  if (SSL_set_fd(ssl_conn, fd) == 0)
    goto free_ssl_conn;
  
again:
  r = SSL_connect(ssl_conn);

  switch(SSL_get_error(ssl_conn, r)) {
  	case SSL_ERROR_WANT_READ:
          r = wait_SSL_connect(fd, 1);
          if (r < 0)
            goto free_ssl_conn;
	  else
	    goto again;
	break;
	case SSL_ERROR_WANT_WRITE:
          r = wait_SSL_connect(fd, 0);
          if (r < 0)
            goto free_ssl_conn;
	  else
	    goto again;
	break;
  }
  if (r <= 0)
    goto free_ssl_conn;
  
  cancel = mailstream_cancel_new();
  if (cancel == NULL)
    goto free_ssl_conn;
  
  r = mailstream_prepare_fd(fd);
  if (r < 0)
    goto free_cancel;
  
  ssl_data = malloc(sizeof(* ssl_data));
  if (ssl_data == NULL)
    goto free_cancel;
  
  ssl_data->fd = fd;
  ssl_data->ssl_conn = ssl_conn;
  ssl_data->ssl_ctx = tmp_ctx;
  ssl_data->cancel = cancel;
  mailstream_ssl_context_free(ssl_context);

  return ssl_data;

 free_cancel:
  mailstream_cancel_free(cancel);
 free_ssl_conn:
  SSL_free(ssl_conn);
 free_ctx:
  SSL_CTX_free(tmp_ctx);
  mailstream_ssl_context_free(ssl_context);
 err:
  return NULL;
}
int WebRequest::Request (
    int request_type
    , std::string url_host
    , int url_port
    , std::string url_path
    , std::string data
) {
	bool secure = false;
	
    mMessageHeader = "";
	mMessageBody.clear();
    // temp fix for POST recognition
    data = "_start_=1&" + data + "&_end_=1";
    
    mReadSize = 1024;
    mError = 0;
	
    if(request_type == HTTPS_GET
        || request_type == HTTPS_POST
        || request_type == HTTPS_PUT
        || request_type == HTTPS_DELETE) {
	   secure = true;		
    }

    #ifdef WIN32
    WSADATA wsa;
    
    // startup winsock
    mError = WSAStartup(MAKEWORD(2,0),&wsa);
    
    if(mError) {
        printf("Error in Startup = %d\n", mError);
        return -1;
    }
    #endif

    // socket 
    int socket = 0;

    // struct for socket
    struct sockaddr_in host_addr = {0};

    // information about host
    struct hostent *host = {0};

    // request of client
    std::string request;
    
    // SSL context
    SSL_CTX *sslContext = NULL;

    // SSL socket
    SSL *sslSocket = NULL;

    // get IP from name host
    host = gethostbyname(url_host.c_str());

    if (host == NULL) {
        printf("Unknown Host %s\n", url_host.c_str());
	return -1;
    }

    // create socket TCP
    socket = ::socket(PF_INET, SOCK_STREAM, 0);

    if (socket < 0) {
	printf("Socket Error\n");
        return -1;
    }

    // create host struct
    host_addr.sin_family = AF_INET;
    // set IP addres
    host_addr.sin_addr = *((struct in_addr *)host->h_addr);
    // set HTTP port
    host_addr.sin_port = htons(url_port);

    // connect
    mError = connect(socket, (struct sockaddr *)&host_addr, sizeof(host_addr));
	
    if (mError == -1) {
    	CloseSocket(socket);
	printf("Connection Error\n");
	return -1;
    }

    if(secure) {
        // init OpenSSL
	SSL_load_error_strings();
	SSL_library_init();

	// create context 
	sslContext = SSL_CTX_new(SSLv23_client_method());

	//create ssl socket
	sslSocket = SSL_new(sslContext);
	
	if(!sslSocket) {
	    CloseSocket(socket);
	    printf("SSL creation error\n");
	    return -1;
	}

        // join sslSocket and socket
	SSL_set_fd(sslSocket, socket);

	// conect sslSocket
	mError = SSL_connect(sslSocket);

	if(!mError) {
	    CloseSocket(socket);
	    printf("SSL connect error = %d\n", mError);
	    mError = SSL_get_error(sslSocket, mError);
	    printf("SSL error: %d\n", mError);
            //std::cin.get();
	    return -1;
	}
    }

    if(request_type == HTTP_GET || request_type == HTTPS_GET) {
	    //create get request
        request = "GET " + url_path + " HTTP/1.0\nHost: " + url_host + " \r\n\r\n";	  
    }
    else if(request_type == HTTP_POST || request_type == HTTPS_POST) {
	    //create get request
	    request = "POST " + url_path + " HTTP/1.0\nHost: " + url_host + "\nContent-Length: " + to_string(data.length()) + "\nContent-Type: application/x-www-form-urlencoded\n" + "\r\n\r\n" + data + "\r\n";	  
    }
    // TODO add DELETE and PUT
    // send data to server

    if(secure) {
        mError = SSL_write(sslSocket, request.c_str(), strlen(request.c_str()));
    }
    else {
        mError = send(socket, request.c_str(), strlen(request.c_str()), 0);
    }
    
    // read in header and body

    char bufferHeader[1];
    int readHeader;
    int lineLength;
    bool loop = true;
    bool bHeader = false;

    // header
    
    mMessageHeader = "";

    while(loop) {
    	if(secure)
            readHeader = SSL_read(sslSocket, bufferHeader, 1);
        else
            readHeader = recv(socket, bufferHeader, 1, 0);
        if(readHeader < 0) loop = false;
        if(bufferHeader[0]=='\n') {
           if(lineLength == 0) loop = false;

           lineLength = 0;
           if(mMessageHeader.find("200") != std::string::npos)
               bHeader = true;

        }
        else if(bufferHeader[0]!='\r') lineLength++;

        mMessageHeader += bufferHeader[0];
    }

    // body

    mMessageBody.clear();

    if(bHeader) {
        unsigned char bufferBody[1024];
        
        if(secure) {
            while((readHeader = SSL_read(sslSocket, bufferBody, sizeof(bufferBody))) > 0) {
				mMessageBody.insert(mMessageBody.end(), bufferBody, bufferBody + readHeader);
            }
        }
        else {
            while((readHeader = recv(socket, (char*)bufferBody, sizeof(bufferBody), 0)) > 0) {
				mMessageBody.insert(mMessageBody.end(), bufferBody, bufferBody + readHeader);
            }
        }
    }

    if(secure) {
        switch(SSL_get_error( sslSocket, mReadSize )) {
	    case SSL_ERROR_ZERO_RETURN: printf( "\n\nSSL::ZERO\n\n" );  break;
            case SSL_ERROR_NONE:        printf( "\n\nSSL::No Error\n\n" );	break;
            case SSL_ERROR_SSL:         printf( "\n\nSSL::SSL ERROR\n\n" ); break;
        }
    }

    #if WIN32
        Sleep(1);   
    #else
 	sleep(1); 
    #endif

    if(secure) {
	
	//close SSLsocket
        SSL_shutdown(sslSocket);
	    //free memory
        SSL_free(sslSocket);
	    // free context
        SSL_CTX_free(sslContext);
    }

    //close scoket
    CloseSocket(socket);

    return 0;
}
Ejemplo n.º 29
0
BOOL 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->PublicKey, &tls->PublicKeyLength))
	{
		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;
}
Ejemplo n.º 30
0
int openSSLConnect()
{
	if(m_ctx == NULL)
		return SSL_PROBLEM;

	m_ssl = SSL_new (m_ctx);   
	if(m_ssl == NULL)
		return SSL_PROBLEM;

	SSL_set_fd (m_ssl, (int)smtp_socket);
	SSL_set_mode(m_ssl, SSL_MODE_AUTO_RETRY);

	int res = 0;
	fd_set fdwrite;
	fd_set fdread;
	int write_blocked = 0;
	int read_blocked = 0;

	timeval time;
	time.tv_sec = TIME_IN_SEC;
	time.tv_usec = 0;

	while(1)
	{
		FD_ZERO(&fdwrite);
		FD_ZERO(&fdread);

		if(write_blocked)
			FD_SET(smtp_socket, &fdwrite);
		if(read_blocked)
			FD_SET(smtp_socket, &fdread);

		if(write_blocked || read_blocked)
		{
			write_blocked = 0;
			read_blocked = 0;
			if((res = select(smtp_socket+1,&fdread,&fdwrite,NULL,&time)) == SOCKET_ERROR)
			{
				FD_ZERO(&fdwrite);
				FD_ZERO(&fdread);
				return WSA_SELECT;
			}
			if(!res)
			{
				//timeout
				FD_ZERO(&fdwrite);
				FD_ZERO(&fdread);
				return SERVER_NOT_RESPONDING;
			}
		}
		res = SSL_connect(m_ssl);
		switch(SSL_get_error(m_ssl, res))
		{
		case SSL_ERROR_NONE:
			FD_ZERO(&fdwrite);
			FD_ZERO(&fdread);
			return CSMTP_NO_ERROR;
			break;

		case SSL_ERROR_WANT_WRITE:
			write_blocked = 1;
			break;

		case SSL_ERROR_WANT_READ:
			read_blocked = 1;
			break;

		default:	      
			FD_ZERO(&fdwrite);
			FD_ZERO(&fdread);
			return SSL_PROBLEM;
		}
	}

	return CSMTP_NO_ERROR;
}