LCOV - code coverage report
Current view: top level - src - OSFinger.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 2 321 0.6 %
Date: 2010-12-13 Functions: 2 9 22.2 %
Branches: 2 360 0.6 %

           Branch data     Line data    Source code
       1                 :            : // $Id: OSFinger.cc 5857 2008-06-26 23:00:03Z vern $
       2                 :            : 
       3                 :            : /*
       4                 :            :   Taken with permission from:
       5                 :            : 
       6                 :            :   p0f - passive OS fingerprinting (GNU LESSER GENERAL PUBLIC LICENSE)
       7                 :            :   -------------------------------------------------------------------
       8                 :            : 
       9                 :            :   "If you sit down at a poker game and don't see a sucker,
      10                 :            :   get up. You're the sucker."
      11                 :            : 
      12                 :            :   (C) Copyright 2000-2003 by Michal Zalewski <lcamtuf@coredump.cx>
      13                 :            : */
      14                 :            : 
      15                 :            : // To make it easier to upgrade this file to newer releases of p0f,
      16                 :            : // it remains in the coding style used by p0f rather than Bro.
      17                 :            : 
      18                 :            : #include "OSFinger.h"
      19                 :            : #include "net_util.h"
      20                 :            : #include "util.h"
      21                 :            : #include "Var.h"
      22                 :            : #include <stdlib.h>
      23                 :            : #include <stdio.h>
      24                 :            : #include <ctype.h>
      25                 :            : 
      26                 :            : 
      27                 :          0 : void int_delete_func(void* v)
      28                 :            :         {
      29                 :          0 :         delete (int*) v;
      30                 :          0 :         }
      31                 :            : 
      32                 :            : 
      33                 :            : // Initializes data structures for fingerprinting in the given mode.
      34                 :          0 : OSFingerprint::OSFingerprint(FingerprintMode arg_mode)
      35                 :            :   {
      36                 :          0 :   err = 0;
      37                 :          0 :   mode = arg_mode;
      38                 :            : 
      39                 :          0 :   sigcnt=gencnt=0;
      40                 :          0 :   problems=0;
      41                 :            :   char* fname;
      42                 :            : 
      43                 :          0 :   memset(sig, 0, sizeof(struct fp_entry)*MAXSIGS);
      44                 :          0 :   memset(bh, 0, sizeof(struct fp_entry*)*OSHSIZE);
      45                 :            : 
      46                 :          0 :   os_matches.SetDeleteFunc(int_delete_func);
      47                 :            : 
      48   [ #  #  #  # ]:          0 :   if (mode == SYN_FINGERPRINT_MODE)
      49                 :            :     {
      50                 :          0 :     fname = copy_string(internal_val("passive_fingerprint_file")->AsString()->CheckString());
      51                 :          0 :     load_config(fname);
      52 [ #  # ][ #  # ]:          0 :     delete [] fname;
      53                 :            :     }
      54 [ #  # ][ #  # ]:          0 :   else if (mode == SYN_ACK_FINGERPRINT_MODE)
      55                 :            :     {//not yet supported
      56                 :          0 :     load_config("p0fsynack.sig");
      57                 :            :     }
      58 [ #  # ][ #  # ]:          0 :   else if (mode == RST_FINGERPRINT_MODE)
      59                 :            :     {//not yet supported
      60                 :          0 :     load_config("p0frst.sig");
      61                 :            :     }
      62                 :            :   else
      63                 :            :     {
      64                 :          0 :     Error("OS fingerprinting: unknown mode!");
      65                 :            :     }
      66                 :          0 : }
      67                 :            : 
      68                 :          0 : bool OSFingerprint::CacheMatch(uint32 addr, int id)
      69                 :            :   {
      70                 :          0 :   HashKey key = HashKey(&addr, 1);
      71                 :          0 :   int* pid = new int;
      72                 :          0 :   *pid=id;
      73                 :          0 :   int* prev = os_matches.Insert(&key, pid);
      74   [ #  #  #  # ]:          0 :   bool ret = (prev ? *prev != id : 1);
      75         [ #  # ]:          0 :   if (prev)
      76                 :          0 :     delete prev;
      77                 :          0 :   return ret;
      78                 :            :   }
      79                 :            : 
      80                 :            : 
      81                 :            : // Determines whether the signature file had any collisions.
      82                 :          0 : void OSFingerprint::collide(uint32 id)
      83                 :            :   {
      84                 :            :   uint32 i,j;
      85                 :            :   uint32 cur;
      86                 :            : 
      87 [ #  # ][ #  # ]:          0 :   if (sig[id].ttl % 32 && sig[id].ttl != 255 && sig[id].ttl % 30)
                 [ #  # ]
      88                 :            :     {
      89                 :          0 :     problems=1;
      90                 :            :     warn(fmt("OS fingerprinting: [!] Unusual TTL (%d) for signature '%s %s' (line %d).",
      91                 :          0 :           sig[id].ttl,sig[id].os,sig[id].desc,sig[id].line));
      92                 :            :     }
      93                 :            : 
      94         [ #  # ]:          0 :   for (i=0;i<id;i++)
      95                 :            :     {
      96 [ #  # ][ #  # ]:          0 :     if (!strcmp(sig[i].os,sig[id].os) &&
      97                 :            :         !strcmp(sig[i].desc,sig[id].desc)) {
      98                 :          0 :       problems=1;
      99                 :            :       warn(fmt("OS fingerprinting: [!] Duplicate signature name: '%s %s' (line %d and %d).",
     100                 :          0 :             sig[i].os,sig[i].desc,sig[i].line,sig[id].line));
     101                 :            :     }
     102                 :            : 
     103                 :            :     /* If TTLs are sufficiently away from each other, the risk of
     104                 :            :        a collision is lower. */
     105         [ #  # ]:          0 :     if (abs((int)sig[id].ttl - (int)sig[i].ttl) > 25) continue;
     106                 :            : 
     107         [ #  # ]:          0 :     if (sig[id].df ^ sig[i].df) continue;
     108         [ #  # ]:          0 :     if (sig[id].zero_stamp ^ sig[i].zero_stamp) continue;
     109                 :            : 
     110                 :            :     /* Zero means >= PACKET_BIG */
     111 [ #  # ][ #  # ]:          0 :     if (sig[id].size) { if (sig[id].size ^ sig[i].size) continue; }
     112         [ #  # ]:          0 :       else if (sig[i].size < PACKET_BIG) continue;
     113                 :            : 
     114         [ #  # ]:          0 :     if (sig[id].optcnt ^ sig[i].optcnt) continue;
     115         [ #  # ]:          0 :     if (sig[id].quirks ^ sig[i].quirks) continue;
     116                 :            : 
     117   [ #  #  #  #  :          0 :     switch (sig[id].wsize_mod) {
                      # ]
     118                 :            : 
     119                 :            :       case 0: /* Current: const */
     120                 :            : 
     121                 :          0 :         cur=sig[id].wsize;
     122                 :            : 
     123                 :          0 : do_const:
     124                 :            : 
     125   [ #  #  #  #  :          0 :         switch (sig[i].wsize_mod) {
                      # ]
     126                 :            : 
     127                 :            :           case 0: /* Previous is also const */
     128                 :            : 
     129                 :            :             /* A problem if values match */
     130         [ #  # ]:          0 :             if (cur ^ sig[i].wsize) continue;
     131                 :          0 :             break;
     132                 :            : 
     133                 :            :           case MOD_CONST: /* Current: const, prev: modulo (or *) */
     134                 :            : 
     135                 :            :             /* A problem if current value is a multiple of that modulo */
     136         [ #  # ]:          0 :             if (cur % sig[i].wsize) continue;
     137                 :          0 :             break;
     138                 :            : 
     139                 :            :           case MOD_MSS: /* Current: const, prev: mod MSS */
     140                 :            : 
     141 [ #  # ][ #  # ]:          0 :             if (sig[i].mss_mod || sig[i].wsize *
                 [ #  # ]
     142                 :            :                (sig[i].mss ? sig[i].mss : 1460 ) != (int) cur)
     143                 :          0 :               continue;
     144                 :            : 
     145                 :          0 :             break;
     146                 :            : 
     147                 :            :           case MOD_MTU: /* Current: const, prev: mod MTU */
     148                 :            : 
     149 [ #  # ][ #  # ]:          0 :             if (sig[i].mss_mod || sig[i].wsize * (
                 [ #  # ]
     150                 :            :                 (sig[i].mss ? sig[i].mss : 1460 )+40) != (int) cur)
     151                 :          0 :               continue;
     152                 :            : 
     153                 :            :             break;
     154                 :            : 
     155                 :            :         }
     156                 :            : 
     157                 :          0 :         break;
     158                 :            : 
     159                 :            :       case 1: /* Current signature is modulo something */
     160                 :            : 
     161                 :            :         /* A problem only if this modulo is a multiple of the
     162                 :            :            previous modulo */
     163                 :            : 
     164         [ #  # ]:          0 :         if (sig[i].wsize_mod != MOD_CONST) continue;
     165         [ #  # ]:          0 :         if (sig[id].wsize % sig[i].wsize) continue;
     166                 :            : 
     167                 :          0 :         break;
     168                 :            : 
     169                 :            :       case MOD_MSS: /* Current is modulo MSS */
     170                 :            : 
     171                 :            :         /* There's likely a problem only if the previous one is close
     172                 :            :            to '*'; we do not check known MTUs, because this particular
     173                 :            :            signature can be made with some uncommon MTUs in mind. The
     174                 :            :            problem would also appear if current signature has a fixed
     175                 :            :            MSS. */
     176                 :            : 
     177 [ #  # ][ #  # ]:          0 :         if (sig[i].wsize_mod != MOD_CONST || sig[i].wsize >= 8) {
     178         [ #  # ]:          0 :           if (!sig[id].mss_mod) {
     179         [ #  # ]:          0 :             cur = (sig[id].mss ? sig[id].mss : 1460 ) * sig[id].wsize;
     180                 :          0 :             goto do_const;
     181                 :            :           }
     182                 :          0 :           continue;
     183                 :            :         }
     184                 :            : 
     185                 :          0 :         break;
     186                 :            : 
     187                 :            :       case MOD_MTU: /* Current is modulo MTU */
     188                 :            : 
     189 [ #  # ][ #  # ]:          0 :         if (sig[i].wsize_mod != MOD_CONST || sig[i].wsize <= 8) {
     190         [ #  # ]:          0 :           if (!sig[id].mss_mod) {
     191         [ #  # ]:          0 :             cur = ( (sig[id].mss ? sig[id].mss : 1460 ) +40) * sig[id].wsize;
     192                 :          0 :             goto do_const;
     193                 :            :           }
     194                 :          0 :           continue;
     195                 :            :         }
     196                 :            : 
     197                 :            :         break;
     198                 :            : 
     199                 :            :     }
     200                 :            : 
     201                 :            :     /* Same for wsc */
     202      [ #  #  # ]:          0 :     switch (sig[id].wsc_mod) {
     203                 :            : 
     204                 :            :       case 0: /* Current: const */
     205                 :            : 
     206                 :          0 :         cur=sig[id].wsc;
     207                 :            : 
     208      [ #  #  # ]:          0 :         switch (sig[i].wsc_mod) {
     209                 :            : 
     210                 :            :           case 0: /* Previous is also const */
     211                 :            : 
     212                 :            :             /* A problem if values match */
     213         [ #  # ]:          0 :             if (cur ^ sig[i].wsc) continue;
     214                 :          0 :             break;
     215                 :            : 
     216                 :            :           case 1: /* Current: const, prev: modulo (or *) */
     217                 :            : 
     218                 :            :             /* A problem if current value is a multiple of that modulo */
     219         [ #  # ]:          0 :             if (cur % sig[i].wsc) continue;
     220                 :            :             break;
     221                 :            : 
     222                 :            :         }
     223                 :            : 
     224                 :          0 :         break;
     225                 :            : 
     226                 :            :       case MOD_CONST: /* Current signature is modulo something */
     227                 :            : 
     228                 :            :         /* A problem only if this modulo is a multiple of the
     229                 :            :            previous modulo */
     230                 :            : 
     231         [ #  # ]:          0 :         if (!sig[i].wsc_mod) continue;
     232         [ #  # ]:          0 :         if (sig[id].wsc % sig[i].wsc) continue;
     233                 :            : 
     234                 :            :         break;
     235                 :            : 
     236                 :            :      }
     237                 :            : 
     238                 :            :     /* Same for mss */
     239      [ #  #  # ]:          0 :     switch (sig[id].mss_mod) {
     240                 :            : 
     241                 :            :       case 0: /* Current: const */
     242                 :            : 
     243                 :          0 :         cur=sig[id].mss;
     244                 :            : 
     245      [ #  #  # ]:          0 :         switch (sig[i].mss_mod) {
     246                 :            : 
     247                 :            :           case 0: /* Previous is also const */
     248                 :            : 
     249                 :            :             /* A problem if values match */
     250         [ #  # ]:          0 :             if (cur ^ sig[i].mss) continue;
     251                 :          0 :             break;
     252                 :            : 
     253                 :            :           case 1: /* Current: const, prev: modulo (or *) */
     254                 :            : 
     255                 :            :             /* A problem if current value is a multiple of that modulo */
     256         [ #  # ]:          0 :             if (cur % sig[i].mss) continue;
     257                 :            :             break;
     258                 :            : 
     259                 :            :         }
     260                 :            : 
     261                 :          0 :         break;
     262                 :            : 
     263                 :            :       case MOD_CONST: /* Current signature is modulo something */
     264                 :            : 
     265                 :            :         /* A problem only if this modulo is a multiple of the
     266                 :            :            previous modulo */
     267                 :            : 
     268         [ #  # ]:          0 :         if (!sig[i].mss_mod) continue;
     269 [ #  # ][ #  # ]:          0 :         if ((sig[id].mss ? sig[id].mss : 1460 ) %
                 [ #  # ]
     270                 :          0 :             (sig[i].mss ? sig[i].mss : 1460 )) continue;
     271                 :            : 
     272                 :            :         break;
     273                 :            : 
     274                 :            :      }
     275                 :            : 
     276                 :            :      /* Now check option sequence */
     277                 :            : 
     278         [ #  # ]:          0 :     for (j=0;j<sig[id].optcnt;j++)
     279         [ #  # ]:          0 :       if (sig[id].opt[j] ^ sig[i].opt[j]) goto reloop;
     280                 :            : 
     281                 :          0 :     problems=1;
     282                 :            :     warn(fmt("OS fingerprinting: [!] Signature '%s %s' (line %d)\n"
     283                 :            :           "    is already covered by '%s %s' (line %d).",
     284                 :            :           sig[id].os,sig[id].desc,sig[id].line,sig[i].os,sig[i].desc,
     285                 :          0 :           sig[i].line));
     286                 :            : 
     287                 :          0 : reloop:
     288                 :            :     ;
     289                 :            :     }
     290                 :          0 :   }
     291                 :            : 
     292                 :            : // Loads a given file into to classes data structures.
     293                 :          0 : void OSFingerprint::load_config(const char* file)
     294                 :            :   {
     295                 :          0 :   uint32 ln=0;
     296                 :            :   char buf[MAXLINE];
     297                 :            :   char* p;
     298                 :          0 :   FILE* c = search_for_file( file, "osf", 0);
     299                 :            : 
     300         [ #  # ]:          0 :   if (!c)
     301                 :            :     {
     302                 :          0 :     Error("Can't open OS passive fingerprinting signature file", file);
     303                 :          0 :     return;
     304                 :            :     }
     305                 :          0 :   sigcnt=0; //every time we read config we reset it to 0;
     306         [ #  # ]:          0 :   while ((p=fgets(buf,sizeof(buf),c)))
     307                 :            :     {
     308                 :            :     uint32 l;
     309                 :            : 
     310                 :            :     char obuf[MAXLINE],genre[MAXLINE],desc[MAXLINE],quirks[MAXLINE];
     311                 :            :     char w[MAXLINE],sb[MAXLINE];
     312                 :          0 :     char* gptr = genre;
     313                 :            :     uint32 t,d,s;
     314                 :            :     struct fp_entry* e;
     315                 :            : 
     316                 :          0 :     ln++;
     317                 :            : 
     318                 :            :     /* Remove leading and trailing blanks */
     319         [ #  # ]:          0 :     while (isspace(*p)) p++;
     320                 :          0 :     l=strlen(p);
     321 [ #  # ][ #  # ]:          0 :     while (l && isspace(*(p+l-1))) *(p+(l--)-1)=0;
     322                 :            :         
     323                 :            :     /* Skip empty lines and comments */
     324         [ #  # ]:          0 :     if (!l) continue;
     325         [ #  # ]:          0 :     if (*p == '#') continue;
     326                 :            : 
     327         [ #  # ]:          0 :     if (sscanf(p,"%[0-9%*()ST]:%d:%d:%[0-9()*]:%[^:]:%[^ :]:%[^:]:%[^:]",
     328                 :            :                   w,         &t,&d,sb,     obuf, quirks,genre,desc) != 8)
     329                 :          0 :       Error("OS fingerprinting: Syntax error in p0f signature config line %d.\n",(uint32)ln);
     330                 :            : 
     331                 :          0 :     gptr = genre;
     332                 :            : 
     333         [ #  # ]:          0 :     if (*sb != '*') s = atoi(sb); else s = 0;
     334                 :            : 
     335                 :          0 : reparse_ptr:
     336                 :            : 
     337   [ #  #  #  #  :          0 :     switch (*gptr)
                      # ]
     338                 :            :       {
     339                 :          0 :       case '-': sig[sigcnt].userland = 1; gptr++; goto reparse_ptr;
     340                 :          0 :       case '*': sig[sigcnt].no_detail = 1; gptr++; goto reparse_ptr;
     341                 :          0 :       case '@': sig[sigcnt].generic = 1; gptr++; gencnt++; goto reparse_ptr;
     342                 :          0 :       case 0: Error("OS fingerprinting: Empty OS genre in line",(uint32)ln);
     343                 :            :       }
     344                 :            : 
     345                 :          0 :     sig[sigcnt].os     = strdup(gptr);
     346                 :          0 :     sig[sigcnt].desc   = strdup(desc);
     347                 :          0 :     sig[sigcnt].ttl    = t;
     348                 :          0 :     sig[sigcnt].size   = s;
     349                 :          0 :     sig[sigcnt].df     = d;
     350                 :            :  
     351         [ #  # ]:          0 :     if (w[0] == '*')
     352                 :            :       {
     353                 :          0 :       sig[sigcnt].wsize = 1;
     354                 :          0 :       sig[sigcnt].wsize_mod = MOD_CONST;
     355                 :            :       }
     356         [ #  # ]:          0 :     else if (tolower(w[0]) == 's')
     357                 :            :       {
     358                 :          0 :       sig[sigcnt].wsize_mod = MOD_MSS;
     359         [ #  # ]:          0 :       if (!isdigit(*(w+1)))
     360                 :          0 :         Error("OS fingerprinting: Bad Snn value in WSS in line",(uint32)ln);
     361                 :          0 :       sig[sigcnt].wsize = atoi(w+1);
     362                 :            :       }
     363         [ #  # ]:          0 :     else if (tolower(w[0]) == 't')
     364                 :            :       {
     365                 :          0 :       sig[sigcnt].wsize_mod = MOD_MTU;
     366         [ #  # ]:          0 :       if (!isdigit(*(w+1)))
     367                 :          0 :         Error("OS fingerprinting: Bad Tnn value in WSS in line",(uint32)ln);
     368                 :          0 :       sig[sigcnt].wsize = atoi(w+1);
     369                 :            :       }
     370         [ #  # ]:          0 :     else if (w[0] == '%')
     371                 :            :       {
     372         [ #  # ]:          0 :       if (!(sig[sigcnt].wsize = atoi(w+1)))
     373                 :          0 :         Error("OS fingerprinting: Null modulo for window size in config line",(uint32)ln);
     374                 :          0 :       sig[sigcnt].wsize_mod = MOD_CONST;
     375                 :            :       }
     376                 :            :     else
     377                 :          0 :       sig[sigcnt].wsize = atoi(w);
     378                 :            : 
     379                 :            :     /* Now let's parse options */
     380                 :            : 
     381                 :          0 :     p=obuf;
     382                 :            : 
     383                 :          0 :     sig[sigcnt].zero_stamp = 1;
     384                 :            : 
     385         [ #  # ]:          0 :     if (*p=='.') p++;
     386                 :            : 
     387         [ #  # ]:          0 :     while (*p)
     388                 :            :       {
     389                 :          0 :       uint8 optcnt = sig[sigcnt].optcnt;
     390 [ #  #  #  #  # :          0 :       switch (tolower(*p))
                #  #  # ]
     391                 :            :         {
     392                 :          0 :         case 'n': sig[sigcnt].opt[optcnt] = TCPOPT_NOP;
     393                 :          0 :                   break;
     394                 :            : 
     395                 :          0 :         case 'e': sig[sigcnt].opt[optcnt] = TCPOPT_EOL;
     396         [ #  # ]:          0 :                   if (*(p+1))
     397                 :          0 :                     Error("OS fingerprinting: EOL not the last option, line",(uint32)ln);
     398                 :          0 :                   break;
     399                 :            : 
     400                 :          0 :         case 's': sig[sigcnt].opt[optcnt] = TCPOPT_SACK_PERMITTED;
     401                 :          0 :                   break;
     402                 :            : 
     403                 :          0 :         case 't': sig[sigcnt].opt[optcnt] = TCPOPT_TIMESTAMP;
     404         [ #  # ]:          0 :                   if (*(p+1)!='0')
     405                 :            :                     {
     406                 :          0 :                     sig[sigcnt].zero_stamp=0;
     407         [ #  # ]:          0 :                     if (isdigit(*(p+1)))
     408                 :          0 :                       Error("OS fingerprinting: Bogus Tstamp specification in line",(uint32)ln);
     409                 :            :                     }
     410                 :          0 :                   break;
     411                 :            : 
     412                 :          0 :         case 'w': sig[sigcnt].opt[optcnt] = TCPOPT_WINDOW;
     413         [ #  # ]:          0 :                   if (p[1] == '*')
     414                 :            :                     {
     415                 :          0 :                     sig[sigcnt].wsc = 1;
     416                 :          0 :                     sig[sigcnt].wsc_mod = MOD_CONST;
     417                 :            :                     }
     418         [ #  # ]:          0 :                   else if (p[1] == '%')
     419                 :            :                     {
     420         [ #  # ]:          0 :                     if (!(sig[sigcnt].wsc = atoi(p+2)))
     421                 :          0 :                       Error("OS fingerprinting: Null modulo for wscale in config line",(uint32)ln);
     422                 :          0 :                     sig[sigcnt].wsc_mod = MOD_CONST;
     423                 :            :                     }
     424         [ #  # ]:          0 :                   else if (!isdigit(*(p+1)))
     425                 :          0 :                     Error("OS fingerprinting: Incorrect W value in line",(uint32)ln);
     426                 :          0 :                   else sig[sigcnt].wsc = atoi(p+1);
     427                 :          0 :                   break;
     428                 :            : 
     429                 :          0 :         case 'm': sig[sigcnt].opt[optcnt] = TCPOPT_MAXSEG;
     430         [ #  # ]:          0 :                   if (p[1] == '*')
     431                 :            :                     {
     432                 :          0 :                     sig[sigcnt].mss = 1;
     433                 :          0 :                     sig[sigcnt].mss_mod = MOD_CONST;
     434                 :            :                     }
     435         [ #  # ]:          0 :                   else if (p[1] == '%')
     436                 :            :                     {
     437         [ #  # ]:          0 :                     if (!(sig[sigcnt].mss = atoi(p+2)))
     438                 :          0 :                       Error("OS fingerprinting: Null modulo for MSS in config line",(uint32)ln);
     439                 :          0 :                     sig[sigcnt].mss_mod = MOD_CONST;
     440                 :            :                     }
     441         [ #  # ]:          0 :                   else if (!isdigit(*(p+1)))
     442                 :          0 :                     Error("OS fingerprinting: Incorrect M value in line",(uint32)ln);
     443                 :          0 :                   else sig[sigcnt].mss = atoi(p+1);
     444                 :          0 :                   break;
     445                 :            : 
     446                 :            :         /* Yuck! */
     447         [ #  # ]:          0 :         case '?': if (!isdigit(*(p+1)))
     448                 :          0 :                     Error("OS fingerprinting: Bogus ?nn value in line",(uint32)ln);
     449                 :          0 :                   else sig[sigcnt].opt[optcnt] = atoi(p+1);
     450                 :          0 :                   break;
     451                 :            : 
     452                 :          0 :         default: Error("OS fingerprinting: Unknown TCP option in config line",(uint32)ln);
     453                 :            :         }
     454                 :            : 
     455         [ #  # ]:          0 :       if (++sig[sigcnt].optcnt >= MAXOPT)
     456                 :          0 :         Error("OS fingerprinting: Too many TCP options specified in config line",(uint32)ln);
     457                 :            : 
     458                 :            :       /* Skip separators */
     459 [ #  # ][ #  # ]:          0 :       do { p++; } while (*p && !isalpha(*p) && *p != '?');
                 [ #  # ]
     460                 :            : 
     461                 :            :     }
     462                 :            :  
     463                 :          0 :     sig[sigcnt].line = ln;
     464                 :            : 
     465                 :          0 :     p = quirks;
     466                 :            : 
     467         [ #  # ]:          0 :     while (*p)
     468 [ #  #  #  #  # :          0 :       switch (toupper(*(p++)))
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
     469                 :            :         {
     470                 :            :         case 'E':
     471                 :          0 :           Error("OS fingerprinting: Quirk 'E' is obsolete. Remove it, append E to the options. Line",(uint32)ln);
     472                 :            : 
     473                 :            :         case 'K':
     474         [ #  # ]:          0 :           if ( mode != RST_FINGERPRINT_MODE )
     475                 :          0 :             Error("OS fingerprinting: Quirk 'K' is valid only in RST+ (-R) mode (wrong config file?). Line",(uint32)ln);
     476                 :          0 :           sig[sigcnt].quirks |= QUIRK_RSTACK;
     477                 :          0 :           break;
     478                 :            : 
     479                 :          0 :         case 'Q': sig[sigcnt].quirks |= QUIRK_SEQEQ; break;
     480                 :          0 :         case '0': sig[sigcnt].quirks |= QUIRK_SEQ0; break;
     481                 :          0 :         case 'P': sig[sigcnt].quirks |= QUIRK_PAST; break;
     482                 :          0 :         case 'Z': sig[sigcnt].quirks |= QUIRK_ZEROID; break;
     483                 :          0 :         case 'I': sig[sigcnt].quirks |= QUIRK_IPOPT; break;
     484                 :          0 :         case 'U': sig[sigcnt].quirks |= QUIRK_URG; break;
     485                 :          0 :         case 'X': sig[sigcnt].quirks |= QUIRK_X2; break;
     486                 :          0 :         case 'A': sig[sigcnt].quirks |= QUIRK_ACK; break;
     487                 :          0 :         case 'T': sig[sigcnt].quirks |= QUIRK_T2; break;
     488                 :          0 :         case 'F': sig[sigcnt].quirks |= QUIRK_FLAGS; break;
     489                 :          0 :         case 'D': sig[sigcnt].quirks |= QUIRK_DATA; break;
     490                 :          0 :         case '!': sig[sigcnt].quirks |= QUIRK_BROKEN; break;
     491                 :          0 :         case '.': break;
     492                 :          0 :         default: Error("OS fingerprinting: Bad quirk in line",(uint32)ln);
     493                 :            :         }
     494                 :            : 
     495                 :          0 :     e = bh[SIGHASH(s,sig[sigcnt].optcnt,sig[sigcnt].quirks,d)];
     496                 :            : 
     497         [ #  # ]:          0 :     if (!e)
     498                 :            :       {
     499                 :          0 :       bh[SIGHASH(s,sig[sigcnt].optcnt,sig[sigcnt].quirks,d)] = &sig[sigcnt];
     500                 :            :       }
     501                 :            :     else
     502                 :            :       {
     503         [ #  # ]:          0 :       while (e->next) e = e->next;
     504                 :          0 :       e->next = &sig[sigcnt];
     505                 :            :       }
     506                 :            : 
     507                 :          0 :     collide(sigcnt);
     508         [ #  # ]:          0 :     if (++sigcnt >= MAXSIGS)
     509                 :          0 :       Error("OS fingerprinting: Maximum signature count exceeded.\n");
     510                 :            : 
     511                 :            :     }
     512                 :            : 
     513                 :          0 :   fclose(c);
     514                 :            : 
     515         [ #  # ]:          0 :   if (!sigcnt)
     516                 :          0 :     Error("OS fingerprinting: no signatures loaded from config file.");
     517                 :            : 
     518                 :            :   }
     519                 :            : 
     520                 :            : // Does the actual match between the packet and the signature database.
     521                 :            : // Modifies retval and contains OS Type and other useful information.
     522                 :            : // Returns config-file line of the matching signature as id.
     523                 :            : int OSFingerprint::FindMatch(struct os_type* retval, uint16 tot,uint8 df,
     524                 :            :                               uint8 ttl,uint16 wss,uint8 ocnt,uint8* op,
     525                 :            :                               uint16 mss,uint8 wsc,uint32 tstamp,
     526                 :          0 :                               uint32 quirks,uint8 ecn) const
     527                 :            :   {
     528                 :            :   uint32 j; //used for counter in loops
     529                 :            :   struct fp_entry* p;
     530                 :          0 :   uint8  orig_df  = df;
     531                 :            : 
     532                 :          0 :   struct fp_entry* fuzzy = 0;
     533                 :          0 :   uint8 fuzzy_now = 0;
     534                 :          0 :   int id = 0; //return value: 0 indicates no match.
     535                 :            : 
     536                 :          0 :   retval->os="UNKNOWN";
     537                 :          0 :   retval->desc=NULL;
     538                 :          0 :   retval->gadgets=0;
     539                 :          0 :   retval->match=0;
     540                 :          0 :   retval->uptime=0;
     541                 :            : 
     542                 :          0 : re_lookup:
     543                 :            : 
     544                 :          0 :   p = bh[SIGHASH(tot,ocnt,quirks,df)];
     545                 :            : 
     546         [ #  # ]:          0 :   while (p)
     547                 :            :     {
     548                 :            :     /* Cheap and specific checks first... */
     549                 :            :     /* psize set to zero means >= PACKET_BIG */
     550 [ #  # ][ #  # ]:          0 :     if (p->size) { if (tot ^ p->size) { p = p->next; continue; } }
     551         [ #  # ]:          0 :       else if (tot < PACKET_BIG) { p = p->next; continue; }
     552                 :            : 
     553         [ #  # ]:          0 :     if (ocnt ^ p->optcnt) { p = p->next; continue; }
     554                 :            : 
     555         [ #  # ]:          0 :     if (p->zero_stamp ^ (!tstamp)) { p = p->next; continue; }
     556         [ #  # ]:          0 :     if (p->df ^ df) { p = p->next; continue; }
     557         [ #  # ]:          0 :     if (p->quirks ^ quirks) { p = p->next; continue; }
     558                 :            : 
     559                 :            :     /* Check MSS and WSCALE... */
     560         [ #  # ]:          0 :     if (!p->mss_mod) {
     561         [ #  # ]:          0 :       if (mss ^ p->mss) { p = p->next; continue; }
     562         [ #  # ]:          0 :     } else if (mss % p->mss) { p = p->next; continue; }
     563                 :            : 
     564         [ #  # ]:          0 :     if (!p->wsc_mod) {
     565         [ #  # ]:          0 :       if (wsc ^ p->wsc) { p = p->next; continue; }
     566         [ #  # ]:          0 :     } else if (wsc % p->wsc) { p = p->next; continue; }
     567                 :            : 
     568                 :            :     /* Then proceed with the most complex WSS check... */
     569   [ #  #  #  #  :          0 :     switch (p->wsize_mod)
                      # ]
     570                 :            :       {
     571                 :            :       case 0:
     572         [ #  # ]:          0 :         if (wss ^ p->wsize) { p = p->next; continue; }
     573                 :          0 :         break;
     574                 :            :       case MOD_CONST:
     575         [ #  # ]:          0 :         if (wss % p->wsize) { p = p->next; continue; }
     576                 :          0 :         break;
     577                 :            :       case MOD_MSS:
     578 [ #  # ][ #  # ]:          0 :         if (mss && !(wss % mss))
     579                 :            :           {
     580         [ #  # ]:          0 :           if ((wss / mss) ^ p->wsize) { p = p->next; continue; }
     581                 :            :           }
     582         [ #  # ]:          0 :         else if (!(wss % 1460))
     583                 :            :           {
     584         [ #  # ]:          0 :           if ((wss / 1460) ^ p->wsize) { p = p->next; continue; }
     585                 :            :           }
     586                 :          0 :         else { p = p->next; continue; }
     587                 :          0 :         break;
     588                 :            :       case MOD_MTU:
     589 [ #  # ][ #  # ]:          0 :         if (mss && !(wss % (mss+40)))
     590                 :            :           {
     591         [ #  # ]:          0 :           if ((wss / (mss+40)) ^ p->wsize) { p = p->next; continue; }
     592                 :            :           }
     593         [ #  # ]:          0 :         else if (!(wss % 1500))
     594                 :            :           {
     595         [ #  # ]:          0 :           if ((wss / 1500) ^ p->wsize) { p = p->next; continue; }
     596                 :            :           }
     597                 :          0 :         else { p = p->next; continue; }
     598                 :            :         break;
     599                 :            :       }
     600                 :            : 
     601                 :            :     /* Numbers agree. Let's check options */
     602         [ #  # ]:          0 :     for (j=0;j<ocnt;j++)
     603         [ #  # ]:          0 :       if (p->opt[j] ^ op[j]) goto continue_search;
     604                 :            : 
     605                 :            :     /* Check TTLs last because we might want to go fuzzy. */
     606         [ #  # ]:          0 :     if (p->ttl < ttl)
     607                 :            :       {
     608         [ #  # ]:          0 :       if ( mode != RST_FINGERPRINT_MODE )fuzzy = p;
     609                 :          0 :       p = p->next;
     610                 :          0 :       continue;
     611                 :            :       }
     612                 :            : 
     613                 :            :     /* Naah... can't happen ;-) */
     614         [ #  # ]:          0 :     if (!p->no_detail)
     615         [ #  # ]:          0 :       if (p->ttl - ttl > MAXDIST)
     616                 :            :         {
     617         [ #  # ]:          0 :         if (mode != RST_FINGERPRINT_MODE ) fuzzy = p;
     618                 :          0 :         p = p->next;
     619                 :          0 :         continue;
     620                 :            :         }
     621                 :            : 
     622                 :          0 : continue_fuzzy:
     623                 :            : 
     624                 :            :     /* Match! */
     625                 :          0 :     id = p->line;
     626         [ #  # ]:          0 :     if (mss & wss)
     627                 :            :       {
     628         [ #  # ]:          0 :       if (p->wsize_mod == MOD_MSS)
     629                 :            :         {
     630 [ #  # ][ #  # ]:          0 :         if ((wss % mss) && !(wss % 1460)) retval->gadgets|=GADGETNAT;
     631                 :            :         }
     632         [ #  # ]:          0 :       else if (p->wsize_mod == MOD_MTU)
     633                 :            :         {
     634 [ #  # ][ #  # ]:          0 :         if ((wss % (mss+40)) && !(wss % 1500)) retval->gadgets|=GADGETNAT2;
     635                 :            :         }
     636                 :            :       }
     637                 :            : 
     638                 :          0 :     retval->os=p->os;
     639                 :          0 :     retval->desc=p->desc;
     640                 :          0 :     retval->dist=p->ttl-ttl;
     641                 :            : 
     642         [ #  # ]:          0 :     if (ecn) retval->gadgets|=GADGETECN;
     643         [ #  # ]:          0 :     if (orig_df ^ df) retval->gadgets|=GADGETFIREWALL;
     644                 :            : 
     645         [ #  # ]:          0 :     if (p->generic) retval->match=MATCHGENERIC;
     646         [ #  # ]:          0 :     if (fuzzy_now) retval->match=MATCHFUZZY;
     647                 :            : 
     648 [ #  # ][ #  # ]:          0 :     if (!p->no_detail && tstamp)
     649                 :            :       {
     650                 :          0 :       retval->uptime=tstamp/360000;
     651                 :          0 :       retval->gadgets|=GADGETUPTIME;
     652                 :            :       }
     653                 :            : 
     654                 :          0 :     return id;
     655                 :            : 
     656                 :          0 : continue_search:
     657                 :            : 
     658                 :          0 :     p = p->next;
     659                 :            : 
     660                 :            :     }
     661                 :            : 
     662         [ #  # ]:          0 :   if (!df) { df = 1; goto re_lookup; } //not found with df=0 do df=1
     663                 :            : 
     664         [ #  # ]:          0 :   if (fuzzy)
     665                 :            :     {
     666                 :          0 :     df = orig_df;
     667                 :          0 :     fuzzy_now = 1;
     668                 :          0 :     p = fuzzy;
     669                 :          0 :     fuzzy = 0;
     670                 :          0 :     goto continue_fuzzy;
     671                 :            :     }
     672                 :            : 
     673         [ #  # ]:          0 :   if (mss & wss)
     674                 :            :     {
     675 [ #  # ][ #  # ]:          0 :     if ((wss % mss) && !(wss % 1460)) retval->gadgets|=GADGETNAT;
     676 [ #  # ][ #  # ]:          0 :     else if ((wss % (mss+40)) && !(wss % 1500)) retval->gadgets|=GADGETNAT2;
     677                 :            :     }
     678                 :            : 
     679         [ #  # ]:          0 :   if (ecn) retval->gadgets|=GADGETECN;
     680                 :            : 
     681         [ #  # ]:          0 :   if (tstamp)
     682                 :            :     {
     683                 :          0 :     retval->uptime=tstamp/360000;
     684                 :          0 :     retval->gadgets|=GADGETUPTIME;
     685                 :            :     }
     686                 :            : 
     687                 :          0 :   return id;
     688 [ +  - ][ +  - ]:          6 :   }

Generated by: LCOV version 1.8