Example #1
0
void reload_cmd(sock_t fd, char *options, unsigned int nb_options)
{
	char *msg;
	
	if (get_active_threads_size() > 0) {
		msg = "Threads still active, cannot reload";
		proxenet_write(fd, (void*)msg, strlen(msg));
		return;
	}

	proxy_state = SLEEPING;
	
	proxenet_destroy_plugins_vm();
	proxenet_delete_list_plugins();

	if( proxenet_initialize_plugins_list() < 0) {
		msg = "Failed to reinitilize plugins";
		proxenet_write(fd, (void*)msg, strlen(msg));
		proxy_state = INACTIVE;
		return;
	}

	proxenet_initialize_plugins();

	proxy_state = ACTIVE;

	msg = "Plugins list successfully reloaded\n";
	proxenet_write(fd, (void*)msg, strlen(msg));

	return;
}
Example #2
0
void threads_cmd(sock_t fd, char *options, unsigned int nb_options)
{
	char msg[BUFSIZE] = {0, };
	char *ptr;
	int n;

	ptr = strtok(options, " \n");
	if (!ptr){
		n = get_active_threads_size();
		n = snprintf(msg, 128, "%d active thread%c/%d max thread%c\n",
			     n, (n>1)?'s':' ',
			     cfg->nb_threads, (cfg->nb_threads>1)?'s':' '
			    );
		proxenet_write(fd, (void*)msg, n);
		return;
	}

	if (strcmp(ptr, "inc")==0 && cfg->nb_threads<MAX_THREADS)
		n = snprintf(msg, BUFSIZE, "Nb threads level is now %d\n", ++cfg->nb_threads);
	else if (strcmp(ptr, "dec")==0 && cfg->nb_threads>1)
		n = snprintf(msg, BUFSIZE, "Nb threads level is now %d\n", --cfg->nb_threads);
	else
		n = snprintf(msg, BUFSIZE, "Invalid action\n Syntax\n threads (inc|dec)\n");

	proxenet_write(fd, (void*)msg, n);
	
	return;
}
Example #3
0
void quit_cmd(sock_t fd, char *options, unsigned int nb_options)
{
	char *msg = "Leaving gracefully\n";
	proxenet_write(fd, (void*)msg, strlen(msg));
	proxy_state = INACTIVE;

	return;
}
Example #4
0
void help_cmd(sock_t fd, char *options, unsigned int nb_options)
{
	struct command_t *cmd;
	char *msg;
	unsigned int msglen = 20 + 80 + 3;

	msg = "Command list:\n";
	proxenet_write(fd, (void*)msg, strlen(msg));

	for (cmd=known_commands; cmd && cmd->name; cmd++) {
		msg = alloca(msglen+1);
		proxenet_xzero(msg, msglen+1);
		snprintf(msg, msglen+1, "%-15s\t%s\n", cmd->name, cmd->desc);
		proxenet_write(fd, (void*)msg, strlen(msg));
	}
	
	return;
}
Example #5
0
void info_cmd(sock_t fd, char *options, unsigned int nb_options)
{
	char msg[BUFSIZE] = {0, };
	char *msg2 = NULL;
	
	snprintf(msg, BUFSIZE,
		 "Infos:\n"
		 "- Listening interface: %s/%s\n"
		 "- Supported IP version: %s\n"
		 "- Logging to %s\n"
		 "- Running/Max threads: %d/%d\n"
		 "- SSL private key: %s\n"
		 "- SSL certificate: %s\n"
		 "- Proxy: %s [%s]\n"
		 "- Plugins directory: %s\n"
		 , 
		 cfg->iface, cfg->port,
		 (cfg->ip_version==AF_INET)? "IPv4": (cfg->ip_version==AF_INET6)?"IPv6": "ANY",
		 (cfg->logfile)?cfg->logfile:"stdout",
		 get_active_threads_size(), cfg->nb_threads,
		 cfg->keyfile,
		 cfg->certfile,
		 cfg->proxy.host ? cfg->proxy.host : "None",
		 cfg->proxy.host ? cfg->proxy.port : "direct",
		 cfg->plugins_path  
		);

	proxenet_write(fd, (void*)msg, strlen(msg));
	
	if (proxenet_plugin_list_size()) {
		msg2 = proxenet_build_plugins_list();
		proxenet_write(fd, (void*)msg2, strlen(msg2));
		proxenet_xfree(msg2);

	} else {
		proxenet_write(fd, (void*)"No plugin loaded\n", 17);
	}
	
	return;
}
Example #6
0
void proxenet_print_plugins_list(int fd)
{
	char *list_str;
	int list_len;

	list_len = 2048;
	list_str = (char*)alloca(list_len);
	memset(list_str, 0, list_len);

	if (!proxenet_build_plugins_list(list_str, &list_len)) {
		xlog(LOG_ERROR, "%s\n", "Failed to build plugins list string");
		return;
	}

	if (fd<0)
		xlog(LOG_INFO, "%s", list_str);
	else {
		proxenet_write(fd, list_str, list_len);
		proxenet_write(fd, "\n", 1);
	}

        return;
}
Example #7
0
int proxenet_handle_control_event(sock_t* sock) {
	char read_buf[BUFSIZE] = {0, };
	char *ptr = NULL;
	int retcode = -1;
	struct command_t *cmd = NULL;
	
	retcode = proxenet_read(*sock, read_buf, BUFSIZE-1);
	if (retcode < 0) {
		xlog(LOG_ERROR, "Failed to read control command: %s\n", strerror(errno));
		return -1;
	}

	if (retcode == 0) {
		return -1;
	}
	
	if (read_buf[0] == '\n') {
		goto cmd_end;
	}
		
	if ( (cmd=get_command(read_buf)) == NULL ) {
		proxenet_write(*sock, CONTROL_INVALID, strlen(CONTROL_INVALID));
		goto cmd_end;
	}
	
#ifdef DEBUG
	xlog(LOG_DEBUG, "Receiving control command: \"%s\" \n", cmd->name);
#endif

	ptr = &read_buf[strlen(cmd->name)];
	cmd->func(*sock, ptr, cmd->nb_opt_max);

cmd_end:
	proxenet_write(*sock, CONTROL_PROMPT, strlen(CONTROL_PROMPT));
	
	return 0;
}
Example #8
0
void plugin_cmd(sock_t fd, char *options, unsigned int nb_options)
{
	char msg[BUFSIZE] = {0, };
	char *ptr, *plist_str;
	int n, res;
	
	ptr = strtok(options, " \n");
	if (!ptr){
		n = snprintf(msg, BUFSIZE, "Invalid action\nSyntax\n plugin [list]|[toggle <num>]\n");
		proxenet_write(fd, (void*)msg, n);
		return;
	}

	if (strcmp(ptr, "list") == 0) {
		plist_str = proxenet_build_plugins_list();
		proxenet_write(fd, (void*)plist_str, strlen(plist_str));
		proxenet_xfree(plist_str);
		return;
		
	} else if (strcmp(ptr, "toggle") == 0) {
		ptr = strtok(NULL, " \n");
		if (!ptr)
			return;

		n = atoi(ptr);
		if (0 < n && n <= proxenet_plugin_list_size() ) {
			res = proxenet_toggle_plugin(n);
			n = snprintf(msg, BUFSIZE, "Plugin %d is now %sACTIVE\n", n, res?"":"IN");
			proxenet_write(fd, (void*)msg, n);
			return;
		}
	}
	
	n = snprintf(msg, BUFSIZE, "Invalid action\nSyntax\n plugin [list]|[toggle <num>]\n");
	proxenet_write(fd, (void*)msg, n);
	return;
}
Example #9
0
void pause_cmd(sock_t fd, char *options, unsigned int nb_options)
{
	char *msg;
	if (proxy_state==SLEEPING) {
		msg = "sleep-mode -> 0\n";
		proxy_state = ACTIVE;
	} else {
		msg = "sleep-mode -> 1\n";
		proxy_state = SLEEPING;
	}

	xlog(LOG_INFO, "%s", msg);
	proxenet_write(fd, (void*)msg, strlen(msg));
	return;
}
Example #10
0
void verbose_cmd(sock_t fd, char *options, unsigned int nb_options)
{
	char msg[BUFSIZE] = {0, };
	char *ptr;
	int n;

	ptr = strtok(options, " \n");
	if (!ptr){
		n = snprintf(msg, BUFSIZE, "Verbose level is at %d\n", cfg->verbose);
		proxenet_write(fd, (void*)msg, n);
		return;
	}

	if (strcmp(ptr, "inc")==0 && cfg->verbose<MAX_VERBOSE_LEVEL)
		n = snprintf(msg, BUFSIZE, "Verbose level is now %d\n", ++cfg->verbose);
	else if (strcmp(ptr, "dec")==0 && cfg->verbose>0)
		n = snprintf(msg, BUFSIZE, "Verbose level is now %d\n", --cfg->verbose);
	else
		n = snprintf(msg, BUFSIZE, "Invalid action\n Syntax\n verbose (inc|dec)\n");

	proxenet_write(fd, (void*)msg, n);

	return;
}
Example #11
0
void xloop(sock_t sock, sock_t ctl_sock)
{
	fd_set sock_set;
	int retcode;
	pthread_attr_t pattr;
	int tid;
	sock_t conn;
	sigset_t curmask, oldmask;
	sock_t ctl_cli_sock = -1;

	/* prepare threads  */
	proxenet_xzero(threads, sizeof(pthread_t) * MAX_THREADS);
	
	if (pthread_attr_init(&pattr)) {
		xlog(LOG_ERROR, "%s\n", "Failed to pthread_attr_init");
		return;
	}
	
	pthread_attr_setdetachstate(&pattr, PTHREAD_CREATE_JOINABLE);

	/* block useful signal */
	sigemptyset(&curmask);
	sigaddset(&curmask, SIGTERM);
	sigaddset(&curmask, SIGINT);
	sigaddset(&curmask, SIGCHLD);
	if (pthread_sigmask(SIG_BLOCK, &curmask, &oldmask) < 0) {
		xlog(LOG_ERROR, "sigprocmask failed : %s\n", strerror(errno));
		return;
	}

	/* proxenet is now running :) */
	proxy_state = ACTIVE;
	
	/* big loop  */
	while (proxy_state != INACTIVE) {
		conn = -1;
		retcode = -1;	
		
		FD_ZERO(&sock_set);

		FD_SET(sock, &sock_set);
		FD_SET(ctl_sock, &sock_set);
		if (ctl_cli_sock > 0)
			FD_SET(ctl_cli_sock, &sock_set);

		purge_zombies();
		
		/* set asynchronous listener */
		struct timespec timeout = {
			.tv_sec = 5,
			.tv_nsec = 0
		};
		
		retcode = pselect(FD_SETSIZE, &sock_set, NULL, NULL, &timeout, &oldmask);
		
		if (retcode < 0) {
			if (errno != EINTR) {
				xlog(LOG_ERROR, "[main] pselect() returned %d: %s\n", retcode, strerror(errno));
				proxy_state = INACTIVE;
				break;
			} else {
				continue;
			}
		}
		
		if (retcode == 0)
			continue;

		if (proxy_state == INACTIVE)
			break;
		
		/* event on the listening socket -> new request */
		if( FD_ISSET(sock, &sock_set) && proxy_state != SLEEPING) {
#ifdef DEBUG
			xlog(LOG_DEBUG, "%s\n", "Incoming listening event");
#endif

			tid = get_new_thread_id();
			if(tid < 0) {
				continue;
			}
			
			struct sockaddr addr;
			socklen_t addrlen = 0;

			proxenet_xzero(&addr, sizeof(struct sockaddr));

			conn = accept(sock, &addr, &addrlen); 
			if (conn < 0) {
				if(errno != EINTR)
					xlog(LOG_ERROR, "[main] accept() failed: %s\n", strerror(errno));
				continue;
			}
			
			retcode = proxenet_start_new_thread(conn, tid, &threads[tid], &pattr);
			if (retcode < 0) {
				xlog(LOG_ERROR, "[main] %s\n", "Error while spawn new thread");
				continue;
			}
			
		} /* end if _socket_event */
		
		
		/* event on control listening socket */
		if( FD_ISSET(ctl_sock, &sock_set) ) {
#ifdef DEBUG
			xlog(LOG_DEBUG, "%s\n", "Incoming control event");
#endif
			struct sockaddr_un sun_cli;
			socklen_t sun_cli_len = 0;
			int new_conn = -1;
			
			proxenet_xzero(&sun_cli, sizeof(struct sockaddr_un));

			new_conn = accept(ctl_sock, (struct sockaddr *)&sun_cli, &sun_cli_len);
			if (new_conn < 0) {
				xlog(LOG_ERROR, "[main] control accept() failed: %s\n", strerror(errno));
				continue;
			}
			
			if (ctl_cli_sock < 0) {
				ctl_cli_sock = new_conn;
				xlog(LOG_INFO, "%s\n", "New connection on Control socket");
				proxenet_write(ctl_cli_sock, CONTROL_MOTD, strlen(CONTROL_MOTD));
				proxenet_write(ctl_cli_sock, CONTROL_PROMPT, strlen(CONTROL_PROMPT));
				
			} else {
				if(new_conn > 0) {
					xlog(LOG_ERROR, "%s\n", "Denied control connection: already established");
					if(close_socket(new_conn) < 0) {
						xlog(LOG_ERROR, "Failed to close socket: %s\n", strerror(errno));
					}
				}
			}
			
		}/* end if _control_listening_event */

		
		/* event on control socket */
		if( ctl_cli_sock > 0 && FD_ISSET(ctl_cli_sock, &sock_set) ) {
			
			if (proxenet_handle_control_event(&ctl_cli_sock) < 0) {
				close_socket(ctl_cli_sock);
				ctl_cli_sock = -1;
			}
			
		} /* end if _control_event */
		
	}  /* endof while(!INACTIVE) */
	
	
	kill_zombies();
	proxenet_destroy_plugins_vm();
	pthread_attr_destroy(&pattr);
	
	return;
}


