1 /*
2  * $Id: fp.h,v 1.6 2003/05/16 08:58:45 skyper Exp $
3  *
4  * Port State fingerprinting
5  */
6 
7 #ifndef __THCRUT_FP_H__
8 #define __THCRUT_FP_H__ 1
9 #include <pcre.h>
10 #include <libnet.h>
11 
12 /*
13  * We store category<->testnr value in one tuple.
14  *
15  * The introduction of categories was probably a design mistake.
16  * The idea was to have the tests sorted by category so that
17  * tests from one category can be performed before another category.
18  * It makes for example sense to run the banner-grapping tests
19  * before the open ports tests.
20  *
21  * We enumarate each tests so that we can look them up quickly when
22  * we have to make a decission if a test matches the results of a host.
23  * This would be easier with a linear number of tests and would
24  * not require a switchtable.
25  *
26  * To still have them sorted by category but linear numbered we should
27  * sort them after we read them in and do the enumeration after
28  * sorting (e.g. a for loop through all categories that copies the
29  * tests one by one). This would require to read in the file
30  * twice. First to load and sort the Testsuite itself, then to
31  * assign the testnumber to the single test-lines.
32  */
33 #define FP_TEST_CAT_NR(cat, nr)   (((nr & 0x1f) << 3) | (cat & 0x7))
34 #define FP_TEST_NR(test)    (((test)->testnr_cat & ~0x7) >> 3)
35 #define FP_TEST_CAT(test)   ((test)->testnr_cat & 0x7)
36 struct _fp_test
37 {
38 	pcre *pattern;
39 	pcre_extra *hints;
40 	unsigned char testnr_cat; /* Number and cat of this test */
41 	unsigned char flags;      /* port state */
42 	char *varname;            /* != NULL: It's a variable. use accuracy */
43 	                          /* value from variable-hash.              */
44 	char accuracy;            /* 1 for port, 2 for banner default */
45 };
46 
47 #define FP_TEST_CLOSED   0x01 /* same for UDP/TCP */
48 #define FP_TEST_OPEN     0x02
49 #define FP_TEST_REGEX    0x03 /* Must match string *str */
50 
51 /*
52  * One 'Fingerprint.*' line may be followed by many
53  * fingerprint test lines. Currently we allocate a new _fp for each
54  * of these lines even if they all point to the same Fingerprint.* line.
55  */
56 struct _fp
57 {
58 	struct _fp *next;
59 	unsigned int class;
60 	unsigned short ofs_string;
61 
62 	unsigned char n_tests;       /* Number of checks for THIS fp */
63 	struct _fp_test fp_tests[0]; /* we love C */
64 };
65 
66 
67 /*
68  * Type W is the www test.
69  * W test occupies 4 bytes of memory
70  * S test occupies 4 bytes of memory
71  * T and U test 2 bytes
72  *
73  * We can even use static char here. We dont expect the user
74  * to have more than 128 different ports.
75  *
76  * Testsuite must carry the human representation of the tests.
77  */
78 struct _fp_ts_test
79 {
80 	unsigned short port;
81 };
82 
83 struct _fp_category
84 {
85 	unsigned char n_tests;
86 	size_t size;  /* total size of bytes for results of this category */
87 	struct _fp_ts_test tests[32];
88 };
89 
90 /*
91  * If you change this you also want to change the 2 bit's in
92  * struct _state_fp
93  */
94 #define FP_CAT_TCP	0x00
95 #define FP_CAT_UDP	0x01
96 #define FP_CAT_BANNER	0x02
97 #define FP_CAT_WWW	0x03
98 #define FP_CAT_SNMP	0x04
99 #define FP_CAT_NVT	0x05
100 #define FP_CAT_SMB	0x06  /* RESERVED */
101 #define FP_CAT_RES3	0x07  /* RESERVERD */
102 #define FP_CAT_MAX	0x08  /* change state.h if exceeded */
103 
104 /*
105  * The performed tests are dynamic and read form the thcrut-os-fingerprints
106  * file. The access to the results of the tests is thus also
107  * dynamic.
108  */
109 struct _fp_testsuite
110 {
111 	int ofs_test_tcp;
112 	int ofs_test_udp;
113 	int ofs_test_banner;
114 	int ofs_test_www;
115 	int ofs_test_snmp;
116 	int ofs_test_nvt;
117 	unsigned char  n_tests; /* Total number of different tests in fp-file */
118 	struct _fp_category cat[6];
119 
120 	unsigned char *strings;
121 	struct _fp *fps;  /* Linked list of Fingerprints */
122 };
123 /*
124  * Required size for the results of the unique tests.
125  */
126 #define FP_WTEST_SZ     (64)   /* HEAD / test output  */
127 #define FP_BTEST_SZ	(128)  /* Banner test         */
128 #define FP_STEST_SZ	(128)  /* SNMP test           */
129 #define FP_NTEST_SZ	(128)  /* NVT Terminal        */
130 
131 struct _fp_nodequery
132 {
133 	unsigned short trans_id;
134 	unsigned short flags;
135 	unsigned short questions;
136 	unsigned short answers;
137 	unsigned short auth_rrs;
138 	unsigned short add_rrs;
139 };
140 
141 /*
142  * Right now all variables are stored lineary.
143  * We do not expect to have more than 50
144  */
145 struct _fp_vararray
146 {
147 	unsigned short ofs_varname;
148 	char accuracy;
149 	struct _fp_tests *tests;    /* Linked list of Tests for this Varname */
150 };
151 
152 /*
153  * Windows NODE query request (port 137).
154  * How dirty to use a static request but it never changes unless
155  * MS decides to change their protocol suite. This wont happen :>
156  */
157 #define FP_NODEQUERY "\x20\x43\x4b\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x00\x00\x21\x00\x01"
158 #define FP_NODEQUERY_LEN (38)
159 
160 /*
161  * WIndows DCE bind request.
162  */
163 #define FP_DCEBIND "\x05\x00\x0b\x03\x10\x00\x00\x00\x48\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x10\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x08\x83\xaf\xe1\x1f\x5d\xc9\x11\x91\xa4\x08\x00\x2b\x14\xa0\xfa\x03\x00\x00\x00\x04\x5d\x88\x8a\xeb\x1c\xc9\x11\x9f\xe8\x08\x00\x2b\x10\x48\x60\x02\x00\x00\x00"
164 /* It is actually enough to send 1 byte of payload to trigger windows for a
165  * reject packet.
166  */
167 #define FP_DCEBIND_LEN (50)
168 
169 /*
170  * SNMP 'public' GET-NEXT system.sysDescr.0
171  */
172 #define FP_SNMP "\x30\x82\x00\x27\x02\x01\x00\x04\x06\x70\x75\x62\x6c\x69\x63\xa1\x1a\x02\x01\x01\x02\x01\x00\x02\x01\x00\x30\x0f\x30\x82\x00\x0b\x06\x07\x2b\x06\x01\x02\x01\x01\x00\x05\x00"
173 #define FP_SNMP_LEN (43)
174 
175 #define FP_MAX_LEN (50)
176 
177 union _classid
178 {
179 	struct
180 	{
181 #if LIBNET_BIG_ENDIAN
182 		unsigned int genre:9;
183 		unsigned int vendor:6;
184 		unsigned int os:5;
185                 /* 9 + 6 + 5 = 20 bits */
186 		unsigned int d:4;
187 		unsigned int dd:4;
188 		unsigned int ddd:4;
189 #elif LIBNET_LIL_ENDIAN
190 		unsigned int ddd:4;
191 		unsigned int dd:4;
192 		unsigned int d:4;
193                 /* 9 + 6 + 5 = 20 bits */
194 		unsigned int os:5;
195 		unsigned int vendor:6;
196 		unsigned int genre:9;
197 #endif
198 	} st;
199 	unsigned int id;
200 };
201 
202 
203 int FP_TS_load(struct _fp_testsuite *fpts, const char *filename);
204 void FP_TS_dump(struct _fp_testsuite *fpts);
205 char *FP_class2str(char *dst, unsigned int val);
206 unsigned int FP_class2int(const char *input);
207 
208 #endif /* !__THCRUT_FP_H__ */
209