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