xref: /aosp_15_r20/external/scapy/test/p0f.uts (revision 7dc08ffc4802948ccbc861daaf1e81c405c2c4bd)
1*7dc08ffcSJunyu Lai% Tests for Scapy's p0f module.
2*7dc08ffcSJunyu Lai
3*7dc08ffcSJunyu Lai~ p0f
4*7dc08ffcSJunyu Lai
5*7dc08ffcSJunyu Lai
6*7dc08ffcSJunyu Lai############
7*7dc08ffcSJunyu Lai############
8*7dc08ffcSJunyu Lai+ Basic p0f module tests
9*7dc08ffcSJunyu Lai
10*7dc08ffcSJunyu Lai= Module loading
11*7dc08ffcSJunyu Laiload_module('p0f')
12*7dc08ffcSJunyu Lai
13*7dc08ffcSJunyu Lai= Fetch database
14*7dc08ffcSJunyu Laifrom __future__ import print_function
15*7dc08ffcSJunyu Laitry:
16*7dc08ffcSJunyu Lai    from urllib.request import urlopen
17*7dc08ffcSJunyu Laiexcept ImportError:
18*7dc08ffcSJunyu Lai    from urllib2 import urlopen
19*7dc08ffcSJunyu Lai
20*7dc08ffcSJunyu Laidef _load_database(file):
21*7dc08ffcSJunyu Lai    for i in range(10):
22*7dc08ffcSJunyu Lai        try:
23*7dc08ffcSJunyu Lai            open(file, 'wb').write(urlopen('https://raw.githubusercontent.com/p0f/p0f/4b4d1f384abebbb9b1b25b8f3c6df5ad7ab365f7/' + file).read())
24*7dc08ffcSJunyu Lai            break
25*7dc08ffcSJunyu Lai        except:
26*7dc08ffcSJunyu Lai            raise
27*7dc08ffcSJunyu Lai            pass
28*7dc08ffcSJunyu Lai
29*7dc08ffcSJunyu Lai_load_database("p0f.fp")
30*7dc08ffcSJunyu Laiconf.p0f_base = "p0f.fp"
31*7dc08ffcSJunyu Lai_load_database("p0fa.fp")
32*7dc08ffcSJunyu Laiconf.p0fa_base = "p0fa.fp"
33*7dc08ffcSJunyu Lai_load_database("p0fr.fp")
34*7dc08ffcSJunyu Laiconf.p0fr_base = "p0fr.fp"
35*7dc08ffcSJunyu Lai_load_database("p0fo.fp")
36*7dc08ffcSJunyu Laiconf.p0fo_base = "p0fo.fp"
37*7dc08ffcSJunyu Lai
38*7dc08ffcSJunyu Laip0f_load_knowledgebases()
39*7dc08ffcSJunyu Lai
40*7dc08ffcSJunyu Lai############
41*7dc08ffcSJunyu Lai############
42*7dc08ffcSJunyu Lai+ Default tests
43*7dc08ffcSJunyu Lai
44*7dc08ffcSJunyu Lai= Test p0f
45*7dc08ffcSJunyu Lai
46*7dc08ffcSJunyu Laipkt = 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*7dc08ffcSJunyu Lai
48*7dc08ffcSJunyu Laiassert p0f(pkt) == [('@Windows', 'XP/2000 (RFC1323+, w+, tstamp-)', 0)]
49*7dc08ffcSJunyu Lai
50*7dc08ffcSJunyu Lai= Test prnp0f
51*7dc08ffcSJunyu Lai
52*7dc08ffcSJunyu Laiwith ContextManagerCaptureOutput() as cmco:
53*7dc08ffcSJunyu Lai    prnp0f(pkt)
54*7dc08ffcSJunyu Lai    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*7dc08ffcSJunyu Lai
56*7dc08ffcSJunyu Lai############
57*7dc08ffcSJunyu Lai############
58*7dc08ffcSJunyu Lai+ Tests for p0f_impersonate
59*7dc08ffcSJunyu Lai
60*7dc08ffcSJunyu Lai# XXX: a lot of pieces of p0f_impersonate don't have tests yet.
61*7dc08ffcSJunyu Lai
62*7dc08ffcSJunyu Lai= Impersonate when window size must be multiple of some integer
63*7dc08ffcSJunyu Laisig = ('%467', 64, 1, 60, 'M*,W*', '.', 'Phony Sys', '1.0')
64*7dc08ffcSJunyu Laipkt = p0f_impersonate(IP()/TCP(), signature=sig)
65*7dc08ffcSJunyu Laiassert pkt.payload.window % 467 == 0
66*7dc08ffcSJunyu Lai
67*7dc08ffcSJunyu Lai= Handle unusual flags ("F") quirk
68*7dc08ffcSJunyu Laisig = ('1024', 64, 0, 60, 'W*', 'F', 'Phony Sys', '1.0')
69*7dc08ffcSJunyu Laipkt = p0f_impersonate(IP()/TCP(), signature=sig)
70*7dc08ffcSJunyu Laiassert (pkt.payload.flags & 40) in (8, 32, 40)
71*7dc08ffcSJunyu Lai
72*7dc08ffcSJunyu Lai= Use valid option values from original packet
73*7dc08ffcSJunyu Laisig = ('S4', 64, 1, 60, 'M*,W*,T', '.', 'Phony Sys', '1.0')
74*7dc08ffcSJunyu Laiopts = [('MSS', 1400), ('WScale', 3), ('Timestamp', (97256, 0))]
75*7dc08ffcSJunyu Laipkt = p0f_impersonate(IP()/TCP(options=opts), signature=sig)
76*7dc08ffcSJunyu Laiassert pkt.payload.options == opts
77*7dc08ffcSJunyu Lai
78*7dc08ffcSJunyu Lai= Use valid option values when multiples required
79*7dc08ffcSJunyu Laisig = ('S4', 64, 1, 60, 'M%37,W%19', '.', 'Phony Sys', '1.0')
80*7dc08ffcSJunyu Laiopts = [('MSS', 37*15), ('WScale', 19*12)]
81*7dc08ffcSJunyu Laipkt = p0f_impersonate(IP()/TCP(options=opts), signature=sig)
82*7dc08ffcSJunyu Laiassert pkt.payload.options == opts
83*7dc08ffcSJunyu Lai
84*7dc08ffcSJunyu Lai= Discard non-multiple option values when multiples required
85*7dc08ffcSJunyu Laisig = ('S4', 64, 1, 60, 'M%37,W%19', '.', 'Phony Sys', '1.0')
86*7dc08ffcSJunyu Laiopts = [('MSS', 37*15 + 1), ('WScale', 19*12 + 1)]
87*7dc08ffcSJunyu Laipkt = p0f_impersonate(IP()/TCP(options=opts), signature=sig)
88*7dc08ffcSJunyu Laiassert pkt.payload.options[0][1] % 37 == 0
89*7dc08ffcSJunyu Laiassert pkt.payload.options[1][1] % 19 == 0
90*7dc08ffcSJunyu Lai
91*7dc08ffcSJunyu Lai= Discard bad timestamp values
92*7dc08ffcSJunyu Laisig = ('S4', 64, 1, 60, 'M*,T', '.', 'Phony Sys', '1.0')
93*7dc08ffcSJunyu Laiopts = [('Timestamp', (0, 1000))]
94*7dc08ffcSJunyu Laipkt = p0f_impersonate(IP()/TCP(options=opts), signature=sig)
95*7dc08ffcSJunyu Lai# since option is "T" and not "T0":
96*7dc08ffcSJunyu Laiassert pkt.payload.options[1][1][0] > 0
97*7dc08ffcSJunyu Lai# since T quirk is not present:
98*7dc08ffcSJunyu Laiassert pkt.payload.options[1][1][1] == 0
99*7dc08ffcSJunyu Lai
100*7dc08ffcSJunyu Lai= Discard 2nd timestamp of 0 if "T" quirk is present
101*7dc08ffcSJunyu Laisig = ('S4', 64, 1, 60, 'M*,T', 'T', 'Phony Sys', '1.0')
102*7dc08ffcSJunyu Laiopts = [('Timestamp', (54321, 0))]
103*7dc08ffcSJunyu Laipkt = p0f_impersonate(IP()/TCP(options=opts), signature=sig)
104*7dc08ffcSJunyu Laiassert pkt.payload.options[1][1][1] > 0
105*7dc08ffcSJunyu Lai
106*7dc08ffcSJunyu Lai+ Clear temp files
107*7dc08ffcSJunyu Lai
108*7dc08ffcSJunyu Lai= Remove fp files
109*7dc08ffcSJunyu Laidef _rem(f):
110*7dc08ffcSJunyu Lai    try:
111*7dc08ffcSJunyu Lai        os.remove(f)
112*7dc08ffcSJunyu Lai    except:
113*7dc08ffcSJunyu Lai        pass
114*7dc08ffcSJunyu Lai
115*7dc08ffcSJunyu Lai_rem("p0f.fp")
116*7dc08ffcSJunyu Lai_rem("p0fa.fp")
117*7dc08ffcSJunyu Lai_rem("p0fr.fp")
118*7dc08ffcSJunyu Lai_rem("p0fo.fp")