Пример #1
0
Файл: ssl.c Проект: FPiriz/uperf
/* Called only once during beginning of the program */
int
ssl_init(void *arg)
{
	int i;

	if (IS_MASTER(options)) {
		if (file_present("server.pem") == 0)
			ctx = initialize_ctx("server.pem", PASS, NULL);
	} else {
		if (file_present("client.pem") == 0)
			ctx = initialize_ctx("client.pem", PASS, NULL);
	}
	if (ctx == NULL)
		return (1);

	ssl_locks = malloc(CRYPTO_num_locks() * sizeof (pthread_mutex_t));
	for (i = 0; i < CRYPTO_num_locks(); i++) {
		pthread_mutex_init(&ssl_locks[i], 0);
	}
	CRYPTO_set_id_callback((unsigned long (*)())id_function);
	CRYPTO_set_locking_callback((void (*)())locking_function);

	/*
	 * We also register an atexit function to cleanup the ENGINE
	 * datastructures
	 */
	atexit(ssl_cleanup);
	return (0);
}
Пример #2
0
int main(int argc,char **argv)
{
  struct ssl_transport *sslt = calloc(1, sizeof(struct ssl_transport));

  printf("Running test\n");

  return initialize_ctx(sslt);

}
Пример #3
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);
  }
Пример #4
0
// Main function     
int main(int argc, char **argv){
	SSL_CTX *ctx;                          // SSL context
	BIO *sbio;
	int sock;                              // socket descriptor 
	extern char *optarg;                   // user input parameters
	int c;                                 // user iput from getopt
	char *filename = "proxyList";          // filename for proxy
	int r = 0, w = 0;                      // slice related parameters
	char *file_requested = "index.html";   // file requeste for HTTP GET
	SPP_SLICE **slice_set;                 // slice array 
	SPP_PROXY **proxies;                   // proxy array 
	int N_proxies = 0;                     // number of proxies in path 
	int action = 0;                        // specify client/server behavior (handshake, 200OK, serve file, browser-like)
	char *file_action = NULL;              // file action to use for browser-liek behavior
	struct timeval tvBeginConnect; 
	struct timeval tvEndConnect; 
	struct timeval tvBegin, tvEnd; 
	struct timeval tvConnect, tvDuration;  // time structures for handshake duration 
	experiment_info = (ExperimentInfo*)malloc(sizeof(ExperimentInfo));
	experiment_info->app_bytes_read = 0;
	experiment_info->app_bytes_written = 0;

#ifdef DEBUG
	printf("\n\n******************** CLIENT STARTING ********************\n");
#endif

	
	// Handle user input parameters
	while((c = getopt(argc, argv, "s:r:w:i:f:c:o:a:b:")) != -1){
			
			switch(c){
	
			// Number of slices
			case 's':	if(! (slices_len = atoi(optarg) )){
							err_exit("Bogus number of slices specified (no. of slices need to be > 1)");
						}
						experiment_info->num_slices = slices_len;
						break;
		
			// Number of proxies with read access (per slice)
			case 'r':	r = atoi(optarg); 
						break; 

			// Number of proxies with write access (per slice)
			case 'w':	w = atoi(optarg); 
						break; 

        	// Integrity check requested 
			case 'i':	require_server_auth = 0;
						break; 
      		
			// Protocol chosen
			case 'c':	if(! (proto = strdup(optarg) )){
							err_exit("Out of memory");
						}
						if (strcmp(proto, "spp_mod") == 0){
                  			proto = "spp"; 
                  			disable_nagle = 1;
						}
						if (strcmp(proto, "ssl_mod") == 0){
                  			proto = "ssl"; 
                  			disable_nagle = 1;
						}
						if (strcmp(proto, "fwd_mod") == 0){
                  			proto = "fwd"; 
                  			disable_nagle = 1;
						}
						if (strcmp(proto, "pln_mod") == 0){
                  			proto = "pln"; 
                  			disable_nagle = 1;
						}
						if (strcmp(proto, "fwd") == 0){
                  			proto = "ssl"; 
						}
						break; 
			
			// File requested for HTTP GET
			case 'f':	if(! (file_requested = strdup(optarg) )){
							err_exit("Out of memory");
						}
						break; 

			// Client/Server behavior 
			case 'o':	action = atoi(optarg); 
						if (action == 2)
						{
							action = 3;
							file_requested = "1";
						}
						break; 

			// Action file 
			// NOTE: necessary only if  -o 4, i.e., browser-like behavior
			case 'a':	if(! (file_action = strdup(optarg) )){
							err_exit("Out of memory");
						}
						break; 
                                
			// Print byte statistics 
			case 'b':	stats = atoi(optarg);
						break; 

			// default case 
			default:	usage(); 
						break; 
		}
    }


	// Read number of proxy from file 
	N_proxies = read_proxy_count(filename); 
	experiment_info->num_proxies = N_proxies - 1;
	
	// Check that input parameters are correct 
	#ifdef DEBUG
	printf("[DEBUG] Parameters count: %d\n", argc); 
	#endif
	if (argc == 1){
		usage(); 
	}
	if ((strcmp(proto, "spp") == 0) && slices_len < 1){
		printf("No. of slices need to be > 0"); 
		usage(); 
	}
	if (action < 1 || action > 4){
		usage(); 
	}
	if ((strcmp(proto, "spp") != 0) && (strcmp(proto, "ssl") != 0) && (strcmp(proto, "pln") != 0)){
		printf("Protocol type specified (%s) is not supported. Supported protocols are: spp, ssl, pln\n", proto); 
		usage(); 
	}
	if (N_proxies == 0){
		printf ("At least one proxy needs to be defined, i.e., the final server\n"); 
		usage(); 
	}
	if (r > N_proxies || w > N_proxies){
		printf ("The values for r and w need to be <= than the number of proxies\n"); 
		usage(); 
	}
	if(action == 4){
		if (file_action == NULL){
			printf ("Action file (-a path_to_file) is required with -o 4\n"); 
			usage(); 
		}else{
			FILE *fp;                   
    		fp = fopen(file_action,"r");  
    		int ch=0;
			// Check for errors while opening file
		    if(fp == NULL){
    		    printf("Error while opening file %s.\r\n", file_action);
        		exit(-1);
			}
			while( ! feof(fp)){
				ch = fgetc(fp);
				if(ch == '\n'){
					lines++;
				}
			}
    		fclose(fp);
		}
	}

	// Generate a clientID
	time_t t;
	srand((unsigned) time(&t));
	clientID = rand() % MAX_CONC_CLIENT; 

	// Construct string for client/server behavior
	char *temp_str; 
	if (action == 1){
		temp_str = "handshake_only";  
	}
	if (action == 2){
		temp_str = "200_OK";  
	}
	if (action == 3){
		temp_str = "serve_file";	
	}
	if (action == 4){
		temp_str = "browser_like";	
	}

	// Logging input parameters 
	#ifdef DEBUG
	printf("[DEBUG] CLIENT-ID=%d host=%s port=%d slices=%d read=%d write=%d n_proxies=%d proto=%s action=%d(%s)\n", clientID, host, port, slices_len, r, w, N_proxies, proto, action, temp_str); 
	#endif 

	// Build SSL context
	ctx = initialize_ctx(KEYFILE, PASSWORD, proto);
	ssl = SSL_new(ctx);

	// Allocate memory for proxies 	
	proxies  = malloc( N_proxies * sizeof (SPP_PROXY*));

	// Read proxy list 
	read_proxy_list(filename, proxies);

	// Print proxy list 
	#ifdef DEBUG
	print_proxy_list(proxies, N_proxies); 
	#endif

	// Start timer for SPP (do not count slice creation for SSL instead) 
	if (strcmp(proto, "spp") == 0){
		gettimeofday(&tvBegin, NULL);
	}

	// Create slices_n slices with incremental purpose 
	slice_set  = malloc( slices_len * sizeof (SPP_SLICE*));
	#ifdef DEBUG
	printf("[DEBUG] Generating %d slices\n", slices_len); 
	#endif
	int i; 
	for (i = 0;  i < slices_len; i++){
		char *newPurpose;  
		char str[30]; 
		sprintf (str, "slices_%d", (i + 2)); 
		newPurpose = (char *)malloc(strlen(str)+1);    
		strcpy(newPurpose, str);
		slice_set[i] = SPP_generate_slice(ssl, newPurpose); 
		#ifdef DEBUG
		printf("\t[DEBUG] Generated slices %d with purpose %s\n", slice_set[i]->slice_id, slice_set[i]->purpose); 
		#endif
	}

	// Assign write access to proxies for all slices 
	// Find MAX between r and w
	int MAX = r; 
	if (w > r) 
		MAX = w; 
		
	// Iterate among proxies
	for (i = 0; i < MAX ; i++){
		// assign read access if requested
		if (i < r){
			if (SPP_assign_proxy_read_slices(ssl, proxies[i], slice_set, slices_len) == 1 ) {
				#ifdef DEBUG
				printf ("[DEBUG] Proxy %s assigned read access to slice-set (READ_COUNT=%d)\n", proxies[i]->address, (i + 1)); 
				#endif
			}
		}

		// assign write access if requested
		if (i < w){
			if (SPP_assign_proxy_write_slices(ssl, proxies[i], slice_set, slices_len) == 1 ) {
				#ifdef DEBUG
				printf ("Proxy %s correctly assigned write access to slice-set (WRITE COUNT=%d)\n", proxies[i]->address, (i + 1)); 
				#endif
			}
		}
	}
	
	// Start timer for "ssl" and "pln" 
	if (strcmp(proto, "ssl") == 0 || strcmp(proto, "pln") == 0){
		gettimeofday(&tvBegin, NULL);
	}
	
	// TCP Connect
	char* address = (char*)malloc(strlen(proxies[0]->address) + 1); // Large enough for string+\0
	memcpy(address, proxies[0]->address, strlen(proxies[0]->address) + 1);
	host = strtok(address, ":");
	port = atoi(strtok(NULL, ":")); 
	#ifdef DEBUG 
	printf("[DEBUG] Opening socket to host: %s, port %d\n", host, port);
	#endif
	sock = tcp_connect(host, port);
	plain_socket = sock;
	// Connect TCP socket to SSL socket 

	// don't init ssl for unencrypted data...
	if (strcmp(proto, "pln") != 0) 
	{
		sbio = BIO_new_socket(sock, BIO_NOCLOSE);
    	SSL_set_bio(ssl, sbio, sbio);
    }
	
	// SSL Connect 
	gettimeofday(&tvBeginConnect, NULL);

	if (strcmp(proto, "pln") != 0){
		doConnect (proto, slices_len, N_proxies, slice_set, proxies);
	}

	// Measure duration of "ssl"/"spp" connect (it does not apply to "pln" of course) 
	gettimeofday(&tvEndConnect, NULL);
	timeval_subtract(&tvConnect, &tvEndConnect, &tvBegin);
	
	// Switch across possible client-server behavior
	// // NOTE: here we can add more complex strategies
	switch(action){
		// Handshake only 
		case 1:		break; 
                
		// Send simple request, wait for 200 OK
		case 2:		http_request(file_requested, proto, false, &tvEnd);
					break; 

		// Send HTTP GET request and wait for file to be received
		case 3:		http_request(file_requested, proto, true, &tvEnd);
					break; 

		// Send several GET request following a browser-like behavior  
		case 4:		http_complex(proto, file_action, &tvEnd);
					break; 
 
		// Unknown option 
		default:	usage();
					break; 
	}
	// Compute duration of action
	if (action > 1){
		timeval_subtract(&tvDuration, &tvEnd, &tvBegin);
	}

	// Remove SSL context
    destroy_ctx(ctx);
    
	// Clode socket
    close(sock);

	//Free memory 
	#ifdef DEBUG
	printf("[DEBUG] Freeing memory\n"); 
	#endif 
	for (i = 0; i < N_proxies ; i++){
	    free(proxies[i]);
	}
	for (i = 0; i < slices_len; i++){
		free(slice_set[i]); 
	}
	free(proxies); 
	free(slice_set); 
	free(experiment_info);

	// Report time statistics
	if (action > 1){
		printf("[RESULTS] No_Slices %d Action %s_%d Duration %ld.%06ld\n", slices_len, temp_str, sizeCheck, tvDuration.tv_sec, tvDuration.tv_usec);	
	}else{
		printf("[RESULTS] No_Slices %d Action %s Handshake_Dur %ld.%06ld\n", slices_len, temp_str, tvConnect.tv_sec, tvConnect.tv_usec);	
	}
	
	// All good
	return 0; 
}
Пример #5
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;
}
Пример #6
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);
}
Пример #7
0
int main(int argc, char** argv) {


    extern dexpd_config conf0;
    int socknum = 0;
    int sock_id = 0;

    int wd = 0;
    int notify_fd = 0;
    int option_index = 0;

    char *peer_str;
    char c;
    int peer_num;

    pthread_t notify_th;
    pthread_t reconnect_th;
    pthread_t listenv6;

    struct sockaddr_in peer_addr;

    static struct option long_options[] = {
        {"dennis",no_argument,0, 'T'},
        {0, 0, 0, 0}
    };

    c = getopt_long (argc, argv, "T",long_options, &option_index);

    switch(c) {

    case 'T':

        dennis_tribute();
        break;

    default:

        break;

    }



    socklen_t addr_len = sizeof(peer_addr);

    printf ("\n");

    printf ("        /\\\n");
    printf ("       /01\\\n");
    printf ("      /0011\\\n");
    printf ("     /000111\\     [[ Obsidian 0.1 == Clement Game 2011 ]]\n");
    printf ("    /00001111\\\n");
    printf ("   /0000011000\\\n");
    printf ("   \\0000000000/\n\n");


    init_config();


    if (conf0.use_tls) {
        printf("initializing TLS config...\n");
        conf0.ctx=(SSL_CTX*)initialize_ctx(conf0.tls_server_cert,"password");
        load_dh_params(conf0.ctx,conf0.tls_server_dh);
    }

    printf("Loading catalog from %s...\n",conf0.data_dir);

    load_catalog(conf0.data_dir);
    printf("starting inotify events listener...\n");

    //inotify init functions on datadir;
    notify_fd = inotify_init();
    wd = inotify_add_watch(notify_fd, conf0.data_dir, IN_CLOSE_WRITE|IN_MOVED_TO);

    //starting a new thread for inotify events read
    pthread_create(&notify_th,NULL,notify_thread,&notify_fd);


    printf("initating connections with peers...\n");
    connectAll();
    pthread_create(&reconnect_th,NULL,reconnect_loop,NULL);

    printf("listening on %s:%d...\n",conf0.listening_addr,conf0.listening_port);

    socknum  = create_socket(conf0.listening_addr,conf0.listening_port);

    if (conf0.use_ipv6) {

        printf("listening on %s:%d...\n",conf0.ipv6_listening_addr,conf0.listening_port);
        pthread_create(&listenv6,NULL,listen_v6,NULL);

    }



    while(1) {

        if((sock_id = accept(socknum,(struct sockaddr*)&peer_addr,&addr_len))<0) {

            fprintf(stderr,"ERROR: CANNOT ACCEPT NEW CONNECTION ON %s:%d",conf0.listening_addr,conf0.listening_port);

        }

        else {

            peer_str = inet_ntoa(peer_addr.sin_addr);
            printf("New Connection From %s\n",peer_str);

            //gerer la notion de public ici
            if ( (peer_num = isPeer(peer_str,sock_id)) < 0 && conf0.pub == 0) {

                fprintf(stderr,"ERROR: REMOTE HOST NOT In PEERS LIST\n");
                close(sock_id);

            }

            else if (conf0.pub == 1) {

                printf("Notice: Accepting public connection for host %s\n",peer_str);
                createPeer(peer_str,sock_id,1);

            }

            else {

                conf0.peers[peer_num].ssl = NULL;
                pthread_create(&conf0.peers[peer_num].ioth,NULL,dexp_serv_ioth,(void*)&conf0.peers[peer_num]);


            }



        }



    }


}
Пример #8
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);
}