Example #1
0
// Perform a connect
void doConnect (char *proto, int slices_len, int N_proxies, SPP_SLICE **slice_set, SPP_PROXY **proxies){
	// SPP CONNECT 
	if (strcmp(proto, "spp") == 0){
		#ifdef DEBUG
		printf("[DEBUG] SPP_connect\n");
		#endif 
		if (SPP_connect(ssl, slice_set, slices_len, proxies, N_proxies) <= 0){
			berr_exit("SPP connect error");
		}
	} 
	
	// SSL CONNECT 
	if (strcmp(proto, "ssl") == 0){
		#ifdef DEBUG
		printf("[DEBUG] SSL_connect\n");
		#endif
		if(SSL_connect(ssl) <= 0)
			berr_exit("SSL connect error");
   	} 

	// TO DO -- Check here 	
	if(require_server_auth){
		#ifdef DEBUG
		printf("[DEBUG] Check certificate\n");
		#endif
		check_cert(host);
	}
}
Example #2
0
// Load parameters from "dh1024.pem"
void load_dh_params(SSL_CTX *ctx, char *file){
	DH *ret=0;
	BIO *bio;

    if ((bio=BIO_new_file(file,"r")) == NULL){
      berr_exit("Couldn't open DH file");
	}

	ret = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
	BIO_free(bio);
	if(SSL_CTX_set_tmp_dh(ctx,ret) < 0){
		berr_exit("Couldn't set DH parameters");
	}
}
Example #3
0
/* Check that the common name matches the host name*/
void check_cert(char *host){
	X509 *peer;
	char peer_CN[256];
  	
	long res = SSL_get_verify_result(ssl);  
	if ((res == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) || (res == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN)){
		#ifdef DEBUG
		printf("[DEBUG] Self signed certificate accepted\n"); 
		#endif
	} else {
    	if(res != X509_V_OK)
			berr_exit("Certificate doesn't verify\n");
	}

    /*Check the cert chain. The chain length
      is automatically checked by OpenSSL when
      we set the verify depth in the ctx */

    /*Check the common name*/
	peer=SSL_get_peer_certificate(ssl);
	X509_NAME_get_text_by_NID (X509_get_subject_name(peer), NID_commonName, peer_CN, 256);
      
	// WARNING NO VALIDATION Validate the hostname
	/*
	if (1) {
		printf("Peer_CN = %s\n", peer_CN);
		printf("Host = %s\n\n", host);
		//err_exit("Common name doesn't match host name");
	}
	*/
}
Example #4
0
static int do_write(int *write_blocked_on_read)
{
	ssize_t w;
	static unsigned long long bytes=0;

	if(ratelimit && check_ratelimit(&bytes)) return 0;
	ERR_clear_error();
	w=SSL_write(ssl, writebuf, writebuflen);

	switch(SSL_get_error(ssl, w))
	{
	  case SSL_ERROR_NONE:
		//logp("wrote: %d\n", w);
		if(ratelimit) bytes+=w;
		memmove(writebuf, writebuf+w, writebuflen-w);
		writebuflen-=w;
		break;
	  case SSL_ERROR_WANT_WRITE:
		break;
	  case SSL_ERROR_WANT_READ:
		*write_blocked_on_read=1;
		break;
	  case SSL_ERROR_SYSCALL:
		if(errno == EAGAIN || errno == EINTR)
			break;
		logp("Got SSL_ERROR_SYSCALL in write, errno=%d (%s)\n",
			errno, strerror(errno));
		// Fall through to write problem
	  default:
		berr_exit("SSL write problem");
		logp("write returned: %d\n", w);
		return -1;
	}
	return 0;
}
Example #5
0
// Listen TCP socket
int tcp_listen(){
    
	int sock;
	struct sockaddr_in sin;
	int val = 1;

	// Create socket, allocate memory and set sock options
	if((sock=socket(AF_INET,SOCK_STREAM,0)) < 0){
		err_exit("Couldn't make socket");
	}
    memset(&sin, 0, sizeof(sin));
    sin.sin_addr.s_addr = INADDR_ANY;
    sin.sin_family = AF_INET;
    sin.sin_port = htons(PORT);
    setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &val,sizeof(val));

    if (disable_nagle == 1)
    	set_nagle(sock, 1); 

	// Bind to socket    
	if(bind(sock,(struct sockaddr *)&sin, sizeof(sin))<0){
		berr_exit("Couldn't bind");
	}

	// Listen to socket
    listen(sock,5);  

	// Return socket descriptor
    return(sock);
}
Example #6
0
// TCP connect function 
int tcp_connect(char *host, int port){

	struct hostent *hp;
	struct sockaddr_in addr;
	int sock;

	// Resolve host 
	if(!(hp = gethostbyname(host))){
		berr_exit("Couldn't resolve host");
	}
	#ifdef DEBUG
	printf("[DEBUG] Host %s resolved\n", host); 
	#endif

	memset(&addr, 0, sizeof(addr));
	addr.sin_addr = *(struct in_addr*)
	hp->h_addr_list[0];
	addr.sin_family = AF_INET;
	addr.sin_port = htons(port);

	if((sock=socket(AF_INET,SOCK_STREAM, IPPROTO_TCP))<0){
		err_exit("Couldn't create socket");
	}
	#ifdef DEBUG
	printf("[DEBUG] Socket correctly created\n"); 
	#endif

    if (disable_nagle == 1)
    	set_nagle(sock, 1); 


	if(connect(sock,(struct sockaddr *)&addr, sizeof(addr))<0){
		err_exit("Couldn't connect socket");
	}
	#ifdef DEBUG
	printf("[DEBUG] Socket connected\n"); 
	#endif
	
   	/* Check solution below if we need to support a timeout -- to debug  
	signal(SIGALRM, AlarmHandler); 
	sTimeout = 0; 
	alarm(CONNECT_TIMEOUT); 

	if ( connect(sock, (struct sockaddr *) &addr, sizeof(addr)) ){
		if ( sTimeout ){
			err_exit("timeout connecting stream socket"); 
		}
	}
	
	sTimeout = 0; 
	alarm(CONNECT_TIMEOUT); 
	*/
	return sock;
}
Example #7
0
SSL_CTX *initialize_ctx(char *keyfile, char *password) {

	SSL_METHOD *meth;
    SSL_CTX *ctx;
    
    if(!bio_err){
      /* Global system initialization*/
      SSL_library_init();
      SSL_load_error_strings();
      
      /* An error write context */
      bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
    }

    /* Set up a SIGPIPE handler */
    signal(SIGPIPE,sigpipe_handle);
    
    /* Create our context*/
    meth=SSLv23_method();
    ctx=SSL_CTX_new(meth);

    /* Load our keys and certificates*/
    if(!(SSL_CTX_use_certificate_chain_file(ctx, keyfile)))
      berr_exit("Can't read certificate file");

    pass=password;
    SSL_CTX_set_default_passwd_cb(ctx, password_cb);
    if(!(SSL_CTX_use_PrivateKey_file(ctx, keyfile, SSL_FILETYPE_PEM)))
      berr_exit("Can't read key file");

    /* Load the CAs we trust*/
    if(!(SSL_CTX_load_verify_locations(ctx, CA_FILE, 0)))
      berr_exit("Can't read CA file");

#if (OPENSSL_VERSION_NUMBER < 0x00905100L)
    SSL_CTX_set_verify_depth(ctx,1);
#endif
    
    return ctx;
}
Example #8
0
// Check for SSL_write error (just write at this point) -- TO DO: check behavior per slice 
void check_SSL_write_error(int r, int request_len){
	
	switch(SSL_get_error(ssl, r)){
		case SSL_ERROR_NONE:
			if(request_len != r){
				err_exit("Incomplete write!");
			}
			break;

		default:
			berr_exit("SSL write problem");
	}
}
Example #9
0
/*
// Name: init_ctx
// In: void
// Out: An SSL context
// Purpose: Initializes the SSL context by setting up the certificate and
// 			private key.
*/
SSL_CTX *init_ctx(void) {
	SSL_METHOD *meth;
	SSL_CTX *ctx;
	if(!bio_err) {
		SSL_library_init();
		SSL_load_error_strings();
		bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
	}

	meth=SSLv23_method();
	ctx=SSL_CTX_new(meth);

	if(!(SSL_CTX_use_certificate_chain_file(ctx, MYCERT))) {
		berr_exit("Cant read certificate file");
	}
	if(!(SSL_CTX_use_PrivateKey_file(ctx, KEYFILE, SSL_FILETYPE_PEM))) {
		berr_exit("Can't read key file");
	}
	if(!SSL_CTX_check_private_key(ctx)) {
		berr_exit("Key isn't matching");
	}
	return ctx;
}
Example #10
0
int tcp_listen()
{
	int socket_fd;
	struct sockaddr_in sin;
	int val = 1;

	if((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
		err_exit("Couldn't make socket");

	memset(&sin, 0, sizeof(sin));
	sin.sin_addr.s_addr = INADDR_ANY;
	sin.sin_family = AF_INET;
	sin.sin_port = htons(PORT);
	setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));

	if(bind(socket_fd, (struct sockaddr *)&sin, sizeof(sin)) < 0)
		berr_exit("Couldn't bind");
	listen(socket_fd, 5);  

	return(socket_fd);
}
Example #11
0
// Emulate browser behavior based on some input traces 
static int http_complex(char *proto, char *fn, struct timeval *tvEnd){

	int r; 
	char buf[BUFSIZZ];
	long bytes_read = 0;

	// Thread for browser-like behavior 
	pthread_t reading_thread;
	if(pthread_create(&reading_thread, NULL, browser_replay, fn)) {
		fprintf(stderr, "Error creating thread\n");
		return -1;
	}else{
		#ifdef DEBUG
		printf("[DEBUG] Reading thread started!\n"); 
		#endif
	}

	// Now read the server's response, assuming  that it's terminated by a close
	while(1){
		// SPP read
		if (strcmp(proto, "spp") == 0){
			#ifdef DEBUG
			printf("[DEBUG] Waiting on SPP_read...\n");
			#endif 
			SPP_SLICE *slice;		// slice for SPP_read
			SPP_CTX *ctx;			// context pointer for SPP_read
			r = SPP_read_record(ssl, buf, BUFSIZZ, &slice, &ctx);	
		} 
		// SSL read
		else if (strcmp(proto, "ssl") == 0){
			#ifdef DEBUG
			printf("[DEBUG] Waiting on SSL_read...\n");
			#endif 
			r = SSL_read(ssl, buf, BUFSIZZ);
		}
		// TCP read 		
		else if (strcmp(proto, "pln") == 0){
			r = read(plain_socket, buf, BUFSIZZ);
			experiment_info->app_bytes_read += r;
		}
		// Check for errors in read 
		if (strcmp(proto, "spp") == 0 || strcmp(proto, "ssl") == 0){
			switch(SSL_get_error(ssl, r)){
				case SSL_ERROR_NONE:			break;
				case SSL_ERROR_ZERO_RETURN:		berr_exit("SSL error zero return");
				case SSL_ERROR_SYSCALL: 		berr_exit("SSL Error: Premature close");
				default:						berr_exit("SSL read problem");
			}
		}

		#ifdef DEBUG
		printf("Read %d bytes\n", r);
		#endif

		// Write buf to stdout
		#ifdef VERBOSE
		printf("[DEBUG] Received:\n%s\n\n", buf); 
		#endif 
    	
		// Update counter of bytes read 
		bytes_read += r;
		
		//if ( r <= 0 || bytes_read == fSize){
		#ifdef DEBUG
		printf("[DEBUG] File transfer stats %d -- %ld\n", bytes_read,  fSize); 
		#endif 
		if (bytes_read == fSize){
			#ifdef DEBUG
			printf("[DEBUG] File transfer done - signaling to other thread\n");
			#endif 
			bytes_read = 0; 
			if (running){
				thr_exit();
			}else{
				#ifdef DEBUG
				printf("[DEBUG] Reading thread is done, so here we are done too\n"); 
				#endif
				break;  
			} 
		}
	}
    
	// Measure time
	gettimeofday(tvEnd, NULL);
	
	// Shutdown connection 
	#ifdef DEBUG
	printf("[DEBUG] Shutdown was requested -- HERE\n"); 
	#endif 
	r = SSL_shutdown(ssl);
	if( !r ){
			shutdown(SSL_get_fd(ssl), 1);
			r = SSL_shutdown(ssl);
		}


	switch(r){
		case 1:
			break; // Success 
		case 0:

		case -1:

		default:
			#ifdef DEBUG 
			printf ("Shutdown failed with code %d\n", r);
			#endif 
			berr_exit("Shutdown failed"); 
	}

	//  Print byte statistics
	if (stats){
		print_stats(ssl);        
	}
	// Free ssl 
	SSL_free(ssl);

	// All good 
	return(0);
}
Example #12
0
static int http_serve(SSL *ssl, int s)
{
	char buf[BUFSIZZ];
	int r,len;
	BIO *io,*ssl_bio;

	io=BIO_new(BIO_f_buffer());
	ssl_bio=BIO_new(BIO_f_ssl());
	BIO_set_ssl(ssl_bio,ssl,BIO_CLOSE);
	BIO_push(io,ssl_bio);

	r=BIO_gets(io,buf,BUFSIZZ-1);

	switch(SSL_get_error(ssl,r)){
	case SSL_ERROR_NONE:
		len=r;
		break;
	default:
		berr_exit("SSL read problem");
	}

	char *saveptr;
	char resource[512] = {'\0'};
	char *token = strtok_r(buf, " ", &saveptr);
	if (token && strcasecmp(token, "GET") == 0)
	{
		token = strtok_r(NULL, " ", &saveptr);
		if (token)
		{
			strncpy(resource, token, sizeof(resource));
		}
	}

	if (resource[0])
	{
		while(1){
			r=BIO_gets(io,buf,BUFSIZZ-1);

			switch(SSL_get_error(ssl,r)){
			case SSL_ERROR_NONE:
				len=r;
				break;
			default:
				berr_exit("SSL read problem");
			}

			/* Look for the blank line that signals
			   the end of the HTTP headers */
			if(!strcmp(buf,"\r\n") || !strcmp(buf,"\n"))
				break;
		}
	}

	if (strcasecmp(resource, "/ciphersuites.txt") == 0)
	{
		http_serve_headers(io, 200, "OK", "text/plain");
		print_ciphersuite_data(io, ssl, 0);
	}
	else if (strcasecmp(resource, "/ciphersuites.js") == 0)
	{
		long protocol = SSL_version(ssl);
		http_serve_headers(io, 200, "OK", "text/javascript");
		if(BIO_printf(io, "$(function() {\n  insert_text('%s', '", get_protocol_name(protocol)) <= 0)
			err_exit("Write error");
		print_ciphersuite_data(io, ssl, 1);
		if(BIO_printf(io, "');\n});") <= 0)
			err_exit("Write error");
	}
	else
	{
		http_serve_headers(io, 404, "Not Found", "text/plain");
		if(BIO_puts(io, "Not found.") <= 0)
			err_exit("Write error");
	}

	if((r=BIO_flush(io))<0)
		err_exit("Error flushing BIO");

	r=SSL_shutdown(ssl);
	if(!r){
		/* If we called SSL_shutdown() first then
		   we always get return value of '0'. In
		   this case, try again, but first send a
		   TCP FIN to trigger the other side's
		   close_notify*/
		shutdown(s,1);
		r=SSL_shutdown(ssl);
	}

	switch(r){  
	case 1:
		break; /* Success */
	case 0:
	case -1:
	default:
		berr_exit("Shutdown failed");
	}

	SSL_free(ssl);
	close(s);

	return(0);
}
Example #13
0
void server(int protocol)
{
	int sock,s;
	BIO *sbio;
	SSL_CTX *ctx;
	SSL *ssl;
	int r;
	pid_t pid;

	/* Build our SSL context*/
	ctx=initialize_ctx(KEYFILE,PASSWORD);
	load_dh_params(ctx,DHFILE);
	SSL_CTX_set_cipher_list(ctx,"ALL");
	long options = SSL_OP_NO_TICKET | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
	int port;
	switch (protocol)
	{
	case SSL2_VERSION:
		options |= SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2;
		port = 4434;
		break;
	case SSL3_VERSION:
		options |= SSL_OP_NO_SSLv2 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2;
		port = 4435;
		break;
	case TLS1_VERSION:
		options |= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2;
		port = 4436;
		break;
	case TLS1_1_VERSION:
		options |= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_2;
		port = 4437;
		break;
	case TLS1_2_VERSION:
		options |= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1;
		port = 4438;
		break;
	default:
		err_exit("Unexpected protocol value");
	}
	SSL_CTX_set_options(ctx, options);

	sock=tcp_listen(port);

	while(1){
		if((s=accept(sock,0,0))<0)
			err_exit("Problem accepting");

		if((pid=fork())){
			close(s);
		}
		else {
			sbio=BIO_new_socket(s,BIO_NOCLOSE);
			ssl=SSL_new(ctx);
			SSL_set_bio(ssl,sbio,sbio);

			if((r=SSL_accept(ssl)<=0))
				berr_exit("SSL accept error");

			http_serve(ssl,s);
			exit(0);
		}
	}
	destroy_ctx(ctx);
}
Example #14
0
static int http_serve(SSL *ssl, int s)
{
	char buf[BUFSIZZ];
	int r,len;
	BIO *io,*ssl_bio;

	io=BIO_new(BIO_f_buffer());
	ssl_bio=BIO_new(BIO_f_ssl());
	BIO_set_ssl(ssl_bio,ssl,BIO_CLOSE);
	BIO_push(io,ssl_bio);

	while(1){
		r=BIO_gets(io,buf,BUFSIZZ-1);

		switch(SSL_get_error(ssl,r)){
		case SSL_ERROR_NONE:
			len=r;
			break;
		case SSL_ERROR_ZERO_RETURN:
			goto shutdown;
			break;
		default:
			berr_exit("SSL read problem");
		}

		/* Look for the blank line that signals
		   the end of the HTTP headers */
		if(!strcmp(buf,"\r\n") ||
			!strcmp(buf,"\n"))
			break;
	}

	/* Now perform renegotiation if requested */
	if(client_auth==CLIENT_AUTH_REHANDSHAKE){
		SSL_set_verify(ssl,SSL_VERIFY_PEER |
			SSL_VERIFY_FAIL_IF_NO_PEER_CERT,0);

		/* Stop the client from just resuming the
		   un-authenticated session */
		SSL_set_session_id_context(ssl,
			(void *)&s_server_auth_session_id_context,
			sizeof(s_server_auth_session_id_context));

		if(SSL_renegotiate(ssl)<=0)
			berr_exit("SSL renegotiation error");
		if(SSL_do_handshake(ssl)<=0)
			berr_exit("SSL renegotiation error");
		ssl->state=SSL_ST_ACCEPT;
		if(SSL_do_handshake(ssl)<=0)
			berr_exit("SSL renegotiation error");
	}

	if((r=BIO_puts
			(io,"HTTP/1.0 200 OK\r\n"))<=0)
		err_exit("Write error");
	if((r=BIO_puts
			(io,"Server: EKRServer\r\n\r\n"))<=0)
		err_exit("Write error");
	if((r=BIO_puts
			(io,"Server test page\r\n"))<=0)
		err_exit("Write error");

	if((r=BIO_flush(io))<0)
		err_exit("Error flushing BIO");


shutdown:
	r=SSL_shutdown(ssl);
	if(!r){
		/* If we called SSL_shutdown() first then
		   we always get return value of '0'. In
		   this case, try again, but first send a
		   TCP FIN to trigger the other side's
		   close_notify*/
		shutdown(s,1);
		r=SSL_shutdown(ssl);
	}

	switch(r){  
	case 1:
		break; /* Success */
	case 0:
	case -1:
	default:
		berr_exit("Shutdown failed");
	}

	SSL_free(ssl);
	close(s);

	return(0);
}
Example #15
0
int main(int argc, char **argv)
{
	int sock,s;
	BIO *sbio;
	SSL_CTX *ctx;
	SSL *ssl;
	int r;
	pid_t pid;
	extern char *optarg;
	int c;

	while((c=getopt(argc,argv,"cCxna:"))!=-1){
		switch(c){
		case 'c':
			client_auth=CLIENT_AUTH_REQUEST;
			break;
		case 'C':
			client_auth=CLIENT_AUTH_REQUIRE;
			break;
		case 'x':
			client_auth=CLIENT_AUTH_REHANDSHAKE;
			break;
		case 'n':
			fork_child=0;
			break;
		case 'a':
			if(!(ciphers=strdup(optarg)))
				err_exit("Out of memory");
			break;
		}
	}

	/* Build our SSL context*/
	ctx=initialize_ctx(KEYFILE,PASSWORD);
	load_dh_params(ctx,DHFILE);

	SSL_CTX_set_session_id_context(ctx,
		(void*)&s_server_session_id_context,
		sizeof s_server_session_id_context); 

	/* Set our cipher list */
	if(ciphers){
		SSL_CTX_set_cipher_list(ctx,ciphers);
	}

	switch(client_auth){
	case CLIENT_AUTH_REQUEST:
		SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER,0);
		break;
	case CLIENT_AUTH_REQUIRE:
		SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER |
			SSL_VERIFY_FAIL_IF_NO_PEER_CERT,0);
		break;
	case CLIENT_AUTH_REHANDSHAKE:
		/* Do nothing */
		break;
	}

	sock=tcp_listen();

	while(1){
		if((s=accept(sock,0,0))<0)
			err_exit("Problem accepting");

		if(fork_child && (pid=fork())){
			close(s);
		}
		else {
			sbio=BIO_new_socket(s,BIO_NOCLOSE);
			ssl=SSL_new(ctx);
			SSL_set_bio(ssl,sbio,sbio);

			if((r=SSL_accept(ssl)<=0))
				berr_exit("SSL accept error");

			http_serve(ssl,s);

			if(fork_child)
				exit(0);
		}
	}
	destroy_ctx(ctx);
	exit(0);
}
Example #16
0
// Send HTTP get and wait for response (SSL/SPP)
static int http_request(char *filename, char *proto, bool requestingFile, struct timeval *tvEnd){
	
	char buf[BUFSIZZ];
	int r;
	int len; 
	long bytes_read = 0;
    // Compute expected data size
	fSize = atoi(filename);
    if (fSize == 0 && filename[0] != '0'){
		if (requestingFile){
			fSize = calculate_file_size(filename);
		}else{
	    	fSize = strlen("HTTP/1.0 200 OK\r\n"); 
		}
	}   
	sizeCheck = fSize; 
	experiment_info->file_size = fSize;

	// Request file (either by name or by size) 
	if (requestingFile){
		sendRequest(filename); 
	}

	// Now read the server's response, assuming  that it's terminated by a close
	while(1){
		// SPP read
		if (strcmp(proto, "spp") == 0){
			/*
			#ifdef DEBUG
			printf("[DEBUG] SPP_read\n");
			#endif 
			*/
			SPP_SLICE *slice;		// slice for SPP_read
			SPP_CTX *ctx;			// context pointer for SPP_read
			r = SPP_read_record(ssl, buf, BUFSIZZ, &slice, &ctx);	
			#ifdef DEBUG 
			printf("[INFO] Read %d bytes\n", r);
			#endif
			if (ssl->read_stats.app_bytes == fSize){
				printf("[INFO] Read %d bytes as expected (fSize=%d). Stopping timer\n", ssl->read_stats.app_bytes, fSize);
				// Stop the timer here (avoid shutdown crap) 
				gettimeofday(tvEnd, NULL); 
				#ifdef VERBOSE
				fwrite(buf, 1, len, stdout);
				#endif
				break; 
				//goto shutdown;
			}
			switch(SSL_get_error(ssl, r)){
				case SSL_ERROR_NONE:
					len = r;
					break;

				case SSL_ERROR_ZERO_RETURN:
					goto shutdown;

				case SSL_ERROR_SYSCALL: 
					fprintf(stderr, "SSL Error: Premature close\n");
					goto done;

				default:
					berr_exit("SSL read problem");
			}
		} 
	
		// SSL read
		else if (strcmp(proto, "ssl") == 0){
			/*
			#ifdef DEBUG
			printf("[DEBUG] SSL_read\n");
			#endif 	
			*/
			r = SSL_read(ssl, buf, BUFSIZZ);
			#ifdef DEBUG 
			printf("[DEBUG] Read %d bytes\n", r);
			#endif
			if (ssl->read_stats.app_bytes == fSize){
				printf("[INFO] Read %d bytes as expected (fSize=%d). Stopping timer\n", ssl->read_stats.app_bytes, fSize);
				gettimeofday(tvEnd, NULL);
				// Write buf to stdout
				#ifdef VERBOSE
				fwrite(buf, 1, len, stdout);
				#endif
				break; 
			}
			switch(SSL_get_error(ssl, r)){
				case SSL_ERROR_NONE:
					len = r;
					break;

				case SSL_ERROR_ZERO_RETURN:
					goto shutdown;

				case SSL_ERROR_SYSCALL: 
					fprintf(stderr, "SSL Error: Premature close\n");
					goto done;

				default:
					berr_exit("SSL read problem");
			}
		}
		// SSL read
		else if (strcmp(proto, "pln") == 0){
			#ifdef DEBUG 
			printf("[DEBUG] Waiting to read bytes in plain mode\n");
			#endif
			r = read(plain_socket, buf, BUFSIZZ);
			experiment_info->app_bytes_read += r;
			bytes_read += r;
			#ifdef DEBUG 
			printf("[DEBUG] Read %d bytes\n", r);
			#endif
			if ( r <= 0 || bytes_read == fSize) /* done reading */
			{
				#ifdef DEBUG
				printf("[DEBUG] File transfer done, done reading socket...\n"); 
				#endif 
				gettimeofday(tvEnd, NULL);
				// Write buf to stdout
				#ifdef VERBOSE
				fwrite(buf, 1, len, stdout);
				#endif 
				goto done;
			}
		}
		
		// Write buf to stdout
		#ifdef VERBOSE
		fwrite(buf, 1, len, stdout);
		#endif 
    }
    
	shutdown:
		#ifdef DEBUG
		printf("[DEBUG] Shutdown was requested\n"); 
		#endif 
		r = SSL_shutdown(ssl);
		if( !r ){
			shutdown(SSL_get_fd(ssl), 1);
			r = SSL_shutdown(ssl);
		}

		switch(r){
			case 1:
				break; // Success 
			case 0:

			case -1:

			default:
				#ifdef DEBUG 
				printf ("Shutdown failed with code %d\n", r);
				#endif 
				berr_exit("Shutdown failed"); 
	}
    
	done:
		if (stats){
			print_stats(ssl);
		}
		SSL_free(ssl);
		return(0);
}
Example #17
0
int main(int argc, char **argv)
{
	int len, sock, port=PORT, r;

	SSL_CTX *ctx;
    SSL *ssl;
    BIO *sbio;
	char *ciphers = "SHA1";

	char *host=HOST;
	char buf[256];
	char *secret = "What's the question?";
  
	/*Parse command line arguments*/
  
	switch(argc){
	case 1:
    	break;
    case 3:
    	host = argv[1];
    	port=atoi(argv[2]);
    	if (port<1||port>65535){
			fprintf(stderr,"invalid port number");
			exit(0);
      	}
      break;
    default:
		printf("Usage: %s server port\n", argv[0]);
    	exit(0);
  }
  
    /* Build our SSL context*/
    ctx=initialize_ctx(KEYFILE, PASSWORD);

    /* Set our cipher list */
    if(ciphers){
      SSL_CTX_set_cipher_list(ctx, ciphers);
    }
    
    SSL_CTX_set_session_id_context(ctx,
      (void*)&s_server_session_id_context,
      sizeof s_server_session_id_context); 

    /* Connect the TCP socket*/
    sock=tcp_connect(host,port);

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

    if(SSL_connect(ssl)<=0) {
		berr_exit(FMT_CONNECT_ERR);
	}
    check_cert(ssl, "Bob's Server");

	r = SSL_write(ssl, secret, strlen(secret));

	switch(SSL_get_error(ssl,r)){
	/* We wrote something*/
	case SSL_ERROR_NONE:
		break;

	case SSL_ERROR_WANT_WRITE:
		break;

	case SSL_ERROR_WANT_READ:
		break;

	/* Some other error */
	default:	      
		berr_exit(FMT_INCORRECT_CLOSE);
	}

  	r=SSL_read(ssl, &buf, 255);
  
	switch(SSL_get_error(ssl,r)){
	case SSL_ERROR_NONE:
		len = r;
	  break;
	case SSL_ERROR_ZERO_RETURN:
	  /* End of data */
	  berr_exit(FMT_INCORRECT_CLOSE);
	  break;
	case SSL_ERROR_WANT_READ:
	  break;
	case SSL_ERROR_WANT_WRITE:
	  break;
	default:
	  berr_exit(FMT_INCORRECT_CLOSE);
  }

	buf[len]='\0';
  
	/* this is how you output something for the marker to pick up */
	printf(FMT_OUTPUT, secret, buf);

	if(SSL_shutdown(ssl) < 0) {
		berr_exit(FMT_INCORRECT_CLOSE);
	}

	SSL_free(ssl);
	close(sock);
	destroy_ctx(ctx);

	return 0;
}
/* Read from the keyboard and write to the server
   Read from the server and write to the keyboard

   we use select() to multiplex
*/
void read_write(SSL *ssl,int sock)
{
    int width;
    int r,c2sl=0,c2s_offset=0;
    int read_blocked_on_write=0,write_blocked_on_read=0,read_blocked=0;
    fd_set readfds,writefds;
    int shutdown_wait=0;
    char c2s[BUFSIZZ],s2c[BUFSIZZ];
    int ofcmode;
    
    /*First we make the socket nonblocking*/
    ofcmode=fcntl(sock,F_GETFL,0);
    ofcmode|=O_NDELAY;
    if(fcntl(sock,F_SETFL,ofcmode))
      err_exit("Couldn't make socket nonblocking");
    

    width=sock+1;
    
    while(1){
      FD_ZERO(&readfds);
      FD_ZERO(&writefds);

      FD_SET(sock,&readfds);

      /* If we're waiting for a read on the socket don't
         try to write to the server */
      if(!write_blocked_on_read){
        /* If we have data in the write queue don't try to
           read from stdin */
        if(c2sl || read_blocked_on_write)
          FD_SET(sock,&writefds);
        else
          FD_SET(fileno(stdin),&readfds);
      }
      
      r=select(width,&readfds,&writefds,0,0);
      if(r==0)
        continue;

      /* Now check if there's data to read */
      if((FD_ISSET(sock,&readfds) && !write_blocked_on_read) ||
        (read_blocked_on_write && FD_ISSET(sock,&writefds))){
        do {
          read_blocked_on_write=0;
          read_blocked=0;
          
          r=SSL_read(ssl,s2c,BUFSIZZ);
          
          switch(SSL_get_error(ssl,r)){
            case SSL_ERROR_NONE:
              /* Note: this call could block, which blocks the
                 entire application. It's arguable this is the
                 right behavior since this is essentially a terminal
                 client. However, in some other applications you
                 would have to prevent this condition */
              fwrite(s2c,1,r,stdout);
              break;
            case SSL_ERROR_ZERO_RETURN:
              /* End of data */
              if(!shutdown_wait)
                SSL_shutdown(ssl);
              goto end;
              break;
            case SSL_ERROR_WANT_READ:
              read_blocked=1;
              break;
              
              /* We get a WANT_WRITE if we're
                 trying to rehandshake and we block on
                 a write during that rehandshake.

                 We need to wait on the socket to be 
                 writeable but reinitiate the read
                 when it is */
            case SSL_ERROR_WANT_WRITE:
              read_blocked_on_write=1;
              break;
            default:
              berr_exit("SSL read problem");
          }

          /* We need a check for read_blocked here because
             SSL_pending() doesn't work properly during the
             handshake. This check prevents a busy-wait
             loop around SSL_read() */
        } while (SSL_pending(ssl) && !read_blocked);
      }
      
      /* Check for input on the console*/
      if(FD_ISSET(fileno(stdin),&readfds)){
        c2sl=read(fileno(stdin),c2s,BUFSIZZ);
        if(c2sl==0){
          shutdown_wait=1;
          if(SSL_shutdown(ssl))
            return;
        }
        c2s_offset=0;
      }

      /* If the socket is writeable... */
      if((FD_ISSET(sock,&writefds) && c2sl) ||
        (write_blocked_on_read && FD_ISSET(sock,&readfds))) {
        write_blocked_on_read=0;

        /* Try to write */
        r=SSL_write(ssl,c2s+c2s_offset,c2sl);
          
        switch(SSL_get_error(ssl,r)){
          /* We wrote something*/
          case SSL_ERROR_NONE:
            c2sl-=r;
            c2s_offset+=r;
            break;
              
            /* We would have blocked */
          case SSL_ERROR_WANT_WRITE:
            break;

            /* We get a WANT_READ if we're
               trying to rehandshake and we block on
               write during the current connection.
               
               We need to wait on the socket to be readable
               but reinitiate our write when it is */
          case SSL_ERROR_WANT_READ:
            write_blocked_on_read=1;
            break;
              
              /* Some other error */
          default:	      
            berr_exit("SSL write problem");
        }
      }
    }
      
  end:
    SSL_free(ssl);
    close(sock);
    return;
  }
