Пример #1
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;
}
Пример #2
0
/**
 * This function updates all the fields of the current request_t with the new values found in the
 * request. Since those values will be useful many times, they are strdup-ed in a specific structure
 * (http_infos_t). Those values *must* be free-ed later on.
 *
 * @return 0 if successful, -1 if any error occurs.
 */
int parse_http_request(request_t *req)
{
        char *ptr, *buf, c;
        int offset;

        buf = req->data;

        /* method */
        ptr = strchr(buf, ' ');
        if (!ptr){
                xlog(LOG_ERROR, "%s\n", "Cannot find HTTP method in request");
                if (cfg->verbose)
                        xlog(LOG_ERROR, "Buffer sent:\n%s\n", buf);
                return -1;
        }

        c = *ptr;
        *ptr = '\0';
        req->http_infos.method = proxenet_xstrdup2(buf);
        if (!req->http_infos.method){
                xlog(LOG_ERROR, "%s\n", "strdup(method) failed, cannot pursue...");
                return -1;
        }

        *ptr = c;

        req->http_infos.proto_type = HTTP;
        if (!strcmp(req->http_infos.method, "CONNECT")){
                /*
                 * We can receive a CONNECT if
                 * - the connection uses HTTPS
                 * - the client tries to upgrade to WebSocket/Secure WebSocket
                 */
                char *upgrade_header = get_header_by_name(buf, "Upgrade:");
                if (upgrade_header){
                        if (strcmp(upgrade_header, "WebSocket")==0){
                                xlog(LOG_INFO, "%s\n", "Upgrading to WebSocket");
                                req->http_infos.proto_type = WS;
                                req->is_ssl = false;
                                req->http_infos.proto = WS_STRING;
                                req->http_infos.port = HTTP_DEFAULT_PORT;
                                req->http_infos.proto_type = WS;
                        }
                        proxenet_xfree(upgrade_header);
                } else {
                        req->is_ssl = true;
                        req->http_infos.proto = HTTPS_STRING;
                        req->http_infos.port = HTTPS_DEFAULT_PORT;
                        req->http_infos.proto_type = HTTPS;
                }

                offset = ptr - buf + 1;

                if( get_hostname_from_uri(req, offset) < 0 ){
                        xlog(LOG_ERROR, "%s\n", "Failed to get hostname (URI)");
                        goto failed_hostname;
                }

                req->http_infos.path = proxenet_xstrdup2("/");
                req->http_infos.version = proxenet_xstrdup2("HTTP/1.0");

                req->http_infos.uri = get_request_full_uri(req);
                if(!req->http_infos.uri){
                        xlog(LOG_ERROR, "%s\n", "get_request_full_uri() failed");
                        goto failed_uri;
                }

                return 0;
        }


        /* hostname and port */
        if (req->is_ssl){
                req->http_infos.port = HTTPS_DEFAULT_PORT;
                req->http_infos.proto = HTTPS_STRING;
        } else {
                req->http_infos.port = HTTP_DEFAULT_PORT;
                req->http_infos.proto = HTTP_STRING;
        }

        if( get_hostname_from_header(req) < 0 ){
                xlog(LOG_ERROR, "%s\n", "Failed to get hostname (Host header)");
                goto failed_hostname;
        }


        /* path */
        buf = ptr+1;

        if (!strncmp(buf, HTTP_PROTO_STRING, strlen(HTTP_PROTO_STRING))){
                buf = strchr(buf + 8, '/');
        }

        ptr = strchr(buf, ' ');
        if (!ptr){
                xlog(LOG_ERROR, "%s\n", "Cannot find HTTP path in request");
                goto failed_path;
        }

        c = *ptr;
        *ptr = '\0';
        req->http_infos.path = proxenet_xstrdup2(buf);
        if (!req->http_infos.path){
                xlog(LOG_ERROR, "%s\n", "strdup(path) failed, cannot pursue...");
                goto failed_path;
        }
        *ptr = c;

        buf = ptr+1;


        /* version */
        ptr = strchr(req->data, '\r');
        if (!ptr){
                xlog(LOG_ERROR, "%s\n", "Cannot find HTTP version");
                goto failed_version;
        }

        c = *ptr;
        *ptr = '\0';
        req->http_infos.version = proxenet_xstrdup2(buf);
        if (!req->http_infos.version){
                xlog(LOG_ERROR, "%s\n", "strdup(version) failed, cannot pursue...");
                goto failed_version;
        }
        *ptr = c;


        /* refresh uri */
        req->http_infos.uri = get_request_full_uri(req);
        if(!req->http_infos.uri){
                xlog(LOG_ERROR, "%s\n", "get_request_full_uri() failed");
                goto failed_uri;
        }


        if (cfg->verbose) {
                xlog(LOG_INFO, "New request %d to '%s'\n",
                     req->id, req->http_infos.uri);

                if (cfg->verbose > 1) {
                        xlog(LOG_INFO,
                             "Request HTTP information:\n"
                             "method=%s\n"
                             "proto=%s\n"
                             "hostname=%s\n"
                             "port=%d\n"
                             "path=%s\n"
                             "version=%s\n"
                             ,
                             req->http_infos.method,
                             req->http_infos.proto,
                             req->http_infos.hostname,
                             req->http_infos.port,
                             req->http_infos.path,
                             req->http_infos.version);
                }
        }

        return 0;


failed_uri:
        proxenet_xfree(req->http_infos.version);

failed_version:
        proxenet_xfree(req->http_infos.path);

failed_path:
        proxenet_xfree(req->http_infos.hostname);

failed_hostname:
        proxenet_xfree(req->http_infos.method);

        return -1;
}
Пример #3
0
/**
 * This function updates all the fields of the current request_t with the new values found in the
 * request. Since those values will be useful many times, they are strdup-ed in a specific structure
 * (http_request_t). Those values *must* be free-ed later on.
 *
 * @return 0 if successful, -1 if any error occurs.
 */
