]> git.ipfire.org Git - people/arne_f/kernel.git/blob - net/netfilter/xt_layer7.c
80460130083a3e8f17410ef8c132f39a202c622e
[people/arne_f/kernel.git] / net / netfilter / xt_layer7.c
1 /*
2 Kernel module to match application layer (OSI layer 7) data in connections.
3
4 http://l7-filter.sf.net
5
6 (C) 2003-2009 Matthew Strait and Ethan Sommer.
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version
11 2 of the License, or (at your option) any later version.
12 http://www.gnu.org/licenses/gpl.txt
13
14 Based on ipt_string.c (C) 2000 Emmanuel Roger <winfield@freegates.be>,
15 xt_helper.c (C) 2002 Harald Welte and cls_layer7.c (C) 2003 Matthew Strait,
16 Ethan Sommer, Justin Levandoski.
17 */
18
19 #include <linux/spinlock.h>
20 #include <linux/version.h>
21 #include <net/ip.h>
22 #include <net/tcp.h>
23 #include <linux/module.h>
24 #include <linux/skbuff.h>
25 #include <linux/netfilter.h>
26 #include <net/netfilter/nf_conntrack.h>
27 #include <net/netfilter/nf_conntrack_core.h>
28 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
29 #include <net/netfilter/nf_conntrack_extend.h>
30 #include <net/netfilter/nf_conntrack_acct.h>
31 #endif
32 #include <linux/netfilter/x_tables.h>
33 #include <linux/netfilter/xt_layer7.h>
34 #include <linux/ctype.h>
35 #include <linux/proc_fs.h>
36
37 #include "regexp/regexp.c"
38
39 MODULE_LICENSE("GPL");
40 MODULE_AUTHOR("Matthew Strait <quadong@users.sf.net>, Ethan Sommer <sommere@users.sf.net>, Arne Fitzenreiter <arne_f@ipfire.org>");
41 MODULE_DESCRIPTION("iptables application layer match module");
42 MODULE_ALIAS("ipt_layer7");
43 MODULE_VERSION("2.30");
44
45 static int maxdatalen = 2048; // this is the default
46 module_param(maxdatalen, int, 0444);
47 MODULE_PARM_DESC(maxdatalen, "maximum bytes of data looked at by l7-filter");
48 #ifdef CONFIG_NETFILTER_XT_MATCH_LAYER7_DEBUG
49 #define DPRINTK(format,args...) printk(format,##args)
50 #else
51 #define DPRINTK(format,args...)
52 #endif
53
54 /* Number of packets whose data we look at.
55 This can be modified through /proc/net/layer7_numpackets */
56 static int num_packets = 10;
57
58 static struct pattern_cache {
59 char * regex_string;
60 regexp * pattern;
61 struct pattern_cache * next;
62 } * first_pattern_cache = NULL;
63
64 static struct proto_cache {
65 char * proto_string;
66 struct proto_cache * next;
67 } * first_proto_cache = NULL;
68
69 DEFINE_SPINLOCK(l7_lock);
70
71 #ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG
72 /* Converts an unfriendly string into a friendly one by
73 replacing unprintables with periods and all whitespace with " ". */
74 static char * friendly_print(unsigned char * s)
75 {
76 char * f = kmalloc(strlen(s) + 1, GFP_ATOMIC);
77 int i;
78
79 if(!f) {
80 if (net_ratelimit())
81 printk(KERN_ERR "layer7: out of memory in "
82 "friendly_print, bailing.\n");
83 return NULL;
84 }
85
86 for(i = 0; i < strlen(s); i++){
87 if(isprint(s[i]) && s[i] < 128) f[i] = s[i];
88 else if(isspace(s[i])) f[i] = ' ';
89 else f[i] = '.';
90 }
91 f[i] = '\0';
92 return f;
93 }
94
95 static char dec2hex(int i)
96 {
97 switch (i) {
98 case 0 ... 9:
99 return (i + '0');
100 break;
101 case 10 ... 15:
102 return (i - 10 + 'a');
103 break;
104 default:
105 if (net_ratelimit())
106 printk("layer7: Problem in dec2hex\n");
107 return '\0';
108 }
109 }
110
111 static char * hex_print(unsigned char * s)
112 {
113 char * g = kmalloc(strlen(s)*3 + 1, GFP_ATOMIC);
114 int i;
115
116 if(!g) {
117 if (net_ratelimit())
118 printk(KERN_ERR "layer7: out of memory in hex_print, "
119 "bailing.\n");
120 return NULL;
121 }
122
123 for(i = 0; i < strlen(s); i++) {
124 g[i*3 ] = dec2hex(s[i]/16);
125 g[i*3 + 1] = dec2hex(s[i]%16);
126 g[i*3 + 2] = ' ';
127 }
128 g[i*3] = '\0';
129
130 return g;
131 }
132 #endif // DEBUG
133
134 /* Use instead of regcomp. As we expect to be seeing the same regexps over and
135 over again, it make sense to cache the results. */
136 static regexp * compile_and_cache(const char * regex_string,
137 const char * protocol)
138 {
139 struct pattern_cache * node = first_pattern_cache;
140 struct pattern_cache * last_pattern_cache = first_pattern_cache;
141 struct pattern_cache * tmp;
142 unsigned int len;
143
144 while (node != NULL) {
145 if (!strcmp(node->regex_string, regex_string))
146 return node->pattern;
147
148 last_pattern_cache = node;/* points at the last non-NULL node */
149 node = node->next;
150 }
151
152 /* If we reach the end of the list, then we have not yet cached
153 the pattern for this regex. Let's do that now.
154 Be paranoid about running out of memory to avoid list corruption. */
155 tmp = kmalloc(sizeof(struct pattern_cache), GFP_ATOMIC);
156
157 if(!tmp) {
158 if (net_ratelimit())
159 printk(KERN_ERR "layer7: out of memory in "
160 "compile_and_cache, bailing.\n");
161 return NULL;
162 }
163
164 tmp->regex_string = kmalloc(strlen(regex_string) + 1, GFP_ATOMIC);
165 tmp->pattern = kmalloc(sizeof(struct regexp), GFP_ATOMIC);
166 tmp->next = NULL;
167
168 if(!tmp->regex_string || !tmp->pattern) {
169 if (net_ratelimit())
170 printk(KERN_ERR "layer7: out of memory in "
171 "compile_and_cache, bailing.\n");
172 kfree(tmp->regex_string);
173 kfree(tmp->pattern);
174 kfree(tmp);
175 return NULL;
176 }
177
178 /* Ok. The new node is all ready now. */
179 node = tmp;
180
181 if(first_pattern_cache == NULL) /* list is empty */
182 first_pattern_cache = node; /* make node the beginning */
183 else
184 last_pattern_cache->next = node; /* attach node to the end */
185
186 /* copy the string and compile the regex */
187 len = strlen(regex_string);
188 DPRINTK("About to compile this: \"%s\"\n", regex_string);
189 node->pattern = regcomp((char *)regex_string, &len);
190 if ( !node->pattern ) {
191 if (net_ratelimit())
192 printk(KERN_ERR "layer7: Error compiling regexp "
193 "\"%s\" (%s)\n",
194 regex_string, protocol);
195 /* pattern is now cached as NULL, so we won't try again. */
196 }
197
198 strcpy(node->regex_string, regex_string);
199 return node->pattern;
200 }
201
202 static char * get_protostr_ptr(const char * protocol)
203 {
204 struct proto_cache * node = first_proto_cache;
205 struct proto_cache * last_proto_cache = first_proto_cache;
206 struct proto_cache * tmp;
207
208 while (node != NULL) {
209 if (!strcmp(node->proto_string, protocol))
210 return node->proto_string;
211
212 last_proto_cache = node;/* points at the last non-NULL node */
213 node = node->next;
214 }
215
216 /* If we reach the end of the list, then we have not yet cached protocol
217 Be paranoid about running out of memory to avoid list corruption. */
218 tmp = kmalloc(sizeof(struct proto_cache), GFP_ATOMIC);
219
220 if(!tmp) {
221 if (net_ratelimit())
222 printk(KERN_ERR "layer7: out of memory in "
223 "proto_cache add, bailing.\n");
224 return NULL;
225 }
226
227 tmp->proto_string = kmalloc(strlen(protocol) + 1 , GFP_ATOMIC);
228 tmp->next = NULL;
229
230 if(!tmp->proto_string) {
231 if (net_ratelimit())
232 printk(KERN_ERR "layer7: out of memory in "
233 "proto_cache add, bailing.\n");
234 kfree(tmp->proto_string);
235 kfree(tmp);
236 return NULL;
237 }
238
239 /* Ok. The new node is all ready now. */
240 node = tmp;
241
242 if(first_proto_cache == NULL) /* list is empty */
243 first_proto_cache = node; /* make node the beginning */
244 else
245 last_proto_cache->next = node; /* attach node to the end */
246
247 strcpy(node->proto_string, protocol);
248 return node->proto_string;
249 }
250
251 static int can_handle(const struct sk_buff *skb)
252 {
253 if(!ip_hdr(skb)) /* not IP */
254 return 0;
255 if(ip_hdr(skb)->protocol != IPPROTO_TCP &&
256 ip_hdr(skb)->protocol != IPPROTO_UDP &&
257 ip_hdr(skb)->protocol != IPPROTO_ICMP)
258 return 0;
259 return 1;
260 }
261
262 /* Returns offset the into the skb->data that the application data starts */
263 static int app_data_offset(const struct sk_buff *skb)
264 {
265 /* In case we are ported somewhere (ebtables?) where ip_hdr(skb)
266 isn't set, this can be gotten from 4*(skb->data[0] & 0x0f) as well. */
267 int ip_hl = 4*ip_hdr(skb)->ihl;
268
269 if( ip_hdr(skb)->protocol == IPPROTO_TCP ) {
270 /* 12 == offset into TCP header for the header length field.
271 Can't get this with skb->h.th->doff because the tcphdr
272 struct doesn't get set when routing (this is confirmed to be
273 true in Netfilter as well as QoS.) */
274 int tcp_hl = 4*(skb->data[ip_hl + 12] >> 4);
275
276 return ip_hl + tcp_hl;
277 } else if( ip_hdr(skb)->protocol == IPPROTO_UDP ) {
278 return ip_hl + 8; /* UDP header is always 8 bytes */
279 } else if( ip_hdr(skb)->protocol == IPPROTO_ICMP ) {
280 return ip_hl + 8; /* ICMP header is 8 bytes */
281 } else {
282 if (net_ratelimit())
283 printk(KERN_ERR "layer7: tried to handle unknown "
284 "protocol!\n");
285 return ip_hl + 8; /* something reasonable */
286 }
287 }
288
289 /* handles whether there's a match when we aren't appending data anymore */
290 static int match_no_append(struct nf_conn * conntrack,
291 struct nf_conn * master_conntrack,
292 enum ip_conntrack_info ctinfo,
293 enum ip_conntrack_info master_ctinfo,
294 const struct xt_layer7_info * info)
295 {
296 /* If we're in here, throw the app data away */
297 if(master_conntrack->layer7.app_data != NULL) {
298
299 #ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG
300 if(!master_conntrack->layer7.app_proto) {
301 char * f =
302 friendly_print(master_conntrack->layer7.app_data);
303 char * g =
304 hex_print(master_conntrack->layer7.app_data);
305 DPRINTK("\nl7-filter gave up after %d bytes "
306 "(%d packets):\n%s\n",
307 strlen(f), master_conntrack->layer7.packets, f);
308 kfree(f);
309 DPRINTK("In hex: %s\n", g);
310 kfree(g);
311 }
312 #endif
313
314 kfree(master_conntrack->layer7.app_data);
315 master_conntrack->layer7.app_data = NULL; /* don't free again */
316 }
317
318 if(master_conntrack->layer7.app_proto){
319 /* Here child connections set their .app_proto (for /proc) */
320 if(!conntrack->layer7.app_proto) {
321 conntrack->layer7.app_proto = master_conntrack->layer7.app_proto;
322 }
323
324 return (!strcmp(master_conntrack->layer7.app_proto,
325 info->protocol));
326 }
327 else {
328 /* If not classified, set to "unknown" to distinguish from
329 connections that are still being tested. */
330 master_conntrack->layer7.app_proto = get_protostr_ptr("unknown");
331 return 0;
332 }
333 }
334
335 /* add the new app data to the conntrack. Return number of bytes added. */
336 static int add_data(struct nf_conn * master_conntrack,
337 char * app_data, int appdatalen)
338 {
339 int length = 0, i;
340 int oldlength = master_conntrack->layer7.app_data_len;
341
342 /* This is a fix for a race condition by Deti Fliegl. However, I'm not
343 clear on whether the race condition exists or whether this really
344 fixes it. I might just be being dense... Anyway, if it's not really
345 a fix, all it does is waste a very small amount of time. */
346 if(!master_conntrack->layer7.app_data) return 0;
347
348 /* Strip nulls. Make everything lower case (our regex lib doesn't
349 do case insensitivity). Add it to the end of the current data. */
350 for(i = 0; i < maxdatalen-oldlength-1 &&
351 i < appdatalen; i++) {
352 if(app_data[i] != '\0') {
353 /* the kernel version of tolower mungs 'upper ascii' */
354 master_conntrack->layer7.app_data[length+oldlength] =
355 isascii(app_data[i])?
356 tolower(app_data[i]) : app_data[i];
357 length++;
358 }
359 }
360
361 master_conntrack->layer7.app_data[length+oldlength] = '\0';
362 master_conntrack->layer7.app_data_len = length + oldlength;
363
364 return length;
365 }
366
367 /* taken from drivers/video/modedb.c */
368 static int my_atoi(const char *s)
369 {
370 int val = 0;
371
372 for (;; s++) {
373 switch (*s) {
374 case '0'...'9':
375 val = 10*val+(*s-'0');
376 break;
377 default:
378 return val;
379 }
380 }
381 }
382
383 static int layer7_numpackets_proc_show(struct seq_file *s, void *p) {
384 seq_printf(s, "%d\n", num_packets);
385
386 return 0;
387 }
388
389 static int layer7_numpackets_proc_open(struct inode *inode, struct file *file) {
390 return single_open(file, layer7_numpackets_proc_show, NULL);
391 }
392
393 /* Read in num_packets from userland */
394 static ssize_t layer7_numpackets_write_proc(struct file* file, const char __user *buffer,
395 size_t count, loff_t *data) {
396 char value[1024];
397 int new_num_packets;
398
399 if (copy_from_user(&value, buffer, sizeof(value)))
400 return -EFAULT;
401
402 new_num_packets = my_atoi(value);
403
404 if ((new_num_packets < 1) || (new_num_packets > 99)) {
405 printk(KERN_WARNING "layer7: numpackets must be between 1 and 99\n");
406 return -EFAULT;
407 }
408
409 num_packets = new_num_packets;
410
411 return count;
412 }
413
414 static bool
415 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
416 match(const struct sk_buff *skbin, struct xt_action_param *par)
417 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
418 match(const struct sk_buff *skbin, const struct xt_match_param *par)
419 #else
420 match(const struct sk_buff *skbin,
421 const struct net_device *in,
422 const struct net_device *out,
423 const struct xt_match *match,
424 const void *matchinfo,
425 int offset,
426 unsigned int protoff,
427 bool *hotdrop)
428 #endif
429 {
430 /* sidestep const without getting a compiler warning... */
431 struct sk_buff * skb = (struct sk_buff *)skbin;
432
433 const struct xt_layer7_info * info =
434 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
435 par->matchinfo;
436 #else
437 matchinfo;
438 #endif
439
440 enum ip_conntrack_info master_ctinfo, ctinfo;
441 struct nf_conn *master_conntrack, *conntrack;
442 unsigned char * app_data;
443 unsigned int pattern_result, appdatalen;
444 regexp * comppattern;
445
446 /* Be paranoid/incompetent - lock the entire match function. */
447 spin_lock_bh(&l7_lock);
448
449 if(!can_handle(skb)){
450 DPRINTK("layer7: This is some protocol I can't handle.\n");
451 spin_unlock_bh(&l7_lock);
452 return info->invert;
453 }
454
455 /* Treat parent & all its children together as one connection, except
456 for the purpose of setting conntrack->layer7.app_proto in the actual
457 connection. This makes /proc/net/ip_conntrack more satisfying. */
458 if(!(conntrack = nf_ct_get(skb, &ctinfo)) ||
459 !(master_conntrack=nf_ct_get(skb,&master_ctinfo))){
460 DPRINTK("layer7: couldn't get conntrack.\n");
461 spin_unlock_bh(&l7_lock);
462 return info->invert;
463 }
464
465 /* Try to get a master conntrack (and its master etc) for FTP, etc. */
466 while (master_ct(master_conntrack) != NULL)
467 master_conntrack = master_ct(master_conntrack);
468
469 /* free unused conntrack data if different master conntrack exists */
470 if (master_conntrack != conntrack) {
471 if (conntrack->layer7.app_data) {
472 DPRINTK("layer7: free unused conntrack memory.\n");
473 kfree(conntrack->layer7.app_data);
474 conntrack->layer7.app_data = NULL; /* don't free again */
475 }
476 }
477
478 /* if we've classified it or seen too many packets */
479 if( master_conntrack->layer7.packets >= num_packets ||
480 master_conntrack->layer7.app_proto) {
481
482 pattern_result = match_no_append(conntrack, master_conntrack,
483 ctinfo, master_ctinfo, info);
484
485 skb->layer7_flags[0] = 1; /* marking it seen here's probably irrelevant */
486
487 spin_unlock_bh(&l7_lock);
488 return (pattern_result ^ info->invert);
489 }
490
491 if(skb_is_nonlinear(skb)){
492 if(skb_linearize(skb) != 0){
493 if (net_ratelimit())
494 printk(KERN_ERR "layer7: failed to linearize "
495 "packet, bailing.\n");
496 spin_unlock_bh(&l7_lock);
497 return info->invert;
498 }
499 }
500
501 /* now that the skb is linearized, it's safe to set these. */
502 app_data = skb->data + app_data_offset(skb);
503 appdatalen = skb_tail_pointer(skb) - app_data;
504
505 /* the return value gets checked later, when we're ready to use it */
506 comppattern = compile_and_cache(info->pattern, info->protocol);
507
508 /* allocate space for app data if not done */
509 if(master_conntrack->packets < num_packets &&
510 !master_conntrack->layer7.app_data){
511 master_conntrack->layer7.app_data =
512 kmalloc(maxdatalen, GFP_ATOMIC);
513 if(!master_conntrack->layer7.app_data){
514 if (net_ratelimit())
515 printk(KERN_ERR "layer7: out of memory in "
516 "match, bailing.\n");
517 spin_unlock_bh(&l7_lock);
518 return info->invert;
519 }
520
521 master_conntrack->layer7.app_data[0] = '\0';
522 }
523
524 if(!skb->layer7_flags[0]){
525 int newbytes;
526 master_conntrack->layer7.packets++;
527 newbytes = add_data(master_conntrack, app_data, appdatalen);
528 if(newbytes == 0) { /* didn't add any data */
529 skb->layer7_flags[0] = 1;
530 /* Didn't match before, not going to match now */
531 spin_unlock_bh(&l7_lock);
532 return info->invert;
533 }
534 }
535
536 /* If looking for "unknown", then never match. "Unknown" means that
537 we've given up; we're still trying with these packets. */
538 if(!strcmp(info->protocol, "unknown")) {
539 pattern_result = 0;
540 /* If looking for "unset", then always match. "Unset" means that we
541 haven't yet classified the connection. */
542 } else if(!strcmp(info->protocol, "unset")) {
543 pattern_result = 2;
544 DPRINTK("layer7: matched unset: not yet classified "
545 "(%d/%d packets)\n",
546 master_conntrack->layer7.packets, num_packets);
547 /* If the regexp failed to compile, don't bother running it */
548 } else if(comppattern &&
549 regexec(comppattern, master_conntrack->layer7.app_data)){
550 DPRINTK("layer7: matched %s\n", info->protocol);
551 pattern_result = 1;
552 } else pattern_result = 0;
553
554 if(pattern_result == 1) {
555 master_conntrack->layer7.app_proto=get_protostr_ptr(info->protocol);
556 } else if(pattern_result > 1) { /* cleanup from "unset" */
557 pattern_result = 1;
558 }
559
560 /* mark the packet seen */
561 skb->layer7_flags[0] = 1;
562
563 spin_unlock_bh(&l7_lock);
564 return (pattern_result ^ info->invert);
565 }
566
567 // load nf_conntrack_ipv4
568 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
569 static int
570 #else
571 static bool
572 #endif
573 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
574 check(const struct xt_mtchk_param *par)
575 {
576 if (nf_ct_l3proto_try_module_get(par->match->family) < 0) {
577 printk(KERN_WARNING "can't load conntrack support for "
578 "proto=%d\n", par->match->family);
579 #else
580 check(const char *tablename, const void *inf,
581 const struct xt_match *match, void *matchinfo,
582 unsigned int hook_mask)
583 {
584 if (nf_ct_l3proto_try_module_get(match->family) < 0) {
585 printk(KERN_WARNING "can't load conntrack support for "
586 "proto=%d\n", match->family);
587 #endif
588 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
589 return -EINVAL;
590 }
591 return 0;
592 #else
593 return 0;
594 }
595 return 1;
596 #endif
597 }
598
599
600 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
601 static void destroy(const struct xt_mtdtor_param *par)
602 {
603 nf_ct_l3proto_module_put(par->match->family);
604 }
605 #else
606 static void destroy(const struct xt_match *match, void *matchinfo)
607 {
608 nf_ct_l3proto_module_put(match->family);
609 }
610 #endif
611
612 static struct xt_match xt_layer7_match[] __read_mostly = {
613 {
614 .name = "layer7",
615 .family = NFPROTO_IPV4,
616 .checkentry = check,
617 .match = match,
618 .destroy = destroy,
619 .matchsize = sizeof(struct xt_layer7_info),
620 .me = THIS_MODULE
621 }
622 };
623
624 static const struct file_operations layer7_numpackets_proc_fops = {
625 .owner = THIS_MODULE,
626 .open = layer7_numpackets_proc_open,
627 .read = seq_read,
628 .llseek = seq_lseek,
629 .release = single_release,
630 .write = layer7_numpackets_write_proc,
631 };
632
633 static int __init xt_layer7_init(void)
634 {
635 need_conntrack();
636
637 // Register proc interface
638 proc_create_data("layer7_numpackets", 0644,
639 init_net.proc_net, &layer7_numpackets_proc_fops, NULL);
640
641 if(maxdatalen < 1) {
642 printk(KERN_WARNING "layer7: maxdatalen can't be < 1, "
643 "using 1\n");
644 maxdatalen = 1;
645 }
646 /* This is not a hard limit. It's just here to prevent people from
647 bringing their slow machines to a grinding halt. */
648 else if(maxdatalen > 65536) {
649 printk(KERN_WARNING "layer7: maxdatalen can't be > 65536, "
650 "using 65536\n");
651 maxdatalen = 65536;
652 }
653 return xt_register_matches(xt_layer7_match,
654 ARRAY_SIZE(xt_layer7_match));
655 }
656
657 static void __exit xt_layer7_fini(void)
658 {
659 remove_proc_entry("layer7_numpackets", init_net.proc_net);
660 xt_unregister_matches(xt_layer7_match, ARRAY_SIZE(xt_layer7_match));
661 }
662
663 module_init(xt_layer7_init);
664 module_exit(xt_layer7_fini);
665