// -*- coding: utf-8 -*-
//+---------------------------------------------------------------------------+
//| 01001110 01100101 01110100 01111010 01101111 01100010 |
//| |
//| Netzob : Inferring communication protocols |
//+---------------------------------------------------------------------------+
//| Copyright (C) 2011-2017 Georges Bossert and Frédéric Guihéry |
//| This program is free software: you can redistribute it and/or modify |
//| it under the terms of the GNU General Public License as published by |
//| the Free Software Foundation, either version 3 of the License, or |
//| (at your option) any later version. |
//| |
//| This program is distributed in the hope that it will be useful, |
//| but WITHOUT ANY WARRANTY; without even the implied warranty of |
//| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
//| GNU General Public License for more details. |
//| |
//| You should have received a copy of the GNU General Public License |
//| along with this program. If not, see . |
//+---------------------------------------------------------------------------+
//| @url : http://www.netzob.org |
//| @contact : contact@netzob.org |
//| @sponsors : Amossys, http://www.amossys.fr |
//| Supélec, http://www.rennes.supelec.fr/ren/rd/cidre/ |
//+---------------------------------------------------------------------------+
#include
#include
#include
#include
#include "relation.h"
static unsigned int MIN_SIZE = 2;
/*
* wrapper of string comparison used to detect a relation with the
* specified parameters.
*/
static int
get_match(const char* cell_ref, const char* cell_rel,
size_t start, size_t len)
{
int ret;
#if defined(__DEBUG__) && false
char* new_rel;
if ((new_rel = malloc((len + 1) * sizeof(*new_rel)))) {
new_rel[len] = '\0';
DLOG("%s == %s ?", cell_ref, strncpy(new_rel, &cell_rel[start], len));
free(new_rel);
}
#endif
ret = strncmp(cell_ref, &cell_rel[start], len);
#if defined(__DEBUG__) && false
DLOG(" %d\n", ret);
#endif
return ret;
}
/*
* Append a node to the set of matches.
*/
static struct relation_matches*
append_match(struct relation_matches** matches,
const struct relation_match* match)
{
struct relation_matches* new = NULL;
if (!(new = malloc(sizeof(*new))))
return NULL;
new->next = *matches;
memcpy(&new->match, match, sizeof(new->match));
*matches = new;
return new;
}
/*
* Returns the first non-matching message index.
*/
static int
verify_match(const char*** messages, size_t msgs_len, size_t cells_len,
const struct relation_match* match)
{
int i;
int ret = 0;
const char** cells;
const char* ref;
const char* rel;
DLOG("Verifying M%04d", 0);
for (i = 0; i < msgs_len; i++) {
if (i == match->message_idx)
continue;
cells = messages[i];
ref = cells[match->cell_ref_idx];
rel = cells[match->cell_rel_idx];
DLOG2("\b\b\b\b%04d", i);
if (get_match(ref, rel, match->cell_rel_off, match->cell_rel_size)) {
ret = i;
break;
}
}
DLOG2("\n");
return ret;
}
/*
* Main function used to build a set of matches.
*/
static struct relation_matches*
relation_equality_find(const char*** messages, int row, int idx,
size_t vlen, size_t hlen)
{
int i, ret;
size_t off;
int found = 0;
int match_res;
const char** cells;
const char* ref;
size_t ref_len;
const char* rel;
size_t rel_len;
struct relation_matches* matches = NULL;
struct relation_match match;
cells = messages[row];
ref = cells[idx];
ref_len = strlen(ref);
for (i = 0; i < hlen; i++) {
rel = cells[i];
rel_len = strlen(rel);
if (i != idx && rel && ref_len <= rel_len && ref_len >= MIN_SIZE) {
for (off = 0; off <= rel_len - ref_len; off++) {
if (!(match_res = get_match(ref, rel, off, ref_len))) {
match.message_idx = row;
match.cell_ref_idx = idx;
match.cell_rel_idx = i;
match.cell_rel_off = off;
match.cell_rel_size = ref_len;
DLOG("possible match found: M%d F%d[:], F%d[%ld:%ld] (%s)\n",
row, idx, i, off, off+ref_len, ref);
if ((ret = verify_match(messages, vlen, hlen,
(const struct relation_match*)&match)) != 0) {
DLOG("verification failed at M%d\n", ret);
continue;
}
DLOG("MATCH FOUND\n");
DLOG(">> %p\n", matches);
append_match(&matches, (const struct relation_match*)&match);
DLOG(">> %p\n", matches);
}
}
}
}
return matches;
}
struct relation_algorithm_operations operations = {
.name = "equality",
.find = relation_equality_find
};