Beispiel #1
0
/**
 * Wrapper to close socket.
 *
 * @param sock
 */
int proxenet_close_socket(sock_t sock, ssl_atom_t* ssl)
{
        int rc = close_socket(sock);

        if (ssl){
                if(ssl->is_valid) {
                        proxenet_ssl_finish(ssl);
                        proxenet_ssl_free_structs(ssl);
                }
        }

        return rc;
}
Beispiel #2
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;
}