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