Files
nginx-custom/naxsi-0.55.3/ext/libinjection/testdriver.c
2017-02-25 23:55:24 +01:00

313 lines
8.0 KiB
C

#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <glob.h>
#include "libinjection.h"
#include "libinjection_sqli.h"
#include "libinjection_html5.h"
#include "libinjection_xss.h"
static char g_test[8096];
static char g_input[8096];
static char g_expected[8096];
size_t modp_rtrim(char* str, size_t len);
size_t print_string(char* buf, size_t len, stoken_t* t);
size_t print_var(char* buf, size_t len, stoken_t* t);
size_t print_token(char* buf, size_t len, stoken_t *t);
int read_file(const char* fname, int flags, int testtype);
const char* h5_type_to_string(enum html5_type x);
size_t print_html5_token(char* buf, size_t len, h5_state_t* hs);
size_t modp_rtrim(char* str, size_t len)
{
while (len) {
char c = str[len -1];
if (c == ' ' || c == '\n' || c == '\t' || c == '\r') {
str[len -1] = '\0';
len -= 1;
} else {
break;
}
}
return len;
}
size_t print_string(char* buf, size_t len, stoken_t* t)
{
int slen = 0;
/* print opening quote */
if (t->str_open != '\0') {
slen = sprintf(buf + len, "%c", t->str_open);
assert(slen >= 0);
len += (size_t) slen;
}
/* print content */
slen = sprintf(buf + len, "%s", t->val);
assert(slen >= 0);
len += (size_t) slen;
/* print closing quote */
if (t->str_close != '\0') {
slen = sprintf(buf + len, "%c", t->str_close);
assert(slen >= 0);
len += (size_t) slen;
}
return len;
}
size_t print_var(char* buf, size_t len, stoken_t* t)
{
int slen = 0;
if (t->count >= 1) {
slen = sprintf(buf + len, "%c", '@');
assert(slen >= 0);
len += (size_t) slen;
}
if (t->count == 2) {
slen = sprintf(buf + len, "%c", '@');
assert(slen >= 0);
len += (size_t) slen;
}
return print_string(buf, len, t);
}
const char* h5_type_to_string(enum html5_type x)
{
switch (x) {
case DATA_TEXT: return "DATA_TEXT";
case TAG_NAME_OPEN: return "TAG_NAME_OPEN";
case TAG_NAME_CLOSE: return "TAG_NAME_CLOSE";
case TAG_NAME_SELFCLOSE: return "TAG_NAME_SELFCLOSE";
case TAG_DATA: return "TAG_DATA";
case TAG_CLOSE: return "TAG_CLOSE";
case ATTR_NAME: return "ATTR_NAME";
case ATTR_VALUE: return "ATTR_VALUE";
case TAG_COMMENT: return "TAG_COMMENT";
case DOCTYPE: return "DOCTYPE";
default:
assert(0);
}
}
size_t print_html5_token(char* buf, size_t len, h5_state_t* hs)
{
int slen;
char* tmp = (char*) malloc(hs->token_len + 1);
memcpy(tmp, hs->token_start, hs->token_len);
/* TODO.. encode to be printable */
tmp[hs->token_len] = '\0';
slen = sprintf(buf + len, "%s,%d,%s\n",
h5_type_to_string(hs->token_type),
(int) hs->token_len,
tmp);
len += (size_t) slen;
free(tmp);
return len;
}
size_t print_token(char* buf, size_t len, stoken_t *t)
{
int slen;
slen = sprintf(buf + len, "%c ", t->type);
assert(slen >= 0);
len += (size_t) slen;
switch (t->type) {
case 's':
len = print_string(buf, len, t);
break;
case 'v':
len = print_var(buf, len, t);
break;
default:
slen = sprintf(buf + len, "%s", t->val);
assert(slen >= 0);
len += (size_t) slen;
}
slen = sprintf(buf + len, "%c", '\n');
assert(slen >= 0);
len += (size_t) slen;
return len;
}
int read_file(const char* fname, int flags, int testtype)
{
int count = 0;
FILE *fp = NULL;
char linebuf[8192];
char g_actual[8192];
char* bufptr = NULL;
size_t slen;
char* copy;
sfilter sf;
int ok = 1;
int num_tokens;
int issqli;
int i;
g_test[0] = '\0';
g_input[0] = '\0';
g_expected[0] = '\0';
fp = fopen(fname, "r");
while(fgets(linebuf, sizeof(linebuf), fp) != NULL) {
if (count == 0 && strcmp(linebuf, "--TEST--\n") == 0) {
bufptr = g_test;
count = 1;
} else if (count == 1 && strcmp(linebuf, "--INPUT--\n") == 0) {
bufptr = g_input;
count = 2;
} else if (count == 2 && strcmp(linebuf, "--EXPECTED--\n") == 0) {
bufptr = g_expected;
count = 3;
} else {
assert(bufptr != NULL);
strcat(bufptr, linebuf);
}
}
fclose(fp);
if (count != 3) {
return 1;
}
g_expected[modp_rtrim(g_expected, strlen(g_expected))] = '\0';
g_input[modp_rtrim(g_input, strlen(g_input))] = '\0';
slen = strlen(g_input);
copy = (char* ) malloc(slen);
memcpy(copy, g_input, slen);
g_actual[0] = '\0';
if (testtype == 0) {
/*
* print sqli tokenization only
*/
libinjection_sqli_init(&sf, copy, slen, flags);
libinjection_sqli_callback(&sf, NULL, NULL);
slen =0;
while (libinjection_sqli_tokenize(&sf) == 1) {
slen = print_token(g_actual, slen, sf.current);
}
} else if (testtype == 1) {
/*
* testing tokenization + folding
*/
libinjection_sqli_init(&sf, copy, slen, flags);
libinjection_sqli_callback(&sf, NULL, NULL);
slen =0;
num_tokens = libinjection_sqli_fold(&sf);
for (i = 0; i < num_tokens; ++i) {
slen = print_token(g_actual, slen, libinjection_sqli_get_token(&sf, i));
}
} else if (testtype == 2) {
/**
* test sqli detection
*/
char buf[100];
issqli = libinjection_sqli(copy, slen, buf);
if (issqli) {
sprintf(g_actual, "%s", buf);
}
} else if (testtype == 3) {
/*
* test html5 tokenization only
*/
h5_state_t hs;
libinjection_h5_init(&hs, copy, slen, DATA_STATE);
slen = 0;
while (libinjection_h5_next(&hs)) {
slen = print_html5_token(g_actual, slen, &hs);
}
} else if (testtype == 4) {
/*
* test XSS detection
*/
sprintf(g_actual, "%d", libinjection_xss(copy, slen));
} else {
fprintf(stderr, "Got stange testtype value of %d\n", testtype);
assert(0);
}
g_actual[modp_rtrim(g_actual, strlen(g_actual))] = '\0';
if (strcmp(g_expected, g_actual) != 0) {
printf("INPUT: \n%s\n==\n", g_input);
printf("EXPECTED: \n%s\n==\n", g_expected);
printf("GOT: \n%s\n==\n", g_actual);
ok = 0;
}
free(copy);
return ok;
}
int main(int argc, char** argv)
{
int offset = 1;
int i;
int ok;
int count = 0;
int count_fail = 0;
int flags = 0;
int testtype = 0;
int quiet = 0;
const char* fname;
while (1) {
if (strcmp(argv[offset], "-q") == 0 || strcmp(argv[offset], "--quiet") == 0) {
quiet = 1;
offset += 1;
} else {
break;
}
}
printf("%s\n", libinjection_version());
for (i = offset; i < argc; ++i) {
fname = argv[i];
count += 1;
if (strstr(fname, "test-tokens-")) {
flags = FLAG_QUOTE_NONE | FLAG_SQL_ANSI;
testtype = 0;
} else if (strstr(fname, "test-folding-")) {
flags = FLAG_QUOTE_NONE | FLAG_SQL_ANSI;
testtype = 1;
} else if (strstr(fname, "test-sqli-")) {
flags = FLAG_NONE;
testtype = 2;
} else if (strstr(fname, "test-html5-")) {
flags = FLAG_NONE;
testtype = 3;
} else if (strstr(fname, "test-xss-")) {
flags = FLAG_NONE;
testtype = 4;
} else {
fprintf(stderr, "Unknown test type: %s, failing\n", fname);
count_fail += 1;
continue;
}
ok = read_file(fname, flags, testtype);
if (ok) {
if (! quiet) {
fprintf(stderr, "%s: ok\n", fname);
}
} else {
count_fail += 1;
if (! quiet) {
fprintf(stderr, "%s: fail\n", fname);
}
}
}
return count > 0 && count_fail > 0;
}