1 //--------------------------------------------------------------------------
2 // Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
3 // Copyright (C) 2004-2013 Sourcefire, Inc.
4 //
5 // This program is free software; you can redistribute it and/or modify it
6 // under the terms of the GNU General Public License Version 2 as published
7 // by the Free Software Foundation. You may not use, modify or distribute
8 // this program under any other version of the GNU General Public License.
9 //
10 // This program is distributed in the hope that it will be useful, but
11 // WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License along
16 // with this program; if not, write to the Free Software Foundation, Inc.,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 //--------------------------------------------------------------------------
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "main/snort_config.h"
25 #include "managers/inspector_manager.h"
26 #include "profiler/profiler.h"
27 #include "protocols/packet.h"
28 #include "stream/stream.h"
29 #include "target_based/snort_protocols.h"
30 #include "utils/util.h"
31
32 #include "ft_main.h"
33 #include "ftp_cmd_lookup.h"
34 #include "ftp_data.h"
35 #include "ftp_module.h"
36 #include "ftp_parse.h"
37 #include "ftp_print.h"
38 #include "ftp_splitter.h"
39 #include "ftpp_return_codes.h"
40 #include "ftpp_si.h"
41 #include "pp_ftp.h"
42 #include "telnet.h"
43
44 using namespace snort;
45
46 SnortProtocolId ftp_data_snort_protocol_id = UNKNOWN_PROTOCOL_ID;
47
48 #define client_help "FTP inspector client module"
49 #define server_help "FTP inspector server module"
50
51 THREAD_LOCAL ProfileStats ftpPerfStats;
52 THREAD_LOCAL FtpStats ftstats;
53
54 //-------------------------------------------------------------------------
55 // implementation stuff
56 //-------------------------------------------------------------------------
57
InspectClientPacket(Packet * p)58 static inline int InspectClientPacket(Packet* p)
59 {
60 return p->has_paf_payload();
61 }
62
SnortFTP(FTP_SESSION * FTPsession,Packet * p,int iInspectMode)63 static int SnortFTP(
64 FTP_SESSION* FTPsession, Packet* p, int iInspectMode)
65 {
66 Profile profile(ftpPerfStats);
67
68 if ( !FTPsession || !FTPsession->server_conf || !FTPsession->client_conf )
69 return FTPP_INVALID_SESSION;
70
71 if ( !FTPsession->server_conf->check_encrypted_data )
72 {
73 if ( FTPsession->encr_state == AUTH_TLS_ENCRYPTED ||
74 FTPsession->encr_state == AUTH_SSL_ENCRYPTED ||
75 FTPsession->encr_state == AUTH_UNKNOWN_ENCRYPTED )
76
77 return FTPP_SUCCESS;
78 }
79
80 if (iInspectMode == FTPP_SI_SERVER_MODE)
81 {
82 // FIXIT-L breaks target-based non-standard ports
83 //if ( !ScPafEnabled() )
84 Stream::flush_client(p);
85 }
86 else if ( !InspectClientPacket(p) )
87 return FTPP_SUCCESS;
88
89 int ret = initialize_ftp(FTPsession, p, iInspectMode);
90 if ( ret )
91 return ret;
92
93 ret = check_ftp(FTPsession, p, iInspectMode);
94 if ( ret == FTPP_SUCCESS )
95 {
96 // FIXIT-L ideally do_detection will look at the cmd & param buffers
97 // or the rsp & msg buffers. We should call it from inside check_ftp
98 // each time we process a pipelined FTP command.
99
100 do_detection(p);
101 }
102
103 return ret;
104 }
105
snort_ftp(Packet * p)106 static int snort_ftp(Packet* p)
107 {
108 FTPP_SI_INPUT SiInput;
109 int iInspectMode = FTPP_SI_NO_MODE;
110 FTP_TELNET_SESSION* ft_ssn = nullptr;
111
112 /*
113 * Set up the FTPP_SI_INPUT pointer. This is what the session_inspection()
114 * routines use to determine client and server traffic. Plus, this makes
115 * the FTPTelnet library very independent from snort.
116 */
117 SetSiInput(&SiInput, p);
118
119 ftstats.total_bytes += p->dsize;
120 if (p->flow)
121 {
122 FtpFlowData* fd = (FtpFlowData*)p->flow->get_flow_data(FtpFlowData::inspector_id);
123 ft_ssn = fd ? &fd->session.ft_ssn : nullptr;
124
125 if (ft_ssn != nullptr)
126 {
127 SiInput.pproto = ft_ssn->proto;
128
129 if (ft_ssn->proto == FTPP_SI_PROTO_FTP)
130 {
131 if (SiInput.pdir != FTPP_SI_NO_MODE)
132 {
133 iInspectMode = SiInput.pdir;
134 }
135 else
136 {
137 if ( p->is_from_server() )
138 {
139 iInspectMode = FTPP_SI_SERVER_MODE;
140 }
141 else if ( p->is_from_client() )
142 {
143 iInspectMode = FTPP_SI_CLIENT_MODE;
144 }
145 else
146 {
147 iInspectMode = FTPGetPacketDir(p);
148 }
149 }
150 }
151 else
152 {
153 /* Not FTP or Telnet */
154 assert(false);
155 p->flow->free_flow_data(FtpFlowData::inspector_id);
156 return 0;
157 }
158 }
159 }
160
161 if (ft_ssn == nullptr)
162 {
163 SiInput.pproto = FTPP_SI_PROTO_UNKNOWN;
164 iInspectMode = FTPP_SI_NO_MODE;
165
166 FTPsessionInspection(p, (FTP_SESSION**)&ft_ssn, &SiInput, &iInspectMode);
167
168 if ( SiInput.pproto != FTPP_SI_PROTO_FTP )
169 return FTPP_INVALID_PROTO;
170 }
171
172 if (ft_ssn != nullptr)
173 {
174 switch (SiInput.pproto)
175 {
176 case FTPP_SI_PROTO_FTP:
177 return SnortFTP((FTP_SESSION*)ft_ssn, p, iInspectMode);
178 }
179 }
180
181 /* Uh, shouldn't get here */
182 return FTPP_INVALID_PROTO;
183 }
184
185 //-------------------------------------------------------------------------
186 // class stuff
187 //-------------------------------------------------------------------------
188
189 class FtpClient : public Inspector
190 {
191 public:
FtpClient(FTP_CLIENT_PROTO_CONF * client)192 FtpClient(FTP_CLIENT_PROTO_CONF* client) : ftp_client(client) { }
193
~FtpClient()194 ~FtpClient() override
195 { delete ftp_client; }
196
197 void show(const SnortConfig*) const override;
eval(Packet *)198 void eval(Packet*) override { }
199
200 FTP_CLIENT_PROTO_CONF* ftp_client;
201 };
202
show(const SnortConfig *) const203 void FtpClient::show(const SnortConfig*) const
204 {
205 if ( ftp_client )
206 print_conf_client(ftp_client);
207 }
208
209 class FtpServer : public Inspector
210 {
211 public:
212 FtpServer(FTP_SERVER_PROTO_CONF*);
213 ~FtpServer() override;
214
215 bool configure(SnortConfig*) override;
216 void show(const SnortConfig*) const override;
217 void eval(Packet*) override;
218 StreamSplitter* get_splitter(bool) override;
219
is_control_channel() const220 bool is_control_channel() const override
221 { return true; }
222
can_start_tls() const223 bool can_start_tls() const override
224 { return true; }
225
226 FTP_SERVER_PROTO_CONF* ftp_server;
227 };
228
FtpServer(FTP_SERVER_PROTO_CONF * server)229 FtpServer::FtpServer(FTP_SERVER_PROTO_CONF* server) :
230 ftp_server(server)
231 {}
232
~FtpServer()233 FtpServer::~FtpServer ()
234 {
235 CleanupFTPServerConf(ftp_server);
236 delete ftp_server;
237 }
238
configure(SnortConfig * sc)239 bool FtpServer::configure(SnortConfig* sc)
240 {
241 ftp_data_snort_protocol_id = sc->proto_ref->add("ftp-data");
242 return !FTPCheckConfigs(sc, ftp_server);
243 }
244
show(const SnortConfig *) const245 void FtpServer::show(const SnortConfig*) const
246 {
247 if ( ftp_server )
248 print_conf_server(ftp_server);
249 }
250
get_splitter(bool c2s)251 StreamSplitter* FtpServer::get_splitter(bool c2s)
252 {
253 return new FtpSplitter(c2s);
254 }
255
eval(Packet * p)256 void FtpServer::eval(Packet* p)
257 {
258 // precondition - what we registered for
259 assert(p->has_tcp_data());
260
261 ++ftstats.total_packets;
262 snort_ftp(p);
263 }
264
265 //-------------------------------------------------------------------------
266 // get the relevant configs required by legacy ftp code
267 // the client must be found if not explicitly bound
268
get_ftp_client(Packet * p)269 FTP_CLIENT_PROTO_CONF* get_ftp_client(Packet* p)
270 {
271 FtpClient* client = (FtpClient*)p->flow->data;
272 if ( !client )
273 {
274 client = (FtpClient*)InspectorManager::get_inspector(FTP_CLIENT_NAME);
275 assert(client);
276 p->flow->set_data(client);
277 }
278 return client->ftp_client;
279 }
280
get_ftp_server(Packet * p)281 FTP_SERVER_PROTO_CONF* get_ftp_server(Packet* p)
282 {
283 FtpServer* server = (FtpServer*)p->flow->gadget;
284 assert(server);
285 return server->ftp_server;
286 }
287
288 //-------------------------------------------------------------------------
289 // api stuff
290 //
291 // fc_ = ftp_client
292 // fs_ = ftp_server
293 //-------------------------------------------------------------------------
294
fc_mod_ctor()295 static Module* fc_mod_ctor()
296 { return new FtpClientModule; }
297
298 // this can be used for both modules
mod_dtor(Module * m)299 static void mod_dtor(Module* m)
300 { delete m; }
301
fc_ctor(Module * m)302 static Inspector* fc_ctor(Module* m)
303 {
304 FtpClientModule* mod = (FtpClientModule*)m;
305 FTP_CLIENT_PROTO_CONF* gc = mod->get_data();
306 unsigned i = 0;
307
308 while ( const BounceTo* bt = mod->get_bounce(i++) )
309 {
310 ProcessFTPAllowBounce(
311 gc, (const uint8_t*)bt->address.c_str(), bt->address.size(), bt->low, bt->high);
312 }
313 return new FtpClient(gc);
314 }
315
fc_dtor(Inspector * p)316 static void fc_dtor(Inspector* p)
317 { delete p; }
318
319 static const InspectApi fc_api =
320 {
321 {
322 PT_INSPECTOR,
323 sizeof(InspectApi),
324 INSAPI_VERSION,
325 0,
326 API_RESERVED,
327 API_OPTIONS,
328 FTP_CLIENT_NAME,
329 client_help,
330 fc_mod_ctor,
331 mod_dtor
332 },
333 IT_PASSIVE,
334 PROTO_BIT__NONE,
335 nullptr, // buffers
336 "ftp",
337 nullptr, // init,
338 nullptr, // pterm
339 nullptr, // tinit
340 nullptr, // tterm
341 fc_ctor,
342 fc_dtor,
343 nullptr, // ssn
344 nullptr // reset
345 };
346
347 //-------------------------------------------------------------------------
348
fs_mod_ctor()349 static Module* fs_mod_ctor()
350 { return new FtpServerModule; }
351
fs_init()352 static void fs_init()
353 {
354 FtpFlowData::init();
355 }
356
fs_ctor(Module * mod)357 static Inspector* fs_ctor(Module* mod)
358 {
359 FtpServerModule* fsm = (FtpServerModule*)mod;
360 FTP_SERVER_PROTO_CONF* conf = fsm->get_data();
361
362 return new FtpServer(conf);
363 }
364
fs_dtor(Inspector * p)365 static void fs_dtor(Inspector* p)
366 {
367 delete p;
368 }
369
370 static const InspectApi fs_api =
371 {
372 {
373 PT_INSPECTOR,
374 sizeof(InspectApi),
375 INSAPI_VERSION,
376 0,
377 API_RESERVED,
378 API_OPTIONS,
379 FTP_SERVER_NAME,
380 server_help,
381 fs_mod_ctor,
382 mod_dtor
383 },
384 IT_SERVICE,
385 PROTO_BIT__PDU,
386 nullptr, // buffers
387 "ftp",
388 fs_init,
389 nullptr, // pterm
390 nullptr, // tinit
391 nullptr, // tterm
392 fs_ctor,
393 fs_dtor,
394 nullptr, // ssn
395 nullptr // reset
396 };
397
398 #ifdef BUILDING_SO
399 SO_PUBLIC const BaseApi* snort_plugins[] =
400 {
401 &fc_api.base,
402 &fs_api.base,
403 &fd_api.base,
404 &tn_api.base,
405 nullptr
406 };
407 #else
408 const BaseApi* sin_telnet = &tn_api.base;
409 const BaseApi* sin_ftp_client = &fc_api.base;
410 const BaseApi* sin_ftp_server = &fs_api.base;
411 const BaseApi* sin_ftp_data = &fd_api.base;
412 #endif
413
414