Ejemplo n.º 1
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;
}
Ejemplo n.º 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_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;
}