Lines 2-7
Link Here
|
2 |
* |
2 |
* |
3 |
* Copyright (C) 2000 Emmanuel Roger <winfield@freegates.be> |
3 |
* Copyright (C) 2000 Emmanuel Roger <winfield@freegates.be> |
4 |
* |
4 |
* |
|
|
5 |
* 2005-08-05 Pablo Neira Ayuso <pablo@eurodev.net> |
6 |
* - reimplemented to use new string matching iptables match |
7 |
* - add functionality to match packets by using window offsets |
8 |
* - add functionality to select the string matching algorithm |
9 |
* |
5 |
* ChangeLog |
10 |
* ChangeLog |
6 |
* 29.12.2003: Michael Rash <mbr@cipherdyne.org> |
11 |
* 29.12.2003: Michael Rash <mbr@cipherdyne.org> |
7 |
* Fixed iptables save/restore for ascii strings |
12 |
* Fixed iptables save/restore for ascii strings |
Lines 21-56
Link Here
|
21 |
#include <stdlib.h> |
26 |
#include <stdlib.h> |
22 |
#include <getopt.h> |
27 |
#include <getopt.h> |
23 |
#include <ctype.h> |
28 |
#include <ctype.h> |
24 |
|
|
|
25 |
#include <iptables.h> |
29 |
#include <iptables.h> |
|
|
30 |
#include <stddef.h> |
26 |
#include <linux/netfilter_ipv4/ipt_string.h> |
31 |
#include <linux/netfilter_ipv4/ipt_string.h> |
27 |
|
32 |
|
28 |
|
|
|
29 |
/* Function which prints out usage message. */ |
33 |
/* Function which prints out usage message. */ |
30 |
static void |
34 |
static void |
31 |
help(void) |
35 |
help(void) |
32 |
{ |
36 |
{ |
33 |
printf( |
37 |
printf( |
34 |
"STRING match v%s options:\n" |
38 |
"STRING match v%s options:\n" |
|
|
39 |
"--from Offset to start searching from\n" |
40 |
"--to Offset to stop searching\n" |
41 |
"--algo Algorithm\n" |
35 |
"--string [!] string Match a string in a packet\n" |
42 |
"--string [!] string Match a string in a packet\n" |
36 |
"--hex-string [!] string Match a hex string in a packet\n", |
43 |
"--hex-string [!] string Match a hex string in a packet\n", |
37 |
IPTABLES_VERSION); |
44 |
IPTABLES_VERSION); |
38 |
} |
45 |
} |
39 |
|
46 |
|
40 |
|
|
|
41 |
static struct option opts[] = { |
47 |
static struct option opts[] = { |
42 |
{ .name = "string", .has_arg = 1, .flag = 0, .val = '1' }, |
48 |
{ "from", 1, 0, '1' }, |
43 |
{ .name = "hex-string", .has_arg = 1, .flag = 0, .val = '2' }, |
49 |
{ "to", 1, 0, '2' }, |
44 |
{ .name = 0 } |
50 |
{ "algo", 1, 0, '3' }, |
|
|
51 |
{ "string", 1, 0, '4' }, |
52 |
{ "hex-string", 1, 0, '5' }, |
53 |
{0} |
45 |
}; |
54 |
}; |
46 |
|
55 |
|
47 |
static void |
56 |
static void |
|
|
57 |
init(struct ipt_entry_match *m, unsigned int *nfcache) |
58 |
{ |
59 |
struct ipt_string_info *i = (struct ipt_string_info *) m->data; |
60 |
|
61 |
if (i->to_offset == 0) |
62 |
i->to_offset = (u_int16_t) ~0UL; |
63 |
} |
64 |
|
65 |
static void |
48 |
parse_string(const unsigned char *s, struct ipt_string_info *info) |
66 |
parse_string(const unsigned char *s, struct ipt_string_info *info) |
49 |
{ |
67 |
{ |
50 |
if (strlen(s) <= BM_MAX_NLEN) strcpy(info->string, s); |
68 |
if (strlen(s) <= IPT_STRING_MAX_PATTERN_SIZE) { |
51 |
else exit_error(PARAMETER_PROBLEM, "STRING too long `%s'", s); |
69 |
strncpy(info->pattern, s, IPT_STRING_MAX_PATTERN_SIZE); |
|
|
70 |
info->patlen = strlen(s); |
71 |
return; |
72 |
} |
73 |
exit_error(PARAMETER_PROBLEM, "STRING too long `%s'", s); |
52 |
} |
74 |
} |
53 |
|
75 |
|
|
|
76 |
static void |
77 |
parse_algo(const unsigned char *s, struct ipt_string_info *info) |
78 |
{ |
79 |
if (strlen(s) <= IPT_STRING_MAX_ALGO_NAME_SIZE) { |
80 |
strncpy(info->algo, s, IPT_STRING_MAX_ALGO_NAME_SIZE); |
81 |
return; |
82 |
} |
83 |
exit_error(PARAMETER_PROBLEM, "ALGO too long `%s'", s); |
84 |
} |
54 |
|
85 |
|
55 |
static void |
86 |
static void |
56 |
parse_hex_string(const unsigned char *s, struct ipt_string_info *info) |
87 |
parse_hex_string(const unsigned char *s, struct ipt_string_info *info) |
Lines 92-98
Link Here
|
92 |
exit_error(PARAMETER_PROBLEM, |
123 |
exit_error(PARAMETER_PROBLEM, |
93 |
"Bad literal placement at end of string"); |
124 |
"Bad literal placement at end of string"); |
94 |
} |
125 |
} |
95 |
info->string[sindex] = s[i+1]; |
126 |
info->pattern[sindex] = s[i+1]; |
96 |
i += 2; /* skip over literal char */ |
127 |
i += 2; /* skip over literal char */ |
97 |
literal_f = 0; |
128 |
literal_f = 0; |
98 |
} else if (hex_f) { |
129 |
} else if (hex_f) { |
Lines 114-135
Link Here
|
114 |
if (! sscanf(hextmp, "%x", &schar)) |
145 |
if (! sscanf(hextmp, "%x", &schar)) |
115 |
exit_error(PARAMETER_PROBLEM, |
146 |
exit_error(PARAMETER_PROBLEM, |
116 |
"Invalid hex char `%c'", s[i]); |
147 |
"Invalid hex char `%c'", s[i]); |
117 |
info->string[sindex] = (char) schar; |
148 |
info->pattern[sindex] = (char) schar; |
118 |
if (s[i+2] == ' ') |
149 |
if (s[i+2] == ' ') |
119 |
i += 3; /* spaces included in the hex block */ |
150 |
i += 3; /* spaces included in the hex block */ |
120 |
else |
151 |
else |
121 |
i += 2; |
152 |
i += 2; |
122 |
} else { /* the char is not part of hex data, so just copy */ |
153 |
} else { /* the char is not part of hex data, so just copy */ |
123 |
info->string[sindex] = s[i]; |
154 |
info->pattern[sindex] = s[i]; |
124 |
i++; |
155 |
i++; |
125 |
} |
156 |
} |
126 |
if (sindex > BM_MAX_NLEN) |
157 |
if (sindex > IPT_STRING_MAX_PATTERN_SIZE) |
127 |
exit_error(PARAMETER_PROBLEM, "STRING too long `%s'", s); |
158 |
exit_error(PARAMETER_PROBLEM, "STRING too long `%s'", s); |
128 |
sindex++; |
159 |
sindex++; |
129 |
} |
160 |
} |
130 |
info->len = sindex; |
161 |
info->patlen = sindex; |
131 |
} |
162 |
} |
132 |
|
163 |
|
|
|
164 |
#define STRING 0x1 |
165 |
#define ALGO 0x2 |
166 |
#define FROM 0x4 |
167 |
#define TO 0x8 |
133 |
|
168 |
|
134 |
/* Function which parses command options; returns true if it |
169 |
/* Function which parses command options; returns true if it |
135 |
ate an option */ |
170 |
ate an option */ |
Lines 143-170
Link Here
|
143 |
|
178 |
|
144 |
switch (c) { |
179 |
switch (c) { |
145 |
case '1': |
180 |
case '1': |
146 |
if (*flags) |
181 |
if (*flags & FROM) |
147 |
exit_error(PARAMETER_PROBLEM, |
182 |
exit_error(PARAMETER_PROBLEM, |
148 |
"Can't specify multiple strings"); |
183 |
"Can't specify multiple --from"); |
149 |
|
184 |
stringinfo->from_offset = atoi(optarg); |
|
|
185 |
*flags |= FROM; |
186 |
break; |
187 |
case '2': |
188 |
if (*flags & TO) |
189 |
exit_error(PARAMETER_PROBLEM, |
190 |
"Can't specify multiple --to"); |
191 |
stringinfo->to_offset = atoi(optarg); |
192 |
*flags |= TO; |
193 |
break; |
194 |
case '3': |
195 |
if (*flags & ALGO) |
196 |
exit_error(PARAMETER_PROBLEM, |
197 |
"Can't specify multiple --algo"); |
198 |
parse_algo(optarg, stringinfo); |
199 |
*flags |= ALGO; |
200 |
break; |
201 |
case '4': |
202 |
if (*flags & STRING) |
203 |
exit_error(PARAMETER_PROBLEM, |
204 |
"Can't specify multiple --string"); |
150 |
check_inverse(optarg, &invert, &optind, 0); |
205 |
check_inverse(optarg, &invert, &optind, 0); |
151 |
parse_string(argv[optind-1], stringinfo); |
206 |
parse_string(argv[optind-1], stringinfo); |
152 |
if (invert) |
207 |
if (invert) |
153 |
stringinfo->invert = 1; |
208 |
stringinfo->invert = 1; |
154 |
stringinfo->len=strlen((char *)&stringinfo->string); |
209 |
stringinfo->patlen=strlen((char *)&stringinfo->pattern); |
155 |
*flags = 1; |
210 |
*flags |= STRING; |
156 |
break; |
211 |
break; |
157 |
|
212 |
|
158 |
case '2': |
213 |
case '5': |
159 |
if (*flags) |
214 |
if (*flags & STRING) |
160 |
exit_error(PARAMETER_PROBLEM, |
215 |
exit_error(PARAMETER_PROBLEM, |
161 |
"Can't specify multiple strings"); |
216 |
"Can't specify multiple --hex-string"); |
162 |
|
217 |
|
163 |
check_inverse(optarg, &invert, &optind, 0); |
218 |
check_inverse(optarg, &invert, &optind, 0); |
164 |
parse_hex_string(argv[optind-1], stringinfo); /* sets length */ |
219 |
parse_hex_string(argv[optind-1], stringinfo); /* sets length */ |
165 |
if (invert) |
220 |
if (invert) |
166 |
stringinfo->invert = 1; |
221 |
stringinfo->invert = 1; |
167 |
*flags = 1; |
222 |
*flags |= STRING; |
168 |
break; |
223 |
break; |
169 |
|
224 |
|
170 |
default: |
225 |
default: |
Lines 178-186
Link Here
|
178 |
static void |
233 |
static void |
179 |
final_check(unsigned int flags) |
234 |
final_check(unsigned int flags) |
180 |
{ |
235 |
{ |
181 |
if (!flags) |
236 |
if (!(flags & STRING)) |
|
|
237 |
exit_error(PARAMETER_PROBLEM, |
238 |
"STRING match: You must specify `--string' or " |
239 |
"`--hex-string'"); |
240 |
if (!(flags & ALGO)) |
182 |
exit_error(PARAMETER_PROBLEM, |
241 |
exit_error(PARAMETER_PROBLEM, |
183 |
"STRING match: You must specify `--string' or `--hex-string'"); |
242 |
"STRING match: You must specify `--algo'"); |
184 |
} |
243 |
} |
185 |
|
244 |
|
186 |
/* Test to see if the string contains non-printable chars or quotes */ |
245 |
/* Test to see if the string contains non-printable chars or quotes */ |
Lines 237-249
Link Here
|
237 |
const struct ipt_string_info *info = |
296 |
const struct ipt_string_info *info = |
238 |
(const struct ipt_string_info*) match->data; |
297 |
(const struct ipt_string_info*) match->data; |
239 |
|
298 |
|
240 |
if (is_hex_string(info->string, info->len)) { |
299 |
if (is_hex_string(info->pattern, info->patlen)) { |
241 |
printf("STRING match %s", (info->invert) ? "!" : ""); |
300 |
printf("STRING match %s", (info->invert) ? "!" : ""); |
242 |
print_hex_string(info->string, info->len); |
301 |
print_hex_string(info->pattern, info->patlen); |
243 |
} else { |
302 |
} else { |
244 |
printf("STRING match %s", (info->invert) ? "!" : ""); |
303 |
printf("STRING match %s", (info->invert) ? "!" : ""); |
245 |
print_string(info->string, info->len); |
304 |
print_string(info->pattern, info->patlen); |
246 |
} |
305 |
} |
|
|
306 |
printf("ALGO name %s ", info->algo); |
307 |
if (info->from_offset != 0) |
308 |
printf("FROM %u ", info->from_offset); |
309 |
if (info->to_offset != 0) |
310 |
printf("TO %u", info->to_offset); |
247 |
} |
311 |
} |
248 |
|
312 |
|
249 |
|
313 |
|
Lines 254-280
Link Here
|
254 |
const struct ipt_string_info *info = |
318 |
const struct ipt_string_info *info = |
255 |
(const struct ipt_string_info*) match->data; |
319 |
(const struct ipt_string_info*) match->data; |
256 |
|
320 |
|
257 |
if (is_hex_string(info->string, info->len)) { |
321 |
if (is_hex_string(info->pattern, info->patlen)) { |
258 |
printf("--hex-string %s", (info->invert) ? "! ": ""); |
322 |
printf("--hex-string %s", (info->invert) ? "! ": ""); |
259 |
print_hex_string(info->string, info->len); |
323 |
print_hex_string(info->pattern, info->patlen); |
260 |
} else { |
324 |
} else { |
261 |
printf("--string %s", (info->invert) ? "! ": ""); |
325 |
printf("--string %s", (info->invert) ? "! ": ""); |
262 |
print_string(info->string, info->len); |
326 |
print_string(info->pattern, info->patlen); |
263 |
} |
327 |
} |
|
|
328 |
printf("--algo %s ", info->algo); |
329 |
if (info->from_offset != 0) |
330 |
printf("--from-offset %u ", info->from_offset); |
331 |
if (info->to_offset != 0) |
332 |
printf("--to-offset %u ", info->to_offset); |
264 |
} |
333 |
} |
265 |
|
334 |
|
266 |
|
335 |
|
267 |
static struct iptables_match string = { |
336 |
static struct iptables_match string = { |
268 |
.name = "string", |
337 |
.name = "string", |
269 |
.version = IPTABLES_VERSION, |
338 |
.version = IPTABLES_VERSION, |
270 |
.size = IPT_ALIGN(sizeof(struct ipt_string_info)), |
339 |
.size = IPT_ALIGN(sizeof(struct ipt_string_info)), |
271 |
.userspacesize = IPT_ALIGN(sizeof(struct ipt_string_info)), |
340 |
.userspacesize = offsetof(struct ipt_string_info, config), |
272 |
.help = &help, |
341 |
.help = help, |
273 |
.parse = &parse, |
342 |
.init = init, |
274 |
.final_check = &final_check, |
343 |
.parse = parse, |
275 |
.print = &print, |
344 |
.final_check = final_check, |
276 |
.save = &save, |
345 |
.print = print, |
277 |
.extra_opts = opts |
346 |
.save = save, |
|
|
347 |
.extra_opts = opts |
278 |
}; |
348 |
}; |
279 |
|
349 |
|
280 |
|
350 |
|