/**
 *
 * @param signum
 */
void sighandler(int signum)
{
#ifdef DEBUG
	xlog(LOG_DEBUG, "Received signal %s [%d]\n", strsignal(signum), signum);
#endif
	
	switch(signum) {
		
		case SIGTERM: 
		case SIGINT:
			if (proxy_state != INACTIVE)
				proxy_state = INACTIVE;
			
			cfg->try_exit++;
			xlog(LOG_INFO, "%s, %d/%d\n", "Trying to leave", cfg->try_exit, cfg->try_exit_max);
			
			if (cfg->try_exit == cfg->try_exit_max) {
				xlog(LOG_CRITICAL, "%s\n", "Failed to exit properly");
				abort();
			}
			
			break;

		case SIGCHLD:
			purge_zombies();
			break;
	}
}
Example #12
0
/**
 * This function is called by all threads to treat to process the request and response.
 * It will also apply the plugins.
 */
void proxenet_process_http_request(sock_t server_socket)
{
	sock_t client_socket;
	request_t req;
	int retcode;
	fd_set rfds;
	struct timespec ts;
	ssl_context_t ssl_context;
	bool is_ssl;
	sigset_t emptyset;
	size_t n;
	
	client_socket = retcode = n = -1;
	
	proxenet_xzero(&req, sizeof(request_t));
	proxenet_xzero(&ssl_context, sizeof(ssl_context_t));

	/* wait for any event on sockets */
	for(;;) {
		
		if (server_socket < 0) {
			xlog(LOG_ERROR, "%s\n", "Sock browser->proxy died unexpectedly");
			break;
		}
		
		ts.tv_sec  = HTTP_TIMEOUT_SOCK;
		ts.tv_nsec = 0;
		
		FD_ZERO(&rfds);
		FD_SET(server_socket, &rfds);
		if (client_socket > 0)
			FD_SET(client_socket, &rfds);

		sigemptyset(&emptyset);
		retcode = pselect(FD_SETSIZE, &rfds, NULL, NULL, &ts, &emptyset);
		
		if (retcode < 0) {
			if (errno == EINTR) {
				continue;
			} else {
				xlog(LOG_CRITICAL, "[thread] pselect returned %d: %s\n", retcode, strerror(errno));
				break;
			}
		}

		if (retcode == 0) {
			break;
		}
		
		is_ssl = ssl_context.use_ssl;
		
		/* is there data from web browser to proxy ? */
		if( FD_ISSET(server_socket, &rfds ) ) {	
			n = - 1;
			
			if(is_ssl) {
				n = proxenet_read_all(server_socket,
						      &req.data,
						      &(ssl_context.server.context));
			} else {
				n = proxenet_read_all(server_socket, &req.data, NULL);
			}
#ifdef DEBUG
			xlog(LOG_DEBUG, "[%d] Got %dB from client (%s)\n", req.id, n, (is_ssl)?"SSL":"PLAIN");
#endif
			
			if (n <= 0) 
				break;

			req.size = n;
			
			/* is connection to server not established ? -> new request */
			if (client_socket < 0) {
			
				retcode = create_http_socket(&req, &server_socket, &client_socket, &ssl_context);
				if (retcode < 0) {
					xlog(LOG_ERROR, "[%d] Failed to create %s->server socket\n", req.id, PROGNAME);
					proxenet_xfree(req.data);
					client_socket = -1;
					break;
				}

				
				if (ssl_context.use_ssl) {
					if (ssl_context.server.is_valid && ssl_context.client.is_valid) {
#ifdef DEBUG
						xlog(LOG_DEBUG, "[%d] SSL interception established\n", req.id);
#endif
						proxenet_xfree(req.data);
						continue;
						
					}
					
					xlog(LOG_ERROR, "[%d] Failed to establish interception\n", req.id);
					proxenet_xfree(req.data);
					client_socket = -1;
					break;
				}
			}
			
			req.type   = REQUEST;
			req.id     = get_new_request_id();

			/* check if request is valid  */
			if (!cfg->proxy.host) {
				if (!is_ssl) {
					if (!is_valid_http_request(&req.data, &req.size)) {
							proxenet_xfree(req.data);
							client_socket = -1;
							break;
					}
				} else {
					set_https_infos(&req);
				}
			}


			if (cfg->verbose) {
				xlog(LOG_INFO, "New request %d to '%s:%d'\n",
				     req.id,
				     req.http_infos.hostname,
				     req.http_infos.port);
				
				if (cfg->verbose > 1)
					xlog(LOG_INFO, "%s %s://%s:%d%s %s\n",
					     req.http_infos.method,
					     req.http_infos.proto,
					     req.http_infos.hostname,
					     req.http_infos.port,
					     req.http_infos.uri,
					     req.http_infos.version);
					     
			}

#ifdef DEBUG
			xlog(LOG_DEBUG, "[%d] Sending buffer %d bytes (%s) - pre-plugins\n",
			     req.id, req.size, (req.http_infos.is_ssl)?"SSL":"PLAIN");
#endif
			/* hook request with all plugins in plugins_list  */
			if ( proxenet_apply_plugins(&req) < 0) {
				/* extremist action: any error on any plugin discard the whole request */
				req.id = 0;
				proxenet_xfree( req.data );
				continue;
			}
			
#ifdef DEBUG
			xlog(LOG_DEBUG, "[%d] Sending buffer %d bytes (%s) - post-plugins\n",
			     req.id, req.size, (req.http_infos.is_ssl)?"SSL":"PLAIN");
#endif
			/* send modified data */
			if (is_ssl) {
				retcode = proxenet_ssl_write(client_socket, req.data, req.size,
							     &(ssl_context.client.context));
			} else {
				retcode = proxenet_write(client_socket, req.data, req.size);
			}

			proxenet_xfree(req.data);

			if (retcode < 0) {
				xlog(LOG_ERROR, "[%d] %s\n", req.id, "Failed to write to server");
				if (req.id)
					req.id = 0;
				break;
			}
			
		} /* end FD_ISSET(data_from_browser) */
		
		
		/* is there data from remote server to proxy ? */
		if( client_socket > 0 && FD_ISSET(client_socket, &rfds ) ) {
			n = -1;

			if (is_ssl)
				n = proxenet_read_all(client_socket, &req.data, &ssl_context.client.context);
			else
				n = proxenet_read_all(client_socket, &req.data, NULL);
			
#ifdef DEBUG
			xlog(LOG_DEBUG, "[%d] Got %dB from server\n", req.id, n);
#endif
			
			if (n <= 0)
				break;

			/* update request data structure */
			req.type   = RESPONSE;
			req.size   = n;
			
			/* execute response hooks */
			if ( proxenet_apply_plugins(&req) < 0) {
				/* extremist action: any error on any plugin discard the whole request */
				req.id = 0;
				proxenet_xfree(req.data);
				continue;
			}

			/* send modified data to client */
			if (is_ssl)
				retcode = proxenet_ssl_write(server_socket, req.data, req.size, &ssl_context.server.context);
			else
				retcode = proxenet_write(server_socket, req.data, req.size);
			
			if (retcode < 0) {
				xlog(LOG_ERROR, "[%d] %s\n", req.id, "proxy->client: write failed");
			}
			
			proxenet_xfree(req.data);

		}  /* end FD_ISSET(data_from_server) */
		
	}  /* end for(;;) { select() } */

	
	if (req.id) {
#ifdef DEBUG
		xlog(LOG_DEBUG, "Free-ing request %d\n", req.id);
#endif
		proxenet_xfree(req.http_infos.method);
		proxenet_xfree(req.http_infos.hostname);
		proxenet_xfree(req.http_infos.uri);
		proxenet_xfree(req.http_infos.version);
	}
	
	/* close client socket */
	if (client_socket > 0) {
#ifdef DEBUG
		xlog(LOG_DEBUG, "Closing proxy->server socket #%d\n", client_socket);
#endif		
		if (ssl_context.client.is_valid) {
			proxenet_ssl_finish(&(ssl_context.client), false);
			close_socket_ssl(client_socket, &ssl_context.client.context);
		
		} else {
			close_socket(client_socket);
		}
	}
	
	
	/* close local socket */
	if (server_socket > 0) {
#ifdef DEBUG
		xlog(LOG_DEBUG, "Closing browser->proxy socket #%d\n", server_socket);
#endif		
		if (ssl_context.server.is_valid) {
			proxenet_ssl_finish(&(ssl_context.server), true);
			close_socket_ssl(server_socket, &ssl_context.server.context);
			
		} else {
			close_socket(server_socket);
		}
	}

	/* and that's all folks */
	return;
}
Example #13
0
/**
 * Establish a connection from proxenet -> server. If proxy forwarding configured, then process
 * request to other proxy.
 * 
 */