int update_http_infos(request_t *req)
{
        char *ptr, *buf, c;

        buf = req->data;

        /* method */
        ptr = strchr(buf, ' ');
        if (!ptr){
                xlog(LOG_ERROR, "%s\n", "Cannot find HTTP method in request");
                if (cfg->verbose)
                        xlog(LOG_ERROR, "Buffer sent:\n%s\n", buf);
                return -1;
        }

        c = *ptr;
        *ptr = '\0';
        req->http_infos.method = proxenet_xstrdup2(buf);
        if (!req->http_infos.method){
                xlog(LOG_ERROR, "%s\n", "strdup(method) failed, cannot pursue...");
                return -1;
        }

        *ptr = c;
        if (!strcmp(req->http_infos.method, "CONNECT")){
                int offset;

                req->is_ssl = true;
                req->http_infos.proto = HTTPS_STRING;
                req->http_infos.port = HTTPS_DEFAULT_PORT;
                offset = ptr - buf + 1;

                if( get_hostname_from_uri(req, offset) < 0 ){
                        xlog(LOG_ERROR, "%s\n", "Failed to get hostname (URI)");
                        goto failed_hostname;
                }

                req->http_infos.path = proxenet_xstrdup2("/");
                req->http_infos.version = proxenet_xstrdup2("HTTP/1.0");

                req->http_infos.uri = get_request_full_uri(req);
                if(!req->http_infos.uri){
                        xlog(LOG_ERROR, "%s\n", "get_request_full_uri() failed");
                        goto failed_uri;
                }

                return 0;
        }


        /* hostname and port */
        if (req->is_ssl){
                req->http_infos.port = HTTPS_DEFAULT_PORT;
                req->http_infos.proto = HTTPS_STRING;
        } else {
                req->http_infos.port = HTTP_DEFAULT_PORT;
                req->http_infos.proto = HTTP_STRING;
        }

        if( get_hostname_from_header(req) < 0 ){
                xlog(LOG_ERROR, "%s\n", "Failed to get hostname (Host header)");
                goto failed_hostname;
        }


        /* path */
        buf = ptr+1;

        if (!strncmp(buf, HTTP_PROTO_STRING, strlen(HTTP_PROTO_STRING))){
                buf = strchr(buf + 8, '/');
        }

        ptr = strchr(buf, ' ');
        if (!ptr){
                xlog(LOG_ERROR, "%s\n", "Cannot find HTTP path in request");
                goto failed_path;
        }

        c = *ptr;
        *ptr = '\0';
        req->http_infos.path = proxenet_xstrdup2(buf);
        if (!req->http_infos.path){
                xlog(LOG_ERROR, "%s\n", "strdup(path) failed, cannot pursue...");
                goto failed_path;
        }
        *ptr = c;

        buf = ptr+1;


        /* version */
        ptr = strchr(req->data, '\r');
        if (!ptr){
                xlog(LOG_ERROR, "%s\n", "Cannot find HTTP version");
                goto failed_version;
        }

        c = *ptr;
        *ptr = '\0';
        req->http_infos.version = proxenet_xstrdup2(buf);
        if (!req->http_infos.version){
                xlog(LOG_ERROR, "%s\n", "strdup(version) failed, cannot pursue...");
                goto failed_version;
        }
        *ptr = c;


        /* refresh uri */
        req->http_infos.uri = get_request_full_uri(req);
        if(!req->http_infos.uri){
                xlog(LOG_ERROR, "%s\n", "get_request_full_uri() failed");
                goto failed_uri;
        }


        if (cfg->verbose) {
                xlog(LOG_INFO, "New request %d to '%s'\n",
                     req->id, req->http_infos.uri);

                if (cfg->verbose >= 2) {
                        xlog(LOG_INFO,
                             "Request HTTP information:\n"
                             "method=%s\n"
                             "proto=%s\n"
                             "hostname=%s\n"
                             "port=%d\n"
                             "path=%s\n"
                             "version=%s\n"
                             ,
                             req->http_infos.method,
                             req->http_infos.proto,
                             req->http_infos.hostname,
                             req->http_infos.port,
                             req->http_infos.path,
                             req->http_infos.version);
                }
        }

        return 0;


failed_uri:
        proxenet_xfree(req->http_infos.version);

failed_version:
        proxenet_xfree(req->http_infos.path);

failed_path:
        proxenet_xfree(req->http_infos.hostname);

failed_hostname:
        proxenet_xfree(req->http_infos.method);

        return -1;
}