Example #19
0
int main(int argc, char** argv)
{
	if(argc<4) {
		printf("Usage: ./wserver cert-file priv-key-file pub-key-file.\n");
		exit(0);
	}
	else {
		CERTFILE = argv[1];
		KEYFILE = argv[2];
		PUBFILE = argv[3];
		const char* PROMPT = "Enter password for Old Key file: ";
		if(argc == 5) {
			OLDKEY = argv[4];
			PASSWORD = getpass(PROMPT);
			OLDPASS = (char*) calloc(1, strlen(PASSWORD)+1);
			strcpy(OLDPASS, PASSWORD);
		}
		PROMPT = "Enter password for Key file: ";
		PASSWORD = getpass(PROMPT);
	}

    int sock,s;
    BIO *sbio;
    SSL_CTX *ctx;
    SSL *ssl;
    int r;
    pid_t pid;
    char buf[BUFSIZZ];
	char *owner = (char*) calloc(1,256);

    ctx=initialize_ctx(CERTFILE,KEYFILE,PASSWORD);
    load_dh_params(ctx,DHFILE);    

    sock=tcp_listen();
	if((s=accept(sock,0,0))<0) err_exit("Problem accepting");
	sbio=BIO_new_socket(s,BIO_NOCLOSE);
	ssl=SSL_new(ctx);
	SSL_set_bio(ssl,sbio,sbio);
	SSL_set_verify(ssl,SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,0);        
	if((r=SSL_accept(ssl)<=0)) berr_exit("SSL accept error");
	if(check_cert(ssl, ctx, &owner)<=0) {
		send_data(ssl, "Revoked");
		printf("Connection Closed.\n");
		close_SSL(ssl, sock);
		destroy_ctx(ctx);
		exit(0);
	}
	send_data(ssl, "Approved");
	printf("User connected: %s\n", owner);

	if((pid=fork())){
		close(s);
	}
	else {
		if(argc == 5) {recrypt();}
		while(1){
			memset((void*)buf, 0, BUFSIZZ);
			if(rec_data(buf, ssl)>0)
			{
				printf("Command received: %s\n", buf);
				if(starts_with(buf, "PUT")){
					put_file(ssl, buf, owner);
				}
				else if(starts_with(buf, "GET")){
					get_file(ssl, buf, owner);
				}
				else if(starts_with(buf, "DELEGATE")){
					delegate(ssl, buf, owner);
				}
				else if(starts_with(buf, "END")){
					close_SSL(ssl, sock);
					break;
				}
				else {
					printf("Command not recognized\n");
				}
			}
			else{
				perror("Error receiving command\n");
				break;
			}
		}
	}
    destroy_ctx(ctx);
    exit(0);
  }
