"Fossies" - the Fresh Open Source Software Archive 
Member "snort-2.9.17/src/dynamic-preprocessors/ftptelnet/ftpp_si.c" (16 Oct 2020, 36219 Bytes) of package /linux/misc/snort-2.9.17.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "ftpp_si.c" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
2.9.16.1_vs_2.9.17.
1 /*
2 * ftpp_si.c
3 *
4 * Copyright (C) 2014-2020 Cisco and/or its affiliates. All rights reserved.
5 * Copyright (C) 2004-2013 Sourcefire, Inc.
6 * Steven A. Sturges <ssturges@sourcefire.com>
7 * Daniel J. Roelker <droelker@sourcefire.com>
8 * Marc A. Norton <mnorton@sourcefire.com>
9 * Kevin Liu <kliu@sourcefire.com>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License Version 2 as
13 * published by the Free Software Foundation. You may not use, modify or
14 * distribute this program under any other version of the GNU General
15 * Public License.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 *
26 * Description:
27 *
28 * This file contains functions to select server configurations
29 * and begin the FTPTelnet process.
30 *
31 * The Session Inspection Module interfaces with the Stream Inspection
32 * Module and the User Interface Module to select the appropriate
33 * FTPTelnet configuration and in the case of stateful inspection the
34 * Session Inspection Module retrieves the user-data from the Stream
35 * Module. For stateless inspection, the Session Inspection Module uses
36 * the same structure for use by each packet.
37 *
38 * The main responsibility of this module is to supply the appropriate
39 * data structures and configurations for the rest of the FTPTelnet
40 * process. The module also determines what type of data is being
41 * inspected, whether it is client, server, or neither.
42 *
43 * NOTES:
44 * - 20.09.04: Initial Development. SAS
45 *
46 */
47 #include <stdlib.h>
48 #include <stdio.h>
49 #include <string.h>
50
51 #ifdef HAVE_CONFIG_H
52 #include "config.h"
53 #endif
54
55 #include "ftpp_return_codes.h"
56 #include "ftpp_ui_config.h"
57 #include "ftpp_ui_client_lookup.h"
58 #include "ftpp_ui_server_lookup.h"
59 #include "ftpp_si.h"
60 #include "spp_ftptelnet.h"
61 #include "stream_api.h"
62 #include "snort_ftptelnet.h"
63 #include "sfPolicyUserData.h"
64 #include "ssl_include.h"
65
66 #ifndef WIN32
67 # include <ctype.h>
68 #endif
69
70 extern tSfPolicyUserContextId ftp_telnet_config;
71
72 static FTP_SESSION StaticSession;
73
74 /*
75 * Function: PortMatch(PROTO_CONF *Conf, unsigned short port)
76 *
77 * Purpose: Given a configuration and a port number, we decide if
78 * the port is in the port list.
79 *
80 * Arguments: PROTO_CONF => pointer to the client or server configuration
81 * port => the port number to check for
82 *
83 * Returns: int => 0 indicates the port is not a client/server port.
84 * 1 indicates the port is one of the client/server ports.
85 *
86 */
87 static int PortMatch(PROTO_CONF *Conf, unsigned short port)
88 {
89 if(Conf->ports[port])
90 {
91 return 1;
92 }
93
94 return 0;
95 }
96
97 /*
98 * Function: TelnetFreeSession(void *preproc_session)
99 *
100 * Purpose: This function frees the data that is associated with a session.
101 *
102 * Arguments: preproc_session => pointer to the session to free
103 *
104 * Returns: None
105 */
106 static void TelnetFreeSession(void *preproc_session)
107 {
108 TELNET_SESSION *ssn = (TELNET_SESSION *)preproc_session;
109 FTPTELNET_GLOBAL_CONF *pPolicyConfig = NULL;
110
111 if (ssn == NULL)
112 return;
113
114 pPolicyConfig = (FTPTELNET_GLOBAL_CONF *)sfPolicyUserDataGet(ssn->global_conf, ssn->policy_id);
115
116 if (pPolicyConfig != NULL)
117 {
118 pPolicyConfig->ref_count--;
119 if ((pPolicyConfig->ref_count == 0) &&
120 (ssn->global_conf != ftp_telnet_config))
121 {
122 sfPolicyUserDataClear (ssn->global_conf, ssn->policy_id);
123 FTPTelnetFreeConfig(pPolicyConfig);
124
125 if (sfPolicyUserPolicyGetActive(ssn->global_conf) == 0)
126 FTPTelnetFreeConfigs(ssn->global_conf);
127 }
128 }
129
130 ftp_telnet_stats.telnet_sessions--;
131 ftp_telnet_stats.heap_memory -= sizeof(TELNET_SESSION);
132
133 free(ssn);
134 }
135
136 /*
137 * Function: TelnetResetSession(TELNET_SESSION *Session)
138 *
139 * Purpose: This function resets all the variables that need to be
140 * initialized for a new Session. I've tried to keep this to
141 * a minimum, so we don't have to worry about initializing big
142 * structures.
143 *
144 * Arguments: Session => pointer to the session to reset
145 *
146 * Returns: int => return code indicating error or success
147 *
148 */
149 static inline int TelnetResetSession(TELNET_SESSION *Session)
150 {
151 Session->ft_ssn.proto = FTPP_SI_PROTO_TELNET;
152 Session->telnet_conf = NULL;
153 Session->global_conf = NULL;
154
155 Session->consec_ayt = 0;
156 Session->encr_state = NO_STATE;
157
158 Session->event_list.stack_count = 0;
159
160 return FTPP_SUCCESS;
161 }
162
163 /*
164 * Function: TelnetStatefulSessionInspection(Packet *p,
165 * FTPTELNET_GLOBAL_CONF *GlobalConf,
166 * TELNET_SESSION **TelnetSession,
167 * FTPP_SI_INPUT *SiInput)
168 *
169 * Purpose: Initialize the session and server configurations for
170 * this packet/stream. In this function, we set the Session
171 * pointer (which includes the correct server configuration).
172 * The actual processing to find which IP is the server and
173 * which is the client, is done in the InitServerConf() function.
174 *
175 * Arguments: p => pointer to the packet/stream
176 * GlobalConf => pointer to the global configuration
177 * Session => double pointer to the Session structure
178 * SiInput => pointer to the session information
179 *
180 * Returns: int => return code indicating error or success
181 *
182 */
183 static int TelnetStatefulSessionInspection(SFSnortPacket *p,
184 FTPTELNET_GLOBAL_CONF *GlobalConf,
185 TELNET_SESSION **TelnetSession,
186 FTPP_SI_INPUT *SiInput)
187 {
188 if (p->stream_session)
189 {
190 TELNET_SESSION *NewSession = (TELNET_SESSION *)calloc(1, sizeof(TELNET_SESSION));
191
192 ftp_telnet_stats.telnet_sessions++;
193 if (ftp_telnet_stats.telnet_sessions > ftp_telnet_stats.max_telnet_sessions)
194 ftp_telnet_stats.max_telnet_sessions = ftp_telnet_stats.telnet_sessions;
195
196 ftp_telnet_stats.heap_memory += sizeof(TELNET_SESSION);
197
198 tSfPolicyId policy_id = _dpd.getNapRuntimePolicy();
199
200 if (NewSession == NULL)
201 {
202 DynamicPreprocessorFatalMessage("Failed to allocate memory for "
203 "new Telnet session.\n");
204 }
205
206 TelnetResetSession(NewSession);
207
208 NewSession->ft_ssn.proto = FTPP_SI_PROTO_TELNET;
209 NewSession->telnet_conf = GlobalConf->telnet_config;
210
211 NewSession->global_conf = ftp_telnet_config;
212 NewSession->policy_id = policy_id;
213 GlobalConf->ref_count++;
214
215 SiInput->pproto = FTPP_SI_PROTO_TELNET;
216
217 _dpd.sessionAPI->set_application_data(p->stream_session,
218 PP_FTPTELNET, NewSession, &TelnetFreeSession);
219
220 *TelnetSession = NewSession;
221 return FTPP_SUCCESS;
222 }
223
224 return FTPP_NONFATAL_ERR;
225 }
226
227 /*
228 * Function: TelnetStatelessSessionInspection(Packet *p,
229 * FTPTELNET_GLOBAL_CONF *GlobalConf,
230 * TELNET_SESSION **TelnetSession,
231 * FTPP_SI_INPUT *SiInput)
232 *
233 * Purpose: Initialize the session and server configurations for this
234 * packet/stream. It is important to note in stateless mode that
235 * we assume no knowledge of the state of a connection, other
236 * than the knowledge that we can glean from an individual packet.
237 * So in essence, each packet is it's own session and there
238 * is no knowledge retained from one packet to another. If you
239 * want to track a telnet session for real, use stateful mode.
240 *
241 * In this function, we set the Session pointer (which includes
242 * the correct server configuration). The actual processing to
243 * find which IP is the server and which is the client, is done in
244 * the InitServerConf() function.
245 *
246 * Arguments: p => pointer to the packet/stream
247 * GlobalConf => pointer to the global configuration
248 * Session => double pointer to the Session structure
249 * SiInput => pointer to the session information
250 *
251 * Returns: int => return code indicating error or success
252 *
253 */
254 static int TelnetStatelessSessionInspection(SFSnortPacket *p,
255 FTPTELNET_GLOBAL_CONF *GlobalConf,
256 TELNET_SESSION **Session,
257 FTPP_SI_INPUT *SiInput)
258 {
259 static TELNET_SESSION TelnetStaticSession;
260
261 TelnetResetSession(&TelnetStaticSession);
262
263 SiInput->pproto = FTPP_SI_PROTO_TELNET;
264 TelnetStaticSession.telnet_conf = GlobalConf->telnet_config;
265 TelnetStaticSession.global_conf = ftp_telnet_config;
266
267 *Session = &TelnetStaticSession;
268
269 return FTPP_SUCCESS;
270 }
271
272
273 /*
274 * Function: TelnetSessionInspection(Packet *p,
275 * FTPTELNET_GLOBAL_CONF *GlobalConf,
276 * FTPP_SI_INPUT *SiInput,
277 * int *piInspectMode)
278 *
279 * Purpose: The Session Inspection module selects the appropriate
280 * configuration for the session, and the type of inspection
281 * to be performed (client or server.)
282 *
283 * When the Session Inspection module is in stateful mode, it
284 * checks to see if there is a TELNET_SESSION pointer already
285 * associated with the stream. If there is, then it uses that
286 * session pointer, otherwise it calculates the server configuration
287 * using the FTP_SI_INPUT and returns a TELNET_SESSION pointer. In
288 * stateful mode, this means that memory is allocated, but in
289 * stateless mode, the same session pointer is used for all packets
290 * to reduce the allocation overhead.
291 *
292 * The inspection mode can be either client or server.
293 *
294 * Arguments: p => pointer to the packet/stream
295 * GlobalConf => pointer to the global configuration
296 * Session => double pointer to the Session structure
297 * SiInput => pointer to the session information
298 * piInspectMode => pointer for setting inspection mode
299 *
300 * Returns: int => return code indicating error or success
301 *
302 */
303 int TelnetSessionInspection(SFSnortPacket *p, FTPTELNET_GLOBAL_CONF *GlobalConf,
304 TELNET_SESSION **TelnetSession, FTPP_SI_INPUT *SiInput, int *piInspectMode)
305 {
306 int iRet;
307 int iTelnetSip;
308 int iTelnetDip;
309 #ifdef TARGET_BASED
310 int16_t app_id = SFTARGET_UNKNOWN_PROTOCOL;
311
312 /* If possible, use Stream API to determine protocol. */
313 if (_dpd.streamAPI)
314 {
315 app_id = _dpd.sessionAPI->get_application_protocol_id(p->stream_session);
316 }
317 if (app_id == SFTARGET_UNKNOWN_PROTOCOL)
318 {
319 return FTPP_INVALID_PROTO;
320 }
321 if (app_id == telnet_app_id)
322 {
323 if (SiInput->pdir == FTPP_SI_CLIENT_MODE ||
324 SiInput->pdir == FTPP_SI_SERVER_MODE)
325 {
326 *piInspectMode = (int)SiInput->pdir;
327 }
328 }
329 else if (app_id && app_id != telnet_app_id)
330 {
331 return FTPP_INVALID_PROTO;
332 }
333 else
334 {
335 #endif
336 iTelnetSip = PortMatch((PROTO_CONF*)GlobalConf->telnet_config,
337 SiInput->sport);
338 iTelnetDip = PortMatch((PROTO_CONF*)GlobalConf->telnet_config,
339 SiInput->dport);
340
341 if (iTelnetSip)
342 {
343 *piInspectMode = FTPP_SI_SERVER_MODE;
344 }
345 else if (iTelnetDip)
346 {
347 *piInspectMode = FTPP_SI_CLIENT_MODE;
348 }
349 else
350 {
351 return FTPP_INVALID_PROTO;
352 }
353 #ifdef TARGET_BASED
354 }
355 #endif
356
357 /*
358 * We get the server configuration and the session structure differently
359 * depending on what type of inspection we are doing. In the case of
360 * stateful processing, we may get the session structure from the Stream
361 * Reassembly module (which includes the server configuration) or the
362 * structure will be allocated and added to the stream pointer for the
363 * rest of the session.
364 *
365 * In stateless mode, we just use a static variable that is contained in
366 * the function here.
367 */
368 if(GlobalConf->inspection_type == FTPP_UI_CONFIG_STATEFUL)
369 {
370 iRet = TelnetStatefulSessionInspection(p, GlobalConf, TelnetSession, SiInput);
371 if (iRet)
372 return iRet;
373 }
374 else
375 {
376 /* Assume stateless processing otherwise */
377 iRet = TelnetStatelessSessionInspection(p, GlobalConf, TelnetSession, SiInput);
378 if (iRet)
379 return iRet;
380 }
381
382 return FTPP_SUCCESS;
383 }
384
385 /*
386 * Function: FTPGetPacketDir(Packet *p)
387 *
388 * Purpose: Attempts to determine the direction of an FTP packet by
389 * examining the first 3 bytes. If all three are numeric,
390 * the packet is a server response packet.
391 *
392 * Arguments: p => pointer to the Packet
393 *
394 * Returns: int => return code indicating the mode
395 *
396 */
397 int FTPGetPacketDir(SFSnortPacket *p)
398 {
399 if (p->payload_size >= 3)
400 {
401 if (isdigit(p->payload[0]) &&
402 isdigit(p->payload[1]) &&
403 isdigit(p->payload[2]) )
404 {
405 return FTPP_SI_SERVER_MODE;
406 }
407 else
408 {
409 return FTPP_SI_CLIENT_MODE;
410 }
411 }
412 return FTPP_SI_NO_MODE;
413 }
414
415 /*
416 * Function: FTPInitConf(Packet *p, FTPTELNET_GLOBAL_CONF *GlobalConf,
417 * FTP_CLIENT_PROTO_CONF **ClientConf,
418 * FTP_SERVER_PROTO_CONF **ServerConf,
419 * FTPP_SI_INPUT *SiInput, int *piInspectMode)
420 *
421 * Purpose: When a session is initialized, we must select the appropriate
422 * server configuration and select the type of inspection based
423 * on the source and destination ports.
424 *
425 * IMPORTANT NOTE:
426 * We should check to make sure that there are some unique configurations,
427 * otherwise we can just default to the global default and work some magic
428 * that way.
429 *
430 * Arguments: p => pointer to the Packet/Session
431 * GlobalConf => pointer to the global configuration
432 * ClientConf => pointer to the address of the client
433 * config so we can set it.
434 * ServerConf => pointer to the address of the server
435 * config so we can set it.
436 * SiInput => pointer to the packet info
437 * piInspectMode => pointer so we can set the inspection mode
438 *
439 * Returns: int => return code indicating error or success
440 *
441 */
442 static int FTPInitConf(SFSnortPacket *p, FTPTELNET_GLOBAL_CONF *GlobalConf,
443 FTP_CLIENT_PROTO_CONF **ClientConf,
444 FTP_SERVER_PROTO_CONF **ServerConf,
445 FTPP_SI_INPUT *SiInput, int *piInspectMode)
446 {
447 FTP_CLIENT_PROTO_CONF *ClientConfSip;
448 FTP_CLIENT_PROTO_CONF *ClientConfDip;
449 FTP_SERVER_PROTO_CONF *ServerConfSip;
450 FTP_SERVER_PROTO_CONF *ServerConfDip;
451 int iServerSip;
452 int iServerDip;
453 int iErr = 0;
454 int iRet = FTPP_SUCCESS;
455 #ifdef TARGET_BASED
456 int16_t app_id = 0;
457 #endif
458 sfaddr_t sip;
459 sfaddr_t dip;
460
461 //structure copy
462 sip = SiInput->sip;
463 dip = SiInput->dip;
464
465 /*
466 * We find the client configurations for both the source and dest IPs.
467 * There should be a check on the global configuration to see if there
468 * is at least one unique client configuration. If there isn't then we
469 * assume the global client configuration.
470 */
471 ClientConfDip = ftpp_ui_client_lookup_find(GlobalConf->client_lookup,
472 &dip,
473 &iErr);
474
475 if(!ClientConfDip)
476 {
477 ClientConfDip = GlobalConf->default_ftp_client;
478 }
479
480 ClientConfSip = ftpp_ui_client_lookup_find(GlobalConf->client_lookup,
481 &sip,
482 &iErr);
483
484 if(!ClientConfSip)
485 {
486 ClientConfSip = GlobalConf->default_ftp_client;
487 }
488
489 /*
490 * Now, we find the server configurations for both the source and dest IPs.
491 * There should be a check on the global configuration to see if there
492 * is at least one unique client configuration. If there isn't then we
493 * assume the global client configuration.
494 */
495 ServerConfDip = ftpp_ui_server_lookup_find(GlobalConf->server_lookup,
496 &dip,
497 &iErr);
498
499 if(!ServerConfDip)
500 {
501 ServerConfDip = GlobalConf->default_ftp_server;
502 }
503
504 ServerConfSip = ftpp_ui_server_lookup_find(GlobalConf->server_lookup,
505 &sip,
506 &iErr);
507
508 if(!ServerConfSip)
509 {
510 ServerConfSip = GlobalConf->default_ftp_server;
511 }
512
513 /*
514 * We check the IP and the port to see if the FTP client is talking in
515 * the session. This should tell us whether it is client communication
516 * or server configuration. If both IPs and ports are servers, then there
517 * is a sort of problem. We don't know which side is the client and which
518 * side is the server so we have to assume one.
519 *
520 * In stateful processing, we only do this stage on the startup of a
521 * session, so we can still assume that the initial packet is the client
522 * talking.
523 */
524 iServerDip = PortMatch((PROTO_CONF*)ServerConfDip, SiInput->dport);
525 iServerSip = PortMatch((PROTO_CONF*)ServerConfSip, SiInput->sport);
526
527 /*
528 * We default to the no FTP traffic case
529 */
530 *piInspectMode = FTPP_SI_NO_MODE;
531 *ClientConf = NULL;
532 *ServerConf = NULL;
533
534 /*
535 * Depending on the type of packet direction we get from the
536 * state machine, we evaluate client/server differently.
537 */
538 switch(SiInput->pdir)
539 {
540 case FTPP_SI_NO_MODE:
541
542 #ifdef TARGET_BASED
543 app_id = _dpd.sessionAPI->get_application_protocol_id(p->stream_session);
544
545 if (app_id == ftp_app_id || app_id == 0)
546 {
547 #endif
548
549 /*
550 * We check for the case where both SIP and DIP
551 * appear to be servers. In this case, we assume server
552 * and process that way.
553 */
554 if(iServerSip && iServerDip)
555 {
556 /*
557 * We check for the case where both SIP and DIP
558 * appear to be servers. In this case, we look at
559 * the first few bytes of the packet to try to
560 * determine direction -- 3 digits indicate server
561 * response.
562 */
563
564 /* look at the first few bytes of the packet. We might
565 * be wrong if this is a reassembled packet and we catch
566 * a server response mid-stream.
567 */
568 *piInspectMode = FTPGetPacketDir(p);
569 if (*piInspectMode == FTPP_SI_SERVER_MODE)
570 {
571 /* Packet is from server --> src is Server */
572 *ClientConf = ClientConfDip;
573 *ServerConf = ServerConfSip;
574 }
575 else /* Assume client */
576 {
577 /* Packet is from client --> dest is Server */
578 *piInspectMode = FTPP_SI_CLIENT_MODE;
579 *ClientConf = ClientConfSip;
580 *ServerConf = ServerConfDip;
581 }
582 SiInput->pproto = FTPP_SI_PROTO_FTP;
583 }
584 else if(iServerDip)
585 {
586 /* Packet is from client --> dest is Server */
587 *piInspectMode = FTPP_SI_CLIENT_MODE;
588 *ClientConf = ClientConfSip;
589 *ServerConf = ServerConfDip;
590 SiInput->pproto = FTPP_SI_PROTO_FTP;
591 }
592 else if(iServerSip)
593 {
594 /* Packet is from server --> src is Server */
595 *piInspectMode = FTPP_SI_SERVER_MODE;
596 *ClientConf = ClientConfDip;
597 *ServerConf = ServerConfSip;
598 SiInput->pproto = FTPP_SI_PROTO_FTP;
599 }
600 break;
601
602 #ifdef TARGET_BASED
603 }
604 #endif
605
606 case FTPP_SI_CLIENT_MODE:
607 /* Packet is from client --> dest is Server */
608 #ifdef TARGET_BASED
609 app_id = _dpd.sessionAPI->get_application_protocol_id(p->stream_session);
610
611 if ((app_id == ftp_app_id) || (!app_id && iServerDip))
612 #else
613 if(iServerDip)
614 #endif
615 {
616 *piInspectMode = FTPP_SI_CLIENT_MODE;
617 *ClientConf = ClientConfSip;
618 *ServerConf = ServerConfDip;
619 SiInput->pproto = FTPP_SI_PROTO_FTP;
620 }
621 else
622 {
623 *piInspectMode = FTPP_SI_NO_MODE;
624 iRet = FTPP_NONFATAL_ERR;
625 }
626 break;
627
628 case FTPP_SI_SERVER_MODE:
629 /* Packet is from server --> src is Server */
630 #ifdef TARGET_BASED
631 app_id = _dpd.sessionAPI->get_application_protocol_id(p->stream_session);
632
633 if ((app_id == ftp_app_id) || (!app_id && iServerSip))
634 #else
635 if(iServerSip)
636 #endif
637 {
638 *piInspectMode = FTPP_SI_SERVER_MODE;
639 *ClientConf = ClientConfDip;
640 *ServerConf = ServerConfSip;
641 SiInput->pproto = FTPP_SI_PROTO_FTP;
642 }
643 else
644 {
645 *piInspectMode = FTPP_SI_NO_MODE;
646 iRet = FTPP_NONFATAL_ERR;
647 }
648 break;
649
650 default:
651 *piInspectMode = FTPP_SI_NO_MODE;
652 *ClientConf = NULL;
653 *ServerConf = NULL;
654 break;
655 }
656
657 return iRet;
658 }
659
660 /*
661 * Function: FTPFreeSession(void *preproc_session)
662 *
663 * Purpose: This function frees the data that is associated with a session.
664 *
665 * Arguments: preproc_session => pointer to the session to free
666 *
667 * Returns: None
668 */
669 static void FTPFreeSession(void *preproc_session)
670 {
671 FTP_SESSION *ssn = (FTP_SESSION *)preproc_session;
672 FTPTELNET_GLOBAL_CONF *pPolicyConfig = NULL;
673 ssl_callback_interface_t *ssl_cb = (ssl_callback_interface_t *)_dpd.getSSLCallback();
674
675 if (ssn == NULL)
676 return;
677
678 pPolicyConfig = (FTPTELNET_GLOBAL_CONF *)sfPolicyUserDataGet(ssn->global_conf, ssn->policy_id);
679
680 if (pPolicyConfig != NULL)
681 {
682 pPolicyConfig->ref_count--;
683 if ((pPolicyConfig->ref_count == 0) &&
684 (ssn->global_conf != ftp_telnet_config))
685 {
686
687 sfPolicyUserDataClear (ssn->global_conf, ssn->policy_id);
688 FTPTelnetFreeConfig(pPolicyConfig);
689
690 if (sfPolicyUserPolicyGetActive(ssn->global_conf) == 0)
691 FTPTelnetFreeConfigs(ssn->global_conf);
692 }
693 }
694
695 if (ssn->filename)
696 {
697 ftp_telnet_stats.heap_memory -= (strlen(ssn->filename) + 1);
698 free(ssn->filename);
699 }
700
701 if ( ssl_cb )
702 ssl_cb->session_free(ssn->flow_id);
703
704 ftp_telnet_stats.ftp_sessions--;
705 ftp_telnet_stats.heap_memory -= sizeof(FTP_SESSION);
706 #ifdef TARGET_BASED
707 FTP_DATA_SESSION *datassn = ssn->datassn;
708 if(datassn && (ssn == datassn->ftpssn))
709 datassn->ftpssn = NULL;
710 free(ssn);
711 #endif
712 }
713
714 #ifdef TARGET_BASED
715 /* Function: FTPDataSessionNew
716 *
717 * Create an ftp-data session from a packet
718 */
719 FTP_DATA_SESSION * FTPDataSessionNew(SFSnortPacket *p)
720 {
721 FTP_DATA_SESSION *ftpdata = calloc(1, sizeof *ftpdata);
722
723 if (!ftpdata)
724 return NULL;
725
726 ftpdata->ft_ssn.proto = FTPP_SI_PROTO_FTP_DATA;
727 ftpdata->flow_id = 0;
728
729 /* Get the ftp-ctrl session key */
730 ftpdata->ftp_key = _dpd.sessionAPI->get_session_key(p);
731
732 if (!ftpdata->ftp_key)
733 {
734 free(ftpdata);
735 ftpdata = NULL;
736 return ftpdata;
737 }
738
739 ftp_telnet_stats.ftp_data_sessions++;
740 if (ftp_telnet_stats.ftp_data_sessions > ftp_telnet_stats.max_ftp_data_sessions)
741 ftp_telnet_stats.max_ftp_data_sessions = ftp_telnet_stats.ftp_data_sessions;
742
743 ftp_telnet_stats.heap_memory += (sizeof (*ftpdata) + sizeof(StreamSessionKey));
744
745 return ftpdata;
746 }
747
748 /*
749 * Function: FTPDataSessionFree
750 *
751 * Free an ftp-data session
752 */
753 void FTPDataSessionFree(void *p_ssn)
754 {
755 FTP_DATA_SESSION *ssn = (FTP_DATA_SESSION *)p_ssn;
756 ssl_callback_interface_t *ssl_cb = (ssl_callback_interface_t *)_dpd.getSSLCallback();
757
758 if (!ssn)
759 return;
760
761 FTP_SESSION * ftpssn = ssn->ftpssn;
762 if(ftpssn && (ssn == ftpssn->datassn))
763 ftpssn->datassn = NULL;
764
765 /* ftp-data key shouldn't exist without this but */
766 if (ssn->ftp_key)
767 {
768 free(ssn->ftp_key);
769 }
770
771 if (ssn->filename)
772 {
773 ftp_telnet_stats.heap_memory -= (strlen(ssn->filename) + 1);
774 free(ssn->filename);
775 }
776
777 if ( ssl_cb )
778 ssl_cb->session_free(ssn->flow_id);
779
780 ftp_telnet_stats.ftp_data_sessions--;
781 ftp_telnet_stats.heap_memory -= sizeof(FTP_DATA_SESSION);
782
783 free(ssn);
784 }
785
786 /* Function: FTPDataDirection
787 *
788 * Return true if packet is from the "sending" host
789 * Return false if packet is from the "receiving" host
790 */
791 bool FTPDataDirection(SFSnortPacket *p, FTP_DATA_SESSION *ftpdata)
792 {
793 uint32_t direction;
794 uint32_t pktdir = _dpd.sessionAPI->get_packet_direction(p);
795
796 if (ftpdata->mode == FTPP_XFER_ACTIVE)
797 direction = ftpdata->direction ? FLAG_FROM_SERVER : FLAG_FROM_CLIENT;
798 else
799 direction = ftpdata->direction ? FLAG_FROM_CLIENT : FLAG_FROM_SERVER;
800
801 return (pktdir == direction);
802 }
803
804 #endif /* TARGET_BASED */
805
806 /*
807 * Function: FTPResetSession(FTP_SESSION *FtpSession, int first)
808 *
809 * Purpose: This function resets all the variables that need to be
810 * initialized for a new Session. I've tried to keep this to
811 * a minimum, so we don't have to worry about initializing big
812 * structures.
813 *
814 * Arguments: FtpSession => pointer to the session to reset
815 * first => indicator whether this is a new conf
816 *
817 * Returns: int => return code indicating error or success
818 *
819 */
820 static inline int FTPResetSession(FTP_SESSION *FtpSession)
821 {
822 FtpSession->ft_ssn.proto = FTPP_SI_PROTO_FTP;
823
824 FtpSession->server.response.pipeline_req = 0;
825 FtpSession->server.response.state = 0;
826 FtpSession->client.request.pipeline_req = 0;
827 FtpSession->client.state = 0;
828
829 FtpSession->client_conf = NULL;
830 FtpSession->server_conf = NULL;
831 FtpSession->global_conf = NULL;
832
833 FtpSession->encr_state = NO_STATE;
834 FtpSession->encr_state_chello = false;
835 FtpSession->flow_id = 0;
836 IP_CLEAR(FtpSession->clientIP);
837 FtpSession->clientPort = 0;
838 IP_CLEAR(FtpSession->serverIP);
839 FtpSession->serverPort = 0;
840 FtpSession->data_chan_state = NO_STATE;
841 FtpSession->data_chan_index = 0;
842 FtpSession->data_xfer_index = 0;
843 FtpSession->ftp_cmd_pipe_index = 1;
844 FtpSession->rest_cmd_offset = 0;
845
846 FtpSession->event_list.stack_count = 0;
847
848 return FTPP_SUCCESS;
849 }
850
851 /*
852 * Function: FTPStatefulSessionInspection(Packet *p,
853 * FTPTELNET_GLOBAL_CONF *GlobalConf,
854 * FTP_SESSION **FtpSession,
855 * FTPP_SI_INPUT *SiInput, int *piInspectMode)
856 *
857 * Purpose: Initialize the session and server configurations for this
858 * packet/stream. In this function, we set the Session pointer
859 * (which includes the correct server configuration). The actual
860 * processing to find which IP is the server and which is the
861 * client, is done in the InitServerConf() function.
862 *
863 * Arguments: p => pointer to the Packet/Session
864 * GlobalConf => pointer to the global configuration
865 * Session => double pointer to the Session structure
866 * SiInput => pointer to the session information
867 * piInspectMode => pointer so the inspection mode can be set
868 *
869 * Returns: int => return code indicating error or success
870 *
871 */
872 static int FTPStatefulSessionInspection(SFSnortPacket *p,
873 FTPTELNET_GLOBAL_CONF *GlobalConf,
874 FTP_SESSION **FtpSession,
875 FTPP_SI_INPUT *SiInput, int *piInspectMode)
876 {
877 if (p->stream_session)
878 {
879 FTP_CLIENT_PROTO_CONF *ClientConf;
880 FTP_SERVER_PROTO_CONF *ServerConf;
881 int iRet;
882
883 iRet = FTPInitConf(p, GlobalConf, &ClientConf, &ServerConf, SiInput, piInspectMode);
884 if (iRet)
885 return iRet;
886
887 if (*piInspectMode)
888 {
889 FTP_SESSION *NewSession = (FTP_SESSION *)calloc(1, sizeof(FTP_SESSION));
890
891 ftp_telnet_stats.ftp_sessions++;
892 if (ftp_telnet_stats.ftp_sessions > ftp_telnet_stats.max_ftp_sessions)
893 ftp_telnet_stats.max_ftp_sessions = ftp_telnet_stats.ftp_sessions;
894
895 ftp_telnet_stats.heap_memory += sizeof(FTP_SESSION);
896
897 tSfPolicyId policy_id = _dpd.getNapRuntimePolicy();
898
899 if (NewSession == NULL)
900 {
901 DynamicPreprocessorFatalMessage("Failed to allocate memory for "
902 "new FTP session.\n");
903 }
904
905 FTPResetSession(NewSession);
906
907 NewSession->ft_ssn.proto = FTPP_SI_PROTO_FTP;
908 NewSession->client_conf = ClientConf;
909 NewSession->server_conf = ServerConf;
910
911 NewSession->global_conf = ftp_telnet_config;
912 NewSession->policy_id = policy_id;
913 GlobalConf->ref_count++;
914
915 _dpd.sessionAPI->set_application_data
916 (p->stream_session, PP_FTPTELNET, NewSession, &FTPFreeSession);
917
918 *FtpSession = NewSession;
919 SiInput->pproto = FTPP_SI_PROTO_FTP;
920 return FTPP_SUCCESS;
921 }
922 }
923
924 return FTPP_INVALID_PROTO;
925 }
926
927 /*
928 * Function: FTPStatelessSessionInspection(Packet *p,
929 * FTPTELNET_GLOBAL_CONF *GlobalConf,
930 * FTP_SESSION **FtpSession,
931 * FTPP_SI_INPUT *SiInput, int *piInspectMode)
932 *
933 * Purpose: Initialize the session and server configurations for this
934 * packet/stream. It is important to note in stateless mode that
935 * we assume no knowledge of the state of a connection, other than
936 * the knowledge that we can glean from an individual packet. So
937 * in essence, each packet is it's own session and there is no
938 * knowledge retained from one packet to another. If you want to
939 * track an FTP session for real, use stateful mode.
940 *
941 * In this function, we set the Session pointer (which includes
942 * the correct server configuration). The actual processing to find
943 * which IP is the server and which is the client, is done in the
944 * InitServerConf() function.
945 *
946 * Arguments: p => pointer to the Packet/Session
947 * GlobalConf => pointer to the global configuration
948 * Session => double pointer to the Session structure
949 * SiInput => pointer to the session information
950 * piInspectMode => pointer so the inspection mode can be set
951 *
952 * Returns: int => return code indicating error or success
953 *
954 */
955 static int FTPStatelessSessionInspection(SFSnortPacket *p,
956 FTPTELNET_GLOBAL_CONF *GlobalConf,
957 FTP_SESSION **FtpSession,
958 FTPP_SI_INPUT *SiInput, int *piInspectMode)
959 {
960 FTP_CLIENT_PROTO_CONF *ClientConf;
961 FTP_SERVER_PROTO_CONF *ServerConf;
962 int iRet;
963
964 FTPResetSession(&StaticSession);
965
966 iRet = FTPInitConf(p, GlobalConf, &ClientConf, &ServerConf, SiInput, piInspectMode);
967 if (iRet)
968 return iRet;
969
970 StaticSession.ft_ssn.proto = FTPP_SI_PROTO_FTP;
971 StaticSession.global_conf = ftp_telnet_config;
972 StaticSession.client_conf = ClientConf;
973 StaticSession.server_conf = ServerConf;
974
975 SiInput->pproto = FTPP_SI_PROTO_FTP;
976 *FtpSession = &StaticSession;
977
978 return FTPP_SUCCESS;
979 }
980
981
982 /*
983 * Function: FTPSessionInspection(Packet *p,
984 * FTPTELNET_GLOBAL_CONF *GlobalConf,
985 * FTPP_SI_INPUT *SiInput, int *piInspectMode)
986 *
987 * Purpose: The Session Inspection module selects the appropriate client
988 * configuration for the session, and the type of inspection to
989 * be performed (client or server.)
990 *
991 * When the Session Inspection module is in stateful mode, it
992 * checks to see if there is a FTP_SESSION pointer already
993 * associated with the stream. If there is, then it uses that
994 * session pointer, otherwise it calculates the server
995 * configuration using the FTP_SI_INPUT and returns a FTP_SESSION
996 * pointer. In stateful mode, this means that memory is allocated,
997 * but in stateless mode, the same session pointer is used for all
998 * packets to reduce the allocation overhead.
999 *
1000 * The inspection mode can be either client or server.
1001 *
1002 * Arguments: p => pointer to the Packet/Session
1003 * GlobalConf => pointer to the global configuration
1004 * SiInput => pointer to the session information
1005 * piInspectMode => pointer so the inspection mode can be set
1006 *
1007 * Returns: int => return code indicating error or success
1008 *
1009 */
1010 int FTPSessionInspection(SFSnortPacket *p, FTPTELNET_GLOBAL_CONF *GlobalConf,
1011 FTP_SESSION **FtpSession, FTPP_SI_INPUT *SiInput, int *piInspectMode)
1012 {
1013 int iRet;
1014
1015 /*
1016 * We get the server configuration and the session structure differently
1017 * depending on what type of inspection we are doing. In the case of
1018 * stateful processing, we may get the session structure from the Stream
1019 * Reassembly module (which includes the server configuration) or the
1020 * structure will be allocated and added to the stream pointer for the
1021 * rest of the session.
1022 *
1023 * In stateless mode, we just use a static variable that is contained in
1024 * the function here.
1025 */
1026 if(GlobalConf->inspection_type == FTPP_UI_CONFIG_STATEFUL)
1027 {
1028 iRet = FTPStatefulSessionInspection(p, GlobalConf, FtpSession, SiInput, piInspectMode);
1029 if (iRet)
1030 return iRet;
1031 }
1032 else
1033 {
1034 /* Assume stateless processing otherwise */
1035 iRet = FTPStatelessSessionInspection(p, GlobalConf, FtpSession, SiInput, piInspectMode);
1036 if (iRet)
1037 return iRet;
1038 }
1039
1040 return FTPP_SUCCESS;
1041 }
1042
1043 /*
1044 * Function: ftpp_si_determine_proto(Packet *p,
1045 * FTPTELNET_GLOBAL_CONF *GlobalConf,
1046 * FTPP_SI_INPUT *SiInput, int *piInspectMode)
1047 *
1048 * Purpose: The Protocol Determination module determines whether this is
1049 * an FTP or telnet request. If this is an FTP request, it sets
1050 * the FTP Session data and inspection mode.
1051 *
1052 * The inspection mode can be either client or server.
1053 *
1054 * Arguments: p => pointer to the Packet/Session
1055 * GlobalConf => pointer to the global configuration
1056 * SiInput => pointer to the session information
1057 * piInspectMode => pointer so the inspection mode can be set
1058 *
1059 * Returns: int => return code indicating error or success
1060 *
1061 */
1062 int ftpp_si_determine_proto(SFSnortPacket *p, FTPTELNET_GLOBAL_CONF *GlobalConf,
1063 FTP_TELNET_SESSION **ft_ssn, FTPP_SI_INPUT *SiInput, int *piInspectMode)
1064 {
1065 /* Default to no FTP or Telnet case */
1066 SiInput->pproto = FTPP_SI_PROTO_UNKNOWN;
1067 *piInspectMode = FTPP_SI_NO_MODE;
1068
1069 TelnetSessionInspection(p, GlobalConf, (TELNET_SESSION **)ft_ssn, SiInput, piInspectMode);
1070 if (SiInput->pproto == FTPP_SI_PROTO_TELNET)
1071 return FTPP_SUCCESS;
1072
1073 FTPSessionInspection(p, GlobalConf, (FTP_SESSION **)ft_ssn, SiInput, piInspectMode);
1074 if (SiInput->pproto == FTPP_SI_PROTO_FTP)
1075 return FTPP_SUCCESS;
1076
1077 return FTPP_INVALID_PROTO;
1078 }