Exemple #1
0
static enum proto_parse_status tns_parse_accept(struct tns_parser unused_ *tns_parser, struct sql_proto_info *info, struct cursor *cursor)
{
    if (info->is_query) return PROTO_PARSE_ERR;
    SLOG(LOG_DEBUG, "Parsing TNS accept PDU of size %zu", cursor->cap_len);

    /* An accept message is constitued of :
     * - 2 bytes version
     * - 2 bytes service options
     * - 2 bytes session data unit size
     * - 2 bytes max transm. data unit size
     * - 2 bytes value of one
     * - 2 bytes data length
     * - 2 bytes data offset
     * - 1 byte connect flag 0
     * - 1 byte connect flag 1 */
    CHECK(10);
    unsigned version = cursor_read_u16n(cursor);
    info->version_maj = version/100;
    info->version_min = version%100;
    info->set_values |= SQL_VERSION;
    sql_set_request_status(info, SQL_REQUEST_COMPLETE);
    return PROTO_OK;
}
Exemple #2
0
static enum proto_parse_status tns_parse_end(struct sql_proto_info *info, struct cursor *cursor)
{
    SLOG(LOG_DEBUG, "Parsing tns end packet");
    enum proto_parse_status status;

    uint_least64_t var[6];
    for (unsigned i = 0; i < 6; i++) {
        if (PROTO_OK != (status = cursor_read_variable_int(cursor, var + i))) return status;
    }

    uint_least64_t nb_rows;
    uint_least64_t error_code;

    // let's use the double 0x00 to guess the position of row number and error code
    if (var[0] > 0 && var[4] == 0 && var[5] == 0) {
        // var[0] is unknown?
        // var[1] == sequence
        // var[2] == rows
        // var[3] == error code
        SLOG(LOG_DEBUG, "Unknown bits after ttc code");
        nb_rows = var[2];
        error_code = var[3];
        DROP_VAR(cursor);
    } else if (var[3] == 0 && var[4] == 0) {
        // var[0] == sequence
        // var[1] == rows
        // var[2] == error code
        nb_rows = var[1];
        error_code = var[2];
    } else {
        // var[0] == rows
        // var[1] == error code
        nb_rows = var[0];
        error_code = var[1];
    }

    if (info->msg_type == SQL_QUERY) {
        sql_set_row_count(info, nb_rows);
        SLOG(LOG_DEBUG, "Nb rows %d", info->u.query.nb_rows);
    }
    SLOG(LOG_DEBUG, "Error code is %zu", error_code);

    DROP_VARS(cursor, 1);
    DROP_FIX(cursor, 2);
    DROP_VARS(cursor, 2);
    DROP_FIX(cursor, 2);
    DROP_VARS(cursor, 2);
    DROP_FIX(cursor, 1);
    DROP_VARS(cursor, 3);

    if (error_code != 0) {
        SLOG(LOG_DEBUG, "Parsing error message");
        char *error_msg = tempstr();
        unsigned error_len;

        // Drop an unknown number of bytes here
        while(cursor->cap_len > 2 && (cursor_peek_u8(cursor, 0) == 0 || !is_print(cursor_peek_u8(cursor, 1)))){
            DROP_FIX(cursor, 1);
        }
        SLOG(LOG_DEBUG, "First printable char is %c", cursor_peek_u8(cursor, 1));
        status = cursor_read_variable_string(cursor, error_msg, TEMPSTR_SIZE, &error_len);
        if (status != PROTO_OK) return status;
        if (error_len < 12) return PROTO_PARSE_ERR;
        // Split "ORA-XXXX: msg"
        // Part before : is the error code
        // Part after is the localized message
        char *colon_pos = memchr(error_msg, ':', error_len);
        sql_set_request_status(info, SQL_REQUEST_ERROR);
        if (colon_pos) {
            // We extract the error code
            unsigned error_code_size = colon_pos - error_msg;
            int size_err = MIN(error_code_size, sizeof(info->error_code));
            memcpy(info->error_code, error_msg, size_err);
            info->error_code[size_err] = '\0';
            info->set_values |= SQL_ERROR_CODE;
            if (0 == strcmp("ORA-01403", info->error_code))
                info->request_status = SQL_REQUEST_COMPLETE;

            // We skip ':' in errror message
            char const *start_message = colon_pos + 1;
            // We skip spaces before errror message
            while (start_message < error_len + error_msg && *start_message == ' ')
                start_message++;

            copy_string(info->error_message, start_message, sizeof(info->error_message));
            info->set_values |= SQL_ERROR_MESSAGE;
        } else {
            copy_string(info->error_message, error_msg, sizeof(info->error_message));
            info->set_values |= SQL_ERROR_MESSAGE;
        }
    }

