Ejemplo n.º 1
0
/**
 * Process as much buffered inbound and outbound data as possible
 * (in that order)
 *
 * @param sd
 */
void process_stored_stream_data(stream_data *sd) {
    int loop = 0;

    do {
        // Reset loop
        loop = 0;

        // Send as much inbound data as possible
        while((sd->connp->in_status == STREAM_STATE_DATA)&&(list_size(sd->inbound_chunks) > 0)) {
            chunk_t *chunk = (chunk_t *)list_get(sd->inbound_chunks, 0);

            int rc = htp_connp_req_data(sd->connp, 0, chunk->data + chunk->consumed, chunk->len - chunk->consumed);
            if (rc == STREAM_STATE_DATA) {
                // The entire chunk was consumed
                list_shift(sd->inbound_chunks);
                free(chunk->data);
                free(chunk);
            } else {
                // Partial consumption
                chunk->consumed = htp_connp_req_data_consumed(sd->connp);
            }
        }

        // Send as much outbound data as possible
        while((sd->connp->out_status == STREAM_STATE_DATA)&&(list_size(sd->outbound_chunks) > 0)) {
            chunk_t *chunk = (chunk_t *)list_get(sd->outbound_chunks, 0);

            int rc = htp_connp_res_data(sd->connp, 0, chunk->data + chunk->consumed, chunk->len - chunk->consumed);
            if (rc == STREAM_STATE_DATA) {
                // The entire chunk was consumed
                list_shift(sd->outbound_chunks);
                free(chunk->data);
                free(chunk);
            } else {
                // Partial consumption
                chunk->consumed = htp_connp_res_data_consumed(sd->connp);
            }

            // Whenever we send some outbound data to the parser,
            // we need to go back and try to send inbound data
            // if we have it.
            loop = 1;
        }
    } while(loop);
}
Ejemplo n.º 2
0
/**
 * Process a chunk of the connection stream.
 *
 * @param sd
 * @param direction
 * @param hlf
 */
void process_stream_data(stream_data *sd, int direction, struct half_stream *hlf) {
    chunk_t *chunk = NULL;
    int rc;

    //printf("#DATA direction %d bytes %d\n", sd->direction, hlf->count_new);

    if (sd->direction == direction) {
        // Inbound data

        switch(sd->connp->in_status) {
            case STREAM_STATE_NEW :
            case STREAM_STATE_DATA :
                // Send data to parser

                rc = htp_connp_req_data(sd->connp, 0, hlf->data, hlf->count_new);
                if (rc == STREAM_STATE_DATA_OTHER) {
                    // Encountered inbound parsing block

                    // Store partial chunk for later
                    chunk = calloc(1, sizeof(chunk_t));
                    // TODO
                    chunk->len = hlf->count_new - htp_connp_req_data_consumed(sd->connp);
                    chunk->data = malloc(chunk->len);
                    // TODO
                    memcpy(chunk->data, hlf->data + htp_connp_req_data_consumed(sd->connp), chunk->len);
                    list_add(sd->inbound_chunks, chunk);
                } else
                if (rc != STREAM_STATE_DATA) {
                    // Inbound parsing error
                    sd->log_level = 0;
                    fprintf(stderr, "[#%d] Inbound parsing error: %d\n", sd->id, rc);
                    // TODO Write connection to disk
                }
                break;

            case STREAM_STATE_ERROR :
                // Do nothing
                break;

            case STREAM_STATE_DATA_OTHER :
                // Store data for later
                chunk = calloc(1, sizeof(chunk_t));
                // TODO
                chunk->len = hlf->count_new;
                chunk->data = malloc(chunk->len);
                // TODO
                memcpy(chunk->data, hlf->data, chunk->len);
                list_add(sd->inbound_chunks, chunk);
                break;
        }
    } else {
        // Outbound data
        switch(sd->connp->out_status) {
            case STREAM_STATE_NEW :
            case STREAM_STATE_DATA :
                // Send data to parser

                rc = htp_connp_res_data(sd->connp, 0, hlf->data, hlf->count_new);
                if (rc == STREAM_STATE_DATA_OTHER) {
                    // Encountered outbound parsing block

                    // Store partial chunk for later
                    chunk = calloc(1, sizeof(chunk_t));
                    // TODO
                    chunk->len = hlf->count_new - htp_connp_res_data_consumed(sd->connp);
                    chunk->data = malloc(chunk->len);
                    // TODO
                    memcpy(chunk->data, hlf->data + htp_connp_res_data_consumed(sd->connp), chunk->len);
                    list_add(sd->outbound_chunks, chunk);
                } else
                if (rc != STREAM_STATE_DATA) {
                    // Outbound parsing error
                    sd->log_level = 0;
                    fprintf(stderr, "[#%d] Outbound parsing error: %d\n", sd->id, rc);
                }
                break;

            case STREAM_STATE_ERROR :
                // Do nothing
                break;

            case STREAM_STATE_DATA_OTHER :
                // Store data for later
                chunk = calloc(1, sizeof(chunk_t));
                // TODO
                chunk->len = hlf->count_new;
                chunk->data = malloc(chunk->len);
                // TODO
                memcpy(chunk->data, hlf->data, chunk->len);
                list_add(sd->outbound_chunks, chunk);
                break;
        }
    }

    // Process as much stored data as possible
    process_stored_stream_data(sd);
}
Ejemplo n.º 3
0
/**
 * Runs a single test.
 *
 * @param[in] filename
 * @param[in] cfg
 * @return A pointer to the instance of htp_connp_t created during
 *         the test, or NULL if the test failed for some reason.
 */