int create_http_socket(request_t* req, sock_t* server_sock, sock_t* client_sock, ssl_context_t* ssl_ctx) 
{
	int retcode;
	char *host, *port;
	char sport[6] = {0, };
	http_request_t* http_infos = &req->http_infos;
	bool use_proxy = (cfg->proxy.host != NULL) ;

	/* get target from string and establish client socket to dest */
	if (get_url_information(req->data, http_infos) == false) {
		xlog(LOG_ERROR, "%s\n", "Failed to extract valid parameters from URL.");
		return -1;
	}

	
#ifdef DEBUG
	char* full_uri = get_request_full_uri(req);
	xlog(LOG_DEBUG, "URL: %s\n", full_uri);
	proxenet_xfree(full_uri);
#endif
	
	ssl_ctx->use_ssl = http_infos->is_ssl;
	snprintf(sport, 5, "%u", http_infos->port);

	/* do we forward to another proxy ? */
	if (use_proxy) {
		host = cfg->proxy.host;
		port = cfg->proxy.port;
		
	} else {
		host = http_infos->hostname;
		port = sport;
	}
	
	retcode = create_connect_socket(host, port);
	if (retcode < 0) {
		if (errno)
			generic_http_error_page(*server_sock, strerror(errno));
		else
			generic_http_error_page(*server_sock, "Unknown error in <i>create_connect_socket</i>");
		
		retcode = -1;
		
	} else {
		*client_sock = retcode;
		
		/* if ssl, set up ssl interception */
		if (http_infos->is_ssl) {

			if (use_proxy) {
				char *connect_buf = NULL;
				
				/* 0. set up proxy->proxy ssl session (i.e. forward CONNECT request) */ 
				retcode = proxenet_write(*client_sock, req->data, req->size);
				if (retcode < 0) {
					xlog(LOG_ERROR, "%s failed to CONNECT to proxy\n", PROGNAME);
					return -1;
				}

				/* read response */
				retcode = proxenet_read_all(*client_sock, &connect_buf, NULL);
				if (retcode < 0) {
					xlog(LOG_ERROR, "%s Failed to read from proxy\n", PROGNAME);
					return -1;
				}

				/* expect HTTP 200 */
				if (   (strncmp(connect_buf, "HTTP/1.0 200", 12) != 0) 
				    && (strncmp(connect_buf, "HTTP/1.1 200", 12) != 0)) {
					xlog(LOG_ERROR, "%s->proxy: bad HTTP version\n", PROGNAME);
					if (cfg->verbose)
							xlog(LOG_ERROR, "Received %s\n", connect_buf);
					
					return -1;
				}
			}

			/* 1. set up proxy->server ssl session */ 
			if(proxenet_ssl_init_client_context(&(ssl_ctx->client)) < 0) {
				return -1;
			}
			
			proxenet_ssl_wrap_socket(&(ssl_ctx->client.context), client_sock);
			if (proxenet_ssl_handshake(&(ssl_ctx->client.context)) < 0) {
				xlog(LOG_ERROR, "%s->server: handshake\n", PROGNAME);
				return -1;
			}

#ifdef DEBUG
			xlog(LOG_DEBUG, "%s %d %d\n", "SSL handshake with server done",
			     *client_sock,
			     *server_sock);
#endif
			if (proxenet_write(*server_sock,
					   "HTTP/1.0 200 Connection established\r\n\r\n",
					   39) < 0){
				return -1;
			}

			/* 2. set up proxy->browser ssl session  */
			if(proxenet_ssl_init_server_context(&(ssl_ctx->server)) < 0) {
				return -1;
			}

			proxenet_ssl_wrap_socket(&(ssl_ctx->server.context), server_sock);
			if (proxenet_ssl_handshake(&(ssl_ctx->server.context)) < 0) {
				xlog(LOG_ERROR, "handshake %s->client '%s:%d' failed\n",
				     PROGNAME, http_infos->hostname, http_infos->port);
				return -1;
			}

#ifdef DEBUG
			xlog(LOG_DEBUG, "%s\n", "SSL Handshake with client done");
#endif
		}
	}
	
	
	return retcode;
}
Example #14
0
/**
 * This function is called by all threads to treat to process the request and response.
 * It will also apply the plugins.
 *
 * @param server_socket is the socket received by the main thread from the web browser (acting like server
 * to web browser)
 */
