Branch data Line data Source code
1 : : // $Id: FTP.cc 6782 2009-06-28 02:19:03Z vern $
2 : : //
3 : : // See the file "COPYING" in the main distribution directory for copyright.
4 : :
5 : : #include "config.h"
6 : :
7 : : #include <stdlib.h>
8 : :
9 : : #include "NetVar.h"
10 : : #include "FTP.h"
11 : : #include "NVT.h"
12 : : #include "Event.h"
13 : : #include "TCP_Rewriter.h"
14 : :
15 : 0 : FTP_Analyzer::FTP_Analyzer(Connection* conn)
16 : 0 : : TCP_ApplicationAnalyzer(AnalyzerTag::FTP, conn)
17 : : {
18 : 0 : pending_reply = 0;
19 : :
20 : 0 : nvt_orig = new NVT_Analyzer(conn, true);
21 : 0 : nvt_orig->SetIsNULSensitive(true);
22 : 0 : nvt_orig->SetIsNULSensitive(true);
23 : 0 : nvt_orig->SetCRLFAsEOL(LF_as_EOL);
24 : 0 : nvt_orig->SetIsNULSensitive(LF_as_EOL);
25 : :
26 : 0 : nvt_resp = new NVT_Analyzer(conn, false);
27 : 0 : nvt_resp->SetIsNULSensitive(true);
28 : 0 : nvt_resp->SetIsNULSensitive(true);
29 : 0 : nvt_resp->SetCRLFAsEOL(LF_as_EOL);
30 : 0 : nvt_resp->SetIsNULSensitive(LF_as_EOL);
31 : :
32 : 0 : nvt_resp->SetPeer(nvt_orig);
33 : 0 : nvt_orig->SetPeer(nvt_resp);
34 : :
35 : 0 : AddSupportAnalyzer(nvt_orig);
36 : 0 : AddSupportAnalyzer(nvt_resp);
37 : 0 : }
38 : :
39 : 0 : void FTP_Analyzer::Done()
40 : : {
41 : 0 : TCP_ApplicationAnalyzer::Done();
42 : :
43 [ # # # # ]: 0 : if ( nvt_orig->HasPartialLine() &&
[ # # ][ # # ]
44 : : (TCP()->OrigState() == TCP_ENDPOINT_CLOSED ||
45 : : TCP()->OrigPrevState() == TCP_ENDPOINT_CLOSED) )
46 : : // ### should include the partial text
47 : 0 : Weird("partial_ftp_request");
48 : 0 : }
49 : :
50 : 0 : void FTP_Analyzer::DeliverStream(int length, const u_char* data, bool orig)
51 : : {
52 : 0 : TCP_ApplicationAnalyzer::DeliverStream(length, data, orig);
53 : :
54 [ # # # # ]: 0 : if ( (orig && ! ftp_request) || (! orig && ! ftp_reply) )
[ # # ][ # # ]
[ # # ]
55 : 0 : return;
56 : :
57 : : // const char* orig_line = line;
58 : 0 : const char* line = (const char*) data;
59 : 0 : const char* end_of_line = line + length;
60 : :
61 : 0 : val_list* vl = new val_list;
62 : 0 : vl->append(BuildConnVal());
63 : :
64 : 0 : EventHandlerPtr f;
65 [ # # ]: 0 : if ( orig )
66 : : {
67 : : int cmd_len;
68 : : const char* cmd;
69 : : StringVal* cmd_str;
70 : :
71 : 0 : line = skip_whitespace(line, end_of_line);
72 : 0 : get_word(length, line, cmd_len, cmd);
73 : 0 : line = skip_whitespace(line + cmd_len, end_of_line);
74 : :
75 [ # # ]: 0 : if ( cmd_len == 0 )
76 : : {
77 : : // Weird("FTP command missing", end_of_line - orig_line, orig_line);
78 : 0 : cmd_str = new StringVal("<missing>");
79 : : }
80 : : else
81 : 0 : cmd_str = (new StringVal(cmd_len, cmd))->ToUpper();
82 : :
83 : 0 : vl->append(cmd_str);
84 : 0 : vl->append(new StringVal(end_of_line - line, line));
85 : :
86 : 0 : f = ftp_request;
87 : 0 : ProtocolConfirmation();
88 : :
89 [ # # ]: 0 : if ( strncmp((const char*) cmd_str->Bytes(),
90 : : "AUTH", cmd_len) == 0 )
91 : 0 : auth_requested = string(line, end_of_line - line);
92 : :
93 [ # # ]: 0 : if ( rule_matcher )
94 : : Conn()->Match(Rule::FTP, (const u_char *) cmd,
95 : 0 : end_of_line - cmd, true, true, 1, true);
96 : : }
97 : : else
98 : : {
99 : : uint32 reply_code;
100 [ # # ][ # # ]: 0 : if ( length >= 3 &&
[ # # ][ # # ]
101 : : isdigit(line[0]) && isdigit(line[1]) && isdigit(line[2]) )
102 : : {
103 : : reply_code = (line[0] - '0') * 100 +
104 : : (line[1] - '0') * 10 +
105 : 0 : (line[2] - '0');
106 : : }
107 : : else
108 : 0 : reply_code = 0;
109 : :
110 : : int cont_resp;
111 : :
112 [ # # ]: 0 : if ( pending_reply )
113 : : {
114 [ # # ][ # # ]: 0 : if ( reply_code == pending_reply &&
[ # # ]
115 : : length > 3 && line[3] == ' ' )
116 : : {
117 : : // This is the end of the reply.
118 : 0 : line = skip_whitespace(line + 3, end_of_line);
119 : 0 : pending_reply = 0;
120 : 0 : cont_resp = 0;
121 : : }
122 : : else
123 : : {
124 : 0 : cont_resp = 1; // not the end
125 : 0 : reply_code = 0; // flag as intermediary
126 : : }
127 : : }
128 : : else
129 : : { // a new reply
130 [ # # ][ # # ]: 0 : if ( reply_code > 0 && length > 3 && line[3] == '-' )
[ # # ]
131 : : { // a continued reply
132 : 0 : pending_reply = reply_code;
133 : 0 : line = skip_whitespace(line + 4, end_of_line);
134 : 0 : cont_resp = 1;
135 : : }
136 : : else
137 : : { // a self-contained reply
138 [ # # ]: 0 : if ( reply_code > 0 )
139 : 0 : line += 3;
140 : : else
141 : : ProtocolViolation("non-numeric reply code",
142 : 0 : (const char*) data, length);
143 : :
144 [ # # ]: 0 : if ( line < end_of_line )
145 : 0 : line = skip_whitespace(line, end_of_line);
146 : : else
147 : 0 : line = end_of_line;
148 : :
149 [ # # ][ # # ]: 0 : if ( auth_requested.size() > 0 &&
[ # # ][ # # ]
150 : : (reply_code == 234 || reply_code == 335) )
151 : : // Server accepted AUTH requested,
152 : : // which means that very likely we
153 : : // won't be able to parse the rest
154 : : // of the session, and thus we stop
155 : : // here.
156 : 0 : SetSkip(true);
157 : :
158 : 0 : cont_resp = 0;
159 : : }
160 : : }
161 : :
162 : 0 : vl->append(new Val(reply_code, TYPE_COUNT));
163 : 0 : vl->append(new StringVal(end_of_line - line, line));
164 : 0 : vl->append(new Val(cont_resp, TYPE_BOOL));
165 : :
166 : 0 : f = ftp_reply;
167 : : }
168 : :
169 : 0 : ConnectionEvent(f, vl);
170 : : }
171 : :
172 : :
173 : : #include "ftp-rw.bif.func_def"
|