Home | History | Annotate | Download | only in test
      1 % Tests for Scapy's p0f module.
      2 
      3 ~ p0f
      4 
      5 
      6 ############
      7 ############
      8 + Basic p0f module tests
      9 
     10 = Module loading
     11 load_module('p0f')
     12 
     13 = Fetch database
     14 from __future__ import print_function
     15 try:
     16     from urllib.request import urlopen
     17 except ImportError:
     18     from urllib2 import urlopen
     19 
     20 def _load_database(file):
     21     for i in range(10):
     22         try:
     23             open(file, 'wb').write(urlopen('https://raw.githubusercontent.com/p0f/p0f/4b4d1f384abebbb9b1b25b8f3c6df5ad7ab365f7/' + file).read())
     24             break
     25         except:
     26             raise
     27             pass
     28 
     29 _load_database("p0f.fp")
     30 conf.p0f_base = "p0f.fp"
     31 _load_database("p0fa.fp")
     32 conf.p0fa_base = "p0fa.fp"
     33 _load_database("p0fr.fp")
     34 conf.p0fr_base = "p0fr.fp"
     35 _load_database("p0fo.fp")
     36 conf.p0fo_base = "p0fo.fp"
     37 
     38 p0f_load_knowledgebases()
     39 
     40 ############
     41 ############
     42 + Default tests
     43 
     44 = Test p0f
     45 
     46 pkt = Ether(b'\x14\x0cv\x8f\xfe(\xd0P\x99V\xdd\xf9\x08\x00E\x00\x0045+@\x00\x80\x06\x00\x00\xc0\xa8\x00w(M\xe2\xf9\xda\xcb\x01\xbbcc\xdd\x1e\x00\x00\x00\x00\x80\x02\xfa\xf0\xcc\x8c\x00\x00\x02\x04\x05\xb4\x01\x03\x03\x08\x01\x01\x04\x02')
     47 
     48 assert p0f(pkt) == [('@Windows', 'XP/2000 (RFC1323+, w+, tstamp-)', 0)]
     49 
     50 = Test prnp0f
     51 
     52 with ContextManagerCaptureOutput() as cmco:
     53     prnp0f(pkt)
     54     assert cmco.get_output() == '192.168.0.119:56011 - @Windows XP/2000 (RFC1323+, w+, tstamp-)\n  -> 40.77.226.249:https (S) (distance 0)\n'
     55 
     56 ############
     57 ############
     58 + Tests for p0f_impersonate
     59 
     60 # XXX: a lot of pieces of p0f_impersonate don't have tests yet.
     61 
     62 = Impersonate when window size must be multiple of some integer
     63 sig = ('%467', 64, 1, 60, 'M*,W*', '.', 'Phony Sys', '1.0')
     64 pkt = p0f_impersonate(IP()/TCP(), signature=sig)
     65 assert pkt.payload.window % 467 == 0
     66 
     67 = Handle unusual flags ("F") quirk
     68 sig = ('1024', 64, 0, 60, 'W*', 'F', 'Phony Sys', '1.0')
     69 pkt = p0f_impersonate(IP()/TCP(), signature=sig)
     70 assert (pkt.payload.flags & 40) in (8, 32, 40)
     71 
     72 = Use valid option values from original packet
     73 sig = ('S4', 64, 1, 60, 'M*,W*,T', '.', 'Phony Sys', '1.0')
     74 opts = [('MSS', 1400), ('WScale', 3), ('Timestamp', (97256, 0))]
     75 pkt = p0f_impersonate(IP()/TCP(options=opts), signature=sig)
     76 assert pkt.payload.options == opts
     77 
     78 = Use valid option values when multiples required
     79 sig = ('S4', 64, 1, 60, 'M%37,W%19', '.', 'Phony Sys', '1.0')
     80 opts = [('MSS', 37*15), ('WScale', 19*12)]
     81 pkt = p0f_impersonate(IP()/TCP(options=opts), signature=sig)
     82 assert pkt.payload.options == opts
     83 
     84 = Discard non-multiple option values when multiples required
     85 sig = ('S4', 64, 1, 60, 'M%37,W%19', '.', 'Phony Sys', '1.0')
     86 opts = [('MSS', 37*15 + 1), ('WScale', 19*12 + 1)]
     87 pkt = p0f_impersonate(IP()/TCP(options=opts), signature=sig)
     88 assert pkt.payload.options[0][1] % 37 == 0
     89 assert pkt.payload.options[1][1] % 19 == 0
     90 
     91 = Discard bad timestamp values
     92 sig = ('S4', 64, 1, 60, 'M*,T', '.', 'Phony Sys', '1.0')
     93 opts = [('Timestamp', (0, 1000))]
     94 pkt = p0f_impersonate(IP()/TCP(options=opts), signature=sig)
     95 # since option is "T" and not "T0":
     96 assert pkt.payload.options[1][1][0] > 0
     97 # since T quirk is not present:
     98 assert pkt.payload.options[1][1][1] == 0
     99 
    100 = Discard 2nd timestamp of 0 if "T" quirk is present
    101 sig = ('S4', 64, 1, 60, 'M*,T', 'T', 'Phony Sys', '1.0')
    102 opts = [('Timestamp', (54321, 0))]
    103 pkt = p0f_impersonate(IP()/TCP(options=opts), signature=sig)
    104 assert pkt.payload.options[1][1][1] > 0
    105 
    106 + Clear temp files
    107 
    108 = Remove fp files
    109 def _rem(f):
    110     try:
    111         os.remove(f)
    112     except:
    113         pass
    114 
    115 _rem("p0f.fp")
    116 _rem("p0fa.fp")
    117 _rem("p0fr.fp")
    118 _rem("p0fo.fp")