Beispiel #1
2
int main(int count, char *strings[])
{   
    FILE * fp;   
    clock_t begin, end;
    double time_spent;

    SSL_CTX *ctx;
    int server,i=0;
    SSL *ssl;
    char buf[1024];
    int bytes;
    char *hostname, *portnum;

while (i<86400) 
{
    begin = clock(); //start time measurement - harith
    
    if ( count != 3 )
    {
        printf("usage: %s <hostname> <portnum>\n", strings[0]);
        exit(0);
    }
    SSL_library_init();
    hostname=strings[1];
    portnum=strings[2];
 
    ctx = InitCTX();
    server = OpenConnection(hostname, atoi(portnum));
    ssl = SSL_new(ctx);      /* create new SSL connection state */
    SSL_set_fd(ssl, server);    /* attach the socket descriptor */
    if ( SSL_connect(ssl) == FAIL )   /* perform the connection */
        ERR_print_errors_fp(stderr);
    else
    {   char *msg = "Hello???";
 
        printf("Connected with %s encryption\n", SSL_get_cipher(ssl));
        ShowCerts(ssl);        /* get any certs */
        SSL_write(ssl, msg, strlen(msg));   /* encrypt & send message */
        bytes = SSL_read(ssl, buf, sizeof(buf)); /* get reply & decrypt */
        buf[bytes] = 0;
        printf("Received: \"%s\"\n\n", buf);
        SSL_free(ssl);        /* release connection state */
    }
    close(server);         /* close socket */
    SSL_CTX_free(ctx);        /* release context */
    
    end = clock(); // stop time measurement -- harith
    time_spent = (double)(end - begin) / CLOCKS_PER_SEC * 1000;
      //printf("Total execution time is: %f \n", time_spent);
      //reset time
      	begin = 0;
	end   = 0; 
      
	fp = fopen( "logfile.txt", "a" ); // Open file for writing

    fprintf(fp, "Sequence %d, Time taken: %f ms \r\n",i,time_spent);

    fclose(fp);
    i++;
    sleep(1);
}
    return 0;
}
Beispiel #2
0
int s_time_main(int argc, char **argv)
{
    char buf[1024 * 8];
    SSL *scon = NULL;
    SSL_CTX *ctx = NULL;
    const SSL_METHOD *meth = NULL;
    char *CApath = NULL, *CAfile = NULL, *cipher = NULL, *www_path = NULL;
    char *host = SSL_CONNECT_NAME, *certfile = NULL, *keyfile = NULL, *prog;
    double totalTime = 0.0;
    int noCApath = 0, noCAfile = 0;
    int maxtime = SECONDS, nConn = 0, perform = 3, ret = 1, i, st_bugs =
        0, ver;
    long bytes_read = 0, finishtime = 0;
    OPTION_CHOICE o;

    meth = TLS_client_method();
    verify_depth = 0;
    verify_error = X509_V_OK;

    prog = opt_init(argc, argv, s_time_options);
    while ((o = opt_next()) != OPT_EOF) {
        switch (o) {
        case OPT_EOF:
        case OPT_ERR:
 opthelp:
            BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
            goto end;
        case OPT_HELP:
            opt_help(s_time_options);
            ret = 0;
            goto end;
        case OPT_CONNECT:
            host = opt_arg();
            break;
        case OPT_REUSE:
            perform = 2;
            break;
        case OPT_NEW:
            perform = 1;
            break;
        case OPT_VERIFY:
            if (!opt_int(opt_arg(), &verify_depth))
                goto opthelp;
            BIO_printf(bio_err, "%s: verify depth is %d\n",
                       prog, verify_depth);
            break;
        case OPT_CERT:
            certfile = opt_arg();
            break;
        case OPT_KEY:
            keyfile = opt_arg();
            break;
        case OPT_CAPATH:
            CApath = opt_arg();
            break;
        case OPT_CAFILE:
            CAfile = opt_arg();
            break;
        case OPT_NOCAPATH:
            noCApath = 1;
            break;
        case OPT_NOCAFILE:
            noCAfile = 1;
            break;
        case OPT_CIPHER:
            cipher = opt_arg();
            break;
        case OPT_BUGS:
            st_bugs = 1;
            break;
        case OPT_TIME:
            if (!opt_int(opt_arg(), &maxtime))
                goto opthelp;
            break;
        case OPT_WWW:
            www_path = opt_arg();
            if (strlen(www_path) > MYBUFSIZ - 100) {
                BIO_printf(bio_err, "%s: -www option too long\n", prog);
                goto end;
            }
            break;
        case OPT_SSL3:
#ifndef OPENSSL_NO_SSL3
            meth = SSLv3_client_method();
#endif
            break;
        }
    }
    argc = opt_num_rest();
    if (argc != 0)
        goto opthelp;

    if (cipher == NULL)
        cipher = getenv("SSL_CIPHER");
    if (cipher == NULL) {
        BIO_printf(bio_err, "No CIPHER specified\n");
        goto end;
    }

    if ((ctx = SSL_CTX_new(meth)) == NULL)
        goto end;

    SSL_CTX_set_quiet_shutdown(ctx, 1);

    if (st_bugs)
        SSL_CTX_set_options(ctx, SSL_OP_ALL);
    if (!SSL_CTX_set_cipher_list(ctx, cipher))
        goto end;
    if (!set_cert_stuff(ctx, certfile, keyfile))
        goto end;

    if (!ctx_set_verify_locations(ctx, CAfile, CApath, noCAfile, noCApath)) {
        ERR_print_errors(bio_err);
        goto end;
    }
    if (!(perform & 1))
        goto next;
    printf("Collecting connection statistics for %d seconds\n", maxtime);

    /* Loop and time how long it takes to make connections */

    bytes_read = 0;
    finishtime = (long)time(NULL) + maxtime;
    tm_Time_F(START);
    for (;;) {
        if (finishtime < (long)time(NULL))
            break;

        if ((scon = doConnection(NULL, host, ctx)) == NULL)
            goto end;

        if (www_path != NULL) {
            BIO_snprintf(buf, sizeof buf, "GET %s HTTP/1.0\r\n\r\n",
                         www_path);
            if (SSL_write(scon, buf, strlen(buf)) <= 0)
                goto end;
            while ((i = SSL_read(scon, buf, sizeof(buf))) > 0)
                bytes_read += i;
        }
#ifdef NO_SHUTDOWN
        SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
#else
        SSL_shutdown(scon);
#endif
        SHUTDOWN2(SSL_get_fd(scon));

        nConn += 1;
        if (SSL_session_reused(scon))
            ver = 'r';
        else {
            ver = SSL_version(scon);
            if (ver == TLS1_VERSION)
                ver = 't';
            else if (ver == SSL3_VERSION)
                ver = '3';
            else
                ver = '*';
        }
        fputc(ver, stdout);
        fflush(stdout);

        SSL_free(scon);
        scon = NULL;
    }
    totalTime += tm_Time_F(STOP); /* Add the time for this iteration */

    i = (int)((long)time(NULL) - finishtime + maxtime);
    printf
        ("\n\n%d connections in %.2fs; %.2f connections/user sec, bytes read %ld\n",
         nConn, totalTime, ((double)nConn / totalTime), bytes_read);
    printf
        ("%d connections in %ld real seconds, %ld bytes read per connection\n",
         nConn, (long)time(NULL) - finishtime + maxtime, bytes_read / nConn);

    /*
     * Now loop and time connections using the same session id over and over
     */

 next:
    if (!(perform & 2))
        goto end;
    printf("\n\nNow timing with session id reuse.\n");

    /* Get an SSL object so we can reuse the session id */
    if ((scon = doConnection(NULL, host, ctx)) == NULL) {
        BIO_printf(bio_err, "Unable to get connection\n");
        goto end;
    }

    if (www_path != NULL) {
        BIO_snprintf(buf, sizeof buf, "GET %s HTTP/1.0\r\n\r\n", www_path);
        if (SSL_write(scon, buf, strlen(buf)) <= 0)
            goto end;
        while (SSL_read(scon, buf, sizeof(buf)) > 0)
            continue;
    }
#ifdef NO_SHUTDOWN
    SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
#else
    SSL_shutdown(scon);
#endif
    SHUTDOWN2(SSL_get_fd(scon));

    nConn = 0;
    totalTime = 0.0;

    finishtime = (long)time(NULL) + maxtime;

    printf("starting\n");
    bytes_read = 0;
    tm_Time_F(START);

    for (;;) {
        if (finishtime < (long)time(NULL))
            break;

        if ((doConnection(scon, host, ctx)) == NULL)
            goto end;

        if (www_path) {
            BIO_snprintf(buf, sizeof buf, "GET %s HTTP/1.0\r\n\r\n",
                         www_path);
            if (SSL_write(scon, buf, strlen(buf)) <= 0)
                goto end;
            while ((i = SSL_read(scon, buf, sizeof(buf))) > 0)
                bytes_read += i;
        }
#ifdef NO_SHUTDOWN
        SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
#else
        SSL_shutdown(scon);
#endif
        SHUTDOWN2(SSL_get_fd(scon));

        nConn += 1;
        if (SSL_session_reused(scon))
            ver = 'r';
        else {
            ver = SSL_version(scon);
            if (ver == TLS1_VERSION)
                ver = 't';
            else if (ver == SSL3_VERSION)
                ver = '3';
            else
                ver = '*';
        }
        fputc(ver, stdout);
        fflush(stdout);
    }
    totalTime += tm_Time_F(STOP); /* Add the time for this iteration */

    printf
        ("\n\n%d connections in %.2fs; %.2f connections/user sec, bytes read %ld\n",
         nConn, totalTime, ((double)nConn / totalTime), bytes_read);
    printf
        ("%d connections in %ld real seconds, %ld bytes read per connection\n",
         nConn, (long)time(NULL) - finishtime + maxtime, bytes_read / nConn);

    ret = 0;

 end:
    SSL_free(scon);
    SSL_CTX_free(ctx);
    return (ret);
}
Beispiel #3
0
static void do_reneg_setup_step(const SSL_TEST_CTX *test_ctx, PEER *peer)
{
    int ret;
    char buf;

    TEST_check(peer->status == PEER_RETRY);
    TEST_check(test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_RENEG_SERVER
                || test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_RENEG_CLIENT);

    /* Check if we are the peer that is going to initiate */
    if ((test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_RENEG_SERVER
                && SSL_is_server(peer->ssl))
            || (test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_RENEG_CLIENT
                && !SSL_is_server(peer->ssl))) {
        /*
         * If we already asked for a renegotiation then fall through to the
         * SSL_read() below.
         */
        if (!SSL_renegotiate_pending(peer->ssl)) {
            /*
             * If we are the client we will always attempt to resume the
             * session. The server may or may not resume dependant on the
             * setting of SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
             */
            if (SSL_is_server(peer->ssl))
                ret = SSL_renegotiate(peer->ssl);
            else
                ret = SSL_renegotiate_abbreviated(peer->ssl);
            if (!ret) {
                peer->status = PEER_ERROR;
                return;
            }
            do_handshake_step(peer);
            /*
             * If status is PEER_RETRY it means we're waiting on the peer to
             * continue the handshake. As far as setting up the renegotiation is
             * concerned that is a success. The next step will continue the
             * handshake to its conclusion.
             *
             * If status is PEER_SUCCESS then we are the server and we have
             * successfully sent the HelloRequest. We need to continue to wait
             * until the handshake arrives from the client.
             */
            if (peer->status == PEER_RETRY)
                peer->status = PEER_SUCCESS;
            else if (peer->status == PEER_SUCCESS)
                peer->status = PEER_RETRY;
            return;
        }
    }

    /*
     * The SSL object is still expecting app data, even though it's going to
     * get a handshake message. We try to read, and it should fail - after which
     * we should be in a handshake
     */
    ret = SSL_read(peer->ssl, &buf, sizeof(buf));
    if (ret >= 0) {
        /*
         * We're not actually expecting data - we're expecting a reneg to
         * start
         */
        peer->status = PEER_ERROR;
        return;
    } else {
        int error = SSL_get_error(peer->ssl, ret);
        if (error != SSL_ERROR_WANT_READ) {
            peer->status = PEER_ERROR;
            return;
        }
        /* If we're no in init yet then we're not done with setup yet */
        if (!SSL_in_init(peer->ssl))
            return;
    }

    peer->status = PEER_SUCCESS;
}
Beispiel #4
0
static void
handle_read( int cnum, struct timeval* nowP )
    {
    char buf[30000];	/* must be larger than throttle / 2 */
    int bytes_to_read, bytes_read, bytes_handled;
    float elapsed;
    ClientData client_data;
    long checksum;

    tmr_reset( nowP, connections[cnum].idle_timer );

    if ( do_throttle )
	bytes_to_read = throttle / 2.0;
    else
	bytes_to_read = sizeof(buf);
    if ( ! connections[cnum].did_response )
	{
	connections[cnum].did_response = 1;
	connections[cnum].response_at = *nowP;
	}
#ifdef USE_SSL
    if ( urls[connections[cnum].url_num].protocol == PROTO_HTTPS )
	bytes_read = SSL_read( connections[cnum].ssl, buf, bytes_to_read );
    else
	bytes_read = read( connections[cnum].conn_fd, buf, bytes_to_read );
#else
    bytes_read = read( connections[cnum].conn_fd, buf, bytes_to_read );
#endif
    if ( bytes_read <= 0 )
	{
	close_connection( cnum );
	return;
	}

    for ( bytes_handled = 0; bytes_handled < bytes_read; )
	{
	switch ( connections[cnum].conn_state )
	    {
	    case CNST_HEADERS:
	    /* State machine to read until we reach the file part.  Looks for
	    ** Content-Length header too.
	    */
	    for ( ; bytes_handled < bytes_read && connections[cnum].conn_state == CNST_HEADERS; ++bytes_handled )
		{
		switch ( connections[cnum].header_state )
		    {

		    case HDST_LINE1_PROTOCOL:
		    switch ( buf[bytes_handled] )
			{
			case ' ': case '\t':
			connections[cnum].header_state = HDST_LINE1_WHITESPACE;
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			}
		    break;

		    case HDST_LINE1_WHITESPACE:
		    switch ( buf[bytes_handled] )
			{
			case ' ': case '\t':
			break;
			case '0': case '1': case '2': case '3': case '4':
			case '5': case '6': case '7': case '8': case '9':
			connections[cnum].http_status =
			    buf[bytes_handled] - '0';
			connections[cnum].header_state = HDST_LINE1_STATUS;
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_LINE1_STATUS:
		    switch ( buf[bytes_handled] )
			{
			case '0': case '1': case '2': case '3': case '4':
			case '5': case '6': case '7': case '8': case '9':
			connections[cnum].http_status =
			    connections[cnum].http_status * 10 +
			    buf[bytes_handled] - '0';
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_BOL:
		    switch ( buf[bytes_handled] )
			{
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			case 'C': case 'c':
			connections[cnum].header_state = HDST_C;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_TEXT:
		    switch ( buf[bytes_handled] )
			{
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			break;
			}
		    break;

		    case HDST_LF:
		    switch ( buf[bytes_handled] )
			{
			case '\n':
			connections[cnum].conn_state = CNST_READING;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			case 'C': case 'c':
			connections[cnum].header_state = HDST_C;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_CR:
		    switch ( buf[bytes_handled] )
			{
			case '\n':
			connections[cnum].header_state = HDST_CRLF;
			break;
			case '\r':
			connections[cnum].conn_state = CNST_READING;
			break;
			case 'C': case 'c':
			connections[cnum].header_state = HDST_C;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_CRLF:
		    switch ( buf[bytes_handled] )
			{
			case '\n':
			connections[cnum].conn_state = CNST_READING;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CRLFCR;
			break;
			case 'C': case 'c':
			connections[cnum].header_state = HDST_C;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_CRLFCR:
		    switch ( buf[bytes_handled] )
			{
			case '\n': case '\r':
			connections[cnum].conn_state = CNST_READING;
			break;
			case 'C': case 'c':
			connections[cnum].header_state = HDST_C;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_C:
		    switch ( buf[bytes_handled] )
			{
			case 'O': case 'o':
			connections[cnum].header_state = HDST_CO;
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_CO:
		    switch ( buf[bytes_handled] )
			{
			case 'N': case 'n':
			connections[cnum].header_state = HDST_CON;
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_CON:
		    switch ( buf[bytes_handled] )
			{
			case 'T': case 't':
			connections[cnum].header_state = HDST_CONT;
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_CONT:
		    switch ( buf[bytes_handled] )
			{
			case 'E': case 'e':
			connections[cnum].header_state = HDST_CONTE;
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_CONTE:
		    switch ( buf[bytes_handled] )
			{
			case 'N': case 'n':
			connections[cnum].header_state = HDST_CONTEN;
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_CONTEN:
		    switch ( buf[bytes_handled] )
			{
			case 'T': case 't':
			connections[cnum].header_state = HDST_CONTENT;
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_CONTENT:
		    switch ( buf[bytes_handled] )
			{
			case '-':
			connections[cnum].header_state = HDST_CONTENT_;
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_CONTENT_:
		    switch ( buf[bytes_handled] )
			{
			case 'L': case 'l':
			connections[cnum].header_state = HDST_CONTENT_L;
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_CONTENT_L:
		    switch ( buf[bytes_handled] )
			{
			case 'E': case 'e':
			connections[cnum].header_state = HDST_CONTENT_LE;
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_CONTENT_LE:
		    switch ( buf[bytes_handled] )
			{
			case 'N': case 'n':
			connections[cnum].header_state = HDST_CONTENT_LEN;
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_CONTENT_LEN:
		    switch ( buf[bytes_handled] )
			{
			case 'G': case 'g':
			connections[cnum].header_state = HDST_CONTENT_LENG;
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_CONTENT_LENG:
		    switch ( buf[bytes_handled] )
			{
			case 'T': case 't':
			connections[cnum].header_state = HDST_CONTENT_LENGT;
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_CONTENT_LENGT:
		    switch ( buf[bytes_handled] )
			{
			case 'H': case 'h':
			connections[cnum].header_state = HDST_CONTENT_LENGTH;
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_CONTENT_LENGTH:
		    switch ( buf[bytes_handled] )
			{
			case ':':
			connections[cnum].header_state = HDST_CONTENT_LENGTH_COLON;
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_CONTENT_LENGTH_COLON:
		    switch ( buf[bytes_handled] )
			{
			case ' ': case '\t':
			connections[cnum].header_state = HDST_CONTENT_LENGTH_COLON_WHITESPACE;
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_CONTENT_LENGTH_COLON_WHITESPACE:
		    switch ( buf[bytes_handled] )
			{
			case ' ': case '\t':
			break;
			case '0': case '1': case '2': case '3': case '4':
			case '5': case '6': case '7': case '8': case '9':
			connections[cnum].content_length = buf[bytes_handled] - '0';
			connections[cnum].header_state = HDST_CONTENT_LENGTH_COLON_WHITESPACE_NUM;
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    case HDST_CONTENT_LENGTH_COLON_WHITESPACE_NUM:
		    switch ( buf[bytes_handled] )
			{
			case '0': case '1': case '2': case '3': case '4':
			case '5': case '6': case '7': case '8': case '9':
			connections[cnum].content_length =
			    connections[cnum].content_length * 10 +
			    buf[bytes_handled] - '0';
			break;
			case '\n':
			connections[cnum].header_state = HDST_LF;
			break;
			case '\r':
			connections[cnum].header_state = HDST_CR;
			break;
			default:
			connections[cnum].header_state = HDST_TEXT;
			break;
			}
		    break;

		    }
		}
	    break;

	    case CNST_READING:
	    connections[cnum].bytes += bytes_read - bytes_handled;
	    if ( do_throttle )
		{
		/* Check if we're reading too fast. */
		elapsed = delta_timeval( &connections[cnum].started_at, nowP ) / 1000000.0;
		if ( elapsed > 0.01 && connections[cnum].bytes / elapsed > throttle )
		    {
		    connections[cnum].conn_state  = CNST_PAUSING;
		    client_data.i = cnum;
		    connections[cnum].wakeup_timer = tmr_create(
			nowP, wakeup_connection, client_data, 1000L, 0 );
		    }
		}
	    if ( do_checksum )
		{
		checksum = connections[cnum].checksum;
		for ( ; bytes_handled < bytes_read; ++bytes_handled )
		    {
		    if ( checksum & 1 )
			checksum = ( checksum >> 1 ) + 0x8000;
		    else
			checksum >>= 1;
		    checksum += buf[bytes_handled];
		    checksum &= 0xffff;
		    }
		connections[cnum].checksum = checksum;
		}
	    else
		bytes_handled = bytes_read;

	    if ( connections[cnum].content_length != -1 &&
		 connections[cnum].bytes >= connections[cnum].content_length )
		{
		close_connection( cnum );
		return;
		}

	    break;
	    }
Beispiel #5
0
int dtls_mainloop(struct openconnect_info *vpninfo, int *timeout)
{
	int work_done = 0;
	char magic_pkt;

	while (1) {
		int len = vpninfo->mtu;
		unsigned char *buf;

		if (!dtls_pkt) {
			dtls_pkt = malloc(sizeof(struct pkt) + len);
			if (!dtls_pkt) {
				vpn_progress(vpninfo, PRG_ERR, "Allocation failed\n");
				break;
			}
		}

		buf = dtls_pkt->data - 1;
		len = SSL_read(vpninfo->dtls_ssl, buf, len + 1);
		if (len <= 0)
			break;

		vpn_progress(vpninfo, PRG_TRACE,
			     _("Received DTLS packet 0x%02x of %d bytes\n"),
			     buf[0], len);

		vpninfo->dtls_times.last_rx = time(NULL);

		switch(buf[0]) {
		case AC_PKT_DATA:
			queue_new_packet(&vpninfo->incoming_queue, buf+1, len-1);
			work_done = 1;
			break;

		case AC_PKT_DPD_OUT:
			vpn_progress(vpninfo, PRG_TRACE, _("Got DTLS DPD request\n"));

			/* FIXME: What if the packet doesn't get through? */
			magic_pkt = AC_PKT_DPD_RESP;
			if (SSL_write(vpninfo->dtls_ssl, &magic_pkt, 1) != 1)
				vpn_progress(vpninfo, PRG_ERR,
					     _("Failed to send DPD response. Expect disconnect\n"));
			continue;

		case AC_PKT_DPD_RESP:
			vpn_progress(vpninfo, PRG_TRACE, _("Got DTLS DPD response\n"));
			break;

		case AC_PKT_KEEPALIVE:
			vpn_progress(vpninfo, PRG_TRACE, _("Got DTLS Keepalive\n"));
			break;

		default:
			vpn_progress(vpninfo, PRG_ERR,
				     _("Unknown DTLS packet type %02x, len %d\n"),
				     buf[0], len);
			if (1) {
				/* Some versions of OpenSSL have bugs with receiving out-of-order
				 * packets. Not only do they wrongly decide to drop packets if
				 * two packets get swapped in transit, but they also _fail_ to
				 * drop the packet in non-blocking mode; instead they return
				 * the appropriate length of garbage. So don't abort... for now. */
				break;
			} else {
				vpninfo->quit_reason = "Unknown packet received";
				return 1;
			}

		}
	}

	switch (keepalive_action(&vpninfo->dtls_times, timeout)) {
	case KA_REKEY:
		vpn_progress(vpninfo, PRG_INFO, _("DTLS rekey due\n"));

		/* There ought to be a method of rekeying DTLS without tearing down
		   the CSTP session and restarting, but we don't (yet) know it */
		if (cstp_reconnect(vpninfo)) {
			vpn_progress(vpninfo, PRG_ERR, _("Reconnect failed\n"));
			vpninfo->quit_reason = "CSTP reconnect failed";
			return 1;
		}

		if (dtls_restart(vpninfo)) {
			vpn_progress(vpninfo, PRG_ERR, _("DTLS rekey failed\n"));
			return 1;
		}
		work_done = 1;
		break;


	case KA_DPD_DEAD:
		vpn_progress(vpninfo, PRG_ERR, _("DTLS Dead Peer Detection detected dead peer!\n"));
		/* Fall back to SSL, and start a new DTLS connection */
		dtls_restart(vpninfo);
		return 1;

	case KA_DPD:
		vpn_progress(vpninfo, PRG_TRACE, _("Send DTLS DPD\n"));

		magic_pkt = AC_PKT_DPD_OUT;
		SSL_write(vpninfo->dtls_ssl, &magic_pkt, 1);
		/* last_dpd will just have been set */
		vpninfo->dtls_times.last_tx = vpninfo->dtls_times.last_dpd;
		work_done = 1;
		break;

	case KA_KEEPALIVE:
		/* No need to send an explicit keepalive
		   if we have real data to send */
		if (vpninfo->outgoing_queue)
			break;

		vpn_progress(vpninfo, PRG_TRACE, _("Send DTLS Keepalive\n"));

		magic_pkt = AC_PKT_KEEPALIVE;
		SSL_write(vpninfo->dtls_ssl, &magic_pkt, 1);
		time(&vpninfo->dtls_times.last_tx);
		work_done = 1;
		break;

	case KA_NONE:
		;
	}

	/* Service outgoing packet queue */
	while (vpninfo->outgoing_queue) {
		struct pkt *this = vpninfo->outgoing_queue;
		int ret;

		vpninfo->outgoing_queue = this->next;
		vpninfo->outgoing_qlen--;

		/* One byte of header */
		this->hdr[7] = AC_PKT_DATA;

		ret = SSL_write(vpninfo->dtls_ssl, &this->hdr[7], this->len + 1);
		if (ret <= 0) {
			ret = SSL_get_error(vpninfo->dtls_ssl, ret);

			/* If it's a real error, kill the DTLS connection and
			   requeue the packet to be sent over SSL */
			if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE) {
				vpn_progress(vpninfo, PRG_ERR,
					     _("DTLS got write error %d. Falling back to SSL\n"),
					     ret);
				report_ssl_errors(vpninfo);
				dtls_restart(vpninfo);
				vpninfo->outgoing_queue = this;
				vpninfo->outgoing_qlen++;
			}
			return 1;
		}
		time(&vpninfo->dtls_times.last_tx);
		vpn_progress(vpninfo, PRG_TRACE,
			     _("Sent DTLS packet of %d bytes; SSL_write() returned %d\n"),
			     this->len, ret);
		free(this);
	}

	return work_done;
}
Beispiel #6
0
BOOL CHTTPClient::SendSSLRequest(char *szHost,
    char *szHostName,
    char *szPath,
    char *szUserID,
    char *szPassword,
    long lPort,
    char *szProxy,
    long lProxyPort,
    char *szProxyUser,
    char *szProxyPswd,
    char *szUserAgent,
    char *szPost,
    long dwTimeout,
    SSL **pssl,
    SSL_CTX **pssl_ctx,
    char *szTransaction)
{
    char *szConnectHost;
    char *szConnectionHeader = "Connection: close\r\n";
    char *szContentLength = "Content-Length: %d\r\n";
    char *szContentType = "Content-Type: application/x-www-form-urlencoded\r\n";
    char *szProxyConn = "Proxy-Connection: Keep-Alive\r\n";
    char *szPragma = "Pragma: no-cache\r\n";
    long lConnectPort;
    char *szBuffer = szSendBuffer;
    char szWork[256];
    char *lpWork;
    char *szGetMethod = "GET";
    char *szPostMethod = "POST";
    char *szMethod;
    BOOL RC = TRUE;
    BOOL bBIOset = FALSE;

    Base64Coder cBase64Coder;

    BIO *bio = 0;
    int done = 0, i, n;
    char buf[2048];

    // Got to have a host
    if (!szHost)
        return(FALSE);

    // Initialize strings used for cookies
    cDomain = szHostName;
    cPath = szPath;
    if (szTransaction)
        cTransaction = szTransaction;
    else
        cTransaction = "";

    // Clean up ssl storage
    try
    {
        if (ssl)
        {
            SSL_free(ssl);
            ssl = 0;
        }
    }
    catch(...)
    {
        ssl = 0;
    }

    try
    {

        // Initialise the ssl library now in rtm startup 

        // Create the context structure. Operate in the normal default SSLv3
        // in a SSLv2 header mode to maximize the number of servers
        // we can connect to.
        if (!ssl_ctx)
        {
            if (!pssl_ctx || !*pssl_ctx)
            {
                if ((ssl_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL)
                {
                    bConnectFailed = TRUE;
                    throw FALSE;
                }
            }
            else
                ssl_ctx = *pssl_ctx;
        }

        // Reset variables for response
        bHeader = FALSE;
        bReadComplete = FALSE;
        bHeadRequest = FALSE;
        lReceivedLength = 0;
        lContentLength = 0;
        cHeader = "";
        cContent = "";

        // turn on all vendor bug compatibility options
        SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL);

        // Create the SSL structure - defaults are inherited from the SSL_CTX
        if ((ssl = SSL_new(ssl_ctx)) == NULL)
        {
            bConnectFailed = TRUE;
            throw FALSE;
        };

        // Set as client side
        SSL_set_connect_state(ssl);

        if (!szProxy)
        {
            // No proxy
            szConnectHost = szHost;
            lConnectPort = lPort;
        }
        else
        {
            // Proxy
            szConnectHost = szProxy;
            lConnectPort = lProxyPort;
        };

        sprintf(szWork, "%s:%u", szConnectHost, (unsigned int) lConnectPort);

        // Create a BIO to handle the connect and SSL handling
        if ((bio = BIO_new_connect(szWork)) == NULL)
        {
            bConnectFailed = TRUE;
            throw FALSE;
        };

        // If using proxy then have to tunnel through to the actual ssl server
        if (szProxy)
        {
            sprintf(szBuffer, "CONNECT %s:%u HTTP/1.0\r\nUser-Agent: %s\r\n", szHostName, (unsigned int) lPort, szUserAgent);

            if (szProxyUser && szProxyPswd && strlen(szProxyUser) > 0 && strlen(szProxyPswd) > 0)
            {
                sprintf(szWork, "%s:%s", szProxyUser, szProxyPswd);
                cBase64Coder.Encode(szWork);
                sprintf(szWork, "Proxy-Authorization: Basic %s\r\n", (LPCTSTR) cBase64Coder.EncodedMessage());
                strcat(szBuffer, szWork);
            }
            strcat(szBuffer, szProxyConn);
            strcat(szBuffer, szPragma);
            strcat(szBuffer, "\r\n");

            // Send connect request
            n = strlen(szBuffer);
            i = 0;
            do
            {
                i = BIO_write(bio, &(szBuffer[i]), n);
                if (i <= 0)
                {
                    bConnectFailed = TRUE;
                    BIO_free(bio);
                    throw FALSE;
                }
                n -= i;
            }
            while(n > 0);

            // Read response from proxy
            i = BIO_read(bio, buf, sizeof(buf));
            if (i <= 0)
            {
                bConnectFailed = TRUE;
                BIO_free(bio);
                throw FALSE;
            };

            buf[i] = '\0';
            lpWork = strstr(buf, "200");
            if (!lpWork)
            {
                bConnectFailed = TRUE;
                BIO_free(bio);
                throw FALSE;
            };

        };

        // Use the newly created connect BIO
        SSL_set_bio(ssl, bio, bio);
        bBIOset = TRUE;
        if (pSession && pssl)
        {
            SSL_set_session(ssl, pSession);
        }
        else
        {
            while(!done)
            {
                int i;
                struct tm *ptr;
                time_t lt;

                lt = time(NULL);

                PROTECT_CALL
                ptr = localtime(&lt);
                char *pszTime = asctime(ptr);
                RAND_seed((unsigned char *) pszTime, strlen(pszTime));
                UNPROTECT_CALL

                // The all important handshake
                i = SSL_do_handshake(ssl);

                switch(SSL_get_error(ssl, i))
                {
                    case SSL_ERROR_NONE: // Handshake has finished, so proceed
                        done = 1;
                        break;
                    case SSL_ERROR_WANT_READ:
                    case SSL_ERROR_WANT_WRITE:
                    case SSL_ERROR_WANT_CONNECT:
                        // Perform the handshake again. 
                        sleep(1);
                        break;
                    default:
                        bConnectFailed = TRUE;
                        throw FALSE;
                        break;
                };
            };
            pSession = SSL_get_session(ssl);
        };

        if (szPost)
            szMethod = szPostMethod;
        else
            szMethod = szGetMethod;

        // Build the request
        sprintf(szBuffer, "%s %s HTTP/1.0\r\nUser-Agent: %s\r\nHost: %s\r\n", szMethod, szPath, szUserAgent, szHostName);

        if (szUserID)
        {
            sprintf(szWork, "%s:%s", szUserID, szPassword);
            cBase64Coder.Encode(szWork);
            sprintf(szWork, "Authorization: Basic %s\r\n", (LPCTSTR) cBase64Coder.EncodedMessage());
            strcat(szBuffer, szWork);
        }

        if (szPost)
        {
            strcat(szBuffer, szContentType);
            sprintf(szWork, szContentLength, strlen(szPost));
            strcat(szBuffer, szWork);
            strcat(szBuffer, szProxyConn);
            strcat(szBuffer, szPragma);
        }
        else
        {
            strcat(szBuffer, szConnectionHeader);
        }

        if (!cTransaction.empty())
            SendCookie(szBuffer);

        // Indicate end of header
        strcat(szBuffer, "\r\n");

        sDebugSendHeader = szBuffer;

        if (szPost)
            strcat(szBuffer, szPost);

        dwStartTime = ::XPlatGetMilliseconds();

        // Send request
        n = strlen(szBuffer);
        i = 0;
        do
        {
            i = SSL_write(ssl, &(szBuffer[i]), n);
            if (i <= 0)
            {
                bConnectFailed = FALSE;
                throw FALSE;
            }
            n -= i;
        }
        while(n > 0);

        // Read from the other side of the protocol
        while(1)
        {
            i = SSL_read(ssl, buf, sizeof(buf));
            if (i <= 0)
                break;

            ProcessData((unsigned char *) buf, i);

            if (!GetTimeLeft(dwTimeout, dwStartTime))
            {
                // Timed out
                bConnectFailed = FALSE;
                throw FALSE;
            };
        };
        if (szPost && !strcmp(szStatus, "100"))
        {
            printf("status 100");
            strcat(szBuffer, szPost);
            // Reset variables for response
            bHeader = FALSE;
            bReadComplete = FALSE;
            bHeadRequest = FALSE;
            lReceivedLength = 0;
            lContentLength = 0;
            cHeader = "";
            cContent = "";


            // Send request
            n = strlen(szBuffer);
            i = 0;
            do
            {
                i = SSL_write(ssl, &(szBuffer[i]), n);
                if (i <= 0)
                {
                    bConnectFailed = FALSE;
                    throw FALSE;
                }
                n -= i;
            }
            while(n > 0);

            // Read from the other side of the protocol
            while(1)
            {
                i = SSL_read(ssl, buf, sizeof(buf));
                if (i <= 0)
                    break;

                ProcessData((unsigned char *) buf, i);

                if (!GetTimeLeft(dwTimeout, dwStartTime))
                {
                    // Timed out
                    bConnectFailed = FALSE;
                    throw FALSE;
                };
            };
        };
        Disconnected();
        throw TRUE;
    }

    catch(BOOL rc)
    {
        RC = rc;

    }

    catch(...)
    {
        RC = FALSE;
        if (!bBIOset && bio)
        {
            try
            {
                BIO_free(bio);
            }
            catch(...)
            {
            }
        }
    }

    if (pssl && pssl_ctx)
    {
        if (*pssl == 0)
        {
            *pssl = ssl;
            *pssl_ctx = ssl_ctx;
            ssl = 0;
        }
        ssl_ctx = 0;
    }

    return RC;

};
Beispiel #7
0
status_t
POP3Protocol::SendCommand(const char *cmd)
{
	if (fSocket < 0 || fSocket > FD_SETSIZE)
		return B_FILE_ERROR;

	//printf(cmd);
	// Flush any accumulated garbage data before we send our command, so we
	// don't misinterrpret responses from previous commands (that got left over
	// due to bugs) as being from this command.

	struct timeval tv;
	tv.tv_sec = 0;
	tv.tv_usec = 1000;
		/* very short timeout, hangs with 0 in R5 */

	struct fd_set readSet;
	FD_ZERO(&readSet);
	FD_SET(fSocket, &readSet);
	int result;
#ifdef USE_SSL
	if (fUseSSL && SSL_pending(fSSL))
		result = 1;
	else
#endif
	result = select(fSocket + 1, &readSet, NULL, NULL, &tv);

	if (result > 0) {
		int amountReceived;
		char tempString [1025];
#ifdef USE_SSL
		if (fUseSSL)
			amountReceived = SSL_read(fSSL, tempString, sizeof(tempString) - 1);
		else
#endif
		amountReceived = recv(fSocket, tempString, sizeof(tempString) - 1, 0);
		if (amountReceived < 0)
			return errno;

		tempString [amountReceived] = 0;
		printf ("POP3Protocol::SendCommand Bug!  Had to flush %d bytes: %s\n",
			amountReceived, tempString);
		//if (amountReceived == 0)
		//	break;
	}

#ifdef USE_SSL
	if (fUseSSL) {
		SSL_write(fSSL, cmd,::strlen(cmd));
	} else
#endif
	if (send(fSocket, cmd, ::strlen(cmd), 0) < 0) {
		fLog = strerror(errno);
		printf("POP3Protocol::SendCommand Send \"%s\" failed, code %d: %s\n",
			cmd, errno, fLog.String());
		return errno;
	}

	fLog = "";
	status_t err = B_OK;

	while (true) {
		int32 len = ReceiveLine(fLog);
		if (len <= 0 || fLog.ICompare("+OK", 3) == 0)
			break;

		if (fLog.ICompare("-ERR", 4) == 0) {
			printf("POP3Protocol::SendCommand \"%s\" got error message "
				"from server: %s\n", cmd, fLog.String());
			err = B_ERROR;
			break;
		} else {
			printf("POP3Protocol::SendCommand \"%s\" got nonsense message "
				"from server: %s\n", cmd, fLog.String());
			err = B_BAD_VALUE;
				// If it's not +OK, and it's not -ERR, then what the heck
				// is it? Presume an error
			break;
		}
	}
	return err;
}
Beispiel #8
0
tb_long_t tb_ssl_read(tb_ssl_ref_t self, tb_byte_t* data, tb_size_t size)
{
    // the ssl
    tb_ssl_t* ssl = (tb_ssl_t*)self;
    tb_assert_and_check_return_val(ssl && ssl->ssl && ssl->bopened && data, -1);

    // read it
    tb_long_t real = SSL_read(ssl->ssl, data, size);

    // trace
    tb_trace_d("read: %ld", real);

    // done
    if (real < 0)
    {
        // the error
        tb_long_t error = SSL_get_error(ssl->ssl, real);

        // want read? continue it
        if (error == SSL_ERROR_WANT_READ)
        {
            // trace
            tb_trace_d("read: want read");

            // save state
            ssl->state = TB_STATE_SOCK_SSL_WANT_READ;
            return 0;
        }
        // want writ? continue it
        else if (error == SSL_ERROR_WANT_WRITE)
        {
            // trace
            tb_trace_d("read: want writ");

            // save state
            ssl->state = TB_STATE_SOCK_SSL_WANT_WRIT;
            return 0;
        }
        // failed?
        else
        {
            // trace
            tb_trace_d("read: failed: %ld, %s", real, tb_ssl_error(error));

            // save state
            ssl->state = TB_STATE_SOCK_SSL_FAILED;
            return -1;
        }
    }
    // closed?
    else if (!real)
    {
        // trace
        tb_trace_d("read: closed");

        // save state
        ssl->state = TB_STATE_CLOSED;
        return -1;
    }

    // ok
    return real;
}
Beispiel #9
0
/*
 *	Read data from a secure connection.
 */
ssize_t
secure_read(Port *port, void *ptr, size_t len)
{
	ssize_t		n;

#ifdef USE_SSL
	if (port->ssl)
	{
		int			err;

rloop:
		errno = 0;
		n = SSL_read(port->ssl, ptr, len);
		err = SSL_get_error(port->ssl, n);
		switch (err)
		{
			case SSL_ERROR_NONE:
				port->count += n;
				break;
			case SSL_ERROR_WANT_READ:
			case SSL_ERROR_WANT_WRITE:
				if (port->noblock)
				{
					errno = EWOULDBLOCK;
					n = -1;
					break;
				}
#ifdef WIN32
				pgwin32_waitforsinglesocket(SSL_get_fd(port->ssl),
											(err == SSL_ERROR_WANT_READ) ?
									FD_READ | FD_CLOSE : FD_WRITE | FD_CLOSE,
											INFINITE);
#endif
				goto rloop;
			case SSL_ERROR_SYSCALL:
				/* leave it to caller to ereport the value of errno */
				if (n != -1)
				{
					errno = ECONNRESET;
					n = -1;
				}
				break;
			case SSL_ERROR_SSL:
				ereport(COMMERROR,
						(errcode(ERRCODE_PROTOCOL_VIOLATION),
						 errmsg("SSL error: %s", SSLerrmessage())));
				/* fall through */
			case SSL_ERROR_ZERO_RETURN:
				errno = ECONNRESET;
				n = -1;
				break;
			default:
				ereport(COMMERROR,
						(errcode(ERRCODE_PROTOCOL_VIOLATION),
						 errmsg("unrecognized SSL error code: %d",
								err)));
				n = -1;
				break;
		}
	}
	else
#endif
	{
		prepare_for_client_read();

		n = recv(port->sock, ptr, len, 0);

		client_read_ended();
	}

	return n;
}
Beispiel #10
0
void main ()
{
  int err;
  int listen_sd;
  int sd;
  struct sockaddr_in sa_serv;
  struct sockaddr_in sa_cli;
  size_t client_len;
  SSL_CTX* ctx;
  SSL*     ssl;
  X509*    client_cert;
  char*    str;
  char     buf [4096];
  SSL_METHOD *meth;
  
  /* SSL preliminaries. We keep the certificate and key with the context. */

  SSL_load_error_strings();
  SSLeay_add_ssl_algorithms();
  meth = SSLv23_server_method();
  ctx = SSL_CTX_new (meth);
  if (!ctx) {
    ERR_print_errors_fp(stderr);
    exit(2);
  }
  
  if (SSL_CTX_use_certificate_file(ctx, CERTF, SSL_FILETYPE_PEM) <= 0) {
    ERR_print_errors_fp(stderr);
    exit(3);
  }
  if (SSL_CTX_use_PrivateKey_file(ctx, KEYF, SSL_FILETYPE_PEM) <= 0) {
    ERR_print_errors_fp(stderr);
    exit(4);
  }

  if (!SSL_CTX_check_private_key(ctx)) {
    fprintf(stderr,"Private key does not match the certificate public key\n");
    exit(5);
  }

  /* ----------------------------------------------- */
  /* Prepare TCP socket for receiving connections */

  listen_sd = socket (AF_INET, SOCK_STREAM, 0);   CHK_ERR(listen_sd, "socket");
  
  memset (&sa_serv, '\0', sizeof(sa_serv));
  sa_serv.sin_family      = AF_INET;
  sa_serv.sin_addr.s_addr = INADDR_ANY;
  sa_serv.sin_port        = htons (1111);          /* Server Port number */
  
  err = bind(listen_sd, (struct sockaddr*) &sa_serv,
	     sizeof (sa_serv));                   CHK_ERR(err, "bind");
	     
  /* Receive a TCP connection. */
	     
  err = listen (listen_sd, 5);                    CHK_ERR(err, "listen");
  
  client_len = sizeof(sa_cli);
  sd = accept (listen_sd, (struct sockaddr*) &sa_cli, &client_len);
  CHK_ERR(sd, "accept");
  close (listen_sd);

  printf ("Connection from %lx, port %x\n",
	  sa_cli.sin_addr.s_addr, sa_cli.sin_port);
  
  /* ----------------------------------------------- */
  /* TCP connection is ready. Do server side SSL. */

  ssl = SSL_new (ctx);                           CHK_NULL(ssl);
  SSL_set_fd (ssl, sd);
  err = SSL_accept (ssl);                        CHK_SSL(err);
  
  /* Get the cipher - opt */
  
  printf ("SSL connection using %s\n", SSL_get_cipher (ssl));
  
  /* Get client's certificate (note: beware of dynamic allocation) - opt */

  client_cert = SSL_get_peer_certificate (ssl);
  if (client_cert != NULL) {
    printf ("Client certificate:\n");
    
    str = X509_NAME_oneline (X509_get_subject_name (client_cert), 0, 0);
    CHK_NULL(str);
    printf ("\t subject: %s\n", str);
    OPENSSL_free (str);
    
    str = X509_NAME_oneline (X509_get_issuer_name  (client_cert), 0, 0);
    CHK_NULL(str);
    printf ("\t issuer: %s\n", str);
    OPENSSL_free (str);
    
    /* We could do all sorts of certificate verification stuff here before
       deallocating the certificate. */
    
    X509_free (client_cert);
  } else
    printf ("Client does not have certificate.\n");

  /* DATA EXCHANGE - Receive message and send reply. */

  err = SSL_read (ssl, buf, sizeof(buf) - 1);                   CHK_SSL(err);
  buf[err] = '\0';
  printf ("Got %d chars:'%s'\n", err, buf);
  
  err = SSL_write (ssl, "I hear you.", strlen("I hear you."));  CHK_SSL(err);

  /* Clean up. */

  close (sd);
  SSL_free (ssl);
  SSL_CTX_free (ctx);
}
Beispiel #11
0
/*
 *	Read from the SSL socket.  Safe with either blocking or
 *	non-blocking IO.  This level of complexity is probably not
 *	necessary, as each packet gets put into one SSL application
 *	record.  When SSL has a full record, we should be able to read
 *	the entire packet via one SSL_read().
 *
 *	When SSL has a partial record, SSL_read() will return
 *	WANT_READ or WANT_WRITE, and zero application data.
 *
 *	Called with the mutex held.
 */
static ssize_t proxy_tls_read(rad_listen_t *listener)
{
	int rcode;
	size_t length;
	uint8_t *data;
	listen_socket_t *sock = listener->data;

	if (!sock->ssn->connected) {
		rcode = try_connect(sock->ssn);
		if (rcode == 0) return 0;

		if (rcode < 0) {
			SSL_shutdown(sock->ssn->ssl);
			return -1;
		}

		sock->ssn->connected = true;
	}

	/*
	 *	Get the maximum size of data to receive.
	 */
	if (!sock->data) sock->data = talloc_array(sock, uint8_t,
						   sock->ssn->mtu);

	data = sock->data;

	if (sock->partial < 4) {
		rcode = SSL_read(sock->ssn->ssl, data + sock->partial,
				 4 - sock->partial);
		if (rcode <= 0) {
			int err = SSL_get_error(sock->ssn->ssl, rcode);
			switch (err) {
			case SSL_ERROR_WANT_READ:
			case SSL_ERROR_WANT_WRITE:
				return 0; /* do some more work later */

			case SSL_ERROR_ZERO_RETURN:
				/* remote end sent close_notify, send one back */
				SSL_shutdown(sock->ssn->ssl);
				/* FALL-THROUGH */

			case SSL_ERROR_SYSCALL:
			do_close:
				return -1;

			default:
				tls_error_log(NULL, "Failed in proxy receive");

				goto do_close;
			}
		}

		sock->partial = rcode;
	} /* try reading the packet header */

	if (sock->partial < 4) return 0; /* read more data */

	length = (data[2] << 8) | data[3];

	/*
	 *	Do these checks only once, when we read the header.
	 */
	if (sock->partial == 4) {
		DEBUG3("Proxy received header saying we have a packet of %u bytes",
		       (unsigned int) length);

		/*
		 *	FIXME: allocate a RADIUS_PACKET, and set
		 *	"data" to be as large as necessary.
		 */
		if (length > sock->ssn->mtu) {
			INFO("Received packet will be too large! Set \"fragment_size = %u\"",
			     (data[2] << 8) | data[3]);
			goto do_close;
		}
	}

	/*
	 *	Try to read some more.
	 */
	if (sock->partial < length) {
		rcode = SSL_read(sock->ssn->ssl, data + sock->partial,
				 length - sock->partial);
		if (rcode <= 0) {
			switch (SSL_get_error(sock->ssn->ssl, rcode)) {
			case SSL_ERROR_WANT_READ:
			case SSL_ERROR_WANT_WRITE:
				return 0;

			case SSL_ERROR_ZERO_RETURN:
				/* remote end sent close_notify, send one back */
				SSL_shutdown(sock->ssn->ssl);
				goto do_close;
			default:
				goto do_close;
			}
		}

		sock->partial += rcode;
	}

	/*
	 *	If we're not done, say so.
	 *
	 *	Otherwise, reset the partially read data flag, and say
	 *	we have a packet.
	 */
	if (sock->partial < length) {
		return 0;
	}

	sock->partial = 0;	/* we've now read the packet */
	return length;
}
Beispiel #12
0
static void ns_read_from_socket(struct ns_connection *conn) {
  char buf[NS_READ_BUFFER_SIZE];
  int n = 0;

  if (conn->flags & NSF_CONNECTING) {
    int ok = 1, ret;
    socklen_t len = sizeof(ok);

    ret = getsockopt(conn->sock, SOL_SOCKET, SO_ERROR, (char *) &ok, &len);
#ifdef NS_ENABLE_SSL
    if (ret == 0 && ok == 0 && conn->ssl != NULL) {
      int res = SSL_connect(conn->ssl);
      int ssl_err = ns_ssl_err(conn, res);
      if (res == 1) {
        conn->flags |= NSF_SSL_HANDSHAKE_DONE;
      } else if (ssl_err == SSL_ERROR_WANT_READ ||
                 ssl_err == SSL_ERROR_WANT_WRITE) {
        return; /* Call us again */
      } else {
        ok = 1;
      }
    }
#endif
    conn->flags &= ~NSF_CONNECTING;
    DBG(("%p ok=%d", conn, ok));
    if (ok != 0) {
      conn->flags |= NSF_CLOSE_IMMEDIATELY;
    }
    ns_call(conn, NS_CONNECT, &ok);
    return;
  }

#ifdef NS_ENABLE_SSL
  if (conn->ssl != NULL) {
    if (conn->flags & NSF_SSL_HANDSHAKE_DONE) {
      /* SSL library may have more bytes ready to read then we ask to read.
       * Therefore, read in a loop until we read everything. Without the loop,
       * we skip to the next select() cycle which can just timeout. */
      while ((n = SSL_read(conn->ssl, buf, sizeof(buf))) > 0) {
        DBG(("%p %lu <- %d bytes (SSL)", conn, conn->flags, n));
        iobuf_append(&conn->recv_iobuf, buf, n);
        ns_call(conn, NS_RECV, &n);
      }
      ns_ssl_err(conn, n);
    } else {
      int res = SSL_accept(conn->ssl);
      int ssl_err = ns_ssl_err(conn, res);
      if (res == 1) {
        conn->flags |= NSF_SSL_HANDSHAKE_DONE;
      } else if (ssl_err == SSL_ERROR_WANT_READ ||
                 ssl_err == SSL_ERROR_WANT_WRITE) {
        return; /* Call us again */
      } else {
        conn->flags |= NSF_CLOSE_IMMEDIATELY;
      }
      return;
    }
  } else
#endif
  {
    while ((n = (int) recv(conn->sock, buf, sizeof(buf), 0)) > 0) {
      DBG(("%p %lu <- %d bytes (PLAIN)", conn, conn->flags, n));
      iobuf_append(&conn->recv_iobuf, buf, n);
      ns_call(conn, NS_RECV, &n);
    }
  }

  if (ns_is_error(n)) {
    conn->flags |= NSF_CLOSE_IMMEDIATELY;
  }
}
Beispiel #13
0
/* {{{ my_recv
 */
int
my_recv(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len)
{
	int		n, nr_bytes;
#ifdef HAVE_FTP_SSL
	int err;
	zend_bool retry = 0;
	SSL *handle = NULL;
	php_socket_t fd;
#endif

	n = php_pollfd_for_ms(s, PHP_POLLREADABLE, ftp->timeout_sec * 1000);
	if (n < 1) {
#ifdef PHP_WIN32
		if (n == 0) {
			_set_errno(ETIMEDOUT);
		}
#else
		if (n == 0) {
			errno = ETIMEDOUT;
		}
#endif
		return -1;
	}

#ifdef HAVE_FTP_SSL
	if (ftp->use_ssl && ftp->fd == s && ftp->ssl_active) {
		handle = ftp->ssl_handle;
		fd = ftp->fd;
	} else if (ftp->use_ssl && ftp->fd != s && ftp->use_ssl_for_data && ftp->data->ssl_active) {
		handle = ftp->data->ssl_handle;
		fd = ftp->data->fd;
	}

	if (handle) {
		do {
			nr_bytes = SSL_read(handle, buf, len);
			err = SSL_get_error(handle, nr_bytes);

			switch (err) {
				case SSL_ERROR_NONE:
					retry = 0;
					break;

				case SSL_ERROR_ZERO_RETURN:
					retry = 0;
					SSL_shutdown(handle);
					break;

				case SSL_ERROR_WANT_READ:
				case SSL_ERROR_WANT_CONNECT: {
						php_pollfd p;
						int i;

						p.fd = fd;
						p.events = POLLIN|POLLPRI;
						p.revents = 0;

						i = php_poll2(&p, 1, 300);

						retry = i > 0;
					}
					break;

				default:
					php_error_docref(NULL, E_WARNING, "SSL read failed");
					return -1;
			}
		} while (retry);
	} else {
#endif
		nr_bytes = recv(s, buf, len, 0);
#ifdef HAVE_FTP_SSL
	}
#endif
	return (nr_bytes);
}
Beispiel #14
0
static int transfer(CLI *c) { /* transfer data */
    fd_set rd_set, wr_set;
    int num, err, fdno;
    int check_SSL_pending;
    int ssl_closing;
        /* 0=not closing SSL, 1=initiate SSL_shutdown,
         * 2=retry SSL_shutdown, 3=SSL_shutdown done */
    int ready;
    struct timeval tv;

    /* fdno=max(c->sock_rfd->fd, c->sock_wfd->fd,
     *     fdno=c->ssl_rfd->fd, fdno=c->ssl_wfd->fd)+1 */
    fdno=c->sock_rfd->fd;
    if(c->sock_wfd->fd>fdno) fdno=c->sock_wfd->fd;
    if(c->ssl_rfd->fd>fdno) fdno=c->ssl_rfd->fd;
    if(c->ssl_wfd->fd>fdno) fdno=c->ssl_wfd->fd;
    fdno+=1;

    c->sock_ptr=c->ssl_ptr=0;
    sock_rd=sock_wr=ssl_rd=ssl_wr=1;
    c->sock_bytes=c->ssl_bytes=0;
    ssl_closing=0;

    while(((sock_rd||c->sock_ptr)&&ssl_wr)||((ssl_rd||c->ssl_ptr)&&sock_wr)) {

        FD_ZERO(&rd_set); /* Setup rd_set */
        if(sock_rd && c->sock_ptr<BUFFSIZE) /* socket input buffer not full*/
            FD_SET(c->sock_rfd->fd, &rd_set);
        if(ssl_rd && (
                c->ssl_ptr<BUFFSIZE || /* SSL input buffer not full */
                ((c->sock_ptr||ssl_closing) && SSL_want_read(c->ssl))
                /* I want to SSL_write or SSL_shutdown but read from the
                 * underlying socket needed for the SSL protocol */
                )) {
            FD_SET(c->ssl_rfd->fd, &rd_set);
        }

        FD_ZERO(&wr_set); /* Setup wr_set */
        if(sock_wr && c->ssl_ptr) /* SSL input buffer not empty */
            FD_SET(c->sock_wfd->fd, &wr_set);
        if (ssl_wr && (
                c->sock_ptr || /* socket input buffer not empty */
                ssl_closing==1 || /* initiate SSL_shutdown */
                ((c->ssl_ptr<BUFFSIZE || ssl_closing==2) &&
                    SSL_want_write(c->ssl))
                /* I want to SSL_read or SSL_shutdown but write to the
                 * underlying socket needed for the SSL protocol */
                )) {
            FD_SET(c->ssl_wfd->fd, &wr_set);
        }

        tv.tv_sec=sock_rd ||
            (ssl_wr&&c->sock_ptr) || (sock_wr&&c->ssl_ptr) ?
            c->opt->timeout_idle : c->opt->timeout_close;
        tv.tv_usec=0;
        ready=sselect(fdno, &rd_set, &wr_set, NULL, &tv);
        if(ready<0) { /* Break the connection for others */
            sockerror("select");
            return -1;
        }
        if(!ready) { /* Timeout */
            if(sock_rd) { /* No traffic for a long time */
                log(LOG_DEBUG, "select timeout: connection reset");
                return -1;
            } else { /* Timeout waiting for SSL close_notify */
                log(LOG_DEBUG, "select timeout waiting for SSL close_notify");
                break; /* Leave the while() loop */
            }
        }

        if(ssl_closing==1 /* initiate SSL_shutdown */ || (ssl_closing==2 && (
                (SSL_want_read(c->ssl) && FD_ISSET(c->ssl_rfd->fd, &rd_set)) ||
                (SSL_want_write(c->ssl) && FD_ISSET(c->ssl_wfd->fd, &wr_set))
                ))) {
            switch(SSL_shutdown(c->ssl)) { /* Send close_notify */
            case 1: /* the shutdown was successfully completed */
                log(LOG_INFO, "SSL_shutdown successfully sent close_notify");
                ssl_wr=0; /* SSL write closed */
                /* TODO: It's not really closed.  We need to distinguish
                 * closed SSL and closed underlying file descriptor */
                ssl_closing=3; /* done! */
                break;
            case 0: /* the shutdown is not yet finished */
                log(LOG_DEBUG, "SSL_shutdown retrying");
                ssl_closing=2; /* next time just retry SSL_shutdown */
                break;
            case -1: /* a fatal error occurred */
                sslerror("SSL_shutdown");
                return -1;
            }
        }

        /* Set flag to try and read any buffered SSL data if we made */
        /* room in the buffer by writing to the socket */
        check_SSL_pending = 0;

        if(sock_wr && FD_ISSET(c->sock_wfd->fd, &wr_set)) {
            switch(num=writesocket(c->sock_wfd->fd, c->ssl_buff, c->ssl_ptr)) {
            case -1: /* error */
                switch(get_last_socket_error()) {
                case EINTR:
                    log(LOG_DEBUG,
                        "writesocket interrupted by a signal: retrying");
                    break;
                case EWOULDBLOCK:
                    log(LOG_NOTICE, "writesocket would block: retrying");
                    break;
                default:
                    sockerror("writesocket");
                    return -1;
                }
                break;
            case 0:
                log(LOG_DEBUG, "No data written to the socket: retrying");
                break;
            default:
                memmove(c->ssl_buff, c->ssl_buff+num, c->ssl_ptr-num);
                if(c->ssl_ptr==BUFFSIZE)
                    check_SSL_pending=1;
                c->ssl_ptr-=num;
                c->sock_bytes+=num;
                if(!ssl_rd && !c->ssl_ptr) {
                    shutdown(c->sock_wfd->fd, SHUT_WR);
                    log(LOG_DEBUG,
                        "Socket write shutdown (no more data to send)");
                    sock_wr=0;
                }
            }
        }

        if(ssl_wr && ( /* SSL sockets are still open */
                (c->sock_ptr && FD_ISSET(c->ssl_wfd->fd, &wr_set)) ||
                /* See if application data can be written */
                (SSL_want_read(c->ssl) && FD_ISSET(c->ssl_rfd->fd, &rd_set))
                /* I want to SSL_write but read from the underlying */
                /* socket needed for the SSL protocol */
                )) {
            num=SSL_write(c->ssl, c->sock_buff, c->sock_ptr);

            err=SSL_get_error(c->ssl, num);
            switch(err) {
            case SSL_ERROR_NONE:
                memmove(c->sock_buff, c->sock_buff+num, c->sock_ptr-num);
                c->sock_ptr-=num;
                c->ssl_bytes+=num;
                if(!ssl_closing && !sock_rd && !c->sock_ptr && ssl_wr) {
                    log(LOG_DEBUG,
                        "SSL write shutdown (no more data to send)");
                    ssl_closing=1;
                }
                break;
            case SSL_ERROR_WANT_WRITE:
            case SSL_ERROR_WANT_READ:
            case SSL_ERROR_WANT_X509_LOOKUP:
                log(LOG_DEBUG, "SSL_write returned WANT_: retrying");
                break;
            case SSL_ERROR_SYSCALL:
                if(num<0) { /* really an error */
                    switch(get_last_socket_error()) {
                    case EINTR:
                        log(LOG_DEBUG,
                            "SSL_write interrupted by a signal: retrying");
                        break;
                    case EAGAIN:
                        log(LOG_DEBUG,
                            "SSL_write returned EAGAIN: retrying");
                        break; 
                    default:
                        sockerror("SSL_write (ERROR_SYSCALL)");
                        return -1;
                    }
                }
                break;
            case SSL_ERROR_ZERO_RETURN: /* close_notify received */
                log(LOG_DEBUG, "SSL closed on SSL_write");
                ssl_rd=ssl_wr=0;
                break;
            case SSL_ERROR_SSL:
                sslerror("SSL_write");
                return -1;
            default:
                log(LOG_ERR, "SSL_write/SSL_get_error returned %d", err);
                return -1;
            }
        }

        if(sock_rd && FD_ISSET(c->sock_rfd->fd, &rd_set)) {
            switch(num=readsocket(c->sock_rfd->fd,
                c->sock_buff+c->sock_ptr, BUFFSIZE-c->sock_ptr)) {
            case -1:
                switch(get_last_socket_error()) {
                case EINTR:
                    log(LOG_DEBUG,
                        "readsocket interrupted by a signal: retrying");
                    break;
                case EWOULDBLOCK:
                    log(LOG_NOTICE, "readsocket would block: retrying");
                    break;
                default:
                    sockerror("readsocket");
                    return -1;
                }
                break;
            case 0: /* close */
                log(LOG_DEBUG, "Socket closed on read");
                sock_rd=0;
                if(!ssl_closing && !c->sock_ptr && ssl_wr) {
                    log(LOG_DEBUG,
                        "SSL write shutdown (output buffer empty)");
                    ssl_closing=1;
                }
                break;
            default:
                c->sock_ptr+=num;
            }
        }

        if(ssl_rd && ( /* SSL sockets are still open */
                (c->ssl_ptr<BUFFSIZE && FD_ISSET(c->ssl_rfd->fd, &rd_set)) ||
                /* See if there's any application data coming in */
                (SSL_want_write(c->ssl) && FD_ISSET(c->ssl_wfd->fd, &wr_set)) ||
                /* I want to SSL_read but write to the underlying */
                /* socket needed for the SSL protocol */
                (check_SSL_pending && SSL_pending(c->ssl))
                /* Write made space from full buffer */
                )) {
            num=SSL_read(c->ssl, c->ssl_buff+c->ssl_ptr, BUFFSIZE-c->ssl_ptr);

            err=SSL_get_error(c->ssl, num);
            switch(err) {
            case SSL_ERROR_NONE:
                c->ssl_ptr+=num;
                break;
            case SSL_ERROR_WANT_WRITE:
            case SSL_ERROR_WANT_READ:
            case SSL_ERROR_WANT_X509_LOOKUP:
                log(LOG_DEBUG, "SSL_read returned WANT_: retrying");
                break;
            case SSL_ERROR_SYSCALL:
                if(num<0) { /* not EOF */
                    switch(get_last_socket_error()) {
                    case EINTR:
                        log(LOG_DEBUG,
                            "SSL_read interrupted by a signal: retrying");
                        break;
                    case EAGAIN:
                        log(LOG_DEBUG,
                            "SSL_read returned EAGAIN: retrying");
                        break; 
                    default:
                        sockerror("SSL_read (ERROR_SYSCALL)");
                        return -1;
                    }
                } else { /* EOF */
                    log(LOG_DEBUG, "SSL socket closed on SSL_read");
                    ssl_rd=ssl_wr=0;
                }
                break;
            case SSL_ERROR_ZERO_RETURN: /* close_notify received */
                log(LOG_DEBUG, "SSL closed on SSL_read");
                ssl_rd=0;
                if(!ssl_closing && !c->sock_ptr && ssl_wr) {
                    log(LOG_DEBUG,
                        "SSL write shutdown (output buffer empty)");
                    ssl_closing=1;
                }
                if(!c->ssl_ptr && sock_wr) {
                    shutdown(c->sock_wfd->fd, SHUT_WR);
                    log(LOG_DEBUG,
                        "Socket write shutdown (output buffer empty)");
                    sock_wr=0;
                }
                break;
            case SSL_ERROR_SSL:
                sslerror("SSL_read");
                return -1;
            default:
                log(LOG_ERR, "SSL_read/SSL_get_error returned %d", err);
                return -1;
            }
        }
    }
    return 0; /* OK */
}
Beispiel #15
0
PUBLIC int HTSSL_read (HTSSL * htssl, int sd, char * buff, int len)
{
    return htssl && htssl->ssl ? SSL_read(htssl->ssl, buff, len) : -1;
}
Beispiel #16
0
extern "C" int32_t CryptoNative_SslRead(SSL* ssl, void* buf, int32_t num)
{
    ERR_clear_error();
    return SSL_read(ssl, buf, num);
}
static ssize_t i_stream_ssl_read_real(struct istream_private *stream)
{
	struct ssl_istream *sstream = (struct ssl_istream *)stream;
	struct ssl_iostream *ssl_io = sstream->ssl_io;
	unsigned char buffer[IO_BLOCK_SIZE];
	size_t max_buffer_size = i_stream_get_max_buffer_size(&stream->istream);
	size_t orig_max_buffer_size = stream->max_buffer_size;
	size_t size;
	ssize_t ret, total_ret;

	if (sstream->seen_eof) {
		stream->istream.eof = TRUE;
		return -1;
	}

	if (stream->pos >= max_buffer_size) {
		i_stream_compress(stream);
		if (stream->pos >= max_buffer_size)
			return -2;
	}

	ret = openssl_iostream_more(ssl_io);
	if (ret <= 0) {
		if (ret < 0) {
			/* handshake failed */
			i_assert(errno != 0);
			io_stream_set_error(&stream->iostream,
					    "%s", ssl_io->last_error);
			stream->istream.stream_errno = errno;
		}
		return ret;
	}

	if (!i_stream_try_alloc(stream, 1, &size))
		i_unreached();
	if (stream->pos + size > max_buffer_size) {
		i_assert(max_buffer_size > stream->pos);
		size = max_buffer_size - stream->pos;
	}

	while ((ret = SSL_read(ssl_io->ssl,
			       stream->w_buffer + stream->pos, size)) <= 0) {
		/* failed to read anything */
		ret = openssl_iostream_handle_error(ssl_io, ret, "SSL_read");
		if (ret <= 0) {
			if (ret == 0)
				return 0;
			if (ssl_io->last_error != NULL) {
				io_stream_set_error(&stream->iostream,
						    "%s", ssl_io->last_error);
			}
			if (errno != EPIPE)
				stream->istream.stream_errno = errno;
			stream->istream.eof = TRUE;
			sstream->seen_eof = TRUE;
			return -1;
		}
		/* we did some BIO I/O, try reading again */
	}
	stream->pos += ret;
	total_ret = ret;

	/* now make sure that we read everything already buffered in OpenSSL
	   into the stream (without reading anything more). this makes I/O loop
	   behave similary for ssl-istream as file-istream. */
	sstream->ssl_io->input_handler = FALSE;
	stream->max_buffer_size = (size_t)-1;
	while ((ret = SSL_read(ssl_io->ssl, buffer, sizeof(buffer))) > 0) {
		memcpy(i_stream_alloc(stream, ret), buffer, ret);
		stream->pos += ret;
		total_ret += ret;
	}
	stream->max_buffer_size = orig_max_buffer_size;
	return total_ret;
}
Beispiel #18
0
int main(int argc, char *argv[])
{
    SSL_library_init();
    SSL_load_error_strings();
    
    SSL * new_ssl;
    SSL_CTX * new_ctx;
    
    new_ctx = dh_setup_ctx();
    
    BIO * acc, * client;
    char port[sizeof(argv[1])] = "";  
    int check = 0;
    long port_num;
    parse_port(argc,argv,port);
    acc = BIO_new_accept("1300");
    port_num = BIO_set_accept_port(acc,port);
    if ( !acc )
    { 
	printf("%s \n", "Error in new bio accept");
	return -1;
    }
    if ( BIO_do_accept(acc) <= 0)
    {
	printf("%s \n", "Error in do accept" );
	return -1;
    }
    int get = 0;
    while ( 1 )
    {
	if( BIO_do_accept(acc) <= 0 )
	{
	    printf("%s \n", "Error in accepting connections");
	    return -1;
	}
	client = BIO_pop(acc);
	if ( !(new_ssl = SSL_new(new_ctx)))
	{
	    printf("%s \n", "Error in creating new SSL");
	    return -1;
	}
	SSL_set_bio(new_ssl,client,client);
	if( SSL_accept(new_ssl) <= 0 )
	{
	    get = SSL_get_error(new_ssl,get);
	    printf("%s \n", "Error in accepting SSL connection");
	    printf("%d \n", get);
	    printf("%s \n",ERR_error_string(get,NULL)); 
	    return -1;
	}
	int buf[256] = { 0 };
	int count = 0;
	if ( SSL_read(new_ssl,buf,sizeof(buf)) > 0)
	{
	    /*get = SSL_get_error(new_ssl,get);
	    printf("%d \n", get);
	    printf("%s \n",ERR_error_string(get,NULL)); 
*/
	    while( (char)buf[count] != EOF )
	    {
		printf("%c" , (char)buf[count]);
		count++;
	    }
	}
	SSL_shutdown(new_ssl);
	SSL_free(new_ssl);
    }
    SSL_CTX_free(new_ctx);
    BIO_free(acc);
    return 0;
}
Beispiel #19
0
status_t
POP3Protocol::RetrieveInternal(const char *command, int32 message,
	BPositionIO *write_to, bool post_progress)
{
	const int bufSize = 1024 * 30;

	// To avoid waiting for the non-arrival of the next data packet, try to
	// receive only the message size, plus the 3 extra bytes for the ".\r\n"
	// after the message.  Of course, if we get it wrong (or it is a huge
	// message or has lines starting with escaped periods), it will then switch
	// back to receiving full buffers until the message is done.
	int amountToReceive = MessageSize (message) + 3;
	if (amountToReceive >= bufSize || amountToReceive <= 0)
		amountToReceive = bufSize - 1;

	BString bufBString; // Used for auto-dealloc on return feature.
	char *buf = bufBString.LockBuffer (bufSize);
	int amountInBuffer = 0;
	int amountReceived;
	int testIndex;
	char *testStr;
	bool cont = true;
	bool flushWholeBuffer = false;
	write_to->Seek(0,SEEK_SET);

	if (SendCommand(command) != B_OK)
		return B_ERROR;

	struct timeval tv;
	tv.tv_sec = POP3_RETRIEVAL_TIMEOUT / 1000000;
	tv.tv_usec = POP3_RETRIEVAL_TIMEOUT % 1000000;

	struct fd_set readSet;
	FD_ZERO(&readSet);
	FD_SET(fSocket, &readSet);

	while (cont) {
		int result = 0;

#ifdef USE_SSL
		if (fUseSSL && SSL_pending(fSSL))
			result = 1;
		else
#endif
		result = select(fSocket + 1, &readSet, NULL, NULL, &tv);
		if (result == 0) {
			// No data available, even after waiting a minute.
			fLog = "POP3 timeout - no data received after a long wait.";
			runner->Stop(true);
			return B_ERROR;
		}
		if (amountToReceive > bufSize - 1 - amountInBuffer)
			amountToReceive = bufSize - 1 - amountInBuffer;
#ifdef USE_SSL
		if (fUseSSL) {
			amountReceived = SSL_read(fSSL, buf + amountInBuffer,
				amountToReceive);
		} else
#endif
		amountReceived = recv(fSocket, buf + amountInBuffer, amountToReceive, 0);
		if (amountReceived < 0) {
			fLog = strerror(errno);
			return errno;
		}
		if (amountReceived == 0) {
			fLog = "POP3 data supposedly ready to receive but not received!";
			return B_ERROR;
		}

		amountToReceive = bufSize - 1; // For next time, read a full buffer.
		amountInBuffer += amountReceived;
		buf[amountInBuffer] = 0; // NUL stops tests past the end of buffer.

		// Look for lines starting with a period.  A single period by itself on
		// a line "\r\n.\r\n" marks the end of the message (thus the need for
		// at least five characters in the buffer for testing).  A period
		// "\r\n.Stuff" at the start of a line get deleted "\r\nStuff", since
		// POP adds one as an escape code to let you have message text with
		// lines starting with a period.  For convenience, assume that no
		// messages start with a period on the very first line, so we can
		// search for the previous line's "\r\n".

		for (testIndex = 0; testIndex <= amountInBuffer - 5; testIndex++) {
			testStr = buf + testIndex;
			if (testStr[0] == '\r' && testStr[1] == '\n' && testStr[2] == '.') {
				if (testStr[3] == '\r' && testStr[4] == '\n') {
					// Found the end of the message marker.  Ignore remaining data.
					if (amountInBuffer > testIndex + 5)
						printf ("POP3Protocol::RetrieveInternal Ignoring %d bytes "
							"of extra data past message end.\n",
							amountInBuffer - (testIndex + 5));
					amountInBuffer = testIndex + 2; // Don't include ".\r\n".
					buf[amountInBuffer] = 0;
					cont = false;
				} else {
					// Remove an extra period at the start of a line.
					// Inefficient, but it doesn't happen often that you have a
					// dot starting a line of text.  Of course, a file with a
					// lot of double period lines will get processed very
					// slowly.
					memmove (buf + testIndex + 2, buf + testIndex + 3,
						amountInBuffer - (testIndex + 3) + 1 /* for NUL at end */);
					amountInBuffer--;
					// Watch out for the end of buffer case, when the POP text
					// is "\r\n..X".  Don't want to leave the resulting
					// "\r\n.X" in the buffer (flush out the whole buffer),
					// since that will get mistakenly evaluated again in the
					// next loop and delete a character by mistake.
					if (testIndex >= amountInBuffer - 4 && testStr[2] == '.') {
						printf ("POP3Protocol::RetrieveInternal: Jackpot!  You have "
							"hit the rare situation with an escaped period at the "
							"end of the buffer.  Aren't you happy it decodes it "
							"correctly?\n");
						flushWholeBuffer = true;
					}
				}
			}
		}

		if (cont && !flushWholeBuffer) {
			// Dump out most of the buffer, but leave the last 4 characters for
			// comparison continuity, in case the line starting with a period
			// crosses a buffer boundary.
			if (amountInBuffer > 4) {
				write_to->Write(buf, amountInBuffer - 4);
				if (post_progress)
					runner->ReportProgress(amountInBuffer - 4,0);
				memmove (buf, buf + amountInBuffer - 4, 4);
				amountInBuffer = 4;
			}
		} else { // Dump everything - end of message or flushing the whole buffer.
			write_to->Write(buf, amountInBuffer);
			if (post_progress)
				runner->ReportProgress(amountInBuffer,0);
			amountInBuffer = 0;
		}
	}
	return B_OK;
}
Beispiel #20
0
int
connect_ssl(char *host, char *port,
            int reconnect,
            int use_sessionid, int use_ticket,
            int delay,
            const char *client_cert, const char *client_key) {
    SSL_CTX*         ctx;
    SSL*             ssl;
    SSL_SESSION*     ssl_session = NULL;
    int              s, n;
    char             buffer[256];
    struct addrinfo* addr;

    start("Initialize OpenSSL library");
    SSL_load_error_strings();
    SSL_library_init();
    if ((ctx = SSL_CTX_new(TLSv1_client_method())) == NULL)
        fail("Unable to initialize SSL context:\n%s",
             ERR_error_string(ERR_get_error(), NULL));

    if (client_cert || client_key) {
        if (SSL_CTX_use_certificate_chain_file(ctx,client_cert)==0) {
            fail("failed to read X509 certificate from file %s into PEM format",client_key);
        }
    }
    if (client_key) {
        if (SSL_CTX_use_PrivateKey_file(ctx,client_key,SSL_FILETYPE_PEM)==0) {
            fail("failed to read private key from file %s into PEM format",client_key);
        }
    }
    if (!use_ticket) {
        start("Disable use of session tickets (RFC 5077)");
        SSL_CTX_set_options(ctx, SSL_OP_NO_TICKET);
    }

    addr = solve(host, port);
    do {
        s = connect_socket(addr, host, port);
        start("Start TLS renegotiation");
        if ((ssl = SSL_new(ctx)) == NULL)
            fail("Unable to create new SSL struct:\n%s",
                 ERR_error_string(ERR_get_error(), NULL));
        SSL_set_fd(ssl, s);
        if (ssl_session) {
            if (!SSL_set_session(ssl, ssl_session)) {
                fail("Unable to set session to previous one:\n%s",
                     ERR_error_string(ERR_get_error(), NULL));
            }
        }
        if (SSL_connect(ssl) != 1)
            fail("Unable to start TLS renegotiation:\n%s",
                 ERR_error_string(ERR_get_error(), NULL));

        start("Check if session was reused");
        if (!SSL_session_reused(ssl) && ssl_session)
            warn("No session was reused.");
        else if (SSL_session_reused(ssl) && !ssl_session)
            warn("Session was reused.");
        else if (SSL_session_reused(ssl))
            end("SSL session correctly reused");
        else
            end("SSL session was not used");
        start("Get current session");
        if (ssl_session) SSL_SESSION_free(ssl_session);
        ssl_session = NULL;
        if (!(ssl_session = SSL_get1_session(ssl)))
            warn("No session available");
        else {
            BIO *mem = BIO_new(BIO_s_mem());
            char *buf;
            if (SSL_SESSION_print(mem, ssl_session) != 1)
                fail("Unable to print session:\n%s",
                     ERR_error_string(ERR_get_error(), NULL));
            n = BIO_get_mem_data(mem, &buf);
            buf[n-1] = '\0';
            end("Session content:\n%s", buf);
            BIO_free(mem);
        }
        if ((!use_sessionid && !use_ticket) ||
                (!use_sessionid && !ssl_session->tlsext_tick)) {
            SSL_SESSION_free(ssl_session);
            ssl_session = NULL;
        }

        start("Send HTTP GET");
        n = snprintf(buffer, sizeof(buffer),
                     "GET / HTTP/1.0\r\n"
                     "Host: %s\r\n"
                     "\r\n", host);
        if (n == -1 || n >= sizeof(buffer))
            fail("Unable to build request to send");
        if (SSL_write(ssl, buffer, strlen(buffer)) != strlen(buffer))
            fail("SSL write request failed:\n%s",
                 ERR_error_string(ERR_get_error(), NULL));

        start("Get HTTP answer");
        if ((n = SSL_read(ssl, buffer, sizeof(buffer) - 1)) <= 0)
            fail("SSL read request failed:\n%s",
                 ERR_error_string(ERR_get_error(), NULL));
        buffer[n] = '\0';
        if (strchr(buffer, '\r'))
            *strchr(buffer, '\r') = '\0';
        end("%s", buffer);

        start("End TLS connection");
        SSL_shutdown(ssl);
        close(s);
        SSL_free(ssl);
        --reconnect;
        if (reconnect < 0) break;
        else {
            start("waiting %d seconds",delay);
            sleep(delay);
        }
    } while (1);

    SSL_CTX_free(ctx);
    return 0;
}
Beispiel #21
0
int main(int argc,char ** argv) {
	SSL *ssl;
	SSL_CTX *ctx;
	SSL_METHOD *client_method;
	X509 *server_cert;

	int sd,err;
	char *str,*hostname,outbuf[4096],inbuf[4096],host_header[512];
	struct hostent *host_entry;
	struct sockaddr_in server_socket_address;
	struct in_addr ip;

	//init ssl library
	SSLeay_add_ssl_algorithms();
	client_method = SSLv23_client_method();
	SSL_load_error_strings();
	ctx = SSL_CTX_new(client_method);
	printf("(1)ssl context init\n\n");

	//convert server hostname into a ip address
	hostname = argv[1];
	host_entry = gethostbyname(hostname);
	bcopy(host_entry->h_addr,&(ip.s_addr),host_entry->h_length);
	printf("(2)%s has ip address %s\n\n",hostname,inet_ntoa(ip));

	//open a tcp connection to port 443 on server

	sd = socket(AF_INET,SOCK_STREAM,0);
	memset(&server_socket_address,'\0',sizeof(server_socket_address));

	server_socket_address.sin_family = AF_INET;
	server_socket_address.sin_port = htons(443);
	memcpy(&(server_socket_address.sin_addr.s_addr),host_entry->h_addr,host_entry->h_length);


	err = connect(sd,(struct sockaddr *)&server_socket_address,sizeof(server_socket_address));
	if(err<0) {
		perror("can not connect to server port");
		exit(1);
	}
	printf("(3) tcp connection open to host %s,port %d\n\n",hostname,server_socket_address.sin_port);

	//init the ssl handshake over tcp connection
	ssl = SSL_new(ctx);
	SSL_set_fd(ssl,sd);
	err = SSL_connect(ssl);
	printf ("(4) ssl endpoint created & handshake compltete \n\n");

	//print out the negotiated cipher chosen
	printf("(5) ssl connected with cipher: %s\n\n",SSL_get_cipher(ssl));

	//print out the server's certificate
	server_cert = SSL_get_peer_certificate(ssl);
	printf("(6) server's certificate was received:\n\n");
	str = X509_NAME_oneline(X509_get_subject_name(server_cert),0,0);
	printf("\tsubject:%s\n",str);
	str = X509_NAME_oneline(X509_get_issuer_name(server_cert),0,0);
	printf("\tissuer:%s\n\n",str);

	//certificate verification would happen here
	X509_free(server_cert);

	//handshake complete--send http request over ssl

	sprintf(host_header,"Host:%s:443\r\n",hostname);
	strcpy(outbuf,"GET / HTTP/1.1\r\n");
	strcat(outbuf,host_header);
	strcat(outbuf,"Connection:close\r\n");
	strcat(outbuf,"\r\n");

	err=SSL_write(ssl,outbuf,strlen(outbuf));
	shutdown(sd,1);//send eof to server
	printf("(7) send http request over encrypted channel:\n\n%s\n",outbuf);

	//read back http response from the ssl stack
	err = SSL_read(ssl,inbuf,sizeof(inbuf)-1);
	inbuf[err]='\0';
	printf("(8)got back %d bytes of http response:\n\n%s\n",err,inbuf);

	//all done,so close connection & clean up
	SSL_shutdown(ssl);
	close(sd);
	SSL_free(ssl);
	SSL_CTX_free(ctx);
	printf("(9) all done ,cleaned up and closed connection\n\n");
	return 0;
}
Beispiel #22
0
int main(int argc, char **argv)
{
    int sockfd, new_fd;
    socklen_t len;
    struct sockaddr_in my_addr, their_addr;
    unsigned int myport, lisnum;
    char buf[MAXBUF + 1];
    SSL_CTX *ctx;
    /* 指定监听端口 */
    if (argc > 1 && argv[1]) {
        myport = atoi(argv[1]);
    } else {
        myport = 8888;
    }
    /* 最大客户端连接数 */
    if (argv[2]) {
        lisnum = atoi(argv[2]);
    } else {
        lisnum = 2;
    }
    /* SSL 库初始化 */
    SSL_library_init();
    /* 载入所有SSL 算法 */
    OpenSSL_add_all_algorithms();
    /* 载入所有SSL 错误消息 */
    SSL_load_error_strings();
    /* 以SSL V2 和V3 标准兼容方式产生一个SSL_CTX ,即SSL Content Text  */
    ctx = SSL_CTX_new(SSLv23_server_method());
    /* 也可以用SSLv2_server_method() 或SSLv3_server_method() 单独表示V2 或V3标准
     */
    if (ctx == NULL) {
        ERR_print_errors_fp(stdout);
        exit(1);
    }
    /* 载入用户的数字证书, 此证书用来发送给客户端。证书里包含有公钥 */
    if (SSL_CTX_use_certificate_file(ctx, argv[4], SSL_FILETYPE_PEM) <= 0) {
        ERR_print_errors_fp(stdout);
        exit(1);
    }
    /* 载入用户私钥 */
    if (SSL_CTX_use_PrivateKey_file(ctx, argv[5], SSL_FILETYPE_PEM) <= 0) {
        ERR_print_errors_fp(stdout);
        exit(1);
    }
    /* 检查用户私钥是否正确 */
    if (!SSL_CTX_check_private_key(ctx)) {
        ERR_print_errors_fp(stdout);
        exit(1);
    }

    /* 开启一个socket 监听 */
    if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
        perror("socket");
        exit(1);
    } else {
        printf("socket created\n");
    }
    bzero(&my_addr, sizeof(my_addr));
    my_addr.sin_family = PF_INET;
    my_addr.sin_port = htons(myport);

    /* 设置监听的IP */
    if (argv[3]) {
        my_addr.sin_addr.s_addr = inet_addr(argv[3]);
    } else {
        /* 如果用户没有指定监听端口,则默认监听0.0.0.0(任意IP) */
        my_addr.sin_addr.s_addr = INADDR_ANY;
    }
    if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) ==
        -1) {
        perror("bind");
        exit(1);
    } else {
        printf("binded\n");
    }
    if (listen(sockfd, lisnum) == -1) {
        perror("listen");
        exit(1);
    } else {
        printf("begin listen\n");
    }
    while (1) {
        SSL *ssl;
        len = sizeof(struct sockaddr);
        /* 等待客户端连上来 */
        if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &len)) ==
            -1) {
            perror("accept");
            exit(errno);
        } else {
            printf("server: got connection from %s, port %d, socket %d\n",
                   inet_ntoa(their_addr.sin_addr), ntohs(their_addr.sin_port),
                   new_fd);
        }
        /* 基于ctx 产生一个新的SSL  */
        ssl = SSL_new(ctx);
        /* 将连接用户的socket 加入到SSL  */
        SSL_set_fd(ssl, new_fd);
        /* 建立SSL 连接 */
        if (SSL_accept(ssl) == -1) {
            perror("accept");
            close(new_fd);
            break;
        }
        /* 开始处理每个新连接上的数据收发 */
        bzero(buf, MAXBUF + 1);
        strcpy(buf, "server->client");
        /* 发消息给客户端 */
        len = SSL_write(ssl, buf, strlen(buf));
        if (len <= 0) {
            printf("消息'%s'发送失败!错误代码是%d,错误信息是'%s'\n", buf,
                   errno, strerror(errno));
            goto finish;
        } else {
            printf("消息'%s'发送成功,共发送了%d 个字节!\n", buf, len);
        }
        bzero(buf, MAXBUF + 1);
        /* 接收客户端的消息 */
        len = SSL_read(ssl, buf, MAXBUF);
        if (len > 0) {
            printf("接收消息成功:'%s',共%d 个字节的数据\n", buf, len);
        } else {
            printf("消息接收失败!错误代码是%d,错误信息是'%s'\n", errno,
                   strerror(errno));
        }
    /* 处理每个新连接上的数据收发结束 */
    finish:
        /* 关闭SSL 连接 */
        SSL_shutdown(ssl);
        /* 释放SSL  */
        SSL_free(ssl);
        /* 关闭socket  */
        close(new_fd);
    }
    /* 关闭监听的socket */
    close(sockfd);
    /* 释放CTX  */
    SSL_CTX_free(ctx);
    return 0;
}
Beispiel #23
0
int YellHttp_ExecRequest(YellHttp_Ctx *ctx, char *url)
{
	int retval;
	int i=0;
	int endi;
	int hostnamei;
	int porti = 0;
	int recvlen;
	int stop = 0;
	int headerspos = 0;
	int linenum = 0;
	int pos=0, pos2 = 0;
	char *hdrfield, *hdrval;
	struct hostent *host;
	struct sockaddr_in client_addr;
	FILE *fhttpdump;
	struct stat filestatus;
	char modifiedsincedate[512];
	char hdrstr[512];
	int send_modifiedsince_hdr = 0;
	int valid_domain_name;
	unsigned long serverip;
	char request_type[8];
	unsigned int content_len;
	int err;
	char errbuffer[80];

	if(url==NULL)return YELLHTTP_EINVAL;
	memset(ctx->url, 0, 512);
	strncpy(ctx->url, url, 511);	
	ctx->server_flags &= YELLHTTP_SRVFLAG_USRFLAGS;

	if(strncmp(ctx->url, "https", 5)==0)
	{
		#ifdef ENABLESSL
		ctx->SSL = 1;
		#else
		return YELLHTTP_ESSLDISABLED;
		#endif
		i+= 8;
	}
	else if(strncmp(ctx->url, "http", 4)==0)
	{
		ctx->SSL = 0;
		i+= 7;
	}
	else
	{
		return YELLHTTP_EINVAL;
	}
	hostnamei = i;

	memset(ctx->hostname, 0, 512);
	while(ctx->url[i]!='/' && ctx->url[i]!=':' && i<strlen(ctx->url))i++;
	if(i>255)return YELLHTTP_EINVAL;
	strncpy(ctx->hostname, &ctx->url[hostnamei], i - hostnamei);

	memset(ctx->uri, 0, 512);
	memset(ctx->portstr, 0, 8);
	ctx->port = 80;
	if(ctx->SSL)ctx->port = 443;
	if(ctx->url[i]==':')
	{
		i++;
		memset(ctx->portstr, 0, 8);
		while((ctx->url[i]>('0'-1) && ctx->url[i]<('9'+1)) && porti<8 && i<strlen(ctx->url))
		{
			ctx->portstr[porti] = ctx->url[i];
			i++;
			porti++;
		}
		sscanf(ctx->portstr, "%hd", &ctx->port);
	}
	strcpy(ctx->uri, &ctx->url[i]);
	i = strlen(ctx->uri) - 1;
	if(i==-1)
	{
		ctx->uri[0] = '/';
		i = 0;
	}
	endi = i;

	memset(ctx->filename, 0, 512);
	while(ctx->uri[i]!='/' && i>0)
	{
		if(ctx->uri[i]=='?')endi = i - 1;
		i--;
	}

	if(strcmp(&ctx->uri[i], "/")==0)
	{
		strncpy(ctx->filename, "index.html", 512);
	}
	else
	{
		i++;
		strncpy(ctx->filename, &ctx->uri[i], (endi + 1) - i);
	}

	printf("Looking up %s...\n", ctx->hostname);
	valid_domain_name = 0;
	for(hostnamei=0; hostnamei<strlen(ctx->hostname); hostnamei++)
	{
		if(ctx->hostname[hostnamei]>='A' && ctx->hostname[hostnamei]<='z')
		{
			valid_domain_name = 1;
			break;
		}
	}

	if(valid_domain_name)
	{
		if((host = gethostbyname(ctx->hostname)) == NULL)
        	{
			return YELLHTTP_EDNSRESOLV;
        	}
		serverip = *((unsigned long *) host->h_addr_list[0]);
	}
	else
	{
		serverip = inet_addr(ctx->hostname);
	}

	client_addr.sin_family = AF_INET;
	client_addr.sin_port = htons(ctx->port);
	client_addr.sin_addr.s_addr = serverip;

	ctx->sock_client = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
	if(ctx->sock_client<0)
	{
		if(ctx->sock_client == -1)
		{
			printf("Failed to create socket: %d\n", ctx->sock_client);
			return YELLHTTP_ESOCK;
		}
		else
		{
			printf("socket() returned %d, ignoring...\n", ctx->sock_client);
		}
	}
	printf("Connecting to %s...\n", ctx->hostname);
	if((retval = connect(ctx->sock_client, (struct sockaddr *)&client_addr, sizeof(client_addr)))<0)
	{
		printf("Failed: %d\n", retval);
		return YELLHTTP_ECONN;
	}

	#ifdef ENABLESSL
	SSL_METHOD* method;
	SSL_CTX* sslctx;
	SSL* ssl;
	if(ctx->SSL)
	{
		InitCyaSSL();
		CyaSSL_Debugging_ON();
		method = SSLv3_client_method();
    		if(method)sslctx = SSL_CTX_new(method);
		if(sslctx)SSL_CTX_set_verify(sslctx, SSL_VERIFY_NONE, 0);
        	if(sslctx)ssl = SSL_new(sslctx);
		if(ssl)SSL_set_fd(ssl, ctx->sock_client);
		
		if(method==NULL || sslctx==NULL || ssl==NULL)
		{
			if(method==NULL)printf("Method init failure ");
			if(method==NULL)printf("SSL ctx init failure ");
			if(method==NULL)printf("SSL init failure ");
			err = SSL_get_error(ssl, 0);
			printf("sslerr = %d, %s\n", err, ERR_error_string(err, errbuffer));
			shutdown(ctx->sock_client,0);
			close(ctx->sock_client);
			if(sslctx)SSL_CTX_free(sslctx);
     			if(ssl)SSL_free(ssl);
			FreeCyaSSL();
			return err;
		}		
		printf("Connecting to %s with SSL...\n", ctx->hostname);
     		if(SSL_connect(ssl)!=SSL_SUCCESS)
		{
			err = SSL_get_error(ssl, 0);
			printf("sslerr = %d, %s\n", err, ERR_error_string(err, errbuffer));
			shutdown(ctx->sock_client,0);
			close(ctx->sock_client);
			SSL_CTX_free(sslctx);
     			SSL_free(ssl);
			FreeCyaSSL();
			return err;
		}
	}	
	#endif

	if(stat(ctx->filename, &filestatus)==0 && !(ctx->server_flags & YELLHTTP_SRVFLAG_NOCACHE))
	{
		memset(modifiedsincedate, 0, 512);
		memset(hdrstr, 0, 512);
		YellHttp_GenDate(modifiedsincedate, filestatus.st_mtime, ctx);
		sprintf(hdrstr, "If-Modified-Since: %s\r\n", modifiedsincedate);
		send_modifiedsince_hdr = 1;
	}

	memset(request_type, 0, 8);
	if(strlen(ctx->request_type)>0)
	{
		strncpy(request_type, ctx->request_type, 8);
		if(strncmp(request_type, "HEAD", 4)==0)stop = 1;
	}
	else
	{
		strncpy(request_type, "GET", 8);
	}
	snprintf((char*)ctx->sendbuf, SENDBUFSZ, "%s %s HTTP/%s\r\nHost: %s\r\nUser-Agent: %s\r\nConnection: close\r\n",  request_type, ctx->uri, ctx->httpversion, ctx->hostname, ctx->useragent);
	
	if(send_modifiedsince_hdr)strncat((char*)ctx->sendbuf, hdrstr, SENDBUFSZ);
	if(ctx->range_end!=0)
	{
		memset(hdrstr, 0, 512);
		snprintf(hdrstr, 512, "Range: bytes=%d-%d\r\n", ctx->range_start, ctx->range_end);
		strncat((char*)ctx->sendbuf, hdrstr, SENDBUFSZ);
	}
	if(ctx->authenticated)
	{
		#ifdef ENABLESSL
		if(ctx->auth_type==1)YellHttp_GenDigestAuthHdr(ctx);
		#endif
		strncat((char*)ctx->sendbuf, ctx->authorization_header, SENDBUFSZ);
	}
	if(strncmp(ctx->request_type, "POST", 4)==0)
	{
		if(ctx->postdata && ctx->postdata>0)
		{
			snprintf(hdrstr, 512, "Content-Type: %s\r\nContent-Length: %d\r\n", ctx->content_type, ctx->postdata_length);
			strncat((char*)ctx->sendbuf, hdrstr, SENDBUFSZ);
		}
	}
	if(strlen(ctx->headers)>0)strncat((char*)ctx->sendbuf, ctx->headers, SENDBUFSZ);

	strncat((char*)ctx->sendbuf, "\r\n", SENDBUFSZ);
	printf("Sending request...\n");
	if(!ctx->SSL)
	{
		YellHttp_SendData(ctx->sock_client, ctx->sendbuf, strlen((char*)ctx->sendbuf));
	}
	else
	{
		#ifdef ENABLESSL
		SSL_write(ssl, ctx->sendbuf, strlen((char*)ctx->sendbuf));
		#endif
	}

	if(strncmp(ctx->request_type, "POST", 4)==0)
	{
		printf("Sending POST data...\n");
		if(ctx->postdata==NULL || ctx->postdata_length==0)
		{
			printf("Ctx->postdata is NULL, or postdata_length is zero.\n");
			shutdown(ctx->sock_client,0);
			close(ctx->sock_client);
			SSL_CTX_free(sslctx);
     			SSL_free(ssl);
			FreeCyaSSL();
			return YELLHTTP_EINVAL;
		}

		if(!ctx->SSL)
		{
			YellHttp_SendData(ctx->sock_client, ctx->postdata, ctx->postdata_length);
		}
		else
		{
			#ifdef ENABLESSL
			SSL_write(ssl, ctx->postdata, ctx->postdata_length);
			#endif
		}
	}

	hdrfield = (char*)malloc(512);
	hdrval = (char*)malloc(512);

	printf("Waiting for response...(Headers)\n");
	fhttpdump = fopen("httpheaders", "wb");
	if(fhttpdump==NULL)
	{
		#ifdef ENABLESSL
		if(ctx->SSL)
		{
			SSL_CTX_free(sslctx);
     			SSL_free(ssl);
			FreeCyaSSL();
		}	
		#endif
		shutdown(ctx->sock_client,0);
		close(ctx->sock_client);
		free(hdrfield);
		free(hdrval);
		return YELLHTTP_EFILE;
	}
	while(1)
	{
		if(!ctx->SSL)
		{
			recvlen = YellHttp_RecvData(ctx->sock_client, &ctx->recvbuf[headerspos], 1);
		}
		else
		{
			#ifdef ENABLESSL
			recvlen = SSL_read(ssl, &ctx->recvbuf[headerspos], 1);
			#endif
		}
		if(recvlen<=0)
		{
			stop = 1;
			break;
		}
		fwrite(&ctx->recvbuf[headerspos], 1, 1, fhttpdump);
		if(ctx->recvbuf[headerspos]==0x0a)
		{
			ctx->recvbuf[headerspos+1]=0;
			if(strlen((char*)ctx->recvbuf)<3)
			{
				headerspos = 0;
				break;
			}

			if(headerspos>4)
			{
				if(linenum==0)
				{
					sscanf((char*)&ctx->recvbuf[9], "%d", &ctx->http_status);
					memcpy(ctx->httpversion, &ctx->recvbuf[5], 3);
					printf("HTTP status: %d\n", ctx->http_status);
					if(ctx->http_status==304)stop = 1;
					if(ctx->http_status==401)
					{
						ctx->auth_requirederrors++;
					}
					else
					{
						ctx->auth_requirederrors = 0;
					}
				}
				else
				{
					memset(hdrfield, 0, 512);
					memset(hdrval, 0, 512);
					pos = 0;
					pos2 = 0;
					while(ctx->recvbuf[pos]!=':' && ctx->recvbuf[pos]!=0x0d && pos2<255)
					{
						hdrfield[pos2] = ctx->recvbuf[pos];
						pos++;
						pos2++;
					}

					if(ctx->recvbuf[pos]==':')
					{
						pos+=2;
						pos2 = 0;
						while(ctx->recvbuf[pos]!=0x0d && pos2<255)
						{
							hdrval[pos2] = ctx->recvbuf[pos];
							pos++;
							pos2++;
						}
					}

					for(i=0; i<32; i++)
					{
						if(headercb_array[i].cb==NULL)continue;
						if(strcmp(headercb_array[i].hdrfield, hdrfield)==0)
						{
							headercb_array[i].cb((char*)ctx->recvbuf, hdrfield, hdrval, ctx, headercb_array[i].usrarg);
						}
					}
				}
				linenum++;
				headerspos = 0;
				continue;
			}
		}
		headerspos++;
	}
	fclose(fhttpdump);
	free(hdrfield);
	free(hdrval);

	if(!stop)
	{
		printf("Receiving content, filename %s ...\n", ctx->filename);
		fhttpdump = fopen(ctx->filename, "wb");
		content_len = ctx->content_length;
		if(fhttpdump==NULL)
		{
			#ifdef ENABLESSL
			if(ctx->SSL)
			{
				SSL_CTX_free(sslctx);
     				SSL_free(ssl);
			FreeCyaSSL();
			}	
			#endif
			shutdown(ctx->sock_client,0);
			close(ctx->sock_client);
			return YELLHTTP_EFILE;
		}

		if(!ctx->SSL)
		{
			if(content_len)
			{
				while(content_len)
				{
					recvlen = YellHttp_RecvData(ctx->sock_client, ctx->recvbuf, RECVBUFSZ);
					fwrite(ctx->recvbuf, 1, recvlen, fhttpdump);
					content_len-= recvlen;
				}
			}
			else
			{
				while((recvlen = YellHttp_RecvData(ctx->sock_client, ctx->recvbuf, RECVBUFSZ))!=0)
				{
					fwrite(ctx->recvbuf, 1, recvlen, fhttpdump);
				}
			}
		}
		else
		{
			#ifdef ENABLESSL
			if(content_len)
			{
				while(content_len)
				{
					recvlen = SSL_read(ssl, ctx->recvbuf, RECVBUFSZ);
					fwrite(ctx->recvbuf, 1, recvlen, fhttpdump);
					content_len-= recvlen;
				}
			}
			else
			{
				while((recvlen = SSL_read(ssl, ctx->recvbuf, RECVBUFSZ))!=0)
				{
					fwrite(ctx->recvbuf, 1, recvlen, fhttpdump);
				}
			}
			#endif
		}
		fclose(fhttpdump);
	}

	#ifdef ENABLESSL
	if(ctx->SSL)
	{
		SSL_CTX_free(sslctx);
     		SSL_free(ssl);
		FreeCyaSSL();
	}	
	#endif
	shutdown(ctx->sock_client,0);
	close(ctx->sock_client);

	if((ctx->http_status>=301 && ctx->http_status<=303) && !(ctx->server_flags & YELLHTTP_SRVFLAG_DISABLEREDIR))
	{
		printf("Redirected: %s\n", ctx->redirecturl);
		return YellHttp_ExecRequest(ctx, ctx->redirecturl);
	}
	if(ctx->http_status==401 && ctx->authenticated)
	{
		if(ctx->authenticated==1)
		{
			return YellHttp_ExecRequest(ctx, url);
		}
	}
	if(ctx->http_status>=400)return -ctx->http_status;
	if(ctx->authenticated)
	{
		ctx->auth_nc++;
	}	
	return 0;
}
Beispiel #24
0
THREAD_RETURN CYASSL_THREAD server_test(void* args)
{
    SOCKET_T sockfd   = 0;
    SOCKET_T clientfd = 0;

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

    char   msg[] = "I hear you fa shizzle!";
    char   input[80];
    int    idx;
    int    ch;
    int    version = SERVER_DEFAULT_VERSION;
    int    doCliCertCheck = 1;
    int    useAnyAddr = 0;
    word16 port = wolfSSLPort;
    int    usePsk = 0;
    int    useAnon = 0;
    int    doDTLS = 0;
    int    needDH = 0;
    int    useNtruKey   = 0;
    int    nonBlocking  = 0;
    int    trackMemory  = 0;
    int    fewerPackets = 0;
    int    pkCallbacks  = 0;
    int    serverReadyFile = 0;
    int    wc_shutdown     = 0;
    int    resume = 0;            /* do resume, and resume count */
    int    minDhKeyBits = DEFAULT_MIN_DHKEY_BITS;
    int    ret;
    char*  alpnList = NULL;
    unsigned char alpn_opt = 0;
    char*  cipherList = NULL;
    const char* verifyCert = cliCert;
    const char* ourCert    = svrCert;
    const char* ourKey     = svrKey;
    const char* ourDhParam = dhParam;
    int    argc = ((func_args*)args)->argc;
    char** argv = ((func_args*)args)->argv;

#ifndef NO_PSK
    int sendPskIdentityHint = 1;
#endif

#ifdef HAVE_SNI
    char*  sniHostName = NULL;
#endif

#ifdef HAVE_OCSP
    int    useOcsp  = 0;
    char*  ocspUrl  = NULL;
#endif

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

#ifdef NO_RSA
    verifyCert = (char*)cliEccCert;
    ourCert    = (char*)eccCert;
    ourKey     = (char*)eccKey;
#endif
    (void)trackMemory;
    (void)pkCallbacks;
    (void)needDH;
    (void)ourKey;
    (void)ourCert;
    (void)ourDhParam;
    (void)verifyCert;
    (void)useNtruKey;
    (void)doCliCertCheck;
    (void)minDhKeyBits;
    (void)alpnList;
    (void)alpn_opt;

#ifdef CYASSL_TIRTOS
    fdOpenSession(Task_self());
#endif

    while ((ch = mygetopt(argc, argv, "?dbstnNufrRawPIp:v:l:A:c:k:Z:S:oO:D:L:"))
                         != -1) {
        switch (ch) {
            case '?' :
                Usage();
                exit(EXIT_SUCCESS);

            case 'd' :
                doCliCertCheck = 0;
                break;

            case 'b' :
                useAnyAddr = 1;
                break;

            case 's' :
                usePsk = 1;
                break;

            case 't' :
            #ifdef USE_WOLFSSL_MEMORY
                trackMemory = 1;
            #endif
                break;

            case 'n' :
                useNtruKey = 1;
                break;

            case 'u' :
                doDTLS  = 1;
                break;

            case 'f' :
                fewerPackets = 1;
                break;

            case 'R' :
                serverReadyFile = 1;
                break;

            case 'r' :
                #ifndef NO_SESSION_CACHE
                    resume = 1;
                #endif
                break;

            case 'P' :
            #ifdef HAVE_PK_CALLBACKS 
                pkCallbacks = 1;
            #endif
                break;

            case 'p' :
                port = (word16)atoi(myoptarg);
                #if !defined(NO_MAIN_DRIVER) || defined(USE_WINDOWS_API)
                    if (port == 0)
                        err_sys("port number cannot be 0");
                #endif
                break;

            case 'w' :
                wc_shutdown = 1;
                break;

            case 'v' :
                version = atoi(myoptarg);
                if (version < 0 || version > 3) {
                    Usage();
                    exit(MY_EX_USAGE);
                }
                break;

            case 'l' :
                cipherList = myoptarg;
                break;

            case 'A' :
                verifyCert = myoptarg;
                break;

            case 'c' :
                ourCert = myoptarg;
                break;

            case 'k' :
                ourKey = myoptarg;
                break;

            case 'D' :
                #ifndef NO_DH
                    ourDhParam = myoptarg;
                #endif
                break;

            case 'Z' :
                #ifndef NO_DH
                    minDhKeyBits = atoi(myoptarg);
                    if (minDhKeyBits <= 0 || minDhKeyBits > 16000) {
                        Usage();
                        exit(MY_EX_USAGE);
                    }
                #endif
                break;

            case 'N':
                nonBlocking = 1;
                break;

            case 'S' :
                #ifdef HAVE_SNI
                    sniHostName = myoptarg;
                #endif
                break;

            case 'o' :
                #ifdef HAVE_OCSP
                    useOcsp = 1;
                #endif
                break;

            case 'O' :
                #ifdef HAVE_OCSP
                    useOcsp = 1;
                    ocspUrl = myoptarg;
                #endif
                break;

            case 'a' :
                #ifdef HAVE_ANON
                    useAnon = 1;
                #endif
                break;
            case 'I':
                #ifndef NO_PSK
                    sendPskIdentityHint = 0;
                #endif
                break;

            case 'L' :
                #ifdef HAVE_ALPN
                    alpnList = myoptarg;

                    if (alpnList[0] == 'C' && alpnList[1] == ':')
                        alpn_opt = WOLFSSL_ALPN_CONTINUE_ON_MISMATCH;
                    else if (alpnList[0] == 'F' && alpnList[1] == ':')
                        alpn_opt = WOLFSSL_ALPN_FAILED_ON_MISMATCH;
                    else {
                        Usage();
                        exit(MY_EX_USAGE);
                    }

                    alpnList += 2;

                #endif
                break;
            default:
                Usage();
                exit(MY_EX_USAGE);
        }
    }

    myoptind = 0;      /* reset for test cases */

    /* sort out DTLS versus TLS versions */
    if (version == CLIENT_INVALID_VERSION) {
        if (doDTLS)
            version = CLIENT_DTLS_DEFAULT_VERSION;
        else
            version = CLIENT_DEFAULT_VERSION;
    }
    else {
        if (doDTLS) {
            if (version == 3)
                version = -2;
            else
                version = -1;
        }
    }

#ifdef USE_CYASSL_MEMORY
    if (trackMemory)
        InitMemoryTracker();
#endif

    switch (version) {
#ifndef NO_OLD_TLS
    #ifdef WOLFSSL_ALLOW_SSLV3
        case 0:
            method = SSLv3_server_method();
            break;
    #endif

    #ifndef NO_TLS
        case 1:
            method = TLSv1_server_method();
            break;


        case 2:
            method = TLSv1_1_server_method();
            break;

        #endif
#endif

#ifndef NO_TLS
        case 3:
            method = TLSv1_2_server_method();
            break;
#endif

#ifdef CYASSL_DTLS
    #ifndef NO_OLD_TLS
        case -1:
            method = DTLSv1_server_method();
            break;
    #endif

        case -2:
            method = DTLSv1_2_server_method();
            break;
#endif

        default:
            err_sys("Bad SSL version");
    }

    if (method == NULL)
        err_sys("unable to get method");

    ctx = SSL_CTX_new(method);
    if (ctx == NULL)
        err_sys("unable to get ctx");

#if defined(HAVE_SESSION_TICKET) && defined(HAVE_CHACHA) && \
                                    defined(HAVE_POLY1305)
    if (TicketInit() != 0)
        err_sys("unable to setup Session Ticket Key context");
    wolfSSL_CTX_set_TicketEncCb(ctx, myTicketEncCb);
#endif

    if (cipherList)
        if (SSL_CTX_set_cipher_list(ctx, cipherList) != SSL_SUCCESS)
            err_sys("server can't set cipher list 1");

#ifdef CYASSL_LEANPSK
    usePsk = 1;
#endif

#if defined(NO_RSA) && !defined(HAVE_ECC)
    usePsk = 1;
#endif

    if (fewerPackets)
        CyaSSL_CTX_set_group_messages(ctx);

#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
    SSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack);
#endif

#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS)
    if (!usePsk && !useAnon) {
        if (SSL_CTX_use_certificate_file(ctx, ourCert, SSL_FILETYPE_PEM)
                                         != SSL_SUCCESS)
            err_sys("can't load server cert file, check file and run from"
                    " wolfSSL home dir");
    }
#endif

#ifndef NO_DH
    wolfSSL_CTX_SetMinDhKey_Sz(ctx, (word16)minDhKeyBits);
#endif

#ifdef HAVE_NTRU
    if (useNtruKey) {
        if (CyaSSL_CTX_use_NTRUPrivateKey_file(ctx, ourKey)
                                != SSL_SUCCESS)
            err_sys("can't load ntru key file, "
                    "Please run from wolfSSL home dir");
    }
#endif
#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS)
    if (!useNtruKey && !usePsk && !useAnon) {
        if (SSL_CTX_use_PrivateKey_file(ctx, ourKey, SSL_FILETYPE_PEM)
                                         != SSL_SUCCESS)
            err_sys("can't load server private key file, check file and run "
                "from wolfSSL home dir");
    }
#endif

    if (usePsk) {
#ifndef NO_PSK
        SSL_CTX_set_psk_server_callback(ctx, my_psk_server_cb);

        if (sendPskIdentityHint == 1)
            SSL_CTX_use_psk_identity_hint(ctx, "cyassl server");

        if (cipherList == NULL) {
            const char *defaultCipherList;
            #if defined(HAVE_AESGCM) && !defined(NO_DH)
                defaultCipherList = "DHE-PSK-AES128-GCM-SHA256";
                needDH = 1;
            #elif defined(HAVE_NULL_CIPHER)
                defaultCipherList = "PSK-NULL-SHA256";
            #else
                defaultCipherList = "PSK-AES128-CBC-SHA256";
            #endif
            if (SSL_CTX_set_cipher_list(ctx, defaultCipherList) != SSL_SUCCESS)
                err_sys("server can't set cipher list 2");
        }
#endif
    }

    if (useAnon) {
#ifdef HAVE_ANON
        CyaSSL_CTX_allow_anon_cipher(ctx);
        if (cipherList == NULL) {
            if (SSL_CTX_set_cipher_list(ctx, "ADH-AES128-SHA") != SSL_SUCCESS)
                err_sys("server can't set cipher list 4");
        }
#endif
    }

#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS)
    /* if not using PSK, verify peer with certs */
    if (doCliCertCheck && usePsk == 0 && useAnon == 0) {
        SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER |
                                SSL_VERIFY_FAIL_IF_NO_PEER_CERT,0);
        if (SSL_CTX_load_verify_locations(ctx, verifyCert, 0) != SSL_SUCCESS)
            err_sys("can't load ca file, Please run from wolfSSL home dir");
    }
#endif

#if defined(CYASSL_SNIFFER)
    /* don't use EDH, can't sniff tmp keys */
    if (cipherList == NULL) {
        if (SSL_CTX_set_cipher_list(ctx, "AES256-SHA256") != SSL_SUCCESS)
            err_sys("server can't set cipher list 3");
    }
#endif

#ifdef HAVE_SNI
    if (sniHostName)
        if (CyaSSL_CTX_UseSNI(ctx, CYASSL_SNI_HOST_NAME, sniHostName,
                                           XSTRLEN(sniHostName)) != SSL_SUCCESS)
            err_sys("UseSNI failed");
#endif

while (1) {  /* allow resume option */
    if (resume > 1) {  /* already did listen, just do accept */
        if (doDTLS == 0) {
            SOCKADDR_IN_T client;
            socklen_t client_len = sizeof(client);
            clientfd = accept(sockfd, (struct sockaddr*)&client,
                             (ACCEPT_THIRD_T)&client_len);
        } else {
            tcp_listen(&sockfd, &port, useAnyAddr, doDTLS);
            clientfd = sockfd;
        }
        #ifdef USE_WINDOWS_API
            if (clientfd == INVALID_SOCKET) err_sys("tcp accept failed");
        #else
            if (clientfd == -1) err_sys("tcp accept failed");
        #endif
    }

    ssl = SSL_new(ctx);
    if (ssl == NULL)
        err_sys("unable to get SSL");

#ifndef NO_HANDSHAKE_DONE_CB
    wolfSSL_SetHsDoneCb(ssl, myHsDoneCb, NULL);
#endif
#ifdef HAVE_CRL
    CyaSSL_EnableCRL(ssl, 0);
    CyaSSL_LoadCRL(ssl, crlPemDir, SSL_FILETYPE_PEM, CYASSL_CRL_MONITOR |
                                                     CYASSL_CRL_START_MON);
    CyaSSL_SetCRL_Cb(ssl, CRL_CallBack);
#endif
#ifdef HAVE_OCSP
    if (useOcsp) {
        if (ocspUrl != NULL) {
            CyaSSL_CTX_SetOCSP_OverrideURL(ctx, ocspUrl);
            CyaSSL_CTX_EnableOCSP(ctx, CYASSL_OCSP_NO_NONCE
                                                    | CYASSL_OCSP_URL_OVERRIDE);
        }
        else
            CyaSSL_CTX_EnableOCSP(ctx, CYASSL_OCSP_NO_NONCE);
    }
#endif
#ifdef HAVE_PK_CALLBACKS
    if (pkCallbacks)
        SetupPkCallbacks(ctx, ssl);
#endif

    if (resume < 2) {  /* do listen and accept */
        tcp_accept(&sockfd, &clientfd, (func_args*)args, port, useAnyAddr,
                   doDTLS, serverReadyFile);
    }

    SSL_set_fd(ssl, clientfd);

#ifdef HAVE_ALPN
    if (alpnList != NULL) {
        printf("ALPN accepted protocols list : %s\n", alpnList);
        wolfSSL_UseALPN(ssl, alpnList, (word32)XSTRLEN(alpnList), alpn_opt);
    }
#endif

#ifdef WOLFSSL_DTLS
    if (doDTLS) {
        SOCKADDR_IN_T cliaddr;
        byte          b[1500];
        int           n;
        socklen_t     len = sizeof(cliaddr);

        /* For DTLS, peek at the next datagram so we can get the client's
         * address and set it into the ssl object later to generate the
         * cookie. */
        n = (int)recvfrom(sockfd, (char*)b, sizeof(b), MSG_PEEK,
                          (struct sockaddr*)&cliaddr, &len);
        if (n <= 0)
            err_sys("recvfrom failed");

        wolfSSL_dtls_set_peer(ssl, &cliaddr, len);
    }
#endif
    if (usePsk == 0 || useAnon == 1 || cipherList != NULL || needDH == 1) {
        #if !defined(NO_FILESYSTEM) && !defined(NO_DH) && !defined(NO_ASN)
            CyaSSL_SetTmpDH_file(ssl, ourDhParam, SSL_FILETYPE_PEM);
        #elif !defined(NO_DH)
            SetDH(ssl);  /* repick suites with DHE, higher priority than PSK */
        #endif
    }

#ifndef CYASSL_CALLBACKS
    if (nonBlocking) {
        CyaSSL_set_using_nonblock(ssl, 1);
        tcp_set_nonblocking(&clientfd);
        NonBlockingSSL_Accept(ssl);
    } else if (SSL_accept(ssl) != SSL_SUCCESS) {
        int err = SSL_get_error(ssl, 0);
        char buffer[CYASSL_MAX_ERROR_SZ];
        printf("error = %d, %s\n", err, ERR_error_string(err, buffer));
        err_sys("SSL_accept failed");
    }
#else
    NonBlockingSSL_Accept(ssl);
#endif
    showPeer(ssl);

#ifdef HAVE_ALPN
    if (alpnList != NULL) {
        int err;
        char *protocol_name = NULL;
        word16 protocol_nameSz = 0;

        err = wolfSSL_ALPN_GetProtocol(ssl, &protocol_name, &protocol_nameSz);
        if (err == SSL_SUCCESS)
            printf("Sent ALPN protocol : %s (%d)\n",
                   protocol_name, protocol_nameSz);
        else if (err == SSL_ALPN_NOT_FOUND)
            printf("No ALPN response sent (no match)\n");
        else
            printf("Getting ALPN protocol name failed\n");
    }
#endif

    idx = SSL_read(ssl, input, sizeof(input)-1);
    if (idx > 0) {
        input[idx] = 0;
        printf("Client message: %s\n", input);

    }
    else if (idx < 0) {
        int readErr = SSL_get_error(ssl, 0);
        if (readErr != SSL_ERROR_WANT_READ)
            err_sys("SSL_read failed");
    }

    if (SSL_write(ssl, msg, sizeof(msg)) != sizeof(msg))
        err_sys("SSL_write failed");
        
    #if defined(WOLFSSL_MDK_SHELL) && defined(HAVE_MDK_RTX)
        os_dly_wait(500) ;
    #elif defined (CYASSL_TIRTOS)
        Task_yield();
    #endif

    if (doDTLS == 0) {
        ret = SSL_shutdown(ssl);
        if (wc_shutdown && ret == SSL_SHUTDOWN_NOT_DONE)
            SSL_shutdown(ssl);    /* bidirectional shutdown */
    }
    SSL_free(ssl);
    if (resume == 1) {
        CloseSocket(clientfd);
        resume++;           /* only do one resume for testing */
        continue;
    }
    break;  /* out of while loop, done with normal and resume option */
}
    SSL_CTX_free(ctx);

    CloseSocket(clientfd);
    CloseSocket(sockfd);
    ((func_args*)args)->return_code = 0;


#if defined(NO_MAIN_DRIVER) && defined(HAVE_ECC) && defined(FP_ECC) \
                            && defined(HAVE_THREAD_LS)
    ecc_fp_free();  /* free per thread cache */
#endif

#ifdef USE_WOLFSSL_MEMORY
    if (trackMemory)
        ShowMemoryTracker();
#endif

#ifdef CYASSL_TIRTOS
    fdCloseSession(Task_self());
#endif

#if defined(HAVE_SESSION_TICKET) && defined(HAVE_CHACHA) && \
                                    defined(HAVE_POLY1305)
    TicketCleanup();
#endif

#ifndef CYASSL_TIRTOS
    return 0;
#endif
}
Beispiel #25
0
ssize_t ws_raw_read(wsh_t *wsh, void *data, size_t bytes, int block)
{
	ssize_t r;
	int err = 0;

	wsh->x++;
	if (wsh->x > 250) ms_sleep(1);

	if (wsh->ssl) {
		do {
			r = SSL_read(wsh->ssl, data, bytes);

			if (r == -1) {
				err = SSL_get_error(wsh->ssl, r);
				
				if (!block && err == SSL_ERROR_WANT_READ) {
					r = -2;
					goto end;
				}

				if (block) {
					wsh->x++;
					ms_sleep(10);
				}
			}

		} while (r == -1 && err == SSL_ERROR_WANT_READ && wsh->x < 100);

		goto end;
	}

	do {

		r = recv(wsh->sock, data, bytes, 0);

		if (r == -1) {
			if (!block && xp_is_blocking(xp_errno())) {
				r = -2;
				goto end;
			}

			if (block) {
				wsh->x++;
				ms_sleep(10);
			}
		}
	} while (r == -1 && xp_is_blocking(xp_errno()) && wsh->x < 100);
	
	if (wsh->x >= 1000 || (block && wsh->x >= 100)) {
		r = -1;
	}

 end:

	if (r > 0) {
		*((char *)data + r) = '\0';
	}

	if (r >= 0) {
		wsh->x = 0;
	}
	
	return r;
}
Beispiel #26
0
int MAIN(int argc, char **argv)
	{
	double totalTime = 0.0;
	int nConn = 0;
	SSL *scon=NULL;
	long finishtime=0;
	int ret=1,i;
	MS_STATIC char buf[1024*8];
	int ver;

	apps_startup();
	s_time_init();

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

	s_time_meth=SSLv23_client_method();

	/* parse the command line arguments */
	if( parseArgs( argc, argv ) < 0 )
		goto end;

	OpenSSL_add_ssl_algorithms();
	if ((tm_ctx=SSL_CTX_new(s_time_meth)) == NULL) return(1);

	SSL_CTX_set_quiet_shutdown(tm_ctx,1);

	if (st_bugs) SSL_CTX_set_options(tm_ctx,SSL_OP_ALL);
	SSL_CTX_set_cipher_list(tm_ctx,tm_cipher);
	if(!set_cert_stuff(tm_ctx,t_cert_file,t_key_file)) 
		goto end;

	SSL_load_error_strings();

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

	if (tm_cipher == NULL)
		tm_cipher = getenv("SSL_CIPHER");

	if (tm_cipher == NULL ) {
		fprintf( stderr, "No CIPHER specified\n" );
	}

	if (!(perform & 1)) goto next;
	printf( "Collecting connection statistics for %d seconds\n", maxTime );

	/* Loop and time how long it takes to make connections */

	bytes_read=0;
	finishtime=(long)time(NULL)+maxTime;
	tm_Time_F(START);
	for (;;)
		{
		if (finishtime < (long)time(NULL)) break;
#ifdef WIN32_STUFF

		if( flushWinMsgs(0) == -1 )
			goto end;

		if( waitingToDie || exitNow )		/* we're dead */
			goto end;
#endif

		if( (scon = doConnection( NULL )) == NULL )
			goto end;

		if (s_www_path != NULL)
			{
			BIO_snprintf(buf,sizeof buf,"GET %s HTTP/1.0\r\n\r\n",s_www_path);
			SSL_write(scon,buf,strlen(buf));
			while ((i=SSL_read(scon,buf,sizeof(buf))) > 0)
				bytes_read+=i;
			}

#ifdef NO_SHUTDOWN
		SSL_set_shutdown(scon,SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
#else
		SSL_shutdown(scon);
#endif
		SHUTDOWN2(SSL_get_fd(scon));

		nConn += 1;
		if (SSL_session_reused(scon))
			ver='r';
		else
			{
			ver=SSL_version(scon);
			if (ver == TLS1_VERSION)
				ver='t';
			else if (ver == SSL3_VERSION)
				ver='3';
			else
				ver='*';
			}
		fputc(ver,stdout);
		fflush(stdout);

		SSL_free( scon );
		scon=NULL;
		}
	totalTime += tm_Time_F(STOP); /* Add the time for this iteration */

	i=(int)((long)time(NULL)-finishtime+maxTime);
	printf( "\n\n%d connections in %.2fs; %.2f connections/user sec, bytes read %ld\n", nConn, totalTime, ((double)nConn/totalTime),bytes_read);
	printf( "%d connections in %ld real seconds, %ld bytes read per connection\n",nConn,(long)time(NULL)-finishtime+maxTime,bytes_read/nConn);

	/* Now loop and time connections using the same session id over and over */

next:
	if (!(perform & 2)) goto end;
	printf( "\n\nNow timing with session id reuse.\n" );

	/* Get an SSL object so we can reuse the session id */
	if( (scon = doConnection( NULL )) == NULL )
		{
		fprintf( stderr, "Unable to get connection\n" );
		goto end;
		}

	if (s_www_path != NULL)
		{
		BIO_snprintf(buf,sizeof buf,"GET %s HTTP/1.0\r\n\r\n",s_www_path);
		SSL_write(scon,buf,strlen(buf));
		while (SSL_read(scon,buf,sizeof(buf)) > 0)
			;
		}
#ifdef NO_SHUTDOWN
	SSL_set_shutdown(scon,SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
#else
	SSL_shutdown(scon);
#endif
	SHUTDOWN2(SSL_get_fd(scon));

	nConn = 0;
	totalTime = 0.0;

	finishtime=(long)time(NULL)+maxTime;

	printf( "starting\n" );
	bytes_read=0;
	tm_Time_F(START);
		
	for (;;)
		{
		if (finishtime < (long)time(NULL)) break;

#ifdef WIN32_STUFF
		if( flushWinMsgs(0) == -1 )
			goto end;

		if( waitingToDie || exitNow )	/* we're dead */
			goto end;
#endif

	 	if( (doConnection( scon )) == NULL )
			goto end;

		if (s_www_path)
			{
			BIO_snprintf(buf,sizeof buf,"GET %s HTTP/1.0\r\n\r\n",s_www_path);
			SSL_write(scon,buf,strlen(buf));
			while ((i=SSL_read(scon,buf,sizeof(buf))) > 0)
				bytes_read+=i;
			}

#ifdef NO_SHUTDOWN
		SSL_set_shutdown(scon,SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
#else
		SSL_shutdown(scon);
#endif
		SHUTDOWN2(SSL_get_fd(scon));
	
		nConn += 1;
		if (SSL_session_reused(scon))
			ver='r';
		else
			{
			ver=SSL_version(scon);
			if (ver == TLS1_VERSION)
				ver='t';
			else if (ver == SSL3_VERSION)
				ver='3';
			else
				ver='*';
			}
		fputc(ver,stdout);
		fflush(stdout);
		}
	totalTime += tm_Time_F(STOP); /* Add the time for this iteration*/


	printf( "\n\n%d connections in %.2fs; %.2f connections/user sec, bytes read %ld\n", nConn, totalTime, ((double)nConn/totalTime),bytes_read);
	printf( "%d connections in %ld real seconds, %ld bytes read per connection\n",nConn,(long)time(NULL)-finishtime+maxTime,bytes_read/nConn);

	ret=0;
end:
	if (scon != NULL) SSL_free(scon);

	if (tm_ctx != NULL)
		{
		SSL_CTX_free(tm_ctx);
		tm_ctx=NULL;
		}
	apps_shutdown();
	OPENSSL_EXIT(ret);
	}
Beispiel #27
0
static int connection_handle_read_ssl(server *srv, connection *con) {
#ifdef USE_OPENSSL
	int r, ssl_err, len, count = 0, read_offset, toread;
	buffer *b = NULL;

	if (!con->conf.is_ssl) return -1;

	ERR_clear_error();
	do {
		if (NULL != con->read_queue->last) {
			b = con->read_queue->last->mem;
		}

		if (NULL == b || b->size - b->used < 1024) {
			b = chunkqueue_get_append_buffer(con->read_queue);
			len = SSL_pending(con->ssl);
			if (len < 4*1024) len = 4*1024; /* always alloc >= 4k buffer */
			buffer_prepare_copy(b, len + 1);

			/* overwrite everything with 0 */
			memset(b->ptr, 0, b->size);
		}

		read_offset = (b->used > 0) ? b->used - 1 : 0;
		toread = b->size - 1 - read_offset;

		len = SSL_read(con->ssl, b->ptr + read_offset, toread);

		if (con->renegotiations > 1 && con->conf.ssl_disable_client_renegotiation) {
			connection_set_state(srv, con, CON_STATE_ERROR);
			log_error_write(srv, __FILE__, __LINE__, "s", "SSL: renegotiation initiated by client");
			return -1;
		}

		if (len > 0) {
			if (b->used > 0) b->used--;
			b->used += len;
			b->ptr[b->used++] = '\0';

			con->bytes_read += len;

			count += len;
		}
	} while (len == toread && count < MAX_READ_LIMIT);


	if (len < 0) {
		int oerrno = errno;
		switch ((r = SSL_get_error(con->ssl, len))) {
		case SSL_ERROR_WANT_READ:
		case SSL_ERROR_WANT_WRITE:
			con->is_readable = 0;

			/* the manual says we have to call SSL_read with the same arguments next time.
			 * we ignore this restriction; no one has complained about it in 1.5 yet, so it probably works anyway.
			 */

			return 0;
		case SSL_ERROR_SYSCALL:
			/**
			 * man SSL_get_error()
			 *
			 * SSL_ERROR_SYSCALL
			 *   Some I/O error occurred.  The OpenSSL error queue may contain more
			 *   information on the error.  If the error queue is empty (i.e.
			 *   ERR_get_error() returns 0), ret can be used to find out more about
			 *   the error: If ret == 0, an EOF was observed that violates the
			 *   protocol.  If ret == -1, the underlying BIO reported an I/O error
			 *   (for socket I/O on Unix systems, consult errno for details).
			 *
			 */
			while((ssl_err = ERR_get_error())) {
				/* get all errors from the error-queue */
				log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
						r, ERR_error_string(ssl_err, NULL));
			}

			switch(oerrno) {
			default:
				log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
						len, r, oerrno,
						strerror(oerrno));
				break;
			}

			break;
		case SSL_ERROR_ZERO_RETURN:
			/* clean shutdown on the remote side */

			if (r == 0) {
				/* FIXME: later */
			}

			/* fall thourgh */
		default:
			while((ssl_err = ERR_get_error())) {
				switch (ERR_GET_REASON(ssl_err)) {
				case SSL_R_SSL_HANDSHAKE_FAILURE:
				case SSL_R_TLSV1_ALERT_UNKNOWN_CA:
				case SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN:
				case SSL_R_SSLV3_ALERT_BAD_CERTIFICATE:
					if (!con->conf.log_ssl_noise) continue;
					break;
				default:
					break;
				}
				/* get all errors from the error-queue */
				log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
				                r, ERR_error_string(ssl_err, NULL));
			}
			break;
		}

		connection_set_state(srv, con, CON_STATE_ERROR);

		return -1;
	} else if (len == 0) {
		con->is_readable = 0;
		/* the other end close the connection -> KEEP-ALIVE */

		return -2;
	} else {
		joblist_append(srv, con);
	}

	return 0;
#else
	UNUSED(srv);
	UNUSED(con);
	return -1;
#endif
}
Beispiel #28
0
void client_test(void* args)
{
    SOCKET_T sockfd = 0;

    SSL_METHOD*  method  = 0;
    SSL_CTX*     ctx     = 0;
    SSL*         ssl     = 0;
    
#ifdef TEST_RESUME
    SSL*         sslResume = 0;
    SSL_SESSION* session = 0;
    char         resumeMsg[] = "resuming cyassl!";
    int          resumeSz    = sizeof(resumeMsg);
#endif

    char msg[64] = "hello cyassl!";
    char reply[1024];
    int  input;
    int  msgSz = strlen(msg);

    int     argc = ((func_args*)args)->argc;
    char**  argv = ((func_args*)args)->argv;

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

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

#ifndef NO_PSK
    SSL_CTX_set_psk_client_callback(ctx, my_psk_client_cb);
#endif

#ifdef OPENSSL_EXTRA
    SSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack);
#endif

#ifdef CYASSL_SNIFFER
    /* don't use EDH, can't sniff tmp keys */
    SSL_CTX_set_cipher_list(ctx, "AES256-SHA");
#endif

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

#ifdef VERIFY_CALLBACK
    SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, myVerify);
#endif

    if (argc == 3) {
        /*  ./client server securePort  */
        SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0);  /* TODO: add ca cert */
                    /* this is just to allow easy testing of other servers */
        tcp_connect(&sockfd, argv[1], (short)atoi(argv[2]));
    }
    else if (argc == 1) {
        /* ./client          // plain mode */
        /* for client cert authentication if server requests */
#ifndef NO_FILESYSTEM
        if (SSL_CTX_use_certificate_file(ctx, cliCert, SSL_FILETYPE_PEM)
                != SSL_SUCCESS)
            err_sys("can't load client cert file");

        if (SSL_CTX_use_PrivateKey_file(ctx, cliKey, SSL_FILETYPE_PEM)
                != SSL_SUCCESS)
            err_sys("can't load client key file");
#else
        load_buffer(ctx, cliCert, CYASSL_CERT);
        load_buffer(ctx, cliKey, CYASSL_KEY);
#endif

        tcp_connect(&sockfd, yasslIP, yasslPort);
    }
    else if (argc == 2) {
        /* time passed in number of connects give average */
        int times = atoi(argv[1]);
        int i = 0;

        double start = current_time(), avg;

        for (i = 0; i < times; i++) {
            tcp_connect(&sockfd, yasslIP, yasslPort);
            ssl = SSL_new(ctx);
            SSL_set_fd(ssl, sockfd);
            if (SSL_connect(ssl) != SSL_SUCCESS)
                err_sys("SSL_connect failed");

            SSL_shutdown(ssl);
            SSL_free(ssl);
            CloseSocket(sockfd);
        }
        avg = current_time() - start;
        avg /= times;
        avg *= 1000;    /* milliseconds */  
        printf("SSL_connect avg took:%6.3f milliseconds\n", avg);

        SSL_CTX_free(ctx);
        ((func_args*)args)->return_code = 0;
        return;
    }
    else
        err_sys("usage: ./client server securePort");

    ssl = SSL_new(ctx);
    SSL_set_fd(ssl, sockfd);
    if (argc != 3)
        CyaSSL_check_domain_name(ssl, "www.yassl.com");
#ifdef NON_BLOCKING
    tcp_set_nonblocking(&sockfd);
    NonBlockingSSL_Connect(ssl);
#else
    #ifndef CYASSL_CALLBACKS
        if (SSL_connect(ssl) != SSL_SUCCESS) { /* see note at top of README */
            int  err = SSL_get_error(ssl, 0);
            char buffer[80];
            printf("err = %d, %s\n", err, ERR_error_string(err, buffer));
            err_sys("SSL_connect failed");/* if you're getting an error here  */
        }
    #else
        timeout.tv_sec  = 2;
        timeout.tv_usec = 0;
        NonBlockingSSL_Connect(ssl);  /* will keep retrying on timeout */
    #endif
#endif
    showPeer(ssl);
    
    if (argc == 3) {
        printf("SSL connect ok, sending GET...\n");
        msgSz = 28;
        strncpy(msg, "GET /index.html HTTP/1.0\r\n\r\n", msgSz);
    }
    if (SSL_write(ssl, msg, msgSz) != msgSz)
        err_sys("SSL_write failed");

    input = SSL_read(ssl, reply, sizeof(reply));
    if (input > 0) {
        reply[input] = 0;
        printf("Server response: %s\n", reply);

        if (argc == 3) {  /* get html */
            while (1) {
                input = SSL_read(ssl, reply, sizeof(reply));
                if (input > 0) {
                    reply[input] = 0;
                    printf("%s\n", reply);
                }
                else
                    break;
            }
        }
    }
  
#ifdef TEST_RESUME
    #ifdef CYASSL_DTLS
        strncpy(msg, "break", 6);
        msgSz = (int)strlen(msg);
        /* try to send session close */
        SSL_write(ssl, msg, msgSz);
    #endif
    session   = SSL_get_session(ssl);
    sslResume = SSL_new(ctx);
#endif

    SSL_shutdown(ssl);
    SSL_free(ssl);
    CloseSocket(sockfd);

#ifdef TEST_RESUME
    #ifdef CYASSL_DTLS
        #ifdef USE_WINDOWS_API 
            Sleep(500);
        #else
            sleep(1);
        #endif
    #endif
    if (argc == 3)
        tcp_connect(&sockfd, argv[1], (short)atoi(argv[2]));
    else
        tcp_connect(&sockfd, yasslIP, yasslPort);
    SSL_set_fd(sslResume, sockfd);
    SSL_set_session(sslResume, session);
   
    showPeer(sslResume); 
    if (SSL_connect(sslResume) != SSL_SUCCESS) err_sys("SSL resume failed");

#ifdef OPENSSL_EXTRA
    if (SSL_session_reused(sslResume))
        printf("reused session id\n");
    else
        printf("didn't reuse session id!!!\n");
#endif
  
    if (SSL_write(sslResume, resumeMsg, resumeSz) != resumeSz)
        err_sys("SSL_write failed");

    input = SSL_read(sslResume, reply, sizeof(reply));
    if (input > 0) {
        reply[input] = 0;
        printf("Server resume response: %s\n", reply);
    }

    /* try to send session break */
    SSL_write(sslResume, msg, msgSz); 

    SSL_shutdown(sslResume);
    SSL_free(sslResume);
#endif /* TEST_RESUME */

    SSL_CTX_free(ctx);
    CloseSocket(sockfd);

    ((func_args*)args)->return_code = 0;
}
Beispiel #29
0
static ssize_t read_socket_with_timeout(int fd,char *buf,size_t mincnt,size_t maxcnt,unsigned int time_out)
{
  fd_set fds;
  int selrtn;
  ssize_t readret;
  size_t nread = 0;
  struct timeval timeout;

  /* just checking .... */
  if (maxcnt <= 0)
    return(0);

  smb_read_error = 0;

  /* Blocking read */
  if (time_out <= 0) {
    if (mincnt == 0) mincnt = maxcnt;

    while (nread < mincnt) {
#ifdef WITH_SSL
      if(fd == sslFd){
        readret = SSL_read(ssl, buf + nread, maxcnt - nread);
      }else{
        readret = read(fd, buf + nread, maxcnt - nread);
      }
#else /* WITH_SSL */
      readret = read(fd, buf + nread, maxcnt - nread);
#endif /* WITH_SSL */

      if (readret == 0) {
        DEBUG(5,("read_socket_with_timeout: blocking read. EOF from client.\n"));
        smb_read_error = READ_EOF;
        return -1;
      }

      if (readret == -1) {
        DEBUG(0,("read_socket_with_timeout: read error = %s.\n", strerror(errno) ));
        smb_read_error = READ_ERROR;
        return -1;
      }
      nread += readret;
    }
    return((ssize_t)nread);
  }
  
  /* Most difficult - timeout read */
  /* If this is ever called on a disk file and 
     mincnt is greater then the filesize then
     system performance will suffer severely as 
     select always returns true on disk files */

  /* Set initial timeout */
  timeout.tv_sec = (time_t)(time_out / 1000);
  timeout.tv_usec = (long)(1000 * (time_out % 1000));

  for (nread=0; nread < mincnt; ) {      
    FD_ZERO(&fds);
    FD_SET(fd,&fds);
      
    selrtn = sys_select(fd+1,&fds,&timeout);

    /* Check if error */
    if(selrtn == -1) {
      /* something is wrong. Maybe the socket is dead? */
      DEBUG(0,("read_socket_with_timeout: timeout read. select error = %s.\n", strerror(errno) ));
      smb_read_error = READ_ERROR;
      return -1;
    }

    /* Did we timeout ? */
    if (selrtn == 0) {
      DEBUG(10,("read_socket_with_timeout: timeout read. select timed out.\n"));
      smb_read_error = READ_TIMEOUT;
      return -1;
    }
      
#ifdef WITH_SSL
    if(fd == sslFd){
      readret = SSL_read(ssl, buf + nread, maxcnt - nread);
    }else{
      readret = read(fd, buf + nread, maxcnt - nread);
    }
#else /* WITH_SSL */
    readret = read(fd, buf+nread, maxcnt-nread);
#endif /* WITH_SSL */

    if (readret == 0) {
      /* we got EOF on the file descriptor */
      DEBUG(5,("read_socket_with_timeout: timeout read. EOF from client.\n"));
      smb_read_error = READ_EOF;
      return -1;
    }

    if (readret == -1) {
      /* the descriptor is probably dead */
      DEBUG(0,("read_socket_with_timeout: timeout read. read error = %s.\n", strerror(errno) ));
      smb_read_error = READ_ERROR;
      return -1;
    }
      
    nread += readret;
  }

  /* Return the number we got */
  return((ssize_t)nread);
}
/*
 *	Process an EAP request
 */
eaptls_status_t eaptls_process(EAP_HANDLER *handler)
{
	tls_session_t *tls_session = (tls_session_t *) handler->opaque;
	EAPTLS_PACKET	*tlspacket;
	eaptls_status_t	status;
	REQUEST *request = handler->request;

	RDEBUG2("processing EAP-TLS");
	if (handler->certs) pairadd(&request->packet->vps,
				    paircopy(handler->certs));

	/* This case is when SSL generates Alert then we
	 * send that alert to the client and then send the EAP-Failure
	 */
	status = eaptls_verify(handler);
	RDEBUG2("eaptls_verify returned %d\n", status);

	switch (status) {
	default:
	case EAPTLS_INVALID:
	case EAPTLS_FAIL:

		/*
		 *	Success means that we're done the initial
		 *	handshake.  For TTLS, this means send stuff
		 *	back to the client, and the client sends us
		 *	more tunneled data.
		 */
	case EAPTLS_SUCCESS:
		return status;
		break;

		/*
		 *	Normal TLS request, continue with the "get rest
		 *	of fragments" phase.
		 */
	case EAPTLS_REQUEST:
		eaptls_request(handler->eap_ds, tls_session);
		return EAPTLS_HANDLED;
		break;

		/*
		 *	The handshake is done, and we're in the "tunnel
		 *	data" phase.
		 */
	case EAPTLS_OK:
		RDEBUG2("Done initial handshake");

		/*
		 *	Get the rest of the fragments.
		 */
	case EAPTLS_FIRST_FRAGMENT:
	case EAPTLS_MORE_FRAGMENTS:
	case EAPTLS_LENGTH_INCLUDED:
	case EAPTLS_MORE_FRAGMENTS_WITH_LENGTH:
		break;
	}

	/*
	 *	Extract the TLS packet from the buffer.
	 */
	if ((tlspacket = eaptls_extract(request, handler->eap_ds, status)) == NULL)
		return EAPTLS_FAIL;

	/*
	 *	Get the session struct from the handler
	 *
	 *	update the dirty_in buffer
	 *
	 *	NOTE: This buffer will contain partial data when M bit is set.
	 *
	 * 	CAUTION while reinitializing this buffer, it should be
	 * 	reinitialized only when this M bit is NOT set.
	 */
	if (tlspacket->dlen !=
	    (tls_session->record_plus)(&tls_session->dirty_in, tlspacket->data, tlspacket->dlen)) {
		eaptls_free(&tlspacket);
		RDEBUG("Exceeded maximum record size");
		return EAPTLS_FAIL;
	}

	/*
	 *	No longer needed.
	 */
	eaptls_free(&tlspacket);

	/*
	 *	SSL initalization is done.  Return.
	 *
	 *	The TLS data will be in the tls_session structure.
	 */
	if (SSL_is_init_finished(tls_session->ssl)) {
		int err;

		/*
		 *	The initialization may be finished, but if
		 *	there more fragments coming, then send ACK,
		 *	and get the caller to continue the
		 *	conversation.
		 */	
	        if ((status == EAPTLS_MORE_FRAGMENTS) ||
        	    (status == EAPTLS_MORE_FRAGMENTS_WITH_LENGTH) ||
            	    (status == EAPTLS_FIRST_FRAGMENT)) {
			/*
			 *	Send the ACK.
			 */
			eaptls_send_ack(handler->eap_ds,
					tls_session->peap_flag);
			RDEBUG2("Init is done, but tunneled data is fragmented");
			return EAPTLS_HANDLED;
		}

		/*	
		 *	Decrypt the complete record.
		 */
		BIO_write(tls_session->into_ssl, tls_session->dirty_in.data,
			  tls_session->dirty_in.used);

		/*
		 *      Clear the dirty buffer now that we are done with it
		 *      and init the clean_out buffer to store decrypted data
		 */
		(tls_session->record_init)(&tls_session->dirty_in);
		(tls_session->record_init)(&tls_session->clean_out);

		/*
		 *      Read (and decrypt) the tunneled data from the
		 *      SSL session, and put it into the decrypted
		 *      data buffer.
		 */
		err = SSL_read(tls_session->ssl, tls_session->clean_out.data,
			       sizeof(tls_session->clean_out.data));

		if (err < 0) {
			RDEBUG("SSL_read Error");

			switch (SSL_get_error(tls_session->ssl, err)) {
			case SSL_ERROR_WANT_READ:
			case SSL_ERROR_WANT_WRITE:
				RDEBUG("Error in fragmentation logic");
				break;
			default:
				/*
				 *	FIXME: Call int_ssl_check?
				 */
				break;
			}
			return EAPTLS_FAIL;
		}

		if (err == 0) {
			RDEBUG("WARNING: No data inside of the tunnel.");
		}
	
		/*
		 *	Passed all checks, successfully decrypted data
		 */
		tls_session->clean_out.used = err;
		
		return EAPTLS_OK;
	}

	/*
	 *	Continue the handshake.
	 */
	return eaptls_operation(status, handler);
}