    return PROTO_OK;
}
Exemple #3
0
/*
 * | 2 bytes | 1 byte   | Variable |
 * | Flags   | TTC code | TTC body |
 */
static enum proto_parse_status tns_parse_data(struct tns_parser *tns_parser, struct sql_proto_info *info, struct cursor *cursor,
        unsigned way)
{
    SLOG(LOG_DEBUG, "Parsing TNS data PDU of size %zu", cursor->cap_len);
    enum proto_parse_status status = PROTO_OK;

    // First, read the data flags
    CHECK(2);
    unsigned flags = cursor_read_u16n(cursor);
    SLOG(LOG_DEBUG, "Data flags = 0x%x", flags);
    if (flags & 0x40) { // End Of File
        if (cursor->cap_len != 0) return PROTO_PARSE_ERR;   // This may be wrong, maybe a command is allowed anyway
        info->msg_type = SQL_EXIT;
        sql_set_request_status(info, SQL_REQUEST_COMPLETE);
        return PROTO_OK;
    }
    info->msg_type = tns_parser->msg_type;
    while (status == PROTO_OK && cursor->cap_len) {
        CHECK(1);
        enum ttc_code ttc_code = cursor_read_u8(cursor);
        SLOG(LOG_DEBUG, "Ttc code = 0x%02x, msg type %s", ttc_code, sql_msg_type_2_str(tns_parser->msg_type));
        switch (ttc_code) {
            case TTC_ROW_PREFIX:
                status = tns_parse_row_prefix(tns_parser, info, cursor);
                break;
            case TTC_ROW_DATA:
                status = tns_parse_row_data(tns_parser, info, cursor);
                break;
            case TTC_ROW_DESCRIPTION_PREFIX:
                status = tns_parse_row_description_prefix(tns_parser, info, cursor);
                break;
            case TTC_ROW_RECAP:
                status = tns_parse_row_recap(cursor);
                break;
            case TTC_ROW_DESCRIPTION:
                status = tns_parse_row_description(cursor);
                break;
            case TTC_LOGIN_PROPERTY:
                status = tns_parse_login_property(info, cursor);
                break;
            case TTC_QUERY:
                status = tns_parse_query(tns_parser, info, cursor);
                break;
            case TTC_END_MESSAGE:
                status = tns_parse_end(info, cursor);
                break;
            case TTC_CLOSE:
                status = tns_parse_close_statement(cursor);
                break;
            default:
                SLOG(LOG_DEBUG, "Unknown ttc_code = %u", ttc_code);
                return PROTO_OK;
        }
        if (status == PROTO_OK) {
            enum sql_msg_type ttc_msg_type = ttc_to_msg_type(tns_parser, ttc_code);
            if (ttc_msg_type != SQL_UNKNOWN) {
                info->msg_type = ttc_msg_type;
                tns_parser->msg_type = ttc_msg_type;
            }
            // Fix c2s_way
            bool old_c2s_way = tns_parser->c2s_way;
            switch (ttc_code) {
                case TTC_ROW_DESCRIPTION_PREFIX:
                case TTC_ROW_RECAP:
                case TTC_ROW_DESCRIPTION:
                case TTC_END_MESSAGE:
                    tns_parser->c2s_way = !way;
                    break;
                case TTC_QUERY:
                case TTC_CLOSE:
                    tns_parser->c2s_way = way;
                    break;
                default:
                    break;
            }
            if (old_c2s_way != tns_parser->c2s_way) {
                SLOG(LOG_DEBUG, "Fix c2s way from %d to %d", old_c2s_way, tns_parser->c2s_way);
            }
            info->is_query = way == tns_parser->c2s_way;
        }
    }
    return status;
}
Exemple #4
0
static enum proto_parse_status tns_parse_end(struct sql_proto_info *info, struct cursor *cursor)
{
    SLOG(LOG_DEBUG, "Parsing tns end packet");
    enum proto_parse_status status;