void proxenet_process_http_request(sock_t server_socket)
{
        sock_t client_socket;
        request_t req;
        int retcode, n;
        fd_set rfds;
        struct timespec ts;
        ssl_context_t ssl_context;
        bool is_ssl;
        sigset_t emptyset;
        bool is_new_http_connection = false;

        client_socket = retcode = n = -1;
        proxenet_xzero(&req, sizeof(request_t));
        proxenet_xzero(&ssl_context, sizeof(ssl_context_t));

        /* wait for any event on sockets */
        while(proxy_state == ACTIVE) {

                if (server_socket < 0) {
                        xlog(LOG_ERROR, "sock browser->%s (#%d) died unexpectedly\n", PROGNAME, server_socket);
                        break;
                }

                ts.tv_sec  = HTTP_TIMEOUT_SOCK;
                ts.tv_nsec = 0;

                FD_ZERO(&rfds);
                FD_SET(server_socket, &rfds);
                if (client_socket > 0)
                        FD_SET(client_socket, &rfds);

                sigemptyset(&emptyset);
                retcode = pselect(FD_SETSIZE, &rfds, NULL, NULL, &ts, &emptyset);
                if (retcode < 0) {
                        if (errno == EINTR) {
                                continue;
                        } else {
                                xlog(LOG_CRITICAL, "[thread] pselect returned %d: %s\n", retcode, strerror(errno));
                                break;
                        }
                }

                if (retcode == 0) {
                        continue;
                }

                is_ssl = ssl_context.use_ssl;

                /* is there data from web browser to proxy ? */
                if( FD_ISSET(server_socket, &rfds ) ) {

                        if(is_ssl && req.do_intercept) {
                                n = proxenet_read_all(server_socket,
                                                      &req.data,
                                                      &(ssl_context.server.context));
                        } else {
                                n = proxenet_read_all(server_socket, &req.data, NULL);
                        }

#ifdef DEBUG
                        xlog(LOG_DEBUG, "Got %dB from client (%s srv_sock=#%d intercept_flag=%s)\n",
                             n, is_ssl?"SSL":"PLAIN", server_socket,
                             req.do_intercept?"true":"false");
#endif

                        if (n < 0) {
                                xlog(LOG_ERROR, "%s\n", "read() failed, end thread");
                                break;
                        }

                        if (n == 0){
#ifdef DEBUG
                                xlog(LOG_DEBUG, "%s\n", "Socket EOF from client");
#endif
                                break;
                        }


                        /* from here, n can only be positive */
                        req.size = (size_t) n;
                        bytes_sent += n;

                        if (req.id > 0 && !req.do_intercept){
#ifdef DEBUG
                                xlog(LOG_DEBUG, "Intercept disabled for browser->'%s'\n", req.http_infos.hostname);
#endif
                                goto send_to_server;
                        }

                        /* proxy keep-alive */
                        if (req.id > 0){
                                request_t* old_req = (request_t*)proxenet_xmalloc(sizeof(request_t));
                                memcpy(old_req, &req, sizeof(request_t));
                                char* host = proxenet_xstrdup2( req.http_infos.hostname );

                                free_http_infos(&(req.http_infos));

                                if (update_http_infos(&req) < 0){
                                        xlog(LOG_ERROR, "Failed to update HTTP information for request %d\n", req.id);
                                        proxenet_xfree( host );
                                        proxenet_xfree( old_req );
                                        req.id = 0;
                                        break;
                                }

                                if (strcmp( host, req.http_infos.hostname )){
                                        /* reset the client connection parameters */
                                        if (cfg->verbose)
                                                xlog(LOG_INFO, "Reusing sock=%d (old request=%d, old sock=%d) %s/%s\n",
                                                     server_socket, req.id, client_socket, host, req.http_infos.hostname );
                                        proxenet_close_socket(client_socket, &(ssl_context.client));
                                        free_http_infos(&(req.http_infos));
                                        client_socket = -1;
                                }

                                proxenet_xclean( old_req, sizeof(request_t) );
                                proxenet_xfree( host );
                        }

                        req.type = REQUEST;
                        req.id = get_new_request_id();

                        /* is connection to server not established ? -> new request */
                        if ( client_socket < 0) {
                                retcode = create_http_socket(&req, &server_socket, &client_socket, &ssl_context);
                                if (retcode < 0) {
                                        xlog(LOG_ERROR, "Failed to create %s->server socket\n", PROGNAME);
                                        proxenet_xfree(req.data);
                                        req.id = 0;
                                        break;
                                }


                                if (ssl_context.use_ssl) {
                                        req.is_ssl = true;

                                        if (req.do_intercept == false) {
#ifdef DEBUG
                                                xlog(LOG_DEBUG, "SSL interception client <-> %s <-> server disabled\n", PROGNAME);
#endif
                                                proxenet_xfree(req.data);
                                                req.type = REQUEST;
                                                req.id = get_new_request_id();
                                                continue;

                                        } else if (ssl_context.server.is_valid && ssl_context.client.is_valid) {
#ifdef DEBUG
                                                xlog(LOG_DEBUG, "SSL interception client <-> %s <-> server established\n", PROGNAME);
#endif
                                                proxenet_xfree(req.data);
                                                is_new_http_connection = true;
                                                continue;
                                        }

                                        xlog(LOG_ERROR, "%s\n", "Failed to establish interception");
                                        proxenet_xfree(req.data);
                                        break;
                                }

                                is_new_http_connection = true;
                        }



                        /* if proxenet does not relay to another proxy */
                        if (!cfg->proxy.host) {

                                if (is_new_http_connection) {

                                        if (is_ssl) {
                                                /*
                                                 * SSL request fields still have the values gathered in the CONNECT
                                                 * Those values must be updated to reflect the real request
                                                 */
                                                free_http_infos(&(req.http_infos));
                                                retcode = update_http_infos(&req);
                                        } else {
                                                /*
                                                 * Format requests
                                                 * GET http://foo/bar.blah HTTP/1.1 ...
                                                 * into
                                                 * GET /bar.blah HTTP/1.1 ...
                                                 */
                                                retcode = format_http_request(&req.data, &req.size);
                                        }
                                } else {
                                        /* if here, at least 1 request has been to server */
                                        /* so simply forward  */
                                        /* e.g. using HTTP/1.1 100 Continue */
#ifdef DEBUG
                                        xlog(LOG_DEBUG, "Resuming stream '%d'->'%d'\n", client_socket, server_socket);
#endif
                                        free_http_infos(&(req.http_infos));
                                        retcode = update_http_infos(&req);
                                }

                                if (retcode < 0){
                                        xlog(LOG_ERROR, "Failed to update %s information in request %d\n",
                                             is_ssl?"HTTPS":"HTTP", req.id);
                                        proxenet_xfree(req.data);
                                        break;
                                }
                        }


                        if(cfg->ie_compat){
                                if (is_ssl)
                                        retcode = ie_compat_read_post_body(server_socket, &req, &(ssl_context.server.context));
                                else
                                        retcode = ie_compat_read_post_body(server_socket, &req, NULL);
                                if (retcode < 0){
                                        xlog(LOG_ERROR, "%s\n", "Extending IE POST: failed");
                                        proxenet_xfree(req.data);
                                        break;
                                }
                        }


                        /* apply plugins for requests (from browser to server) */
                        if (cfg->verbose) {
                                xlog(LOG_INFO, "%s request to '%s:%d'\n",
                                     is_ssl?"SSL":"plain", req.http_infos.hostname, req.http_infos.port);

                                if (cfg->verbose > 1)
                                        xlog(LOG_INFO, "%s %s %s\n",
                                             req.http_infos.method, req.http_infos.uri, req.http_infos.version);
                        }

#ifdef DEBUG
                        xlog(LOG_DEBUG, "Request %d pre-plugins: buflen:%lu\n",
                             req.id, req.size);
#endif
                        /* hook request with all plugins in plugins_list  */
                        if ( proxenet_apply_plugins(&req) < 0) {
                                /* extremist action: any error on any plugin discard the whole request */
                                proxenet_xfree( req.data );
                                break;
                        }
#ifdef DEBUG
                        xlog(LOG_DEBUG, "Request %d post-plugins: buflen:%lu\n",
                             req.id, req.size);

                        if(cfg->verbose > 2)
                                proxenet_hexdump(req.data, req.size);
#endif

                send_to_server:
                        /* send modified data */
                        if (is_ssl && req.do_intercept) {
                                retcode = proxenet_ssl_write(&(ssl_context.client.context), req.data, req.size);
                        } else {
                                retcode = proxenet_write(client_socket, req.data, req.size);
                        }

                        /* reset data */
                        proxenet_xfree(req.data);
                        req.size = 0;

                        if (retcode < 0) {
                                xlog(LOG_ERROR, "[%d] %s\n", req.id, "Failed to write to server");
                                break;
                        }

#ifdef DEBUG
                        xlog(LOG_DEBUG, "Written %d bytes to server (socket=%s socket #%d)\n",
                             retcode, is_ssl?"SSL":"PLAIN", client_socket);
#endif

                } /* end FD_ISSET(data_from_browser) */


                /* is there data from remote server to proxy ? */
                if( client_socket > 0 && FD_ISSET(client_socket, &rfds ) ) {

                        if(req.is_ssl && req.do_intercept) {
                                n = proxenet_read_all(client_socket, &req.data, &ssl_context.client.context);
                        } else {
                                n = proxenet_read_all(client_socket, &req.data, NULL);
                        }

                        if (n < 0){
                                xlog(LOG_ERROR, "read() %s on cli_sock=#%d failed: %d\n",
                                     is_ssl?"SSL":"PLAIN",
                                     client_socket, n);
                                break;
                        }

                        if (n==0){
#ifdef DEBUG
                                xlog(LOG_DEBUG, "Socket EOF from server (cli_sock=#%d)\n",
                                     client_socket);
#endif
                                break;
                        }

                        /* update request data structure */
                        req.type   = RESPONSE;

                        /* from here, n can only be positive */
                        req.size   = (size_t) n;
                        bytes_recv += n;

                        if (req.do_intercept==false){
#ifdef DEBUG
                                xlog(LOG_DEBUG, "Intercept disabled for '%s'->browser\n", req.http_infos.hostname);
#endif
                                goto send_to_client;
                        }

                        /* apply plugins for response (from server to browser) */
#ifdef DEBUG
                        xlog(LOG_DEBUG, "Response %d pre-plugins: buflen:%lu\n",
                             req.id, req.size);
#endif
                        /* execute response hooks */
                        if ( proxenet_apply_plugins(&req) < 0) {
                                /* extremist action: any error on any plugin discard the whole request */
                                proxenet_xfree(req.data);
                                break;
                        }
#ifdef DEBUG
                        xlog(LOG_DEBUG, "Response %d post-plugins: buflen:%lu\n",
                             req.id, req.size);

                        if(cfg->verbose > 2)
                                proxenet_hexdump(req.data, req.size);
#endif

                send_to_client:
                        /* send modified data to client */
                        if (req.is_ssl && req.do_intercept)
                                retcode = proxenet_ssl_write(&(ssl_context.server.context), req.data, req.size);
                        else
                                retcode = proxenet_write(server_socket, req.data, req.size);

                        if (retcode < 0) {
                                xlog(LOG_ERROR, "[%d] %s\n", req.id, "proxy->client: write failed");
                                proxenet_xfree(req.data);
                                break;
                        }

#ifdef DEBUG
                        xlog(LOG_DEBUG, "Written %d bytes to browser (socket=%s socket #%d)\n",
                             retcode, is_ssl?"SSL":"PLAIN", client_socket);
#endif
                        proxenet_xfree(req.data);

                }  /* end FD_ISSET(data_from_server) */

        }  /* end for(;;) { select() } */


        if (req.id) {
                if (cfg->verbose)
                        xlog(LOG_INFO, "End of request %d, cleaning context\n", req.id);

                free_http_infos(&(req.http_infos));
        }


        /* close client socket */
        if (client_socket > 0) {
                if (cfg->verbose >= 2)
                        xlog(LOG_INFO, "Closing %s->server (fd=#%d)\n", PROGNAME, client_socket);

                proxenet_close_socket(client_socket, &(ssl_context.client));
        }


        /* close local socket */
        if (server_socket > 0) {
                if (cfg->verbose >= 2)
                        xlog(LOG_INFO, "Closing browser->%s (fd=#%d)\n", PROGNAME, server_socket);

                proxenet_close_socket(server_socket, &(ssl_context.server));
        }


#ifdef DEBUG
        xlog(LOG_DEBUG, "Request %d: Structures closed, leaving\n", req.id);
#endif
        /* and that's all folks */
        return;
}
Example #15
0
int create_http_socket(char* http_request, sock_t* server_sock, sock_t* client_sock, ssl_context_t* ssl_ctx) 
{
	http_request_t http_infos;
	int retcode;
	char* err;
	char sport[7] = {0, };

	err = NULL;
	proxenet_xzero(&http_infos, sizeof(http_request_t));
	http_infos.method = NULL;
	http_infos.hostname = NULL;
	http_infos.request_uri = NULL;
	
	/* get target from string and establish client socket to dest */
	if (get_url_information(http_request, &http_infos) == false) {
		xlog(LOG_ERROR, "%s\n", "Failed to extract valid parameters from URL.");
		return -1;
	}

	ssl_ctx->use_ssl = http_infos.is_ssl;
	snprintf(sport, 6, "%d", http_infos.port);
	
	retcode = create_connect_socket(http_infos.hostname, sport, &err);
	if (retcode < 0) {
		if (err)
			generic_http_error_page(*server_sock, err);
		else
			generic_http_error_page(*server_sock, "Unknown error in <i>create_connect_socket</i>");
		
		retcode = -1;
		
	} else {
		*client_sock = retcode;
		
		/* if ssl, set up ssl interception */
		if (http_infos.is_ssl) {
			
			/* 1. set up proxy->server ssl session */ 
			if(proxenet_ssl_init_client_context(&(ssl_ctx->client)) < 0) {
				retcode = -1;
				goto http_sock_end;
			}

			proxenet_ssl_wrap_socket(&(ssl_ctx->client.context), client_sock);
			if (proxenet_ssl_handshake(&(ssl_ctx->client.context)) < 0) {
				xlog(LOG_ERROR, "%s\n", "proxy->server: handshake");
				retcode = -1;
				goto http_sock_end;
			}
#ifdef DEBUG
			xlog(LOG_DEBUG, "%s\n", "SSL handshake with server done");
#endif
			proxenet_write(*server_sock,
				       "HTTP/1.0 200 Connection established\r\n\r\n",
				       39);
			
			/* 2.set up proxy->browser ssl session  */
			if(proxenet_ssl_init_server_context(&(ssl_ctx->server)) < 0) {
				retcode = -1;
				goto http_sock_end;
			}

			proxenet_ssl_wrap_socket(&(ssl_ctx->server.context), server_sock);
			if (proxenet_ssl_handshake(&(ssl_ctx->server.context)) < 0) {
				xlog(LOG_ERROR, "handshake proxy->client '%s:%d' failed\n",
				     http_infos.hostname, http_infos.port);
				retcode = -1;
				goto http_sock_end;
			}
			
#ifdef DEBUG
			xlog(LOG_DEBUG, "%s\n", "SSL Handshake with client done");
#endif
		}
	}
	
http_sock_end:
	proxenet_xfree(http_infos.method);
	proxenet_xfree(http_infos.hostname);
	proxenet_xfree(http_infos.request_uri);
	
	return retcode;
}
Example #16
0
int create_https_socket(request_t *req, sock_t *cli_sock, sock_t *srv_sock, ssl_context_t* ctx, bool use_http_proxy)
{
        char *connect_buf = NULL;
        http_infos_t* http_infos = &req->http_infos;
        int retcode = -1;


        /* disable all interception if ssl intercept was explicitely disabled by config */
        if (cfg->ssl_intercept == false)
                req->do_intercept = false;

        if (use_http_proxy) {

                /* 0. set up proxy->proxy ssl session (i.e. forward CONNECT request) */
                retcode = proxenet_write(*cli_sock, req->data, req->size);
                if (retcode < 0) {
                        xlog(LOG_ERROR, "%s failed to CONNECT to proxy\n", PROGNAME);
                        return -1;
                }

                /* read response */
                retcode = proxenet_read_all(*cli_sock, &connect_buf, NULL);
                if (retcode < 0) {
                        xlog(LOG_ERROR, "%s Failed to read from proxy\n", PROGNAME);
                        proxenet_xfree(connect_buf);
                        return -1;
                }

                /* expect HTTP 200 */
                if (   (strncmp(connect_buf, "HTTP/1.0 200", 12) != 0)
                       && (strncmp(connect_buf, "HTTP/1.1 200", 12) != 0)) {
                        xlog(LOG_ERROR, "%s->proxy: bad HTTP version\n", PROGNAME);
                        proxenet_xfree(connect_buf);

                        if (cfg->verbose)
                                xlog(LOG_ERROR, "Received %s\n", connect_buf);

                        return -1;
                }

                proxenet_xfree(connect_buf);
        }

        if (req->do_intercept){

                /* 1. set up proxy->server ssl session with hostname */
                if(proxenet_ssl_init_client_context(&(ctx->client), http_infos->hostname) < 0) {
                        return -1;
                }

                proxenet_ssl_wrap_socket(&(ctx->client.context), cli_sock);

                retcode = proxenet_ssl_handshake(&(ctx->client.context));
                if (retcode < 0) {
                        xlog(LOG_ERROR, "handshake %s->server failed [code: %#x]\n", PROGNAME, retcode);
                        xlog(LOG_ERROR, "Client SSL handshake failed for '%s:%d'.\n",
                             http_infos->hostname, http_infos->port, retcode);
                        return -1;
                }

#ifdef DEBUG
                xlog(LOG_DEBUG, "SSL handshake with %s done, cli_sock=%d\n",
                     use_http_proxy?"proxy":"server", *cli_sock);
#endif
        }

        if (proxenet_write(*srv_sock, "HTTP/1.0 200 Connection established\r\n\r\n", 39) < 0){
                return -1;
        }

        if (req->do_intercept) {

                /* 2. set up proxy->browser ssl session with hostname */
                if(proxenet_ssl_init_server_context(&(ctx->server), http_infos->hostname) < 0) {
                        return -1;
                }

                proxenet_ssl_wrap_socket(&(ctx->server.context), srv_sock);

                retcode = proxenet_ssl_handshake(&(ctx->server.context));
                if (retcode < 0) {
                        xlog(LOG_ERROR, "handshake %s->client failed [code: %#x]\n", PROGNAME, retcode);
                        xlog(LOG_ERROR, "Server SSL handshake failed for '%s:%d'.\n",
                             http_infos->hostname, http_infos->port, retcode);
                        return -1;
                }

#ifdef DEBUG
                xlog(LOG_DEBUG, "SSL handshake with client done, srv_sock=%d\n", *srv_sock);
#endif
        }

        return 0;
}
Example #17
0
/**
 * Establish a connection from proxenet -> server.
 * If proxy forwarding configured, then this function performs the negociation with the other proxy.
 * If the host applies for SSL intercept rules, this function also handles the SSL handshake.
 *
 * @return 0 if successful, -1 otherwise
 */
