Branch data Line data Source code
1 : : // $Id: Ident.cc 6219 2008-10-01 05:39:07Z vern $
2 : : //
3 : : // See the file "COPYING" in the main distribution directory for copyright.
4 : :
5 : : #include "config.h"
6 : :
7 : : #include <ctype.h>
8 : :
9 : : #include "NetVar.h"
10 : : #include "Ident.h"
11 : : #include "Event.h"
12 : : #include "TCP_Rewriter.h"
13 : :
14 : 0 : Ident_Analyzer::Ident_Analyzer(Connection* conn)
15 : 0 : : TCP_ApplicationAnalyzer(AnalyzerTag::Ident, conn)
16 : : {
17 : 0 : did_bad_reply = did_deliver = 0;
18 : :
19 : 0 : orig_ident = new ContentLine_Analyzer(conn, true);
20 : 0 : resp_ident = new ContentLine_Analyzer(conn, false);
21 : :
22 : 0 : orig_ident->SetIsNULSensitive(true);
23 : 0 : resp_ident->SetIsNULSensitive(true);
24 : :
25 : 0 : AddSupportAnalyzer(orig_ident);
26 : 0 : AddSupportAnalyzer(resp_ident);
27 : 0 : }
28 : :
29 : 0 : void Ident_Analyzer::Done()
30 : : {
31 : 0 : TCP_ApplicationAnalyzer::Done();
32 : :
33 [ # # ]: 0 : if ( TCP() )
34 [ # # ][ # # ]: 0 : if ( (! did_deliver || orig_ident->HasPartialLine()) &&
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
35 : : (TCP()->OrigState() == TCP_ENDPOINT_CLOSED ||
36 : : TCP()->OrigPrevState() == TCP_ENDPOINT_CLOSED) &&
37 : : TCP()->OrigPrevState() != TCP_ENDPOINT_PARTIAL &&
38 : : TCP()->RespPrevState() != TCP_ENDPOINT_PARTIAL &&
39 : : TCP()->OrigPrevState() != TCP_ENDPOINT_INACTIVE &&
40 : : TCP()->RespPrevState() != TCP_ENDPOINT_INACTIVE )
41 : 0 : Weird("partial_ident_request");
42 : 0 : }
43 : :
44 : 0 : void Ident_Analyzer::DeliverStream(int length, const u_char* data, bool is_orig)
45 : : {
46 : 0 : TCP_ApplicationAnalyzer::DeliverStream(length, data, is_orig);
47 : :
48 : : int remote_port, local_port;
49 : 0 : const char* line = (const char*) data;
50 : 0 : const char* orig_line = line;
51 : 0 : const char* end_of_line = line + length;
52 : :
53 : 0 : TCP_Endpoint* s = 0;
54 : :
55 [ # # ]: 0 : if ( TCP() )
56 [ # # ]: 0 : s = is_orig ? TCP()->Orig() : TCP()->Resp();
57 : :
58 [ # # ]: 0 : if ( is_orig )
59 : : {
60 [ # # ]: 0 : if ( ! ident_request )
61 : 0 : return;
62 : :
63 : 0 : line = ParsePair(line, end_of_line, remote_port, local_port);
64 [ # # ]: 0 : if ( ! line )
65 : : {
66 [ # # ][ # # ]: 0 : if ( s && s->state == TCP_ENDPOINT_CLOSED &&
[ # # ][ # # ]
67 : : (s->prev_state == TCP_ENDPOINT_INACTIVE ||
68 : : s->prev_state == TCP_ENDPOINT_PARTIAL) )
69 : : // not surprising the request is mangled.
70 : 0 : return;
71 : :
72 : 0 : BadRequest(length, orig_line);
73 : 0 : return;
74 : : }
75 : :
76 [ # # ]: 0 : if ( line != end_of_line )
77 : 0 : Weird("ident_request_addendum", length, orig_line);
78 : :
79 : 0 : val_list* vl = new val_list;
80 : 0 : vl->append(BuildConnVal());
81 : 0 : vl->append(new PortVal(local_port, TRANSPORT_TCP));
82 : 0 : vl->append(new PortVal(remote_port, TRANSPORT_TCP));
83 : :
84 : 0 : ConnectionEvent(ident_request, vl);
85 : :
86 : 0 : did_deliver = 1;
87 : : }
88 : :
89 : : else
90 : : {
91 [ # # ]: 0 : if ( ! ident_reply )
92 : 0 : return;
93 : :
94 : 0 : line = ParsePair(line, end_of_line, remote_port, local_port);
95 : :
96 [ # # # # ]: 0 : if ( ! line || line == end_of_line || line[0] != ':' )
[ # # ]
97 : : {
98 [ # # ][ # # ]: 0 : if ( s && s->state == TCP_ENDPOINT_CLOSED &&
[ # # ][ # # ]
99 : : (s->prev_state == TCP_ENDPOINT_INACTIVE ||
100 : : s->prev_state == TCP_ENDPOINT_PARTIAL) )
101 : : // not surprising the request is mangled.
102 : 0 : return;
103 : :
104 : 0 : BadReply(length, orig_line);
105 : 0 : return;
106 : : }
107 : :
108 : 0 : line = skip_whitespace(line + 1, end_of_line);
109 : 0 : int restlen = end_of_line - line;
110 : :
111 : : int is_error;
112 [ # # # # ]: 0 : if ( restlen >= 5 && ! strncmp(line, "ERROR", 5) )
113 : : {
114 : 0 : is_error = 1;
115 : 0 : line += 5;
116 : : }
117 [ # # ][ # # ]: 0 : else if ( restlen >= 6 && ! strncmp(line, "USERID", 6) )
118 : : {
119 : 0 : is_error = 0;
120 : 0 : line += 6;
121 : : }
122 : : else
123 : : {
124 : 0 : BadReply(length, orig_line);
125 : 0 : return;
126 : : }
127 : :
128 : 0 : line = skip_whitespace(line, end_of_line);
129 : :
130 [ # # # # ]: 0 : if ( line >= end_of_line || line[0] != ':' )
131 : : {
132 : 0 : BadReply(length, orig_line);
133 : 0 : return;
134 : : }
135 : :
136 : 0 : line = skip_whitespace(line + 1, end_of_line);
137 : :
138 [ # # ]: 0 : if ( is_error )
139 : : {
140 : 0 : val_list* vl = new val_list;
141 : 0 : vl->append(BuildConnVal());
142 : 0 : vl->append(new PortVal(local_port, TRANSPORT_TCP));
143 : 0 : vl->append(new PortVal(remote_port, TRANSPORT_TCP));
144 : 0 : vl->append(new StringVal(end_of_line - line, line));
145 : :
146 : 0 : ConnectionEvent(ident_error, vl);
147 : : }
148 : :
149 : : else
150 : : {
151 : 0 : const char* sys_type = line;
152 : 0 : const char* colon = strchr_n(line, end_of_line, ':');
153 : 0 : const char* comma = strchr_n(line, end_of_line, ',');
154 [ # # ]: 0 : if ( ! colon )
155 : : {
156 : 0 : BadReply(length, orig_line);
157 : 0 : return;
158 : : }
159 : :
160 : : const char* sys_end = (comma && comma < colon) ?
161 [ # # ][ # # ]: 0 : comma : colon;
162 : :
163 [ # # ][ # # ]: 0 : while ( --sys_end > sys_type && isspace(*sys_end) )
[ # # ]
164 : : ;
165 : :
166 : : BroString* sys_type_s =
167 : : new BroString((const u_char*) sys_type,
168 : 0 : sys_end - sys_type + 1, 1);
169 : :
170 : 0 : line = skip_whitespace(colon + 1, end_of_line);
171 : :
172 : 0 : val_list* vl = new val_list;
173 : 0 : vl->append(BuildConnVal());
174 : 0 : vl->append(new PortVal(local_port, TRANSPORT_TCP));
175 : 0 : vl->append(new PortVal(remote_port, TRANSPORT_TCP));
176 : 0 : vl->append(new StringVal(end_of_line - line, line));
177 : 0 : vl->append(new StringVal(sys_type_s));
178 : :
179 : 0 : ConnectionEvent(ident_reply, vl);
180 : : }
181 : : }
182 : : }
183 : :
184 : 0 : const char* Ident_Analyzer::ParsePair(const char* line, const char* end_of_line, int & p1, int& p2)
185 : : {
186 : 0 : line = ParsePort(line, end_of_line, p1);
187 [ # # ]: 0 : if ( ! line )
188 : : {
189 : 0 : return 0;
190 : : }
191 : :
192 [ # # ][ # # ]: 0 : if ( line >= end_of_line || line[0] != ',' )
193 : 0 : return 0;
194 : :
195 : 0 : ++line;
196 : :
197 : 0 : line = ParsePort(line, end_of_line, p2);
198 [ # # ]: 0 : if ( ! line )
199 : 0 : return 0;
200 : :
201 : 0 : return line;
202 : : }
203 : :
204 : : const char* Ident_Analyzer::ParsePort(const char* line, const char* end_of_line,
205 : 0 : int& pn)
206 : : {
207 : 0 : int n = 0;
208 : :
209 : 0 : line = skip_whitespace(line, end_of_line);
210 [ # # ]: 0 : if ( ! isdigit(*line) )
211 : 0 : return 0;
212 : :
213 : 0 : const char* l = line;
214 : :
215 [ # # ]: 0 : do
216 : : {
217 : 0 : n = n * 10 + (*line - '0');
218 : 0 : ++line;
219 : : }
220 : : while ( isdigit(*line) );
221 : :
222 : 0 : line = skip_whitespace(line, end_of_line);
223 : :
224 [ # # # # ]: 0 : if ( n < 0 || n > 65535 )
225 : : {
226 : 0 : Weird("bad_ident_port", l);
227 : 0 : n = 0;
228 : : }
229 : :
230 : 0 : pn = n;
231 : :
232 : 0 : return line;
233 : : }
234 : :
235 : 0 : void Ident_Analyzer::BadRequest(int length, const char* line)
236 : : {
237 : 0 : Weird("bad_ident_request", length, line);
238 : 0 : }
239 : :
240 : 0 : void Ident_Analyzer::BadReply(int length, const char* line)
241 : : {
242 [ # # ]: 0 : if ( ! did_bad_reply )
243 : : {
244 : 0 : Weird("bad_ident_reply", length, line);
245 : 0 : did_bad_reply = 1;
246 : : }
247 : 0 : }
248 : :
249 : : #include "ident-rw.bif.func_def"
250 : :
|