    uint_least64_t var0;
    uint_least64_t var1;
    uint_least64_t var2;
    uint_least64_t var3;
    uint_least64_t var4;
    uint_least64_t var5;
    if (PROTO_OK != (status = cursor_read_variable_int(cursor, &var0))) return status;
    if (PROTO_OK != (status = cursor_read_variable_int(cursor, &var1))) return status;
    if (PROTO_OK != (status = cursor_read_variable_int(cursor, &var2))) return status;
    if (PROTO_OK != (status = cursor_read_variable_int(cursor, &var3))) return status;
    if (PROTO_OK != (status = cursor_read_variable_int(cursor, &var4))) return status;
    if (PROTO_OK != (status = cursor_read_variable_int(cursor, &var5))) return status;

    uint_least64_t nb_rows;
    uint_least64_t error_code;

    if (var0 != 0 && var4 == 0 && var5 == 0) {
        // First var is unknown?
        SLOG(LOG_DEBUG, "Unknown bits after ttc code");
        nb_rows = var2;
        error_code = var3;
        DROP_VAR(cursor);
    } else {
        // var0 == sequence
        // var1 == rows
        // var2 == error code
        nb_rows = var1;
        error_code = var2;
    }

    if (info->msg_type == SQL_QUERY) {
        sql_set_row_count(info, nb_rows);
        SLOG(LOG_DEBUG, "Nb rows %d", info->u.query.nb_rows);
    }
    SLOG(LOG_DEBUG, "Error code is %zu", error_code);

    DROP_VARS(cursor, 1);
    DROP_FIX(cursor, 2);
    DROP_VARS(cursor, 2);
    DROP_FIX(cursor, 2);
    DROP_VARS(cursor, 2);
    DROP_FIX(cursor, 1);
    DROP_VARS(cursor, 3);
    DROP_FIX(cursor, 2);
    DROP_VARS(cursor, 2);

    if (error_code != 0) {
        SLOG(LOG_DEBUG, "Parsing error message");
        char *error_msg;
        unsigned error_len;

        // Drop an unknown number of column here
        while(cursor->cap_len > 1 && !isprint(*(cursor->head + 1))){
            DROP_FIX(cursor, 1);
        }
        status = cursor_read_variable_string(cursor, &error_msg, &error_len);
        if (status != PROTO_OK) return status;
        // Split "ORA-XXXX: msg"
        // Part before : is the error code
        // Part after is the localized message
        char *colon_pos = memchr(error_msg, ':', error_len);
        sql_set_request_status(info, SQL_REQUEST_ERROR);
        if (colon_pos) {
            // We extract the error code
            unsigned error_code_size = colon_pos - error_msg;
            int size_err = MIN(error_code_size, sizeof(info->error_code));
            memcpy(info->error_code, error_msg, size_err);
            info->error_code[size_err] = '\0';
            info->set_values |= SQL_ERROR_CODE;
            if (0 == strcmp("ORA-01403", info->error_code))
                info->request_status = SQL_REQUEST_COMPLETE;

            // We skip ':' in errror message
            char const *start_message = colon_pos + 1;
            // We skip spaces before errror message
            while (start_message < error_len + error_msg && *start_message == ' ')
                start_message++;

            copy_string(info->error_message, start_message, sizeof(info->error_message));
            info->set_values |= SQL_ERROR_MESSAGE;
        } else {
            copy_string(info->error_message, error_msg, sizeof(info->error_message));
            info->set_values |= SQL_ERROR_MESSAGE;
        }
    }

    return PROTO_OK;
}