int create_http_socket(request_t* req, sock_t* server_sock, sock_t* client_sock, ssl_context_t* ssl_ctx)
{
        int retcode;
        char *host, *port;
        char sport[7] = {0, };
        http_request_t* http_infos = &req->http_infos;
        bool use_proxy = (cfg->proxy.host != NULL);
        bool use_http_proxy = use_proxy && (cfg->is_socks_proxy == false);
        bool use_socks_proxy = use_proxy && cfg->is_socks_proxy;
        char errmsg[512]={0,};

        if (update_http_infos(req) < 0){
                xlog(LOG_ERROR, "%s\n", "Failed to extract valid parameters from URL.");
                return -1;
        }

        ssl_ctx->use_ssl = req->is_ssl;
        proxenet_xsnprintf(sport, sizeof(sport), "%hu", http_infos->port);

        /* do we forward to another proxy ? */
        if (use_proxy) {
                host = cfg->proxy.host;
                port = cfg->proxy.port;
        } else {
                host = http_infos->hostname;
                port = sport;
        }


#ifdef DEBUG
        xlog(LOG_DEBUG, "Relay request %s to '%s:%s'\n",
             use_http_proxy ? "via HTTP proxy" : "direct",
             host, port);
#endif

        retcode = proxenet_open_socket(host, port);
        if (retcode < 0) {
                proxenet_xsnprintf(errmsg, sizeof(errmsg), "Cannot connect to %s:%s<br><br>Reason: %s",
                         host, port, errno?strerror(errno):"<i>proxenet_open_socket()</i> failed");

                generic_http_error_page(*server_sock, errmsg);
                return -1;
        }

#ifdef DEBUG
        xlog(LOG_DEBUG, "Socket to %s '%s:%s': fd=%d\n",
             use_http_proxy?"HTTP proxy":(use_socks_proxy?"SOCKS4 proxy":"server"),
             host, port, retcode);
#endif

        *client_sock = retcode;

        req->do_intercept = ( (cfg->intercept_mode==INTERCEPT_ONLY && \
                               fnmatch(cfg->intercept_pattern, http_infos->hostname, 0)==0) || \
                              (cfg->intercept_mode==INTERCEPT_EXCEPT && \
                               fnmatch(cfg->intercept_pattern, http_infos->hostname, 0)==FNM_NOMATCH) );

#ifdef DEBUG
        xlog(LOG_DEBUG, "Server '%s' %s match interception '%s' with pattern '%s'\n",
             http_infos->hostname,
             req->do_intercept?"do":"do not",
             cfg->intercept_mode==INTERCEPT_ONLY?"INTERCEPT_ONLY":"INTERCEPT_EXCEPT",
             cfg->intercept_pattern);
#endif

        if(use_socks_proxy){
                char*rhost = http_infos->hostname;
                int  rport = http_infos->port;
                retcode = proxenet_socks_connect(*client_sock, rhost, rport, true);
                if( retcode<0 ){
                        proxenet_xsnprintf(errmsg, sizeof(errmsg), "Failed to open SOCKS4 tunnel to %s:%s.\n",
                                 host, port);
                        generic_http_error_page(*server_sock, errmsg);
                        xlog(LOG_ERROR, "%s", errmsg);
                        return -1;
                }
        }

        /* set up ssl layer */
        if (req->is_ssl) {

                /* adjust do_intercept if we do not SSL intercept was explicitely disabled */
                req->do_intercept = cfg->ssl_intercept;

                if (use_http_proxy) {
                        char *connect_buf = NULL;

                        /* 0. set up proxy->proxy ssl session (i.e. forward CONNECT request) */
                        retcode = proxenet_write(*client_sock, req->data, req->size);
                        if (retcode < 0) {
                                xlog(LOG_ERROR, "%s failed to CONNECT to proxy\n", PROGNAME);
                                return -1;
                        }

                        /* read response */
                        retcode = proxenet_read_all(*client_sock, &connect_buf, NULL);
                        if (retcode < 0) {
                                xlog(LOG_ERROR, "%s Failed to read from proxy\n", PROGNAME);
                                return -1;
                        }

                        /* expect HTTP 200 */
                        if (   (strncmp(connect_buf, "HTTP/1.0 200", 12) != 0)
                               && (strncmp(connect_buf, "HTTP/1.1 200", 12) != 0)) {
                                xlog(LOG_ERROR, "%s->proxy: bad HTTP version\n", PROGNAME);
                                if (cfg->verbose)
                                        xlog(LOG_ERROR, "Received %s\n", connect_buf);

                                return -1;
                        }
#ifdef DEBUG
                        xlog(LOG_DEBUG, "HTTP Connect Ok with '%s:%s', cli_sock=%d\n", host, port, *client_sock);
#endif
                }

                if (req->do_intercept){

                        /* 1. set up proxy->server ssl session with hostname */
                        if(proxenet_ssl_init_client_context(&(ssl_ctx->client), http_infos->hostname) < 0) {
                                return -1;
                        }

                        proxenet_ssl_wrap_socket(&(ssl_ctx->client.context), client_sock);

                        retcode = proxenet_ssl_handshake(&(ssl_ctx->client.context));
                        if (retcode < 0) {
                                xlog(LOG_ERROR, "handshake %s->server failed [code: %#x]\n", PROGNAME, retcode);
                                xlog(LOG_ERROR, "Client SSL handshake failed for '%s:%d'.\n",
                                     http_infos->hostname, http_infos->port, retcode);
                                return -1;
                        }

#ifdef DEBUG
                        xlog(LOG_DEBUG, "SSL handshake with %s done, cli_sock=%d\n",
                             use_http_proxy?"proxy":"server", *client_sock);
#endif
                }

                if (proxenet_write(*server_sock, "HTTP/1.0 200 Connection established\r\n\r\n", 39) < 0){
                        return -1;
                }

                if (req->do_intercept) {

                        /* 2. set up proxy->browser ssl session with hostname */
                        if(proxenet_ssl_init_server_context(&(ssl_ctx->server), http_infos->hostname) < 0) {
                                return -1;
                        }

                        proxenet_ssl_wrap_socket(&(ssl_ctx->server.context), server_sock);

                        retcode = proxenet_ssl_handshake(&(ssl_ctx->server.context));
                        if (retcode < 0) {
                                xlog(LOG_ERROR, "handshake %s->client failed [code: %#x]\n", PROGNAME, retcode);
                                xlog(LOG_ERROR, "Server SSL handshake failed for '%s:%d'.\n",
                                     http_infos->hostname, http_infos->port, retcode);
                                return -1;
                        }

#ifdef DEBUG
                        xlog(LOG_DEBUG, "SSL handshake with client done, srv_sock=%d\n", *server_sock);
#endif
                }
        }


        return retcode;
}