int test_run_ex(const char *testsdir, const char *testname, htp_cfg_t *cfg, htp_connp_t **connp, int clone_count) {
    char filename[1025];
    test_t test;
    struct timeval tv_start, tv_end;
    int rc;

    *connp = NULL;

    strncpy(filename, testsdir, 1024);
    strncat(filename, "/", 1024 - strlen(filename));
    strncat(filename, testname, 1024 - strlen(filename));

    // printf("Filename: %s\n", filename);

    // Initinialize test

    rc = test_init(&test, filename, clone_count);
    if (rc < 0) {
        return rc;
    }

    gettimeofday(&tv_start, NULL);

    test_start(&test);

    // Create parser
    *connp = htp_connp_create(cfg);
    if (*connp == NULL) {
        fprintf(stderr, "Failed to create connection parser\n");
        exit(1);
    }

    htp_connp_set_user_data(*connp, (void *) 0x02);

    // Does the filename contain connection metdata?
    if (strncmp(testname, "stream", 6) == 0) {
        // It does; use it
        char *remote_addr = NULL, *local_addr = NULL;
        int remote_port = -1, local_port = -1;

        parse_filename(testname, &remote_addr, &remote_port, &local_addr, &local_port);
        htp_connp_open(*connp, (const char *) remote_addr, remote_port, (const char *) local_addr, local_port, &tv_start);
        free(remote_addr);
        free(local_addr);
    } else {
        // No connection metadata; provide some fake information instead
        htp_connp_open(*connp, (const char *) "127.0.0.1", 10000, (const char *) "127.0.0.1", 80, &tv_start);
    }

    // Find all chunks and feed them to the parser
    int in_data_other = 0;
    char *in_data = NULL;
    size_t in_data_len = 0;
    size_t in_data_offset = 0;

    int out_data_other = 0;
    char *out_data = NULL;
    size_t out_data_len = 0;
    size_t out_data_offset = 0;

    for (;;) {
        if (test_next_chunk(&test) <= 0) {
            break;
        }

        if (test.chunk_direction == CLIENT) {
            if (in_data_other) {
                test_destroy(&test);
                fprintf(stderr, "Unable to buffer more than one inbound chunk.\n");
                return -1;
            }
            
            rc = htp_connp_req_data(*connp, &tv_start, test.chunk, test.chunk_len);
            if (rc == HTP_STREAM_ERROR) {
                test_destroy(&test);
                return -101;
            }
            if (rc == HTP_STREAM_DATA_OTHER) {
                // Parser needs to see the outbound stream in order to continue
                // parsing the inbound stream.
                in_data_other = 1;
                in_data = test.chunk;
                in_data_len = test.chunk_len;
                in_data_offset = htp_connp_req_data_consumed(*connp);                
            }
        } else {
            if (out_data_other) {
                rc = htp_connp_res_data(*connp, &tv_start, out_data + out_data_offset, out_data_len - out_data_offset);
                if (rc == HTP_STREAM_ERROR) {
                    test_destroy(&test);
                    return -104;
                }
                
                out_data_other = 0;
            }

            rc = htp_connp_res_data(*connp, &tv_start, test.chunk, test.chunk_len);
            if (rc == HTP_STREAM_ERROR) {
                test_destroy(&test);
                return -102;
            }
            if (rc == HTP_STREAM_DATA_OTHER) {
                // Parser needs to see the outbound stream in order to continue
                // parsing the inbound stream.
                out_data_other = 1;
                out_data = test.chunk;
                out_data_len = test.chunk_len;
                out_data_offset = htp_connp_res_data_consumed(*connp);
                // printf("# YYY out offset is %d\n", out_data_offset);
            }

            if (in_data_other) {
                rc = htp_connp_req_data(*connp, &tv_start, in_data + in_data_offset, in_data_len - in_data_offset);
                if (rc == HTP_STREAM_ERROR) {
                    test_destroy(&test);
                    return -103;
                }
                
                in_data_other = 0;
            }
        }
    }

    if (out_data_other) {
        rc = htp_connp_res_data(*connp, &tv_start, out_data + out_data_offset, out_data_len - out_data_offset);
        if (rc == HTP_STREAM_ERROR) {
            test_destroy(&test);
            return -104;
        }
        out_data_other = 0;
    }

    gettimeofday(&tv_end, NULL);

    // Close the connection
    htp_connp_close(*connp, &tv_end);

    // Clean up
    test_destroy(&test);

    return 1;
}