1 /*
2 
3   p0f - passive OS fingerprinting
4   -------------------------------
5 
6   "If you sit down at a poker game and don't see a sucker,
7   get up. You're the sucker."
8 
9   (C) Copyright 2000-2003 by Michal Zalewski <lcamtuf@coredump.cx>
10 
11   WIN32 port (C) Copyright 2003 by Michael A. Davis <mike@datanerds.net>
12              (C) Copyright 2003 by Kirby Kuehl <kkuehl@cisco.com>
13 
14 */
15 
16 #include <config.h>
17 
18 #include <unilib/output.h>
19 
20 #include <stdlib.h>
21 
22 #include <unistd.h>
23 #include <netdb.h>
24 #include <sys/un.h>
25 #include <grp.h>
26 
27 #include <stdio.h>
28 #include <stdarg.h>
29 
30 #include <ctype.h>
31 
32 /* #define DEBUG_HASH - display signature hash table stats */
33 
34 #include "p0f-config.h"
35 #include "tcp.h"
36 #include "mtu.h"
37 #include "tos.h"
38 #include "fpentry.h"
39 
40 #ifndef MSG_NOSIGNAL
41 #define MSG_NOSIGNAL 0
42 #endif /* ! MSG_NOSIGNAL */
43 
44 static struct fp_entry sig[MAXSIGS];
45 static uint32_t sigcnt,gencnt;
46 
47 /* By hash */
48 static struct fp_entry* bh[16];
49 
50 #define SIGHASH(tsize,optcnt,q,df) \
51 	(( (uint8_t) (((tsize) << 1) ^ ((optcnt) << 1) ^ (df) ^ (q) )) & 0x0f)
52 
53 #define DEBUG(fmt, args...) display_builtin(M_DBG1, __FILE__, __LINE__, fmt, ## args);
54 #define FATAL(fmt, args...) do { display_builtin(M_ERR, __FILE__, __LINE__, fmt, ## args); return; } while (0)
55 
56 static uint32_t pkcnt;
57 static uint8_t problems;
58 
59 static void outbuf_add(const char *, ...) __attribute__((format(printf, 1, 2)));
60 static void outbuf_reset(void);
61 static char *outbuf_return(void);
62 
63 static uint8_t no_extra,
64            no_osdesc,
65            no_known,
66            no_unknown,
67            ack_mode,
68            rst_mode,
69            always_sig,
70            check_collide,
71            use_fuzzy;
72 
73 
set_ackmode(void)74 void set_ackmode(void) {
75 	ack_mode=1; rst_mode=0;
76 }
77 
set_rstmode(void)78 void set_rstmode(void) {
79 	rst_mode=1; ack_mode=0;
80 }
set_fuzzy(void)81 void set_fuzzy(void) {
82 	use_fuzzy=1;
83 }
84 
collide(uint32_t id)85 static void collide(uint32_t id) {
86   uint32_t i,j;
87   uint32_t cur;
88 
89   if (sig[id].ttl % 32 && sig[id].ttl != 255 && sig[id].ttl % 30) {
90     problems=1;
91     DEBUG("[!] Unusual TTL (%d) for signature '%s %s' (line %d).\n",
92           sig[id].ttl,sig[id].os,sig[id].desc,sig[id].line);
93   }
94 
95   for (i=0;i<id;i++) {
96 
97     if (!strcmp(sig[i].os,sig[id].os) &&
98         !strcmp(sig[i].desc,sig[id].desc)) {
99       problems=1;
100       DEBUG("[!] Duplicate signature name: '%s %s' (line %d and %d).\n",
101             sig[i].os,sig[i].desc,sig[i].line,sig[id].line);
102     }
103 
104     /* If TTLs are sufficiently away from each other, the risk of
105        a collision is lower. */
106     if (abs((int32_t)sig[id].ttl - (int32_t)sig[i].ttl) > 25) continue;
107 
108     if (sig[id].df ^ sig[i].df) continue;
109     if (sig[id].zero_stamp ^ sig[i].zero_stamp) continue;
110 
111     /* Zero means >= PACKET_BIG */
112     if (sig[id].size) { if (sig[id].size ^ sig[i].size) continue; }
113       else if (sig[i].size < PACKET_BIG) continue;
114 
115     if (sig[id].optcnt ^ sig[i].optcnt) continue;
116     if (sig[id].quirks ^ sig[i].quirks) continue;
117 
118     switch (sig[id].wsize_mod) {
119 
120       case 0: /* Current: const */
121 
122         cur=sig[id].wsize;
123 
124 do_const:
125 
126         switch (sig[i].wsize_mod) {
127 
128           case 0: /* Previous is also const */
129 
130             /* A problem if values match */
131             if (cur ^ sig[i].wsize) continue;
132             break;
133 
134           case MOD_CONST: /* Current: const, prev: modulo (or *) */
135 
136             /* A problem if current value is a multiple of that modulo */
137             if (cur % sig[i].wsize) continue;
138             break;
139 
140           case MOD_MSS: /* Current: const, prev: mod MSS */
141 
142             if (sig[i].mss_mod || sig[i].wsize *
143 	       (sig[i].mss ? sig[i].mss : 1460 ) != cur)
144               continue;
145 
146             break;
147 
148           case MOD_MTU: /* Current: const, prev: mod MTU */
149 
150             if (sig[i].mss_mod || sig[i].wsize * (
151 	        (sig[i].mss ? sig[i].mss : 1460 )+40) != cur)
152               continue;
153 
154             break;
155 
156         }
157 
158         break;
159 
160       case 1: /* Current signature is modulo something */
161 
162         /* A problem only if this modulo is a multiple of the
163            previous modulo */
164 
165         if (sig[i].wsize_mod != MOD_CONST) continue;
166         if (sig[id].wsize % sig[i].wsize) continue;
167 
168         break;
169 
170       case MOD_MSS: /* Current is modulo MSS */
171 
172         /* There's likely a problem only if the previous one is close
173            to '*'; we do not check known MTUs, because this particular
174            signature can be made with some uncommon MTUs in mind. The
175            problem would also appear if current signature has a fixed
176            MSS. */
177 
178         if (sig[i].wsize_mod != MOD_CONST || sig[i].wsize >= 8) {
179           if (!sig[id].mss_mod) {
180             cur = (sig[id].mss ? sig[id].mss : 1460 ) * sig[id].wsize;
181             goto do_const;
182           }
183           continue;
184         }
185 
186         break;
187 
188       case MOD_MTU: /* Current is modulo MTU */
189 
190         if (sig[i].wsize_mod != MOD_CONST || sig[i].wsize <= 8) {
191           if (!sig[id].mss_mod) {
192             cur = ( (sig[id].mss ? sig[id].mss : 1460 ) +40) * sig[id].wsize;
193             goto do_const;
194           }
195           continue;
196         }
197 
198         break;
199 
200     }
201 
202     /* Same for wsc */
203     switch (sig[id].wsc_mod) {
204 
205       case 0: /* Current: const */
206 
207         cur=sig[id].wsc;
208 
209         switch (sig[i].wsc_mod) {
210 
211           case 0: /* Previous is also const */
212 
213             /* A problem if values match */
214             if (cur ^ sig[i].wsc) continue;
215             break;
216 
217           case 1: /* Current: const, prev: modulo (or *) */
218 
219             /* A problem if current value is a multiple of that modulo */
220             if (cur % sig[i].wsc) continue;
221             break;
222 
223         }
224 
225         break;
226 
227       case MOD_CONST: /* Current signature is modulo something */
228 
229         /* A problem only if this modulo is a multiple of the
230            previous modulo */
231 
232         if (!sig[i].wsc_mod) continue;
233         if (sig[id].wsc % sig[i].wsc) continue;
234 
235         break;
236 
237      }
238 
239     /* Same for mss */
240     switch (sig[id].mss_mod) {
241 
242       case 0: /* Current: const */
243 
244         cur=sig[id].mss;
245 
246         switch (sig[i].mss_mod) {
247 
248           case 0: /* Previous is also const */
249 
250             /* A problem if values match */
251             if (cur ^ sig[i].mss) continue;
252             break;
253 
254           case 1: /* Current: const, prev: modulo (or *) */
255 
256             /* A problem if current value is a multiple of that modulo */
257             if (cur % sig[i].mss) continue;
258             break;
259 
260         }
261 
262         break;
263 
264       case MOD_CONST: /* Current signature is modulo something */
265 
266         /* A problem only if this modulo is a multiple of the
267            previous modulo */
268 
269         if (!sig[i].mss_mod) continue;
270         if ((sig[id].mss ? sig[id].mss : 1460 ) %
271 	    (sig[i].mss ? sig[i].mss : 1460 )) continue;
272 
273         break;
274 
275      }
276 
277      /* Now check option sequence */
278 
279     for (j=0;j<sig[id].optcnt;j++)
280       if (sig[id].opt[j] ^ sig[i].opt[j]) goto reloop;
281 
282     problems=1;
283     DEBUG("[!] Signature '%s %s' (line %d)\n"
284           "    is already covered by '%s %s' (line %d).\n",
285           sig[id].os,sig[id].desc,sig[id].line,sig[i].os,sig[i].desc,
286           sig[i].line);
287 
288 reloop:
289 
290     ;
291 
292   }
293 
294 }
295 
296 
load_config(void)297 void load_config(void) {
298   uint32_t ln=0;
299   uint8_t buf[MAXLINE];
300   uint8_t* p;
301   const char *cf=NULL;
302   FILE *c=NULL;
303 
304   if (ack_mode) {
305     cf=CONFIG_DIR "/" SYNACK_DB;
306   }
307   else {
308     cf=CONFIG_DIR "/" RST_DB;
309   }
310   c = fopen(cf ,"r");
311 
312   if (c == NULL) {
313     FATAL("cant open config file `%s'", cf);
314     return;
315   }
316 
317   while ((p=fgets(buf,sizeof(buf),c))) {
318     uint32_t l;
319 
320     uint8_t obuf[MAXLINE],genre[MAXLINE],desc[MAXLINE],quirks[MAXLINE];
321     uint8_t w[MAXLINE],sb[MAXLINE];
322     uint8_t* gptr = genre;
323     uint32_t t,d,s;
324     struct fp_entry* e;
325 
326     ln++;
327 
328     /* Remove leading and trailing blanks */
329     while (isspace(*p)) p++;
330     l=strlen(p);
331     while (l && isspace(*(p+l-1))) *(p+(l--)-1)=0;
332 
333     /* Skip empty lines and comments */
334     if (!l) continue;
335     if (*p == '#') continue;
336 
337     if (sscanf(p,"%[0-9%*()ST]:%d:%d:%[0-9()*]:%[^:]:%[^ :]:%[^:]:%[^:]",
338                   w,         &t,&d,sb,     obuf, quirks,genre,desc) != 8)
339       FATAL("Syntax error in config line %d.\n",ln);
340 
341     gptr = genre;
342 
343     if (*sb != '*') s = atoi(sb); else s = 0;
344 
345 reparse_ptr:
346 
347     switch (*gptr) {
348       case '-': sig[sigcnt].userland = 1; gptr++; goto reparse_ptr;
349       case '*': sig[sigcnt].no_detail = 1; gptr++; goto reparse_ptr;
350       case '@': sig[sigcnt].generic = 1; gptr++; gencnt++; goto reparse_ptr;
351       case 0: FATAL("Empty OS genre in line %d.\n",ln);
352     }
353 
354     sig[sigcnt].os     = strdup(gptr);
355     sig[sigcnt].desc   = strdup(desc);
356     sig[sigcnt].ttl    = t;
357     sig[sigcnt].size   = s;
358     sig[sigcnt].df     = d;
359 
360     if (w[0] == '*') {
361       sig[sigcnt].wsize = 1;
362       sig[sigcnt].wsize_mod = MOD_CONST;
363     } else if (tolower(w[0]) == 's') {
364       sig[sigcnt].wsize_mod = MOD_MSS;
365       if (!isdigit(*(w+1))) FATAL("Bad Snn value in WSS in line %d.\n",ln);
366       sig[sigcnt].wsize = atoi(w+1);
367     } else if (tolower(w[0]) == 't') {
368       sig[sigcnt].wsize_mod = MOD_MTU;
369       if (!isdigit(*(w+1))) FATAL("Bad Tnn value in WSS in line %d.\n",ln);
370       sig[sigcnt].wsize = atoi(w+1);
371     } else if (w[0] == '%') {
372       if (!(sig[sigcnt].wsize = atoi(w+1)))
373         FATAL("Null modulo for window size in config line %d.\n",ln);
374       sig[sigcnt].wsize_mod = MOD_CONST;
375     } else sig[sigcnt].wsize = atoi(w);
376 
377     /* Now let's parse options */
378 
379     p=obuf;
380 
381     sig[sigcnt].zero_stamp = 1;
382 
383     if (*p=='.') p++;
384 
385     while (*p) {
386       uint8_t optcnt = sig[sigcnt].optcnt;
387       switch (tolower(*p)) {
388 
389         case 'n': sig[sigcnt].opt[optcnt] = TCPOPT_NOP;
390                   break;
391 
392         case 'e': sig[sigcnt].opt[optcnt] = TCPOPT_EOL;
393                   if (*(p+1))
394                     FATAL("EOL not the last option (line %d).\n",ln);
395                   break;
396 
397         case 's': sig[sigcnt].opt[optcnt] = TCPOPT_SACKOK;
398                   break;
399 
400         case 't': sig[sigcnt].opt[optcnt] = TCPOPT_TIMESTAMP;
401                   if (*(p+1)!='0') {
402                     sig[sigcnt].zero_stamp=0;
403                     if (isdigit(*(p+1)))
404                       FATAL("Bogus Tstamp specification in line %d.\n",ln);
405                   }
406                   break;
407 
408         case 'w': sig[sigcnt].opt[optcnt] = TCPOPT_WSCALE;
409                   if (p[1] == '*') {
410                     sig[sigcnt].wsc = 1;
411                     sig[sigcnt].wsc_mod = MOD_CONST;
412                   } else if (p[1] == '%') {
413                     if (!(sig[sigcnt].wsc = atoi(p+2)))
414                       FATAL("Null modulo for wscale in config line %d.\n",ln);
415                     sig[sigcnt].wsc_mod = MOD_CONST;
416                   } else if (!isdigit(*(p+1)))
417                     FATAL("Incorrect W value in line %d.\n",ln);
418                   else sig[sigcnt].wsc = atoi(p+1);
419                   break;
420 
421         case 'm': sig[sigcnt].opt[optcnt] = TCPOPT_MAXSEG;
422                   if (p[1] == '*') {
423                     sig[sigcnt].mss = 1;
424                     sig[sigcnt].mss_mod = MOD_CONST;
425                   } else if (p[1] == '%') {
426                     if (!(sig[sigcnt].mss = atoi(p+2)))
427                       FATAL("Null modulo for MSS in config line %d.\n",ln);
428                     sig[sigcnt].mss_mod = MOD_CONST;
429                   } else if (!isdigit(*(p+1)))
430                     FATAL("Incorrect M value in line %d.\n",ln);
431                   else sig[sigcnt].mss = atoi(p+1);
432                   break;
433 
434         /* Yuck! */
435         case '?': if (!isdigit(*(p+1)))
436                     FATAL("Bogus ?nn value in line %d.\n",ln);
437                   else sig[sigcnt].opt[optcnt] = atoi(p+1);
438                   break;
439 
440         default: FATAL("Unknown TCP option '%c' in config line %d.\n",*p,ln);
441       }
442 
443       if (++sig[sigcnt].optcnt >= MAXOPT)
444         FATAL("Too many TCP options specified in config line %d.\n",ln);
445 
446       /* Skip separators */
447       do { p++; } while (*p && !isalpha(*p) && *p != '?');
448 
449     }
450 
451     sig[sigcnt].line = ln;
452 
453     p = quirks;
454 
455     while (*p)
456       switch (toupper(*(p++))) {
457         case 'E':
458           FATAL("Quirk 'E' (line %d) is obsolete. Remove it, append E to the "
459           "options.\n",ln);
460 
461         case 'K':
462 	  if (!rst_mode) FATAL("Quirk 'K' (line %d) is valid only in RST+ (-R)"
463 	      " mode (wrong config file?).\n",ln);
464   	  sig[sigcnt].quirks |= QUIRK_RSTACK;
465 	  break;
466 
467         case 'Q': sig[sigcnt].quirks |= QUIRK_SEQEQ; break;
468         case '0': sig[sigcnt].quirks |= QUIRK_SEQ0; break;
469         case 'P': sig[sigcnt].quirks |= QUIRK_PAST; break;
470         case 'Z': sig[sigcnt].quirks |= QUIRK_ZEROID; break;
471         case 'I': sig[sigcnt].quirks |= QUIRK_IPOPT; break;
472         case 'U': sig[sigcnt].quirks |= QUIRK_URG; break;
473         case 'X': sig[sigcnt].quirks |= QUIRK_X2; break;
474         case 'A': sig[sigcnt].quirks |= QUIRK_ACK; break;
475         case 'T': sig[sigcnt].quirks |= QUIRK_T2; break;
476         case 'F': sig[sigcnt].quirks |= QUIRK_FLAGS; break;
477         case 'D': sig[sigcnt].quirks |= QUIRK_DATA; break;
478         case '!': sig[sigcnt].quirks |= QUIRK_BROKEN; break;
479         case '.': break;
480         default: FATAL("Bad quirk '%c' in line %d.\n",*(p-1),ln);
481       }
482 
483     e = bh[SIGHASH(s,sig[sigcnt].optcnt,sig[sigcnt].quirks,d)];
484 
485     if (!e) {
486       bh[SIGHASH(s,sig[sigcnt].optcnt,sig[sigcnt].quirks,d)] = sig + sigcnt;
487     } else {
488       while (e->next) e = e->next;
489       e->next = sig + sigcnt;
490     }
491 
492     if (check_collide) collide(sigcnt);
493 
494     if (++sigcnt >= MAXSIGS)
495       FATAL("Maximum signature count exceeded.\n");
496 
497   }
498 
499   fclose(c);
500 
501   if (check_collide && !problems)
502     DEBUG("[+] Signature collision check successful.\n");
503 
504   if (!sigcnt)
505     DEBUG("[!] WARNING: no signatures loaded from config file.\n");
506 
507 }
508 
509 
510 
511 
lookup_link(uint16_t mss,uint8_t txt)512 static uint8_t* lookup_link(uint16_t mss,uint8_t txt) {
513   uint32_t i;
514   static uint8_t tmp[32];
515 
516   if (!mss) return txt ? "unspecified" : 0;
517   mss += 40;
518 
519   for (i=0;i<MTU_CNT;i++) {
520    if (mss == mtu[i].mtu) return mtu[i].dev;
521    if (mss < mtu[i].mtu)  goto unknown;
522   }
523 
524 unknown:
525 
526   if (!txt) return 0;
527   sprintf(tmp,"unknown-%d",mss);
528   return tmp;
529 
530 }
531 
532 
lookup_tos(uint8_t t)533 static uint8_t* lookup_tos(uint8_t t) {
534   uint32_t i;
535 
536   if (!t) return 0;
537 
538   for (i=0;i<TOS_CNT;i++) {
539    if (t == tos[i].tos) return tos[i].desc;
540    if (t < tos[i].tos) break;
541   }
542 
543   return 0;
544 
545 }
546 
display_signature(uint8_t ttl,uint16_t tot,uint8_t df,uint8_t * op,uint8_t ocnt,uint16_t mss,uint16_t wss,uint8_t wsc,uint32_t tstamp,uint32_t quirks)547 static inline void display_signature(uint8_t ttl,uint16_t tot,uint8_t df,uint8_t* op,uint8_t ocnt,
548                                      uint16_t mss,uint16_t wss,uint8_t wsc,uint32_t tstamp,
549                                      uint32_t quirks) {
550 
551   uint32_t j;
552   uint8_t d=0;
553 
554   if (mss && wss && !(wss % mss)) outbuf_add("S%d",wss/mss); else
555   if (wss && !(wss % 1460)) outbuf_add("S%d",wss/1460); else
556   if (mss && wss && !(wss % (mss+40))) outbuf_add("T%d",wss/(mss+40)); else
557   if (wss && !(wss % 1500)) outbuf_add("T%d",wss/1500); else
558   if (wss == 12345) outbuf_add("*(12345)"); else outbuf_add("%d",wss);
559 
560   if (tot < PACKET_BIG) outbuf_add(":%d:%d:%d:",ttl,df,tot);
561   else outbuf_add(":%d:%d:*(%d):",ttl,df,tot);
562 
563   for (j=0;j<ocnt;j++) {
564     switch (op[j]) {
565       case TCPOPT_NOP: outbuf_add("%c", 'N'); d=1; break;
566       case TCPOPT_WSCALE: outbuf_add("W%d",wsc); d=1; break;
567       case TCPOPT_MAXSEG: outbuf_add("M%d",mss); d=1; break;
568       case TCPOPT_TIMESTAMP: outbuf_add("%c",'T');
569         if (!tstamp) outbuf_add("%c",'0'); d=1; break;
570       case TCPOPT_SACKOK: outbuf_add("%c",'S'); d=1; break;
571       case TCPOPT_EOL: outbuf_add("%c",'E'); d=1; break;
572       default: outbuf_add("?%d",op[j]); d=1; break;
573     }
574     if (j != ocnt-1) outbuf_add("%c",',');
575   }
576 
577   if (!d) outbuf_add("%c",'.');
578 
579   outbuf_add("%c",':');
580 
581   if (!quirks) outbuf_add("%c",'.'); else {
582     if (quirks & QUIRK_RSTACK) outbuf_add("%c",'K');
583     if (quirks & QUIRK_SEQEQ) outbuf_add("%c",'Q');
584     if (quirks & QUIRK_SEQ0) outbuf_add("%c",'0');
585     if (quirks & QUIRK_PAST) outbuf_add("%c",'P');
586     if (quirks & QUIRK_ZEROID) outbuf_add("%c",'Z');
587     if (quirks & QUIRK_IPOPT) outbuf_add("%c",'I');
588     if (quirks & QUIRK_URG) outbuf_add("%c",'U');
589     if (quirks & QUIRK_X2) outbuf_add("%c",'X');
590     if (quirks & QUIRK_ACK) outbuf_add("%c",'A');
591     if (quirks & QUIRK_T2) outbuf_add("%c",'T');
592     if (quirks & QUIRK_FLAGS) outbuf_add("%c",'F');
593     if (quirks & QUIRK_DATA) outbuf_add("%c",'D');
594     if (quirks & QUIRK_BROKEN) outbuf_add("%c",'!');
595   }
596 
597 }
598 
599 
find_match(uint16_t tot,uint8_t df,uint8_t ttl,uint16_t wss,uint32_t src,uint32_t dst,uint16_t sp,uint16_t dp,uint8_t ocnt,uint8_t * op,uint16_t mss,uint8_t wsc,uint32_t tstamp,uint8_t tos,uint32_t quirks,uint8_t ecn,uint8_t * pkt,uint8_t plen,uint8_t * pay)600 static inline void find_match(uint16_t tot,uint8_t df,uint8_t ttl,uint16_t wss,uint32_t src,
601                        uint32_t dst,uint16_t sp,uint16_t dp,uint8_t ocnt,uint8_t* op,uint16_t mss,
602                        uint8_t wsc,uint32_t tstamp,uint8_t tos,uint32_t quirks,uint8_t ecn,
603                        uint8_t* pkt,uint8_t plen,uint8_t* pay) {
604 
605   uint32_t j;
606   uint8_t* a;
607   uint8_t  nat=0;
608   struct fp_entry* p;
609   uint8_t  orig_df  = df;
610   uint8_t* tos_desc = 0;
611 
612   struct fp_entry* fuzzy = 0;
613   uint8_t fuzzy_now = 0;
614 
615 re_lookup:
616 
617   p = bh[SIGHASH(tot,ocnt,quirks,df)];
618 
619   if (tos) tos_desc = lookup_tos(tos);
620 
621   while (p) {
622 
623     /* Cheap and specific checks first... */
624 
625     /* psize set to zero means >= PACKET_BIG */
626     if (p->size) { if (tot ^ p->size) { p = p->next; continue; } }
627       else if (tot < PACKET_BIG) { p = p->next; continue; }
628 
629     if (ocnt ^ p->optcnt) { p = p->next; continue; }
630 
631     if (p->zero_stamp ^ (!tstamp)) { p = p->next; continue; }
632     if (p->df ^ df) { p = p->next; continue; }
633     if (p->quirks ^ quirks) { p = p->next; continue; }
634 
635     /* Check MSS and WSCALE... */
636     if (!p->mss_mod) {
637       if (mss ^ p->mss) { p = p->next; continue; }
638     } else if (mss % p->mss) { p = p->next; continue; }
639 
640     if (!p->wsc_mod) {
641       if (wsc ^ p->wsc) { p = p->next; continue; }
642     } else if (wsc % p->wsc) { p = p->next; continue; }
643 
644     /* Then proceed with the most complex WSS check... */
645     switch (p->wsize_mod) {
646       case 0:
647         if (wss ^ p->wsize) { p = p->next; continue; }
648         break;
649       case MOD_CONST:
650         if (wss % p->wsize) { p = p->next; continue; }
651         break;
652       case MOD_MSS:
653         if (mss && !(wss % mss)) {
654           if ((wss / mss) ^ p->wsize) { p = p->next; continue; }
655         } else if (!(wss % 1460)) {
656           if ((wss / 1460) ^ p->wsize) { p = p->next; continue; }
657         } else { p = p->next; continue; }
658         break;
659       case MOD_MTU:
660         if (mss && !(wss % (mss+40))) {
661           if ((wss / (mss+40)) ^ p->wsize) { p = p->next; continue; }
662         } else if (!(wss % 1500)) {
663           if ((wss / 1500) ^ p->wsize) { p = p->next; continue; }
664         } else { p = p->next; continue; }
665         break;
666      }
667 
668     /* Numbers agree. Let's check options */
669 
670     for (j=0;j<ocnt;j++)
671       if (p->opt[j] ^ op[j]) goto continue_search;
672 
673     /* Check TTLs last because we might want to go fuzzy. */
674     if (p->ttl < ttl) {
675       if (use_fuzzy) fuzzy = p;
676       p = p->next;
677       continue;
678     }
679 
680     /* Naah... can't happen ;-) */
681     if (!p->no_detail)
682       if (p->ttl - ttl > MAXDIST) {
683         if (use_fuzzy) fuzzy = p;
684         p = p->next;
685         continue;
686       }
687 
688 continue_fuzzy:
689 
690     /* Match! */
691 
692     if (mss & wss) {
693       if (p->wsize_mod == MOD_MSS) {
694         if ((wss % mss) && !(wss % 1460)) nat=1;
695       } else if (p->wsize_mod == MOD_MTU) {
696         if ((wss % (mss+40)) && !(wss % 1500)) nat=2;
697       }
698     }
699 
700     if (!no_known) {
701 
702       a=(uint8_t*)&src;
703 
704       outbuf_add("%s ",p->os);
705 
706       if (!no_osdesc) outbuf_add("%s ",p->desc);
707 
708       if (nat == 1) outbuf_add("(NAT!) "); else
709         if (nat == 2) outbuf_add("(NAT2!) ");
710 
711       if (ecn) outbuf_add("(ECN) ");
712       if (orig_df ^ df) outbuf_add("(firewall!) ");
713 
714       if (tos) {
715         if (tos_desc) outbuf_add("[%s] ",tos_desc); else outbuf_add("[tos %d] ",tos);
716       }
717 
718       if (p->generic) outbuf_add("[GENERIC] ");
719       if (fuzzy_now) outbuf_add("[FUZZY] ");
720 
721       if (p->no_detail) outbuf_add("* "); else
722         if (tstamp) outbuf_add("up: %d hrs ",tstamp/360000);
723 
724       if (always_sig || (p->generic && !no_unknown)) {
725 
726         outbuf_add("Signature: [");
727 
728         display_signature(ttl,tot,orig_df,op,ocnt,mss,wss,wsc,tstamp,quirks);
729 
730         if (p->generic)
731           outbuf_add(":%s:?] ",p->os);
732         else
733           outbuf_add("] ");
734 
735       }
736 
737       if (!no_extra && !p->no_detail) {
738 	a=(uint8_t*)&dst;
739 
740         if (fuzzy_now)
741           outbuf_add(" link: %s",
742                lookup_link(mss,1));
743         else
744           outbuf_add(" distance %d, link: %s",
745                  p->ttl - ttl,
746                  lookup_link(mss,1));
747       }
748 
749     }
750 
751     return;
752 
753 continue_search:
754 
755     p = p->next;
756 
757   }
758 
759   if (!df) { df = 1; goto re_lookup; }
760 
761   if (use_fuzzy && fuzzy) {
762     df = orig_df;
763     fuzzy_now = 1;
764     p = fuzzy;
765     fuzzy = 0;
766     goto continue_fuzzy;
767   }
768 
769   if (mss & wss) {
770     if ((wss % mss) && !(wss % 1460)) nat=1;
771     else if ((wss % (mss+40)) && !(wss % 1500)) nat=2;
772   }
773 
774   if (!no_unknown) {
775     a=(uint8_t*)&src;
776     outbuf_add("UNKNOWN [");
777 
778     display_signature(ttl,tot,orig_df,op,ocnt,mss,wss,wsc,tstamp,quirks);
779 
780     outbuf_add(":?:?] ");
781 
782     if (rst_mode) {
783 
784       /* Display a reasonable diagnosis of the RST+ACK madness! */
785 
786       switch (quirks & (QUIRK_RSTACK | QUIRK_SEQ0 | QUIRK_ACK)) {
787 
788         /* RST+ACK, SEQ=0, ACK=0 */
789         case QUIRK_RSTACK | QUIRK_SEQ0:
790           outbuf_add("(invalid-K0) "); break;
791 
792         /* RST+ACK, SEQ=0, ACK=n */
793         case QUIRK_RSTACK | QUIRK_ACK | QUIRK_SEQ0:
794           outbuf_add("(refused) "); break;
795 
796         /* RST+ACK, SEQ=n, ACK=0 */
797         case QUIRK_RSTACK:
798           outbuf_add("(invalid-K) "); break;
799 
800         /* RST+ACK, SEQ=n, ACK=n */
801         case QUIRK_RSTACK | QUIRK_ACK:
802           outbuf_add("(invalid-KA) "); break;
803 
804         /* RST, SEQ=n, ACK=0 */
805         case 0:
806           outbuf_add("(dropped) "); break;
807 
808         /* RST, SEQ=m, ACK=n */
809         case QUIRK_ACK:
810           outbuf_add("(dropped 2) "); break;
811 
812         /* RST, SEQ=0, ACK=0 */
813         case QUIRK_SEQ0:
814           outbuf_add("(invalid-0) "); break;
815 
816         /* RST, SEQ=0, ACK=n */
817         case QUIRK_ACK | QUIRK_SEQ0:
818           outbuf_add("(invalid-0A) "); break;
819 
820       }
821 
822     }
823 
824     if (nat == 1) outbuf_add("(NAT!) ");
825       else if (nat == 2) outbuf_add("(NAT2!) ");
826 
827     if (ecn) outbuf_add("(ECN) ");
828 
829     if (tos) {
830       if (tos_desc) outbuf_add("[%s] ",tos_desc); else outbuf_add("[tos %d] ",tos);
831     }
832 
833     if (tstamp) outbuf_add("up: %d hrs ",tstamp/360000);
834 
835     if (!no_extra) {
836       a=(uint8_t*)&dst;
837       outbuf_add(" link: %s", lookup_link(mss,1));
838     }
839 
840     fflush(0);
841 
842   }
843 
844 }
845 
846 
847 #define GET16(p) \
848         ((uint16_t) *((uint8_t*)(p)+0) << 8 | \
849          (uint16_t) *((uint8_t*)(p)+1) )
850 
851 
p0f_parse(const uint8_t * packet,uint16_t pklen)852 char *p0f_parse(const uint8_t* packet, uint16_t pklen) {
853   const struct ip_header *iph;
854   const struct tcp_header *tcph;
855   const uint8_t*   end_ptr;
856   const uint8_t*   opt_ptr;
857   const uint8_t*   pay = 0;
858   int32_t   ilen,olen;
859 
860   uint8_t    op[MAXOPT];
861   uint8_t    ocnt = 0;
862   uint16_t   mss_val = 0, wsc_val = 0;
863   uint32_t   tstamp = 0;
864   uint32_t   quirks = 0;
865 
866   pkcnt++;
867 
868   outbuf_reset();
869 
870   /* Paranoia! */
871   end_ptr = packet + pklen;
872 
873   iph = (const struct ip_header*)(packet);
874 
875   /* Whoops, IP header ends past end_ptr */
876   if ((const uint8_t*)(iph + 1) > end_ptr) return NULL;
877 
878   if ( ((iph->ihl & 0x40) != 0x40) || iph->proto != IPPROTO_TCP) {
879     return NULL;
880   }
881 
882   /* If the declared length is shorter than the snapshot (etherleak
883      or such), truncate this bad boy. */
884 
885   opt_ptr = (const uint8_t*)iph + htons(iph->tot_len);
886   if (end_ptr > opt_ptr) end_ptr = opt_ptr;
887 
888   ilen = iph->ihl & 15;
889 
890   /* Borken packet */
891   if (ilen < 5) return NULL;
892 
893   if (ilen > 5) {
894 
895     quirks |= QUIRK_IPOPT;
896   }
897 
898   tcph = (const struct tcp_header*)(packet + (ilen << 2));
899   opt_ptr = (const uint8_t*)(tcph + 1);
900 
901   if (ack_mode && (tcph->flags & (TH_ACK|TH_SYN)) != (TH_ACK|TH_SYN)) return NULL;
902   if (rst_mode && (tcph->flags & TH_RST) != TH_RST) return NULL;
903 
904   /* Whoops, TCP header would end past end_ptr */
905   if (opt_ptr > end_ptr) return NULL;
906 
907   if (rst_mode && (tcph->flags & TH_ACK)) quirks |= QUIRK_RSTACK;
908 
909   if (tcph->seq == tcph->ack) quirks |= QUIRK_SEQEQ;
910   if (!tcph->seq) quirks |= QUIRK_SEQ0;
911 
912   if (tcph->flags & ~(TH_SYN|TH_ACK|TH_RST|TH_ECE|TH_CWR))
913     quirks |= QUIRK_FLAGS;
914 
915   ilen=((tcph->doff) << 2) - sizeof(struct tcp_header);
916 
917   if ( (const uint8_t*)opt_ptr + ilen < end_ptr) {
918 
919 #ifdef DEBUG_EXTRAS
920     uint32_t i;
921 
922     outbuf_add("  -- EXTRA PAYLOAD (packet below): ");
923 
924     for (i=0;i< (uint32_t)end_ptr - ilen - (uint32_t)opt_ptr;i++)
925       outbuf_add("%02x ",*(opt_ptr + ilen + i));
926 
927     outbuf_add("%c",'\n');
928     fflush(0);
929 #endif /* DEBUG_EXTRAS */
930 
931     quirks |= QUIRK_DATA;
932     pay = opt_ptr + ilen;
933 
934   }
935 
936   while (ilen > 0) {
937 
938     ilen--;
939 
940     switch (*(opt_ptr++)) {
941       case TCPOPT_EOL:
942         /* EOL */
943         op[ocnt] = TCPOPT_EOL;
944         ocnt++;
945 
946         if (ilen) {
947 
948           quirks |= QUIRK_PAST;
949 
950         }
951 
952         /* This goto will be probably removed at some point. */
953         goto end_parsing;
954 
955       case TCPOPT_NOP:
956         /* NOP */
957         op[ocnt] = TCPOPT_NOP;
958         ocnt++;
959         break;
960 
961       case TCPOPT_SACKOK:
962         /* SACKOK LEN */
963         op[ocnt] = TCPOPT_SACKOK;
964         ocnt++; ilen--; opt_ptr++;
965         break;
966 
967       case TCPOPT_MAXSEG:
968         /* MSS LEN D0 D1 */
969         if (opt_ptr + 3 > end_ptr) {
970 borken:
971           quirks |= QUIRK_BROKEN;
972           goto end_parsing;
973         }
974         op[ocnt] = TCPOPT_MAXSEG;
975         mss_val = GET16(opt_ptr+1);
976         ocnt++; ilen -= 3; opt_ptr += 3;
977         break;
978 
979       case TCPOPT_WSCALE:
980         /* WSCALE LEN D0 */
981         if (opt_ptr + 2 > end_ptr) goto borken;
982         op[ocnt] = TCPOPT_WSCALE;
983         wsc_val = *(uint8_t *)(opt_ptr + 1);
984         ocnt++; ilen -= 2; opt_ptr += 2;
985         break;
986 
987       case TCPOPT_TIMESTAMP:
988         /* TSTAMP LEN T0 T1 T2 T3 A0 A1 A2 A3 */
989         if (opt_ptr + 9 > end_ptr) goto borken;
990         op[ocnt] = TCPOPT_TIMESTAMP;
991 
992 	memcpy(&tstamp, opt_ptr+5, 4);
993         if (tstamp) quirks |= QUIRK_T2;
994 
995 	memcpy(&tstamp, opt_ptr+1, 4);
996         tstamp = ntohl(tstamp);
997 
998         ocnt++; ilen -= 9; opt_ptr += 9;
999         break;
1000 
1001       default:
1002 
1003         /* Hrmpf... */
1004         if (opt_ptr + 1 > end_ptr) goto borken;
1005 
1006         op[ocnt] = *(opt_ptr-1);
1007         olen = *(uint8_t*)(opt_ptr)-1;
1008         if (olen > 32 || (olen < 0)) goto borken;
1009 
1010         ocnt++; ilen -= olen; opt_ptr += olen;
1011         break;
1012 
1013      }
1014 
1015      if (ocnt >= MAXOPT-1) goto borken;
1016 
1017      /* Whoops, we're past end_ptr */
1018      if (ilen > 0)
1019        if (opt_ptr >= end_ptr) goto borken;
1020 
1021    }
1022 
1023 end_parsing:
1024 
1025    if (tcph->ack) quirks |= QUIRK_ACK;
1026    if (tcph->urg) quirks |= QUIRK_URG;
1027    if (tcph->_x2) quirks |= QUIRK_X2;
1028    if (!iph->id)  quirks |= QUIRK_ZEROID;
1029 
1030    find_match(
1031      /* total */ ntohs(iph->tot_len),
1032      /* DF */    (ntohs(iph->off) & IP_DF) != 0,
1033      /* TTL */   iph->ttl,
1034      /* WSS */   ntohs(tcph->win),
1035      /* src */   iph->saddr,
1036      /* dst */   iph->daddr,
1037      /* sp */    ntohs(tcph->sport),
1038      /* dp */    ntohs(tcph->dport),
1039      /* ocnt */  ocnt,
1040      /* op */    op,
1041      /* mss */   mss_val,
1042      /* wsc */   wsc_val,
1043      /* tst */   tstamp,
1044      /* TOS */   iph->tos,
1045      /* Q? */    quirks,
1046      /* ECN */   tcph->flags & (TH_ECE|TH_CWR),
1047      /* pkt */   (uint8_t*)iph,
1048      /* len */   end_ptr - (uint8_t*)iph,
1049      /* pay */   pay
1050   );
1051 
1052   return outbuf_return();
1053 }
1054 
1055 static char outbuf[256];
1056 static size_t outbuf_off=0;
outbuf_add(const char * fmt,...)1057 static void outbuf_add(const char *fmt, ...) {
1058 	va_list ap;
1059 	int s_ret=0;
1060 
1061 	va_start(ap, fmt);
1062 	s_ret=vsnprintf(&outbuf[outbuf_off], sizeof(outbuf) - (1 + outbuf_off), fmt, ap);
1063 	assert(s_ret > 0);
1064 
1065 	outbuf_off += s_ret;
1066 	assert(outbuf_off < sizeof(outbuf));
1067 }
1068 
outbuf_reset()1069 static void outbuf_reset() {
1070 	memset(outbuf, 0, sizeof(outbuf));
1071 	outbuf_off=0;
1072 	return;
1073 }
1074 
outbuf_return(void)1075 static char *outbuf_return(void) {
1076 	return &outbuf[0];
1077 }
1078