Example #20
0
/* Read from the keyboard and write to the server
   Read from the server and write to the keyboard

*/
void read_write (SSL *ssl, int sock)
  {
    int width;
    int r,c2sl=0,c2s_offset=0;
    fd_set readfds,writefds;
    int shutdown_wait=0;
    char c2s[BUFSIZZ],s2c[BUFSIZZ];
    int ofcmode;
    
    /*First we make the socket nonblocking*/
    ofcmode=fcntl(sock,F_GETFL,0);
    ofcmode|=O_NDELAY;
    if(fcntl(sock,F_SETFL,ofcmode))
      err_exit("Couldn't make socket nonblocking");
    

    width=sock+1;
    
    while(1){
      FD_ZERO(&readfds);
      FD_ZERO(&writefds);

      FD_SET(sock,&readfds);

      /*If we've still got data to write then don't try to read*/
      if(c2sl)
        FD_SET(sock,&writefds);
      else
        FD_SET(fileno(stdin),&readfds);

      r=select(width,&readfds,&writefds,0,0);
      if(r==0)
        continue;

      /* Now check if there's data to read */
      if(FD_ISSET(sock,&readfds)){
        do {
          r=SSL_read(ssl,s2c,BUFSIZZ);
          
          switch(SSL_get_error(ssl,r)){
            case SSL_ERROR_NONE:
              fwrite(s2c,1,r,stdout);
              break;
            case SSL_ERROR_ZERO_RETURN:
              /* End of data */
              if(!shutdown_wait)
                SSL_shutdown(ssl);
              goto end;
              break;
            case SSL_ERROR_WANT_READ:
              break;
            default:
              berr_exit("SSL read problem");
          }
        } while (SSL_pending(ssl));
      }
      
      /* Check for input on the console*/
      if(FD_ISSET(fileno(stdin),&readfds)){
        c2sl=read(fileno(stdin),c2s,BUFSIZZ);
        if(c2sl==0){
          shutdown_wait=1;
          if(SSL_shutdown(ssl))
            return;
        }
        c2s_offset=0;
      }

      /* If we've got data to write then try to write it*/
      if(c2sl && FD_ISSET(sock,&writefds)){
        r=SSL_write(ssl,c2s+c2s_offset,c2sl);

        switch(SSL_get_error(ssl,r)){
          /* We wrote something*/
          case SSL_ERROR_NONE:
            c2sl-=r;
            c2s_offset+=r;
            break;
            
            /* We would have blocked */
          case SSL_ERROR_WANT_WRITE:
            break;

            /* Some other error */
          default:	      
            berr_exit("SSL write problem");
        }
      }

      
    }
  end:
    SSL_free(ssl);
    close(sock);
    return;

 }