1 /*
2 * spp_ftptelnet.c
3 *
4 * Copyright (C) 2014-2021 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 initializes FTPTelnet as a Snort preprocessor.
29 *
30 * This file registers the FTPTelnet initialization function,
31 * adds the FTPTelnet function into the preprocessor list, reads
32 * the user configuration in the snort.conf file, and prints out
33 * the configuration that is read.
34 *
35 * In general, this file is a wrapper to FTPTelnet functionality,
36 * by interfacing with the Snort preprocessor functions. The rest
37 * of FTPTelnet should be separate from the preprocessor hooks.
38 *
39 * NOTES:
40 * - 16.09.04: Initial Development. SAS
41 *
42 */
43
44 #include <assert.h>
45 #include <string.h>
46 #include <stdio.h>
47 #include <sys/types.h>
48 #include <time.h>
49
50 #ifdef HAVE_CONFIG_H
51 #include "config.h"
52 #endif
53
54 #include "sf_types.h"
55 #include "snort_debug.h"
56
57 #include "ftpp_ui_config.h"
58 #include "snort_ftptelnet.h"
59 #include "spp_ftptelnet.h"
60 #include "sf_preproc_info.h"
61
62 #include "profiler.h"
63
64 #include "sfPolicy.h"
65 #include "sfPolicyUserData.h"
66 #ifdef REG_TEST
67 #include "ftpp_si.h"
68 #endif
69
70 #ifdef DUMP_BUFFER
71 #include "ftptelnet_buffer_dump.h"
72 #endif
73
74 #include "reg_test.h"
75 #include "memory_stats.h"
76
77 const int MAJOR_VERSION = 1;
78 const int MINOR_VERSION = 2;
79 const int BUILD_VERSION = 13;
80 const char *PREPROC_NAME = "SF_FTPTELNET";
81
82 #define SetupFTPTelnet DYNAMIC_PREPROC_SETUP
83
84
85 /*
86 * Defines for preprocessor initialization
87 */
88 /*
89 * snort.conf preprocessor keyword
90 */
91 #define GLOBAL_KEYWORD "ftp_telnet"
92 #define PROTOCOL_KEYWORD "ftp_telnet_protocol"
93
94 /*
95 * The length of the error string buffer.
96 */
97 #define ERRSTRLEN 1000
98
99 /*
100 * External Global Variables
101 * Variables that we need from Snort to log errors correctly and such.
102 */
103 #ifdef PERF_PROFILING
104 PreprocStats ftpPerfStats;
105 PreprocStats telnetPerfStats;
106 #ifdef TARGET_BASED
107 PreprocStats ftpdataPerfStats;
108 #endif
109 #endif
110 FTPTelnet_Stats ftp_telnet_stats;
111
112 /*
113 * Global Variables
114 * This is the only way to work with Snort preprocessors because
115 * the user configuration must be kept between the Init function
116 * the actual preprocessor. There is no interaction between the
117 * two except through global variable usage.
118 */
119 tSfPolicyUserContextId ftp_telnet_config = NULL;
120 FTPTELNET_GLOBAL_CONF *ftp_telnet_eval_config = NULL;
121
122 #ifdef TARGET_BASED
123 int16_t ftp_app_id = 0;
124 int16_t ftp_data_app_id = 0;
125 int16_t telnet_app_id = 0;
126 #endif
127
128 /* static function prototypes */
129 static void FTPTelnetReset(int, void *);
130 static void FTPTelnetResetStats(int, void *);
131 static void FTPTelnetStats(int);
132
133 #ifdef SNORT_RELOAD
134 static void FtpTelnetReloadGlobal(struct _SnortConfig *, char *, void **);
135 static void FtpTelnetReload(struct _SnortConfig *, char *, void **);
136 static int FtpTelnetReloadVerify(struct _SnortConfig *, void *);
137 static void * FtpTelnetReloadSwap(struct _SnortConfig *, void *);
138 static void FtpTelnetReloadSwapFree(void *);
139 #endif
140 int ftptelnet_print_mem_stats(FILE *, char*, PreprocMemInfo *);
141
142 extern char *maxToken;
143
144 /*
145 * Function: FTPTelnetChecks(Packet *p)
146 *
147 * Purpose: This function wraps the functionality in the generic FTPTelnet
148 * processing. We get a Packet structure and pass this into the
149 * FTPTelnet module where the first stage in FTPTelnet is the
150 * Normalization stage where most of the other Snortisms are
151 * taken care of. After that, the modules are generic.
152 *
153 * Arguments: p => pointer to a Packet structure that contains
154 * Snort info about the packet.
155 *
156 * Returns: None
157 *
158 */
FTPTelnetChecks(void * pkt,void * context)159 void FTPTelnetChecks(void *pkt, void *context)
160 {
161 SFSnortPacket *p = (SFSnortPacket*)pkt;
162
163 // precondition - what we registered for
164 assert(IsTCP(p) && p->payload && p->payload_size);
165
166 SnortFTPTelnet(p);
167 }
168
169 #ifdef TARGET_BASED
FTPDataTelnetChecks(void * pkt,void * context)170 void FTPDataTelnetChecks(void *pkt, void *context)
171 {
172 SFSnortPacket *p = (SFSnortPacket*)pkt;
173
174 // precondition - what we registered for
175 assert(IsTCP(p));
176
177 if ( _dpd.fileAPI->get_max_file_depth(NULL, false) >= 0 )
178 {
179 if ( _dpd.sessionAPI->get_application_protocol_id(p->stream_session)
180 == ftp_data_app_id )
181 {
182 PROFILE_VARS;
183 PREPROC_PROFILE_START(ftpdataPerfStats);
184 SnortFTPData(p);
185 PREPROC_PROFILE_END(ftpdataPerfStats);
186 return;
187 }
188 }
189 if ( !p->payload_size || (p->payload == NULL) )
190 return;
191
192 SnortFTPTelnet(p);
193 }
194 #endif
195
196 /*
197 * Function: FTPTelnetInit(char *args)
198 *
199 * Purpose: This function cleans up FTPTelnet memory from the configuration
200 * data.
201 *
202 * Arguments: sig => signal causing this to be called
203 * args => pointer to a context strucutre
204 *
205 * Returns: None
206 *
207 */
FTPTelnetCleanExit(int sig,void * args)208 void FTPTelnetCleanExit(int sig, void *args)
209 {
210 FTPTelnetFreeConfigs(ftp_telnet_config);
211 ftp_telnet_config = NULL;
212 }
213
214 /*
215 * Function: FTPTelnetInit(char *args)
216 *
217 * Purpose: This function initializes FTPTelnetInit with a user configuration.
218 * The function is called when FTPTelnet is configured in snort.conf.
219 * It gets passed a string of arguments, which gets parsed into
220 * configuration constructs that FTPTelnet understands.
221 *
222 * This function gets called for every FTPTelnet configure line. We
223 * use this characteristic to split up the configuration, so each
224 * line is a configuration construct. We need to keep track of what
225 * part of the configuration has been configured, so we don't
226 * configure one part, then configure it again.
227 *
228 * Any upfront memory is allocated here (if necessary).
229 *
230 * Arguments: args => pointer to a string to the preprocessor arguments.
231 *
232 * Returns: None
233 *
234 */
235
236 extern char* mystrtok (char* s, const char* delim);
237
238 #ifdef REG_TEST
PrintFTPSize(void)239 static inline void PrintFTPSize(void)
240 {
241 _dpd.logMsg("\nFTP Session Size: %lu\n", (long unsigned int)sizeof(FTP_SESSION));
242 }
243 #endif
244
FTPTelnetInit(struct _SnortConfig * sc,char * args)245 static void FTPTelnetInit(struct _SnortConfig *sc, char *args)
246 {
247 char *pcToken;
248 char ErrorString[ERRSTRLEN];
249 int iErrStrLen = ERRSTRLEN;
250 int iRet = 0;
251 tSfPolicyId policy_id = _dpd.getParserPolicy(sc);
252 FTPTELNET_GLOBAL_CONF *pPolicyConfig = NULL;
253
254 ErrorString[0] = '\0';
255
256 #ifdef REG_TEST
257 PrintFTPSize();
258 #endif
259
260 if ((args == NULL) || (strlen(args) == 0))
261 {
262 DynamicPreprocessorFatalMessage("%s(%d) No arguments to FtpTelnet "
263 "configuration.\n", *_dpd.config_file, *_dpd.config_line);
264 }
265
266 /* Find out what is getting configured */
267 maxToken = args + strlen(args);
268 pcToken = mystrtok(args, CONF_SEPARATORS);
269 if (pcToken == NULL)
270 {
271 DynamicPreprocessorFatalMessage("%s(%d)mystrtok returned NULL when it "
272 "should not.", __FILE__, __LINE__);
273 }
274
275 if (ftp_telnet_config == NULL)
276 {
277 //create a context
278 ftp_telnet_config = sfPolicyConfigCreate();
279
280 if (ftp_telnet_config == NULL)
281 {
282 DynamicPreprocessorFatalMessage("No memory to allocate "
283 "FTP/Telnet configuration.\n");
284 }
285
286 _dpd.addPreprocExit(FTPTelnetCleanExit, NULL, PRIORITY_APPLICATION, PP_FTPTELNET);
287 _dpd.addPreprocReset(FTPTelnetReset, NULL, PRIORITY_APPLICATION, PP_FTPTELNET);
288 _dpd.addPreprocResetStats(FTPTelnetResetStats, NULL, PRIORITY_APPLICATION, PP_FTPTELNET);
289 _dpd.addPreprocConfCheck(sc, FTPConfigCheck);
290 _dpd.registerPreprocStats("ftp_telnet", FTPTelnetStats);
291
292 #ifdef PERF_PROFILING
293 _dpd.addPreprocProfileFunc("ftptelnet_ftp", (void*)&ftpPerfStats, 0, _dpd.totalPerfStats, NULL);
294 _dpd.addPreprocProfileFunc("ftptelnet_telnet", (void*)&telnetPerfStats, 0, _dpd.totalPerfStats, NULL);
295 #ifdef TARGET_BASED
296 _dpd.addPreprocProfileFunc("ftptelnet_ftpdata", (void*)&ftpdataPerfStats, 0, _dpd.totalPerfStats, NULL);
297 #endif
298 #endif
299
300 #ifdef TARGET_BASED
301 if (_dpd.streamAPI != NULL)
302 {
303 /* Find and store the application ID for FTP & Telnet */
304 ftp_app_id = _dpd.addProtocolReference("ftp");
305 ftp_data_app_id = _dpd.addProtocolReference("ftp-data");
306 telnet_app_id = _dpd.addProtocolReference("telnet");
307 }
308
309 // register with session to handle applications
310 _dpd.sessionAPI->register_service_handler( PP_FTPTELNET, ftp_app_id );
311 _dpd.sessionAPI->register_service_handler( PP_FTPTELNET, ftp_data_app_id );
312 _dpd.sessionAPI->register_service_handler( PP_FTPTELNET, telnet_app_id );
313 #endif
314 }
315
316 /*
317 * Global Configuration Processing
318 * We only process the global configuration once, but always check for
319 * user mistakes, like configuring more than once. That's why we
320 * still check for the global token even if it's been checked.
321 */
322 sfPolicyUserPolicySet (ftp_telnet_config, policy_id);
323 pPolicyConfig = (FTPTELNET_GLOBAL_CONF *)sfPolicyUserDataGetCurrent(ftp_telnet_config);
324 if (pPolicyConfig == NULL)
325 {
326 if (strcasecmp(pcToken, GLOBAL) != 0)
327 {
328 DynamicPreprocessorFatalMessage("%s(%d) Must configure the "
329 "ftptelnet global configuration first.\n",
330 *_dpd.config_file, *_dpd.config_line);
331 }
332
333 pPolicyConfig = (FTPTELNET_GLOBAL_CONF *)_dpd.snortAlloc(1,
334 sizeof(FTPTELNET_GLOBAL_CONF),
335 PP_FTPTELNET,
336 PP_MEM_CATEGORY_CONFIG);
337
338 if (pPolicyConfig == NULL)
339 {
340 DynamicPreprocessorFatalMessage("No memory to allocate "
341 "FTP/Telnet configuration.\n");
342 }
343
344 sfPolicyUserDataSetCurrent(ftp_telnet_config, pPolicyConfig);
345
346 iRet = FtpTelnetInitGlobalConfig(pPolicyConfig,
347 ErrorString, iErrStrLen);
348
349 if (iRet == 0)
350 {
351 iRet = ProcessFTPGlobalConf(pPolicyConfig,
352 ErrorString, iErrStrLen);
353
354 if (iRet == 0)
355 {
356 PrintFTPGlobalConf(pPolicyConfig);
357
358 _dpd.preprocOptRegister(sc, "ftp.bounce", &FTPPBounceInit, &FTPPBounceEval,
359 NULL, NULL, NULL, NULL, NULL);
360
361 #ifdef TARGET_BASED
362 if (_dpd.streamAPI != NULL)
363 {
364 _dpd.streamAPI->set_service_filter_status
365 (sc, ftp_app_id, PORT_MONITOR_SESSION, policy_id, 1);
366
367 _dpd.streamAPI->set_service_filter_status
368 (sc, telnet_app_id, PORT_MONITOR_SESSION, policy_id, 1);
369 }
370 #endif
371 }
372 }
373 }
374 else if (strcasecmp(pcToken, TELNET) == 0)
375 {
376 iRet = ProcessTelnetConf(pPolicyConfig, ErrorString, iErrStrLen);
377 enableFtpTelnetPortStreamServices( sc, &pPolicyConfig->telnet_config->proto_ports, NULL,
378 SSN_DIR_FROM_SERVER | SSN_DIR_FROM_CLIENT );
379 }
380 else if (strcasecmp(pcToken, FTP) == 0)
381 {
382 pcToken = NextToken(CONF_SEPARATORS);
383
384 if ( !pcToken )
385 {
386 DynamicPreprocessorFatalMessage(
387 "%s(%d) Missing ftp_telnet ftp keyword.\n",
388 *(_dpd.config_file), *(_dpd.config_line));
389 }
390 else if (strcasecmp(pcToken, SERVER) == 0)
391 {
392 iRet = ProcessFTPServerConf(sc, pPolicyConfig, ErrorString, iErrStrLen);
393 }
394 else if (strcasecmp(pcToken, CLIENT) == 0)
395 {
396 iRet = ProcessFTPClientConf(sc, pPolicyConfig, ErrorString, iErrStrLen);
397 }
398 else
399 {
400 DynamicPreprocessorFatalMessage("%s(%d) Invalid ftp_telnet ftp keyword.\n",
401 *(_dpd.config_file), *(_dpd.config_line));
402 }
403 }
404 else
405 {
406 DynamicPreprocessorFatalMessage("%s(%d) Invalid ftp_telnet keyword.\n",
407 *(_dpd.config_file), *(_dpd.config_line));
408 }
409
410 if (iRet)
411 {
412 if(iRet > 0)
413 {
414 /*
415 * Non-fatal Error
416 */
417 if(*ErrorString)
418 {
419 _dpd.errMsg("WARNING: %s(%d) => %s\n",
420 *(_dpd.config_file), *(_dpd.config_line), ErrorString);
421 }
422 }
423 else
424 {
425 /*
426 * Fatal Error, log error and exit.
427 */
428 if(*ErrorString)
429 {
430 DynamicPreprocessorFatalMessage("%s(%d) => %s\n",
431 *(_dpd.config_file), *(_dpd.config_line), ErrorString);
432 }
433 else
434 {
435 /*
436 * Check if ErrorString is undefined.
437 */
438 if(iRet == -2)
439 {
440 DynamicPreprocessorFatalMessage("%s(%d) => ErrorString is undefined.\n",
441 *(_dpd.config_file), *(_dpd.config_line));
442 }
443 else
444 {
445 DynamicPreprocessorFatalMessage("%s(%d) => Undefined Error.\n",
446 *(_dpd.config_file), *(_dpd.config_line));
447 }
448 }
449 }
450 }
451 }
452
453 /*
454 * Function: SetupFTPTelnet()
455 *
456 * Purpose: This function initializes FTPTelnet as a Snort preprocessor.
457 *
458 * It registers the preprocessor keyword for use in the snort.conf
459 * and sets up the initialization module for the preprocessor, in
460 * case it is configured.
461 *
462 * This function must be called in InitPreprocessors() in plugbase.c
463 * in order to be recognized by Snort.
464 *
465 * Arguments: None
466 *
467 * Returns: None
468 *
469 */
SetupFTPTelnet(void)470 void SetupFTPTelnet(void)
471 {
472 #ifndef SNORT_RELOAD
473 _dpd.registerPreproc(GLOBAL_KEYWORD, FTPTelnetInit);
474 _dpd.registerPreproc(PROTOCOL_KEYWORD, FTPTelnetInit);
475 #else
476 _dpd.registerPreproc(GLOBAL_KEYWORD, FTPTelnetInit, FtpTelnetReloadGlobal,
477 FtpTelnetReloadVerify, FtpTelnetReloadSwap,
478 FtpTelnetReloadSwapFree);
479 _dpd.registerPreproc(PROTOCOL_KEYWORD, FTPTelnetInit,
480 FtpTelnetReload, NULL, NULL, NULL);
481 #endif
482
483 DEBUG_WRAP(DebugMessage(DEBUG_FTPTELNET, "Preprocessor: FTPTelnet is "
484 "setup . . .\n"););
485 #ifdef DUMP_BUFFER
486 _dpd.registerBufferTracer(getFTPTelnetBuffers, FTPTELNET_BUFFER_DUMP_FUNC);
487 #endif
488 _dpd.registerMemoryStatsFunc(PP_FTPTELNET, ftptelnet_print_mem_stats);
489 }
490
FTPTelnetReset(int signal,void * data)491 static void FTPTelnetReset(int signal, void *data)
492 {
493 return;
494 }
495
FTPTelnetResetStats(int signal,void * data)496 static void FTPTelnetResetStats(int signal, void *data)
497 {
498 return;
499 }
500
FTPTelnetStats(int exiting)501 static void FTPTelnetStats(int exiting)
502 {
503 _dpd.logMsg("FTPTelnet Preprocessor Statistics\n");
504 _dpd.logMsg(" Current active FTP sessions : " STDu64 "\n",
505 ftp_telnet_stats.ftp_sessions);
506 _dpd.logMsg(" Max concurrent FTP sessions : " STDu64 "\n",
507 ftp_telnet_stats.max_ftp_sessions);
508 _dpd.logMsg(" Total FTP Data sessions : " STDu64 "\n",
509 ftp_telnet_stats.ftp_data_sessions);
510 _dpd.logMsg(" Max concurrent FTP Data sessions : " STDu64 "\n",
511 ftp_telnet_stats.max_ftp_data_sessions);
512 _dpd.logMsg(" Current active Telnet sessions : " STDu64 "\n",
513 ftp_telnet_stats.telnet_sessions);
514 _dpd.logMsg(" Max concurrent Telnet sessions : " STDu64 "\n",
515 ftp_telnet_stats.max_telnet_sessions);
516 _dpd.logMsg(" Current ftp_telnet session non-mempool memory : " STDu64 "\n",
517 ftp_telnet_stats.heap_memory);
518 }
519
ftptelnet_print_mem_stats(FILE * fd,char * buffer,PreprocMemInfo * meminfo)520 int ftptelnet_print_mem_stats(FILE *fd, char* buffer, PreprocMemInfo *meminfo)
521 {
522 time_t curr_time = time(NULL);
523 int len = 0;
524 size_t total_heap_memory = meminfo[PP_MEM_CATEGORY_SESSION].used_memory
525 + meminfo[PP_MEM_CATEGORY_CONFIG].used_memory;
526 if (fd)
527 {
528 len = fprintf(fd, ","STDu64","STDu64","STDu64""
529 ","STDu64","STDu64","STDu64""
530 ",%lu,%u,%u,%lu,%u,%u,%lu"
531 , ftp_telnet_stats.ftp_sessions
532 , ftp_telnet_stats.max_ftp_sessions
533 , ftp_telnet_stats.ftp_data_sessions
534 , ftp_telnet_stats.max_ftp_data_sessions
535 , ftp_telnet_stats.telnet_sessions
536 , ftp_telnet_stats.max_telnet_sessions
537 , meminfo[PP_MEM_CATEGORY_SESSION].used_memory
538 , meminfo[PP_MEM_CATEGORY_SESSION].num_of_alloc
539 , meminfo[PP_MEM_CATEGORY_SESSION].num_of_free
540 , meminfo[PP_MEM_CATEGORY_CONFIG].used_memory
541 , meminfo[PP_MEM_CATEGORY_CONFIG].num_of_alloc
542 , meminfo[PP_MEM_CATEGORY_CONFIG].num_of_free
543 , total_heap_memory);
544 return len;
545 }
546 if (buffer)
547 {
548 len = snprintf(buffer, CS_STATS_BUF_SIZE,
549 "\n\nMemory Statistics for FTPTelnet at: %s\n"
550 "FTPTelnet Preprocessor Statistics:\n"
551 " Current active FTP sessions : "STDu64"\n"
552 " Max concurrent FTP sessions : "STDu64"\n"
553 " Total FTP Data sessions : "STDu64"\n"
554 " Max concurrent FTP Data sessions : "STDu64"\n"
555 " Current active Telnet sessions : "STDu64"\n"
556 " Max concurrent Telnet sessions : "STDu64"\n"
557 , ctime(&curr_time)
558 , ftp_telnet_stats.ftp_sessions
559 , ftp_telnet_stats.max_ftp_sessions
560 , ftp_telnet_stats.ftp_data_sessions
561 , ftp_telnet_stats.max_ftp_data_sessions
562 , ftp_telnet_stats.telnet_sessions
563 , ftp_telnet_stats.max_telnet_sessions);
564 }
565 else
566 {
567 _dpd.logMsg("\n");
568 _dpd.logMsg("Memory Statistics of FTPTelnet at: %s\n",
569 ctime(&curr_time));
570 _dpd.logMsg(" Current active FTP sessions : "STDu64"\n",
571 ftp_telnet_stats.ftp_sessions);
572 _dpd.logMsg(" Max concurrent FTP sessions : "STDu64"\n",
573 ftp_telnet_stats.max_ftp_sessions);
574 _dpd.logMsg(" Total FTP Data sessions : "STDu64"\n",
575 ftp_telnet_stats.ftp_data_sessions);
576 _dpd.logMsg(" Max concurrent FTP Data sessions : "STDu64"\n",
577 ftp_telnet_stats.max_ftp_data_sessions);
578 _dpd.logMsg(" Current active Telnet sessions : "STDu64"\n",
579 ftp_telnet_stats.telnet_sessions);
580 _dpd.logMsg(" Max concurrent Telnet sessions : "STDu64"\n",
581 ftp_telnet_stats.max_telnet_sessions);
582 }
583 return len;
584 }
585
586 #ifdef SNORT_RELOAD
_FtpTelnetReload(struct _SnortConfig * sc,tSfPolicyUserContextId ftp_telnet_swap_config,char * args)587 static void _FtpTelnetReload(struct _SnortConfig *sc, tSfPolicyUserContextId ftp_telnet_swap_config, char *args)
588 {
589 char *pcToken;
590 char ErrorString[ERRSTRLEN];
591 int iErrStrLen = ERRSTRLEN;
592 int iRet = 0;
593 tSfPolicyId policy_id = _dpd.getParserPolicy(sc);
594 FTPTELNET_GLOBAL_CONF *pPolicyConfig = NULL;
595
596 ErrorString[0] = '\0';
597
598 if ((args == NULL) || (strlen(args) == 0))
599 {
600 DynamicPreprocessorFatalMessage("%s(%d) No arguments to FtpTelnet "
601 "configuration.\n", *_dpd.config_file, *_dpd.config_line);
602 }
603
604 /* Find out what is getting configured */
605 maxToken = args + strlen(args);
606 pcToken = mystrtok(args, CONF_SEPARATORS);
607 if (pcToken == NULL)
608 {
609 DynamicPreprocessorFatalMessage("%s(%d)mystrtok returned NULL when it "
610 "should not.", __FILE__, __LINE__);
611 }
612
613 /*
614 * Global Configuration Processing
615 * We only process the global configuration once, but always check for
616 * user mistakes, like configuring more than once. That's why we
617 * still check for the global token even if it's been checked.
618 */
619 sfPolicyUserPolicySet (ftp_telnet_swap_config, policy_id);
620 pPolicyConfig = (FTPTELNET_GLOBAL_CONF *)sfPolicyUserDataGetCurrent(ftp_telnet_swap_config);
621
622 if (pPolicyConfig == NULL)
623 {
624 if (strcasecmp(pcToken, GLOBAL) != 0)
625 {
626 DynamicPreprocessorFatalMessage("%s(%d) Must configure the "
627 "ftptelnet global configuration first.\n",
628 *_dpd.config_file, *_dpd.config_line);
629 }
630
631 pPolicyConfig = (FTPTELNET_GLOBAL_CONF *)_dpd.snortAlloc(1,
632 sizeof(FTPTELNET_GLOBAL_CONF),
633 PP_FTPTELNET,
634 PP_MEM_CATEGORY_CONFIG);
635
636 if (pPolicyConfig == NULL)
637 {
638 DynamicPreprocessorFatalMessage("No memory to allocate "
639 "FTP/Telnet configuration.\n");
640 }
641
642 sfPolicyUserDataSetCurrent(ftp_telnet_swap_config, pPolicyConfig);
643
644 iRet = FtpTelnetInitGlobalConfig(pPolicyConfig,
645 ErrorString, iErrStrLen);
646
647 if (iRet == 0)
648 {
649 iRet = ProcessFTPGlobalConf(pPolicyConfig,
650 ErrorString, iErrStrLen);
651
652 if (iRet == 0)
653 {
654 PrintFTPGlobalConf(pPolicyConfig);
655
656 _dpd.preprocOptRegister(sc, "ftp.bounce", &FTPPBounceInit, &FTPPBounceEval,
657 NULL, NULL, NULL, NULL, NULL);
658 }
659 }
660 }
661 else if (strcasecmp(pcToken, TELNET) == 0)
662 {
663 iRet = ProcessTelnetConf(pPolicyConfig, ErrorString, iErrStrLen);
664 enableFtpTelnetPortStreamServices( sc, &pPolicyConfig->telnet_config->proto_ports, NULL,
665 SSN_DIR_FROM_SERVER | SSN_DIR_FROM_CLIENT );
666 }
667 else if (strcasecmp(pcToken, FTP) == 0)
668 {
669 pcToken = NextToken(CONF_SEPARATORS);
670
671 if ( !pcToken )
672 {
673 DynamicPreprocessorFatalMessage(
674 "%s(%d) Missing ftp_telnet ftp keyword.\n",
675 *(_dpd.config_file), *(_dpd.config_line));
676 }
677 else if (strcasecmp(pcToken, SERVER) == 0)
678 {
679 iRet = ProcessFTPServerConf(sc, pPolicyConfig, ErrorString, iErrStrLen);
680 }
681 else if (strcasecmp(pcToken, CLIENT) == 0)
682 {
683 iRet = ProcessFTPClientConf(sc, pPolicyConfig, ErrorString, iErrStrLen);
684 }
685 else
686 {
687 DynamicPreprocessorFatalMessage("%s(%d) Invalid ftp_telnet ftp keyword.\n",
688 *(_dpd.config_file), *(_dpd.config_line));
689 }
690 }
691 else
692 {
693 DynamicPreprocessorFatalMessage("%s(%d) Invalid ftp_telnet keyword.\n",
694 *(_dpd.config_file), *(_dpd.config_line));
695 }
696
697 if (iRet)
698 {
699 if(iRet > 0)
700 {
701 /*
702 * Non-fatal Error
703 */
704 if(*ErrorString)
705 {
706 _dpd.errMsg("WARNING: %s(%d) => %s\n",
707 *(_dpd.config_file), *(_dpd.config_line), ErrorString);
708 }
709 }
710 else
711 {
712 /*
713 * Fatal Error, log error and exit.
714 */
715 if(*ErrorString)
716 {
717 DynamicPreprocessorFatalMessage("%s(%d) => %s\n",
718 *(_dpd.config_file), *(_dpd.config_line), ErrorString);
719 }
720 else
721 {
722 /*
723 * Check if ErrorString is undefined.
724 */
725 if(iRet == -2)
726 {
727 DynamicPreprocessorFatalMessage("%s(%d) => ErrorString is undefined.\n",
728 *(_dpd.config_file), *(_dpd.config_line));
729 }
730 else
731 {
732 DynamicPreprocessorFatalMessage("%s(%d) => Undefined Error.\n",
733 *(_dpd.config_file), *(_dpd.config_line));
734 }
735 }
736 }
737 }
738 }
739
FtpTelnetReloadGlobal(struct _SnortConfig * sc,char * args,void ** new_config)740 static void FtpTelnetReloadGlobal(struct _SnortConfig *sc, char *args, void **new_config)
741 {
742 tSfPolicyUserContextId ftp_telnet_swap_config = (tSfPolicyUserContextId)*new_config;
743
744 if (ftp_telnet_swap_config == NULL)
745 {
746 //create a context
747 ftp_telnet_swap_config = sfPolicyConfigCreate();
748
749 if (ftp_telnet_swap_config == NULL)
750 {
751 DynamicPreprocessorFatalMessage("No memory to allocate "
752 "FTP/Telnet swap_configuration.\n");
753 }
754 *new_config = (void *)ftp_telnet_swap_config;
755 }
756 _FtpTelnetReload(sc, ftp_telnet_swap_config, args);
757 }
758
FtpTelnetReload(struct _SnortConfig * sc,char * args,void ** new_config)759 static void FtpTelnetReload(struct _SnortConfig *sc, char *args, void **new_config)
760 {
761 tSfPolicyUserContextId ftp_telnet_swap_config;
762 ftp_telnet_swap_config = (tSfPolicyUserContextId)_dpd.getRelatedReloadData(sc, GLOBAL_KEYWORD);
763 _FtpTelnetReload(sc, ftp_telnet_swap_config, args);
764 }
765
FtpTelnetReloadVerifyPolicy(struct _SnortConfig * sc,tSfPolicyUserContextId config,tSfPolicyId policyId,void * pData)766 static int FtpTelnetReloadVerifyPolicy(
767 struct _SnortConfig *sc,
768 tSfPolicyUserContextId config,
769 tSfPolicyId policyId,
770 void* pData
771 )
772 {
773 return FTPTelnetCheckConfigs( sc, pData, policyId );
774 }
775
FtpTelnetReloadVerify(struct _SnortConfig * sc,void * new_config)776 static int FtpTelnetReloadVerify(struct _SnortConfig *sc, void *new_config)
777 {
778 tSfPolicyUserContextId ftp_telnet_swap_config = (tSfPolicyUserContextId)new_config;
779
780 if (ftp_telnet_swap_config == NULL)
781 return 0;
782
783 if (sfPolicyUserDataIterate (sc, ftp_telnet_swap_config, FtpTelnetReloadVerifyPolicy))
784 return -1;
785
786 return 0;
787 }
788
FtpTelnetReloadSwapPolicy(struct _SnortConfig * sc,tSfPolicyUserContextId config,tSfPolicyId policyId,void * pData)789 static int FtpTelnetReloadSwapPolicy(
790 struct _SnortConfig *sc,
791 tSfPolicyUserContextId config,
792 tSfPolicyId policyId,
793 void* pData
794 )
795 {
796 FTPTELNET_GLOBAL_CONF *pPolicyConfig = (FTPTELNET_GLOBAL_CONF *)pData;
797
798 //do any housekeeping before freeing FTPTELNET_GLOBAL_CONF
799 if (pPolicyConfig->ref_count == 0)
800 {
801 sfPolicyUserDataClear (config, policyId);
802 FTPTelnetFreeConfig(pPolicyConfig);
803 }
804
805 return 0;
806 }
807
FtpTelnetReloadSwap(struct _SnortConfig * sc,void * new_config)808 static void * FtpTelnetReloadSwap(struct _SnortConfig *sc, void *new_config)
809 {
810 tSfPolicyUserContextId ftp_telnet_swap_config = (tSfPolicyUserContextId)new_config;
811 tSfPolicyUserContextId old_config = ftp_telnet_config;
812
813 if (ftp_telnet_swap_config == NULL)
814 return NULL;
815
816 ftp_telnet_config = ftp_telnet_swap_config;
817
818 sfPolicyUserDataIterate (sc, old_config, FtpTelnetReloadSwapPolicy);
819
820 if (sfPolicyUserPolicyGetActive(old_config) == 0)
821 return (void *)old_config;
822
823 return NULL;
824 }
825
FtpTelnetReloadSwapFree(void * data)826 static void FtpTelnetReloadSwapFree(void *data)
827 {
828 if (data == NULL)
829 return;
830
831 FTPTelnetFreeConfigs((tSfPolicyUserContextId)data);
832 }
833
834 #endif
835