]> git.pld-linux.org Git - packages/kernel.git/blob - 2.6.1-rc1-NF-osf-20040105.patch
- added description of djurban's branch
[packages/kernel.git] / 2.6.1-rc1-NF-osf-20040105.patch
1 diff -Nur linux-2.6.1-rc1.org/include/linux/netfilter_ipv4/ipt_osf.h linux-2.6.1-rc1/include/linux/netfilter_ipv4/ipt_osf.h
2 --- linux-2.6.1-rc1.org/include/linux/netfilter_ipv4/ipt_osf.h  1970-01-01 01:00:00.000000000 +0100
3 +++ linux-2.6.1-rc1/include/linux/netfilter_ipv4/ipt_osf.h      2004-01-05 12:41:36.000000000 +0100
4 @@ -0,0 +1,130 @@
5 +/*
6 + * ipt_osf.h
7 + *
8 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
9 + *
10 + *
11 + * This program is free software; you can redistribute it and/or modify
12 + * it under the terms of the GNU General Public License as published by
13 + * the Free Software Foundation; either version 2 of the License, or
14 + * (at your option) any later version.
15 + *
16 + * This program is distributed in the hope that it will be useful,
17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 + * GNU General Public License for more details.
20 + *
21 + * You should have received a copy of the GNU General Public License
22 + * along with this program; if not, write to the Free Software
23 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 + */
25 +
26 +#ifndef _IPT_OSF_H
27 +#define _IPT_OSF_H
28 +
29 +#define MAXGENRELEN            32
30 +#define MAXDETLEN              64
31 +
32 +#define IPT_OSF_GENRE          1
33 +#define IPT_OSF_SMART          2
34 +#define IPT_OSF_LOG            4
35 +
36 +#define IPT_OSF_LOGLEVEL_ALL           0
37 +#define IPT_OSF_LOGLEVEL_FIRST 1
38 +
39 +#include <linux/list.h>
40 +
41 +struct ipt_osf_info
42 +{
43 +       char                    genre[MAXGENRELEN];
44 +       int                     len;
45 +       unsigned long           flags;
46 +       int                     loglevel;
47 +       int                     invert; /* UNSUPPORTED */
48 +};
49 +
50 +struct osf_wc
51 +{
52 +       char                    wc;
53 +       unsigned long           val;
54 +};
55 +
56 +/* This struct represents IANA options
57 + * http://www.iana.org/assignments/tcp-parameters
58 + */
59 +struct osf_opt
60 +{
61 +       unsigned char           kind;
62 +       unsigned char           length;
63 +       struct osf_wc           wc;
64 +};
65 +
66 +#ifdef __KERNEL__
67 +
68 +struct osf_finger
69 +{
70 +       struct list_head        flist;
71 +       struct osf_wc           wss;
72 +       unsigned char           ttl;
73 +       unsigned char           df;
74 +       unsigned long           ss;
75 +       char                    genre[MAXGENRELEN];
76 +       char                    version[MAXGENRELEN], subtype[MAXGENRELEN];
77 +       
78 +       /* Not needed, but for consistency with original table from Michal Zalewski */
79 +       char                    details[MAXDETLEN]; 
80 +
81 +       int                     opt_num;
82 +       struct osf_opt          opt[MAX_IPOPTLEN]; /* In case it is all NOP or EOL */
83 +
84 +};
85 +
86 +/* Defines for IANA option kinds */
87 +
88 +#define OSFOPT_EOL             0       /* End of options */
89 +#define OSFOPT_NOP             1       /* NOP */
90 +#define OSFOPT_MSS             2       /* Maximum segment size */
91 +#define OSFOPT_WSO             3       /* Window scale option */
92 +#define OSFOPT_SACKP           4       /* SACK permitted */
93 +#define OSFOPT_SACK            5       /* SACK */
94 +#define OSFOPT_ECHO            6       
95 +#define OSFOPT_ECHOREPLY       7
96 +#define OSFOPT_TS              8       /* Timestamp option */
97 +#define OSFOPT_POCP            9       /* Partial Order Connection Permitted */
98 +#define OSFOPT_POSP            10      /* Partial Order Service Profile */
99 +/* Others are not used in current OSF */
100 +
101 +static struct osf_opt IANA_opts[] = 
102 +{
103 +       {0, 1,},
104 +       {1, 1,},
105 +       {2, 4,},
106 +       {3, 3,},
107 +       {4, 2,},
108 +       {5, 1 ,}, /* SACK length is not defined */
109 +       {6, 6,},
110 +       {7, 6,},
111 +       {8, 10,},
112 +       {9, 2,},
113 +       {10, 3,},
114 +       {11, 1,}, /* CC: Suppose 1 */
115 +       {12, 1,}, /* the same */
116 +       {13, 1,}, /* and here too */
117 +       {14, 3,},
118 +       {15, 1,}, /* TCP Alternate Checksum Data. Length is not defined */
119 +       {16, 1,},
120 +       {17, 1,},
121 +       {18, 3,},
122 +       {19, 18,},
123 +       {20, 1,},
124 +       {21, 1,},
125 +       {22, 1,},
126 +       {23, 1,},
127 +       {24, 1,},
128 +       {25, 1,},
129 +       {26, 1,},
130 +};
131 +
132 +#endif /* __KERNEL__ */
133 +
134 +#endif /* _IPT_OSF_H */
135 diff -Nur linux-2.6.1-rc1.org/net/ipv4/netfilter/Kconfig linux-2.6.1-rc1/net/ipv4/netfilter/Kconfig
136 --- linux-2.6.1-rc1.org/net/ipv4/netfilter/Kconfig      2004-01-05 12:31:23.000000000 +0100
137 +++ linux-2.6.1-rc1/net/ipv4/netfilter/Kconfig  2004-01-05 12:41:36.000000000 +0100
138 @@ -609,5 +609,54 @@
139           lengths.
140           Details and examples are in the kernel module source.
141  
142 +config IP_NF_MATCH_OSF
143 +       tristate  'OSF match support'
144 +       depends on IP_NF_IPTABLES
145 +         help
146 +         The idea of passive OS fingerprint matching exists for quite a long time,
147 +         but was created as extension fo OpenBSD pf only some weeks ago.
148 +         Original idea was lurked in some OpenBSD mailing list (thanks
149 +         grange@open...) and than adopted for Linux netfilter in form of this code.
150 +         
151 +         Original table was created by Michal Zalewski <lcamtuf@coredump.cx> for
152 +         his excellent p0f and than changed a bit for more convenience.
153 +         
154 +         This module compares some data(WS, MSS, options and it's order, ttl,
155 +         df and others) from first SYN packet (actually from packets with SYN
156 +         bit set) with hardcoded in fingers[] table ones.
157 +         
158 +         Example: (Of course this only an example, do not get inspired by this)
159 +         
160 +         # iptables -N LINUX
161 +         # iptables -A LINUX -j LOG --log-prefix "Linux"
162 +         
163 +         # iptables -A INPUT -p tcp -m osf --genre Linux -j LINUX
164 +         # iptables -A INPUT -p tcp -m osf --genre FreeBSD -j REJECT
165 +         
166 +         NOTE: -p tcp is obviously required as it is a TCP match.
167 +         
168 +         OSF also has:
169 +         --log 1/0. 
170 +               If present, OSF will log determined genres even if they don't match
171 +               desired one.    
172 +               0 - log all determined entries, 
173 +               1 - only first one.
174 +               
175 +               Example:
176 +               #iptables -I INPUT -j ACCEPT -p tcp -m osf --genre Linux --log 1 --smart
177 +         
178 +               In syslog you find something like this:
179 +               ipt_osf: Windows [Windows XP Pro SP1, 2000 SP3]: 11.22.33.55:4024 -> 11.22.33.44:139
180 +               ipt_osf: Unknown: 16384:106:1:48:020405B401010402 44.33.22.11:1239 -> 11.22.33.44:80
181 +         
182 +           --smart
183 +               if present, OSF will use some smartness to determine remote OS.
184 +               Now only not use TTL( with it far remote machines can be determined).
185 +         
186 +         Fingerprints can be loaded through /proc/sys/net/ipv4/osf file.
187 +         Only one fingerprint per open/close.
188 +         
189 +         Fingerprints can be downloaded from http://www.openbsd.org/cgi-bin/cvsweb/src/etc/pf.os
190 +
191  endmenu
192  
193 diff -Nur linux-2.6.1-rc1.org/net/ipv4/netfilter/Makefile linux-2.6.1-rc1/net/ipv4/netfilter/Makefile
194 --- linux-2.6.1-rc1.org/net/ipv4/netfilter/Makefile     2004-01-05 12:31:23.000000000 +0100
195 +++ linux-2.6.1-rc1/net/ipv4/netfilter/Makefile 2004-01-05 12:41:36.000000000 +0100
196 @@ -51,6 +51,9 @@
197  obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
198  obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
199  
200 +obj-$(CONFIG_IP_NF_MATCH_OSF) += ipt_osf.o
201 +
202 +
203  obj-$(CONFIG_IP_NF_MATCH_TIME) += ipt_time.o
204  
205  
206 diff -Nur linux-2.6.1-rc1.org/net/ipv4/netfilter/ipt_osf.c linux-2.6.1-rc1/net/ipv4/netfilter/ipt_osf.c
207 --- linux-2.6.1-rc1.org/net/ipv4/netfilter/ipt_osf.c    1970-01-01 01:00:00.000000000 +0100
208 +++ linux-2.6.1-rc1/net/ipv4/netfilter/ipt_osf.c        2004-01-05 12:41:36.000000000 +0100
209 @@ -0,0 +1,733 @@
210 +/*
211 + * ipt_osf.c
212 + *
213 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
214 + *
215 + *
216 + * This program is free software; you can redistribute it and/or modify
217 + * it under the terms of the GNU General Public License as published by
218 + * the Free Software Foundation; either version 2 of the License, or
219 + * (at your option) any later version.
220 + *
221 + * This program is distributed in the hope that it will be useful,
222 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
223 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
224 + * GNU General Public License for more details.
225 + *
226 + * You should have received a copy of the GNU General Public License
227 + * along with this program; if not, write to the Free Software
228 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
229 + */
230 +
231 +/*
232 + * OS fingerprint matching module.
233 + * It simply compares various parameters from SYN packet with
234 + * some hardcoded ones.
235 + *
236 + * Original table was created by Michal Zalewski <lcamtuf@coredump.cx>
237 + * for his p0f.
238 + */
239 +
240 +#include <linux/config.h>
241 +#include <linux/kernel.h>
242 +#include <linux/smp.h>
243 +#include <linux/module.h>
244 +#include <linux/skbuff.h>
245 +#include <linux/file.h>
246 +#include <linux/ip.h>
247 +#include <linux/proc_fs.h>
248 +#include <linux/fs.h>
249 +#include <linux/slab.h>
250 +#include <linux/spinlock.h>
251 +#include <linux/ctype.h>
252 +#include <linux/list.h>
253 +
254 +#include <net/sock.h>
255 +#include <net/ip.h>
256 +
257 +#include <linux/netfilter_ipv4/ip_tables.h>
258 +
259 +#include <linux/netfilter_ipv4/ipt_osf.h>
260 +
261 +#define OSF_DEBUG
262 +
263 +#ifdef OSF_DEBUG
264 +#define log(x...)              printk(KERN_INFO "ipt_osf: " x)
265 +#define loga(x...)             printk(x)
266 +#else
267 +#define log(x...)              do {} while(0)
268 +#define loga(x...)             do {} while(0)
269 +#endif
270 +
271 +#define FMATCH_WRONG           0
272 +#define FMATCH_OK              1
273 +#define FMATCH_OPT_WRONG       2
274 +
275 +#define OPTDEL                 ','
276 +#define OSFPDEL                ':'
277 +#define MAXOPTSTRLEN           128
278 +#define OSFFLUSH               "FLUSH"
279 +
280 +static rwlock_t osf_lock = RW_LOCK_UNLOCKED;
281 +static struct list_head        finger_list;    
282 +
283 +static int match(const struct sk_buff *, const struct net_device *, const struct net_device *,
284 +                     const void *, int, const void *, u_int16_t, int *);
285 +static int checkentry(const char *, const struct ipt_ip *, void *,
286 +                          unsigned int, unsigned int);
287 +
288 +static struct ipt_match osf_match = 
289 +{ 
290 +       { NULL, NULL }, 
291 +       "osf", 
292 +       &match, 
293 +       &checkentry, 
294 +       NULL, 
295 +       THIS_MODULE 
296 +};
297 +
298 +static inline int smart_dec(unsigned long flags, unsigned char ip_ttl, unsigned char f_ttl)
299 +{
300 +       if (flags & IPT_OSF_SMART)
301 +               return 1;
302 +       else
303 +               return (ip_ttl == f_ttl);
304 +}
305 +
306 +static int
307 +match(const struct sk_buff *skb,
308 +      const struct net_device *in,
309 +      const struct net_device *out,
310 +      const void *matchinfo,
311 +      int offset,
312 +      const void *hdr,
313 +      u_int16_t datalen,
314 +      int *hotdrop)
315 +{
316 +       struct ipt_osf_info *info = (struct ipt_osf_info *)matchinfo;
317 +       struct iphdr *ip = skb->nh.iph;
318 +       struct tcphdr *tcp;
319 +       int fmatch = FMATCH_WRONG, fcount = 0;
320 +       unsigned long totlen, optsize = 0, window;
321 +       unsigned char df, *optp = NULL, *_optp = NULL;
322 +       char check_WSS = 0;
323 +       struct list_head *ent;
324 +       struct osf_finger *f;
325 +
326 +       if (!ip || !info)
327 +               return 0;
328 +                               
329 +       tcp = (struct tcphdr *)((u_int32_t *)ip + ip->ihl);
330 +
331 +       if (!tcp->syn)
332 +               return 0;
333 +       else if (tcp->ack)
334 +               return 0;
335 +       
336 +       totlen = ntohs(ip->tot_len);
337 +       df = ((ntohs(ip->frag_off) & IP_DF)?1:0);
338 +       window = ntohs(tcp->window);
339 +       
340 +       if (tcp->doff*4 > sizeof(struct tcphdr))
341 +       {
342 +               _optp = optp = (char *)(tcp+1);
343 +               optsize = tcp->doff*4 - sizeof(struct tcphdr);
344 +       }
345 +
346 +       
347 +       /* Actually we can create hash/table of all genres and search
348 +        * only in appropriate part, but here is initial variant,
349 +        * so will use slow path.
350 +        */
351 +       read_lock(&osf_lock);
352 +       list_for_each(ent, &finger_list)
353 +       {
354 +               f = list_entry(ent, struct osf_finger, flist);
355 +       
356 +               if (!(info->flags & IPT_OSF_LOG) && strcmp(info->genre, f->genre)) 
357 +                       continue;
358 +
359 +               optp = _optp;
360 +               fmatch = FMATCH_WRONG;
361 +
362 +               if (totlen == f->ss && df == f->df && 
363 +                       smart_dec(info->flags, ip->ttl, f->ttl))
364 +               {
365 +                       unsigned long foptsize;
366 +                       int optnum;
367 +                       unsigned short mss = 0;
368 +
369 +                       check_WSS = 0;
370 +
371 +                       switch (f->wss.wc)
372 +                       {
373 +                               case 0:   check_WSS = 0; break;
374 +                               case 'S': check_WSS = 1; break;
375 +                               case 'T': check_WSS = 2; break;
376 +                               case '%': check_WSS = 3; break;
377 +                               default: log("Wrong fingerprint wss.wc=%d, %s - %s\n", 
378 +                                                        f->wss.wc, f->genre, f->details);
379 +                                        check_WSS = 4;
380 +                                        break;
381 +                       }
382 +                       if (check_WSS == 4)
383 +                               continue;
384 +
385 +                       /* Check options */
386 +
387 +                       foptsize = 0;
388 +                       for (optnum=0; optnum<f->opt_num; ++optnum)
389 +                               foptsize += f->opt[optnum].length;
390 +
391 +                               
392 +                       if (foptsize > MAX_IPOPTLEN || optsize > MAX_IPOPTLEN || optsize != foptsize)
393 +                               continue;
394 +
395 +                       if (!optp)
396 +                       {
397 +                               fmatch = FMATCH_OK;
398 +                               loga("\tYEP : matching without options.\n");
399 +                               if ((info->flags & IPT_OSF_LOG) && 
400 +                                       info->loglevel == IPT_OSF_LOGLEVEL_FIRST)
401 +                                       break;
402 +                               else
403 +                                       continue;
404 +                       }
405 +                       
406 +
407 +                       for (optnum=0; optnum<f->opt_num; ++optnum)
408 +                       {
409 +                               if (f->opt[optnum].kind == (*optp))
410 +                               {
411 +                                       unsigned char len = f->opt[optnum].length;
412 +                                       unsigned char *optend = optp + len;
413 +
414 +                                       fmatch = FMATCH_OK;
415 +
416 +                                       if (*optp == OSFOPT_MSS) /* MSS */
417 +                                               mss = ntohs(*(unsigned short *)(optp+2));
418 +                                       
419 +                                       if (len != 1)
420 +                                       {
421 +                                               /* Skip kind and length fields*/
422 +                                               optp += 2; 
423 +
424 +                                               if (f->opt[optnum].wc.wc != 0)
425 +                                               {
426 +                                                       unsigned long tmp = 0;
427 +                                                       
428 +                                                       /* Hmmm... It looks a bit ugly. :) */
429 +                                                       memcpy(&tmp, &f->opt[optnum].wc.val, 
430 +                                                               (len > sizeof(unsigned long)?
431 +                                                                       sizeof(unsigned long):len));
432 +
433 +                                                       tmp = ntohl(tmp);
434 +                                                       if (tmp != f->opt[optnum].wc.val)
435 +                                                               fmatch = FMATCH_OPT_WRONG;
436 +                                               }
437 +                                       }
438 +
439 +                                       optp = optend;
440 +                               }
441 +                               else
442 +                                       fmatch = FMATCH_OPT_WRONG;
443 +
444 +                               if (fmatch != FMATCH_OK)
445 +                                       break;
446 +                       }
447 +
448 +                       if (fmatch != FMATCH_OPT_WRONG)
449 +                       {
450 +                               fmatch = FMATCH_WRONG;
451 +
452 +                               switch (check_WSS)
453 +                               {
454 +                                       case 0:
455 +                                               if (window == f->wss.val)
456 +                                                       fmatch = FMATCH_OK;
457 +                                               break;
458 +                                       case 1: /* MSS */
459 +                                               if (window == f->wss.val*mss)
460 +                                                       fmatch = FMATCH_OK;
461 +                                               break;
462 +                                       case 2: /* MTU */
463 +                                               if (window == f->wss.val*(mss+40))
464 +                                                       fmatch = FMATCH_OK;
465 +                                               break;
466 +                                       case 3: /* MOD */
467 +                                               if (window % f->wss.val == 0)
468 +                                                       fmatch = FMATCH_OK;
469 +                                               break;
470 +                               }
471 +                       }
472 +                                       
473 +
474 +                       if (fmatch == FMATCH_OK)
475 +                       {
476 +                               fcount++;
477 +                               log("%s [%s]: %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u\n", 
478 +                                       f->genre, f->details,
479 +                                       NIPQUAD(ip->saddr), ntohs(tcp->source),
480 +                                       NIPQUAD(ip->daddr), ntohs(tcp->dest));
481 +                               if ((info->flags & IPT_OSF_LOG) && 
482 +                                       info->loglevel == IPT_OSF_LOGLEVEL_FIRST)
483 +                                       break;
484 +                       }
485 +               }
486 +       }
487 +       if (!fcount && (info->flags & IPT_OSF_LOG))
488 +       {
489 +               log("Unknown: %lu:%d:%d:%lu:", window, ip->ttl, df, totlen);
490 +               if (optp)
491 +               {
492 +                       unsigned char opt[4 * 15 - sizeof(struct tcphdr)];
493 +                       unsigned int i, optsize;
494 +
495 +                       optsize = tcp->doff * 4 - sizeof(struct tcphdr);
496 +                       if (skb_copy_bits(skb, ip->ihl*4 + sizeof(struct tcphdr),
497 +                                         opt, optsize) < 0)
498 +                               loga("TRUNCATED");
499 +                       else
500 +                               for (i = 0; i < optsize; i++)
501 +                                       loga("%02X", opt[i]);
502 +                       
503 +               }  
504 +               loga(" %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u\n", 
505 +                       NIPQUAD(ip->saddr), ntohs(tcp->source),
506 +                       NIPQUAD(ip->daddr), ntohs(tcp->dest));
507 +       }
508 +       read_unlock(&osf_lock);
509 +
510 +       return (fmatch == FMATCH_OK)?1:0;
511 +}
512 +
513 +static int
514 +checkentry(const char *tablename,
515 +           const struct ipt_ip *ip,
516 +           void *matchinfo,
517 +           unsigned int matchsize,
518 +           unsigned int hook_mask)
519 +{
520 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_osf_info)))
521 +               return 0;
522 +       if (ip->proto != IPPROTO_TCP)
523 +              return 0;
524 +
525 +       return 1;
526 +}
527 +
528 +static char * osf_strchr(char *ptr, char c)
529 +{
530 +       char *tmp;
531 +
532 +       tmp = strchr(ptr, c);
533 +
534 +       while (tmp && tmp+1 && isspace(*(tmp+1)))
535 +               tmp++;
536 +
537 +       return tmp;
538 +}
539 +
540 +static struct osf_finger * finger_alloc(void)
541 +{
542 +       struct osf_finger *f;
543 +
544 +       f = kmalloc(sizeof(struct osf_finger), GFP_KERNEL);
545 +       if (f)
546 +               memset(f, 0, sizeof(struct osf_finger));
547 +       
548 +       return f;
549 +}
550 +
551 +static void finger_free(struct osf_finger *f)
552 +{
553 +       memset(f, 0, sizeof(struct osf_finger));
554 +       kfree(f);
555 +}
556 +
557 +
558 +static void osf_parse_opt(struct osf_opt *opt, int *optnum, char *obuf, int olen)
559 +{
560 +       int i, op;
561 +       char *ptr, wc;
562 +       unsigned long val;
563 +
564 +       ptr = &obuf[0];
565 +       i = 0;
566 +       while (ptr != NULL && i < olen)
567 +       {
568 +               val = 0;
569 +               op = 0;
570 +               wc = 0;
571 +               switch (obuf[i])
572 +               {
573 +                       case 'N': 
574 +                               op = OSFOPT_NOP;
575 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
576 +                               if (ptr)
577 +                               {
578 +                                       *ptr = '\0';
579 +                                       ptr++;
580 +                                       i += (int)(ptr-&obuf[i]);
581 +
582 +                               }
583 +                               else
584 +                                       i++;
585 +                               break;
586 +                       case 'S': 
587 +                               op = OSFOPT_SACKP;
588 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
589 +                               if (ptr)
590 +                               {
591 +                                       *ptr = '\0';
592 +                                       ptr++;
593 +                                       i += (int)(ptr-&obuf[i]);
594 +
595 +                               }
596 +                               else
597 +                                       i++;
598 +                               break;
599 +                       case 'T': 
600 +                               op = OSFOPT_TS;
601 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
602 +                               if (ptr)
603 +                               {
604 +                                       *ptr = '\0';
605 +                                       ptr++;
606 +                                       i += (int)(ptr-&obuf[i]);
607 +
608 +                               }
609 +                               else
610 +                                       i++;
611 +                               break;
612 +                       case 'W': 
613 +                               op = OSFOPT_WSO;
614 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
615 +                               if (ptr)
616 +                               {
617 +                                       switch (obuf[i+1])
618 +                                       {
619 +                                               case '%':       wc = '%'; break;
620 +                                               case 'S':       wc = 'S'; break;
621 +                                               case 'T':       wc = 'T'; break;
622 +                                               default:        wc = 0; break;
623 +                                       }
624 +                                       
625 +                                       *ptr = '\0';
626 +                                       ptr++;
627 +                                       if (wc)
628 +                                               val = simple_strtoul(&obuf[i+2], NULL, 10);
629 +                                       else
630 +                                               val = simple_strtoul(&obuf[i+1], NULL, 10);
631 +                                       i += (int)(ptr-&obuf[i]);
632 +
633 +                               }
634 +                               else
635 +                                       i++;
636 +                               break;
637 +                       case 'M': 
638 +                               op = OSFOPT_MSS;
639 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
640 +                               if (ptr)
641 +                               {
642 +                                       if (obuf[i+1] == '%')
643 +                                               wc = '%';
644 +                                       *ptr = '\0';
645 +                                       ptr++;
646 +                                       if (wc)
647 +                                               val = simple_strtoul(&obuf[i+2], NULL, 10);
648 +                                       else
649 +                                               val = simple_strtoul(&obuf[i+1], NULL, 10);
650 +                                       i += (int)(ptr-&obuf[i]);
651 +
652 +                               }
653 +                               else
654 +                                       i++;
655 +                               break;
656 +                       case 'E': 
657 +                               op = OSFOPT_EOL;
658 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
659 +                               if (ptr)
660 +                               {
661 +                                       *ptr = '\0';
662 +                                       ptr++;
663 +                                       i += (int)(ptr-&obuf[i]);
664 +
665 +                               }
666 +                               else
667 +                                       i++;
668 +                               break;
669 +                       default:
670 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
671 +                               if (ptr)
672 +                               {
673 +                                       ptr++;
674 +                                       i += (int)(ptr-&obuf[i]);
675 +
676 +                               }
677 +                               else
678 +                                       i++;
679 +                               break;
680 +               }
681 +
682 +               opt[*optnum].kind       = IANA_opts[op].kind;
683 +               opt[*optnum].length     = IANA_opts[op].length;
684 +               opt[*optnum].wc.wc      = wc;
685 +               opt[*optnum].wc.val     = val;
686 +
687 +               (*optnum)++;
688 +       }
689 +}
690 +
691 +static int osf_proc_read(char *buf, char **start, off_t off, int count, int *eof, void *data)
692 +{
693 +       struct list_head *ent;
694 +       struct osf_finger *f = NULL;
695 +       int i;
696 +       
697 +       *eof = 1;
698 +       count = 0;
699 +
700 +       read_lock_bh(&osf_lock);
701 +       list_for_each(ent, &finger_list)
702 +       {
703 +               f = list_entry(ent, struct osf_finger, flist);
704 +
705 +               log("%s [%s]", f->genre, f->details);
706 +               
707 +               count += sprintf(buf+count, "%s - %s[%s] : %s", 
708 +                                       f->genre, f->version,
709 +                                       f->subtype, f->details);
710 +               
711 +               if (f->opt_num)
712 +               {
713 +                       loga(" OPT: ");
714 +                       //count += sprintf(buf+count, " OPT: ");
715 +                       for (i=0; i<f->opt_num; ++i)
716 +                       {
717 +                               //count += sprintf(buf+count, "%d.%c%lu; ", 
718 +                               //      f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
719 +                               loga("%d.%c%lu; ", 
720 +                                       f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
721 +                       }
722 +               }
723 +               loga("\n");
724 +               count += sprintf(buf+count, "\n");
725 +       }
726 +       read_unlock_bh(&osf_lock);
727 +
728 +       return count;
729 +}
730 +
731 +static int osf_proc_write(struct file *file, const char *buffer, unsigned long count, void *data)
732 +{
733 +       int cnt;
734 +       unsigned long i;
735 +       char obuf[MAXOPTSTRLEN];
736 +       struct osf_finger *finger;
737 +       struct list_head *ent, *n;
738 +
739 +       char *pbeg, *pend;
740 +
741 +       if (count == strlen(OSFFLUSH) && !strncmp(buffer, OSFFLUSH, strlen(OSFFLUSH)))
742 +       {
743 +               int i = 0;
744 +               write_lock_bh(&osf_lock);
745 +               list_for_each_safe(ent, n, &finger_list)
746 +               {
747 +                       i++;
748 +                       finger = list_entry(ent, struct osf_finger, flist);
749 +                       list_del(&finger->flist);
750 +                       finger_free(finger);
751 +               }
752 +               write_unlock_bh(&osf_lock);
753 +       
754 +               log("Flushed %d entries.\n", i);
755 +               
756 +               return count;
757 +       }
758 +
759 +       
760 +       cnt = 0;
761 +       for (i=0; i<count && buffer[i] != '\0'; ++i)
762 +               if (buffer[i] == ':')
763 +                       cnt++;
764 +
765 +       if (cnt != 8 || i != count)
766 +       {
767 +               log("Wrong input line cnt=%d[8], len=%lu[%lu]\n", 
768 +                       cnt, i, count);
769 +               return count;
770 +       }
771 +
772 +       memset(obuf, 0, sizeof(obuf));
773 +       
774 +       finger = finger_alloc();
775 +       if (!finger)
776 +       {
777 +               log("Failed to allocate new fingerprint entry.\n");
778 +               return -ENOMEM;
779 +       }
780 +
781 +       pbeg = (char *)buffer;
782 +       pend = osf_strchr(pbeg, OSFPDEL);
783 +       if (pend)
784 +       {
785 +               *pend = '\0';
786 +               if (pbeg[0] == 'S')
787 +               {
788 +                       finger->wss.wc = 'S';
789 +                       if (pbeg[1] == '%')
790 +                               finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
791 +                       else if (pbeg[1] == '*')
792 +                               finger->wss.val = 0;
793 +                       else 
794 +                               finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
795 +               }
796 +               else if (pbeg[0] == 'T')
797 +               {
798 +                       finger->wss.wc = 'T';
799 +                       if (pbeg[1] == '%')
800 +                               finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
801 +                       else if (pbeg[1] == '*')
802 +                               finger->wss.val = 0;
803 +                       else 
804 +                               finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
805 +               }
806 +               if (isdigit(pbeg[0]))
807 +               {
808 +                       finger->wss.wc = 0;
809 +                       finger->wss.val = simple_strtoul(pbeg, NULL, 10);
810 +               }
811 +
812 +               pbeg = pend+1;
813 +       }
814 +       pend = osf_strchr(pbeg, OSFPDEL);
815 +       if (pend)
816 +       {
817 +               *pend = '\0';
818 +               finger->ttl = simple_strtoul(pbeg, NULL, 10);
819 +               pbeg = pend+1;
820 +       }
821 +       pend = osf_strchr(pbeg, OSFPDEL);
822 +       if (pend)
823 +       {
824 +               *pend = '\0';
825 +               finger->df = simple_strtoul(pbeg, NULL, 10);
826 +               pbeg = pend+1;
827 +       }
828 +       pend = osf_strchr(pbeg, OSFPDEL);
829 +       if (pend)
830 +       {
831 +               *pend = '\0';
832 +               finger->ss = simple_strtoul(pbeg, NULL, 10);
833 +               pbeg = pend+1;
834 +       }
835 +
836 +       pend = osf_strchr(pbeg, OSFPDEL);
837 +       if (pend)
838 +       {
839 +               *pend = '\0';
840 +               cnt = snprintf(obuf, sizeof(obuf), "%s", pbeg);
841 +               pbeg = pend+1;
842 +       }
843 +
844 +       pend = osf_strchr(pbeg, OSFPDEL);
845 +       if (pend)
846 +       {
847 +               *pend = '\0';
848 +               if (pbeg[0] == '@' || pbeg[0] == '*')
849 +                       cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg+1);
850 +               else
851 +                       cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg);
852 +               pbeg = pend+1;
853 +       }
854 +       
855 +       pend = osf_strchr(pbeg, OSFPDEL);
856 +       if (pend)
857 +       {
858 +               *pend = '\0';
859 +               cnt = snprintf(finger->version, sizeof(finger->version), "%s", pbeg);
860 +               pbeg = pend+1;
861 +       }
862 +       
863 +       pend = osf_strchr(pbeg, OSFPDEL);
864 +       if (pend)
865 +       {
866 +               *pend = '\0';
867 +               cnt = snprintf(finger->subtype, sizeof(finger->subtype), "%s", pbeg);
868 +               pbeg = pend+1;
869 +       }
870 +
871 +       cnt = snprintf(finger->details, 
872 +                       ((count - (pbeg - buffer)+1) > MAXDETLEN)?MAXDETLEN:(count - (pbeg - buffer)+1), 
873 +                       "%s", pbeg);
874 +       
875 +       log("%s - %s[%s] : %s\n", 
876 +               finger->genre, finger->version,
877 +               finger->subtype, finger->details);
878 +       
879 +       osf_parse_opt(finger->opt, &finger->opt_num, obuf, sizeof(obuf));
880 +       
881 +
882 +       write_lock_bh(&osf_lock);
883 +       list_add_tail(&finger->flist, &finger_list);
884 +       write_unlock_bh(&osf_lock);
885 +
886 +       return count;
887 +}
888 +
889 +static int __init osf_init(void)
890 +{
891 +       int err;
892 +       struct proc_dir_entry *p;
893 +
894 +       log("Startng OS fingerprint matching module.\n");
895 +
896 +       INIT_LIST_HEAD(&finger_list);
897 +       
898 +       err = ipt_register_match(&osf_match);
899 +       if (err)
900 +       {
901 +               log("Failed to register OS fingerprint matching module.\n");
902 +               return -ENXIO;
903 +       }
904 +
905 +       p = create_proc_entry("sys/net/ipv4/osf", S_IFREG | 0644, NULL);
906 +       if (!p)
907 +       {
908 +               ipt_unregister_match(&osf_match);
909 +               return -ENXIO;
910 +       }
911 +
912 +       p->write_proc = osf_proc_write;
913 +       p->read_proc  = osf_proc_read;
914 +
915 +       return 0;
916 +}
917 +
918 +static void __exit osf_fini(void)
919 +{
920 +       struct list_head *ent, *n;
921 +       struct osf_finger *f;
922 +       
923 +       remove_proc_entry("sys/net/ipv4/osf", NULL);
924 +       ipt_unregister_match(&osf_match);
925 +
926 +       list_for_each_safe(ent, n, &finger_list)
927 +       {
928 +               f = list_entry(ent, struct osf_finger, flist);
929 +               list_del(&f->flist);
930 +               finger_free(f);
931 +       }
932 +       
933 +       log("OS fingerprint matching module finished.\n");
934 +}
935 +
936 +module_init(osf_init);
937 +module_exit(osf_fini);
938 +
939 +MODULE_LICENSE("GPL");
940 +MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
941 +MODULE_DESCRIPTION("Passive OS fingerprint matching.");
942 +
This page took 3.462366 seconds and 3 git commands to generate.