1 /*
2  * Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
3  * Copyright (C) 2007-2013 Sourcefire, Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License Version 2 as
7  * published by the Free Software Foundation.  You may not use, modify or
8  * distribute this program under any other version of the GNU General
9  * Public License.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  */
20 
21 /*
22  * File: ssl_config.c
23  * Author: Bhagyashree Bantwal <bbantwal@cisco.com>
24  * Brief: Configuration for the SSL preprocessor
25 */
26 
27 
28 #include "ssl_config.h"
29 #ifdef ENABLE_HA
30 #include "ssl_ha.h"
31 #endif
32 #include <errno.h>
33 
34 #define PATH_MAX 4096
35 #define MIN_HB_LEN 0
36 #define MAX_HB_LEN 65535
37 
38 #ifdef TARGET_BASED
39 int16_t ssl_app_id = SFTARGET_UNKNOWN_PROTOCOL;
40 #endif
41 
42 #ifdef PERF_PROFILING
43 PreprocStats sslpp_perf_stats;
44 #endif
45 
46 
47 tSfPolicyUserContextId ssl_config = NULL;
48 
49 static void SSLFreeConfig(tSfPolicyUserContextId config, bool full_cleanup);
50 static void SSLCleanExit(int, void *);
51 static void SSLResetStats(int, void *);
52 static int SSLPP_CheckConfig(struct _SnortConfig *);
53 
54 /* Parsing for the ssl_state rule option */
SSLPP_state_init(struct _SnortConfig * sc,char * name,char * params,void ** data)55 static int SSLPP_state_init(struct _SnortConfig *sc, char *name, char *params, void **data)
56 {
57     int flags = 0, mask = 0;
58     char *end = NULL;
59     char *tok;
60     SslRuleOptData *sdata;
61 
62     tok = strtok_r(params, ",", &end);
63 
64     if(!tok)
65         DynamicPreprocessorFatalMessage("%s(%d) => missing argument to"
66             "ssl_state keyword\n", *(_dpd.config_file), *(_dpd.config_line));
67 
68     do
69     {
70         int negated = 0;
71 
72         if (tok[0] == '!')
73         {
74             negated = 1;
75             tok++;
76         }
77 
78         if(!strcasecmp("client_hello", tok))
79         {
80             flags |= SSL_CUR_CLIENT_HELLO_FLAG;
81             if (negated)
82                 mask |= SSL_CUR_CLIENT_HELLO_FLAG;
83         }
84         else if(!strcasecmp("server_hello", tok))
85         {
86             flags |= SSL_CUR_SERVER_HELLO_FLAG;
87             if (negated)
88                 mask |= SSL_CUR_SERVER_HELLO_FLAG;
89         }
90         else if(!strcasecmp("client_keyx", tok))
91         {
92             flags |= SSL_CUR_CLIENT_KEYX_FLAG;
93             if (negated)
94                 mask |= SSL_CUR_CLIENT_KEYX_FLAG;
95         }
96         else if(!strcasecmp("server_keyx", tok))
97         {
98             flags |= SSL_CUR_SERVER_KEYX_FLAG;
99             if (negated)
100                 mask |= SSL_CUR_SERVER_KEYX_FLAG;
101         }
102         else if(!strcasecmp("unknown", tok))
103         {
104             flags |= SSL_UNKNOWN_FLAG;
105             if (negated)
106                 mask |= SSL_UNKNOWN_FLAG;
107         }
108         else
109         {
110             DynamicPreprocessorFatalMessage(
111                     "%s(%d) => %s is not a recognized argument to %s.\n",
112                     *(_dpd.config_file), _dpd.config_file, tok, name);
113         }
114 
115     } while( (tok = strtok_r(NULL, ",", &end)) != NULL );
116 
117     sdata = (SslRuleOptData *)calloc(1, sizeof(*sdata));
118     if (sdata == NULL)
119     {
120         DynamicPreprocessorFatalMessage("Could not allocate memory for the "
121                 "ssl_state preprocessor rule option.\n");
122     }
123 
124     sdata->flags = flags;
125     sdata->mask = mask;
126     *data = (void *)sdata;
127 
128     return 1;
129 }
130 
131 /* Parsing for the ssl_version rule option */
SSLPP_ver_init(struct _SnortConfig * sc,char * name,char * params,void ** data)132 static int SSLPP_ver_init(struct _SnortConfig *sc, char *name, char *params, void **data)
133 {
134     int flags = 0, mask = 0;
135     char *end = NULL;
136     char *tok;
137     SslRuleOptData *sdata;
138 
139     tok = strtok_r(params, ",", &end);
140 
141     if(!tok)
142         DynamicPreprocessorFatalMessage("%s(%d) => missing argument to"
143             "ssl_state keyword\n", *(_dpd.config_file), *(_dpd.config_line));
144 
145     do
146     {
147         int negated = 0;
148 
149         if (tok[0] == '!')
150         {
151             negated = 1;
152             tok++;
153         }
154 
155         if(!strcasecmp("sslv2", tok))
156         {
157             flags |= SSL_VER_SSLV2_FLAG;
158             if (negated)
159                 mask |= SSL_VER_SSLV2_FLAG;
160         }
161         else if(!strcasecmp("sslv3", tok))
162         {
163             flags |= SSL_VER_SSLV3_FLAG;
164             if (negated)
165                 mask |= SSL_VER_SSLV3_FLAG;
166         }
167         else if(!strcasecmp("tls1.0", tok))
168         {
169             flags |= SSL_VER_TLS10_FLAG;
170             if (negated)
171                 mask |= SSL_VER_TLS10_FLAG;
172         }
173         else if(!strcasecmp("tls1.1", tok))
174         {
175             flags |= SSL_VER_TLS11_FLAG;
176             if (negated)
177                 mask |= SSL_VER_TLS11_FLAG;
178         }
179         else if(!strcasecmp("tls1.2", tok))
180         {
181             flags |= SSL_VER_TLS12_FLAG;
182             if (negated)
183                 mask |= SSL_VER_TLS12_FLAG;
184         }
185         else
186         {
187             DynamicPreprocessorFatalMessage(
188                     "%s(%d) => %s is not a recognized argument to %s.\n",
189                     *(_dpd.config_file), _dpd.config_file, tok, name);
190         }
191 
192     } while( (tok = strtok_r(NULL, ",", &end)) != NULL );
193 
194     sdata = (SslRuleOptData *)calloc(1, sizeof(*sdata));
195     if (sdata == NULL)
196     {
197         DynamicPreprocessorFatalMessage("Could not allocate memory for the "
198                 "ssl_version preprocessor rule option.\n");
199     }
200 
201     sdata->flags = flags;
202     sdata->mask = mask;
203     *data = (void *)sdata;
204 
205     return 1;
206 }
207 
UpdatePathToDir(char * full_path_dirname,unsigned int max_size,char * dirname)208 static void UpdatePathToDir(char *full_path_dirname, unsigned int max_size, char *dirname)
209 {
210     int iRet;
211     char *snort_conf_dir = *(_dpd.snort_conf_dir);
212 
213     if (!snort_conf_dir || !(*snort_conf_dir) || !full_path_dirname || !dirname)
214     {
215         DynamicPreprocessorFatalMessage(" %s(%d) => can't create path.\n",
216                 *(_dpd.config_file), *(_dpd.config_line));
217     }
218     /*dirname is too long*/
219     if ( max_size < strlen(dirname) )
220     {
221         DynamicPreprocessorFatalMessage(" %s(%d) => the dir name length %u is longer than allowed %u.\n",
222                 *(_dpd.config_file), *(_dpd.config_line), strlen(dirname), max_size);
223     }
224 
225     /*
226      *  If an absolute path is specified, then use that.
227      */
228 #ifndef WIN32
229     if(dirname[0] == '/')
230     {
231         iRet = snprintf(full_path_dirname, max_size, "%s", dirname);
232     }
233     else
234     {
235         /*
236          * Set up the dir name directory.
237          */
238         if (snort_conf_dir[strlen(snort_conf_dir) - 1] == '/')
239         {
240             iRet = snprintf(full_path_dirname,max_size,
241                     "%s%s", snort_conf_dir, dirname);
242         }
243         else
244         {
245             iRet = snprintf(full_path_dirname, max_size,
246                     "%s/%s", snort_conf_dir, dirname);
247         }
248     }
249 #else
250     if(strlen(dirname)>3 && dirname[1]==':' && dirname[2]=='\\')
251     {
252         iRet = snprintf(full_path_dirname, max_size, "%s", dirname);
253     }
254     else
255     {
256         /*
257          **  Set up the dir name directory
258          */
259         if (snort_conf_dir[strlen(snort_conf_dir) - 1] == '\\' ||
260                 snort_conf_dir[strlen(snort_conf_dir) - 1] == '/' )
261         {
262             iRet = snprintf(full_path_dirname,max_size,
263                     "%s%s", snort_conf_dir, dirname);
264         }
265         else
266         {
267             iRet = snprintf(full_path_dirname, max_size,
268                     "%s\\%s", snort_conf_dir, dirname);
269         }
270     }
271 #endif
272 
273     if(iRet < 0)
274     {
275         DynamicPreprocessorFatalMessage(" %s(%d) => the dir name length %u is longer than allowed %u.\n",
276                 *(_dpd.config_file), *(_dpd.config_line), strlen(dirname), max_size);
277     }
278 }
279 
280 /* SSL Preprocessor configuration parsing */
SSLPP_config(SSLPP_config_t * config,char * conf)281 static void SSLPP_config(SSLPP_config_t *config, char *conf)
282 {
283     char *saveptr;
284     char *space_tok;
285     char *comma_tok;
286     char *portptr;
287     char *search;
288     SFP_errstr_t err;
289 
290     if(!conf)
291         return;
292 
293     if (config == NULL)
294         return;
295 
296     search = conf;
297 
298     while( (comma_tok = strtok_r(search, ",", &saveptr)) != NULL )
299     {
300         search = NULL;
301 
302         space_tok = strtok_r(comma_tok, " ", &portptr);
303 
304         if(!space_tok)
305             return;
306 
307         if(!strcasecmp(space_tok, "ports"))
308         {
309             memset(config->ports, 0, sizeof(config->ports));
310 
311             if(SFP_ports(config->ports, portptr, err) != SFP_SUCCESS)
312                 DynamicPreprocessorFatalMessage(
313                     "%s(%d) => Failed to parse: %s\n",
314                    *(_dpd.config_file), *(_dpd.config_line), SFP_GET_ERR(err));
315 
316         }
317         else if(!strcasecmp(space_tok, "noinspect_encrypted"))
318         {
319             char *tmpChar;
320             tmpChar = strtok_r(NULL, " \t\n", &portptr);
321             if(tmpChar)
322             {
323         	    DynamicPreprocessorFatalMessage("%s(%d) => Invalid argument to the"
324         	                    " SSL preprocessor: '%s' in %s\n",
325         	                    *(_dpd.config_file), *(_dpd.config_line), space_tok, tmpChar);
326             }
327             config->flags |= SSLPP_DISABLE_FLAG;
328         }
329         else if(!strcasecmp(space_tok, "trustservers"))
330         {
331             char *tmpChar;
332             tmpChar = strtok_r(NULL, " \t\n", &portptr);
333             if(tmpChar)
334             {
335                 DynamicPreprocessorFatalMessage("%s(%d) => Invalid argument to the"
336                     " SSL preprocessor: '%s' in %s\n",
337                     *(_dpd.config_file), *(_dpd.config_line), space_tok, tmpChar);
338             }
339             config->flags |= SSLPP_TRUSTSERVER_FLAG;
340         }
341         else if(!strcasecmp(space_tok, "pki_dir"))
342         {
343             char *tmpChar;
344             char full_path_dirname[PATH_MAX+1];
345             tmpChar = strtok_r(NULL, " \t\n", &portptr);
346             if(tmpChar == NULL)
347             {
348                 DynamicPreprocessorFatalMessage("%s(%d) => Invalid argument to '%s' option in the"
349                     " SSL preprocessor\n",
350                     *(_dpd.config_file), *(_dpd.config_line), space_tok);
351             }
352             UpdatePathToDir(full_path_dirname, PATH_MAX, tmpChar);
353             config->pki_dir = strdup(full_path_dirname);
354             if (!config->pki_dir)
355             {
356                 DynamicPreprocessorFatalMessage("%s(%d) Failed to allocate memory for "
357                     "option in SSL preprocessor\n", __FILE__, __LINE__);
358             }
359         }
360         else if(!strcasecmp(space_tok, "ssl_rules_dir"))
361         {
362             char *tmpChar;
363             char full_path_dirname[PATH_MAX+1];
364             tmpChar = strtok_r(NULL, " \t\n", &portptr);
365             if(tmpChar == NULL)
366             {
367                 DynamicPreprocessorFatalMessage("%s(%d) => Invalid argument to '%s' option in the"
368                     " SSL preprocessor\n",
369                     *(_dpd.config_file), *(_dpd.config_line), space_tok);
370             }
371             UpdatePathToDir(full_path_dirname, PATH_MAX, tmpChar);
372             config->ssl_rules_dir = strdup(full_path_dirname);
373             if (!config->ssl_rules_dir)
374             {
375                 DynamicPreprocessorFatalMessage("%s(%d) Failed to allocate memory for "
376                     "option in SSL preprocessor\n", __FILE__, __LINE__);
377             }
378         }
379         else if(!strcasecmp(space_tok, "memcap"))
380         {
381             int value;
382             char *endStr = NULL;
383             char *tmpChar;
384 
385             tmpChar = strtok_r(NULL, " \t\n", &portptr);
386             if(tmpChar == NULL)
387             {
388                 DynamicPreprocessorFatalMessage("%s(%d) => Invalid argument to '%s' option in the"
389                     " SSL preprocessor\n",
390                     *(_dpd.config_file), *(_dpd.config_line), space_tok);
391             }
392 
393             value = _dpd.SnortStrtol( tmpChar, &endStr, 10);
394 
395             if (( *endStr) || (errno == ERANGE))
396             {
397                 DynamicPreprocessorFatalMessage("%s(%d) => Invalid argument to '%s' option in the"
398                     " SSL preprocessor\n",
399                     *(_dpd.config_file), *(_dpd.config_line), space_tok);
400             }
401 
402             config->memcap = value;
403 
404         }
405         else if(!strcasecmp(space_tok, "decrypt_memcap"))
406         {
407             int value;
408             char *endStr = NULL;
409             char *tmpChar;
410 
411             tmpChar = strtok_r(NULL, " \t\n", &portptr);
412             if(tmpChar == NULL)
413             {
414                 DynamicPreprocessorFatalMessage("%s(%d) => Invalid argument to '%s' option in the"
415                     " SSL preprocessor\n",
416                     *(_dpd.config_file), *(_dpd.config_line), space_tok);
417             }
418 
419             value = _dpd.SnortStrtol( tmpChar, &endStr, 10);
420 
421             if (( *endStr) || (errno == ERANGE))
422             {
423                 DynamicPreprocessorFatalMessage("%s(%d) => Invalid argument to '%s' option in the"
424                     " SSL preprocessor\n",
425                     *(_dpd.config_file), *(_dpd.config_line), space_tok);
426             }
427 
428             config->decrypt_memcap = value;
429 
430         }
431 #ifdef ENABLE_HA
432         else if(!strcasecmp(space_tok, "enable_ssl_ha"))
433         {
434             char *tmpChar;
435             tmpChar = strtok_r(NULL, " \t\n", &portptr);
436             if(tmpChar == NULL)
437             {
438                 DynamicPreprocessorFatalMessage("%s(%d) => Invalid argument to '%s' option in the"
439                     " SSL preprocessor\n",
440                     *(_dpd.config_file), *(_dpd.config_line), space_tok);
441             }
442             if(!strcasecmp(tmpChar, "yes"))
443                 config->enable_ssl_ha = true;
444             else if(!strcasecmp(tmpChar, "no"))
445                 config->enable_ssl_ha = false;
446             else
447             {
448                 DynamicPreprocessorFatalMessage("%s(%d) => Invalid argument '%s' to '%s' option in the"
449                     " SSL preprocessor\n",
450                     *(_dpd.config_file), *(_dpd.config_line), tmpChar, space_tok);
451             }
452         }
453 #endif
454         else if(!strcasecmp(space_tok, "max_heartbeat_length"))
455         {
456             int value;
457             char *endStr = NULL;
458             char *tmpChar;
459 
460             tmpChar = strtok_r(NULL, " \t\n", &portptr);
461             if(tmpChar == NULL)
462             {
463                 DynamicPreprocessorFatalMessage("%s(%d) => Invalid argument to '%s' option in the"
464                     " SSL preprocessor\n",
465                     *(_dpd.config_file), *(_dpd.config_line), space_tok);
466             }
467 
468             value = _dpd.SnortStrtol( tmpChar, &endStr, 10);
469 
470             if (( *endStr) || (errno == ERANGE))
471             {
472                 DynamicPreprocessorFatalMessage("%s(%d) => Invalid argument to '%s' option in the"
473                     " SSL preprocessor\n",
474                     *(_dpd.config_file), *(_dpd.config_line), space_tok);
475             }
476 
477             if (value < MIN_HB_LEN || value > MAX_HB_LEN)
478             {
479                 DynamicPreprocessorFatalMessage(" %s(%d) => Value specified for %s is out of "
480                         "bounds.  Please specify an integer between %d and %d.\n",
481                         *(_dpd.config_file), *(_dpd.config_line),
482                         space_tok, MIN_HB_LEN, MAX_HB_LEN);
483             }
484 
485             config->max_heartbeat_len = value;
486         }
487         else
488         {
489             DynamicPreprocessorFatalMessage("%s(%d) => Invalid argument to the"
490                 " SSL preprocessor: '%s' in %s\n",
491                 *(_dpd.config_file), *(_dpd.config_line), comma_tok, conf);
492         }
493     }
494 
495     /* Verify configured options make sense */
496     if ((config->flags & SSLPP_TRUSTSERVER_FLAG) &&
497         !(config->flags & SSLPP_DISABLE_FLAG))
498     {
499         DynamicPreprocessorFatalMessage("%s(%d) => SSL preprocessor: 'trustservers' "
500             "requires 'noinspect_encrypted' to be useful.\n",
501             *(_dpd.config_file), *(_dpd.config_line));
502     }
503 }
504 
SSLPP_print_config(SSLPP_config_t * config)505 static void SSLPP_print_config(SSLPP_config_t *config)
506 {
507     char buf[1024];    /* For syslog printing */
508     int i;
509     int newline;
510 
511     if (config == NULL)
512         return;
513 
514     memset(buf, 0, sizeof(buf));
515 
516     _dpd.logMsg("SSLPP config:\n");
517     _dpd.logMsg("    Encrypted packets: %s\n",
518            config->flags & SSLPP_DISABLE_FLAG ? "not inspected" : "inspected");
519 
520     _dpd.logMsg("    Ports:\n");
521 
522     for(newline = 0, i = 0; i < MAXPORTS; i++)
523     {
524         if( config->ports[ PORT_INDEX(i) ] & CONV_PORT(i) )
525         {
526             SFP_snprintfa(buf, sizeof(buf), "    %5d", i);
527             if( !((++newline) % 5) )
528             {
529                 SFP_snprintfa(buf, sizeof(buf), "\n");
530                 _dpd.logMsg(buf);
531                 memset(buf, 0, sizeof(buf));
532             }
533         }
534     }
535 
536     if(newline % 5)
537         SFP_snprintfa(buf, sizeof(buf), "\n");
538 
539     _dpd.logMsg(buf);
540 
541     if ( config->flags & SSLPP_TRUSTSERVER_FLAG )
542     {
543         _dpd.logMsg("    Server side data is trusted\n");
544     }
545 
546     if ( config->pki_dir )
547     {
548         _dpd.logMsg("    PKI Directory: %s\n", config->pki_dir);
549     }
550 
551     if ( config->ssl_rules_dir )
552     {
553         _dpd.logMsg("    SSL Rules Directory: %s\n", config->ssl_rules_dir);
554     }
555 
556 #ifdef ENABLE_HA
557         _dpd.logMsg("    SSL HA enabled     : %s\n", config->enable_ssl_ha ? "YES" : "NO" );
558 #endif
559     _dpd.logMsg("    Maximum SSL Heartbeat length: %d\n", config->max_heartbeat_len);
560 
561 }
562 
SSLSetPort(SSLPP_config_t * config,int port)563 static inline void SSLSetPort(SSLPP_config_t *config, int port)
564 {
565     if (config == NULL)
566         return;
567 
568     config->ports[ PORT_INDEX(port) ] |= CONV_PORT(port);
569 }
570 
571 
572 
SSLPP_init_config(SSLPP_config_t * config)573 static void SSLPP_init_config(SSLPP_config_t *config)
574 {
575     if (config == NULL)
576         return;
577     config->ssl_rules_dir = NULL;
578     config->pki_dir = NULL;
579     config->memcap = 100000;
580     config->enable_ssl_ha = false;
581     config->decrypt_memcap = 100000;
582     config->current_handle = NULL;
583     config->reload_handle = NULL;
584     config->max_heartbeat_len = 0;
585 
586     /* Setup default ports */
587     SSLSetPort(config, 443); /* HTTPS */
588     SSLSetPort(config, 465); /* SMTPS */
589     SSLSetPort(config, 563); /* NNTPS */
590     SSLSetPort(config, 636); /* LDAPS */
591     SSLSetPort(config, 989); /* FTPS */
592     SSLSetPort(config, 992); /* TelnetS */
593     SSLSetPort(config, 993); /* IMAPS */
594     SSLSetPort(config, 994); /* IRCS */
595     SSLSetPort(config, 995); /* POPS */
596 }
597 
registerPortsForDispatch(struct _SnortConfig * sc,SSLPP_config_t * policy)598 static void registerPortsForDispatch( struct _SnortConfig *sc, SSLPP_config_t *policy )
599 {
600     int port;
601 
602     for ( port = 0; port < MAXPORTS; port++ )
603     {
604         if( policy->ports[ port / 8 ] & ( 1 << ( port % 8 ) ) )
605         {
606             _dpd.sessionAPI->enable_preproc_for_port( sc, PP_SSL, PROTO_BIT__TCP, port );
607         }
608     }
609 }
610 
registerPortsForReassembly(SSLPP_config_t * policy,int direction)611 static void registerPortsForReassembly( SSLPP_config_t *policy, int direction )
612 {
613     uint32_t port;
614 
615     for ( port = 0; port < MAXPORTS; port++ )
616     {
617         if( policy->ports[ port / 8 ] & ( 1 << ( port % 8 ) ) )
618         {
619             _dpd.streamAPI->register_reassembly_port( NULL, port, direction );
620         }
621     }
622 }
623 
624 
_addPortsToStream5Filter(struct _SnortConfig * sc,SSLPP_config_t * config,tSfPolicyId policy_id)625 static void _addPortsToStream5Filter(struct _SnortConfig *sc, SSLPP_config_t *config, tSfPolicyId policy_id)
626 {
627     unsigned int portNum;
628 
629     if (config == NULL)
630         return;
631 
632     for (portNum = 0; portNum < MAXPORTS; portNum++)
633     {
634         if(config->ports[(portNum/8)] & (1<<(portNum%8)))
635         {
636             //Add port the port
637             _dpd.streamAPI->set_port_filter_status
638                 (sc, IPPROTO_TCP, (uint16_t)portNum, PORT_MONITOR_SESSION, policy_id, 1);
639         }
640     }
641 }
642 
643 #ifdef TARGET_BASED
_addServicesToStream5Filter(struct _SnortConfig * sc,tSfPolicyId policy_id)644 static void _addServicesToStream5Filter(struct _SnortConfig *sc, tSfPolicyId policy_id)
645 {
646     _dpd.streamAPI->set_service_filter_status
647         (sc, ssl_app_id, PORT_MONITOR_SESSION, policy_id, 1);
648 }
649 #endif
650 
SSLPP_init(struct _SnortConfig * sc,char * args)651 void SSLPP_init(struct _SnortConfig *sc, char *args)
652 {
653     tSfPolicyId policy_id = _dpd.getParserPolicy(sc);
654     SSLPP_config_t *pPolicyConfig = NULL;
655 
656 	/* For SFR CLI*/
657 	_dpd.controlSocketRegisterHandler(CS_TYPE_SSL_STATS, NULL, NULL, &DisplaySSLPPStats);
658     if (ssl_config == NULL)
659     {
660         //create a context
661         ssl_config = sfPolicyConfigCreate();
662 
663         if (ssl_config == NULL)
664         {
665             DynamicPreprocessorFatalMessage("Could not allocate memory for the "
666                                             "SSL preprocessor configuration.\n");
667         }
668 
669         if (_dpd.streamAPI == NULL)
670         {
671             DynamicPreprocessorFatalMessage(
672                                             "SSLPP_init(): The Stream preprocessor must be enabled.\n");
673         }
674 
675         SSL_InitGlobals();
676 
677         _dpd.registerPreprocStats("ssl", SSLPP_drop_stats);
678         _dpd.addPreprocConfCheck(sc, SSLPP_CheckConfig);
679         _dpd.addPreprocExit(SSLCleanExit, NULL, PRIORITY_LAST, PP_SSL);
680         _dpd.addPreprocResetStats(SSLResetStats, NULL, PRIORITY_LAST, PP_SSL);
681 
682 #ifdef PERF_PROFILING
683         _dpd.addPreprocProfileFunc("ssl", (void *)&sslpp_perf_stats, 0, _dpd.totalPerfStats, NULL);
684 #endif
685 
686 #ifdef ENABLE_HA
687         _dpd.addFuncToPostConfigList(sc, SSLHAPostConfigInit, NULL);
688 #endif
689 
690 #ifdef TARGET_BASED
691         ssl_app_id = _dpd.findProtocolReference("ssl");
692         if (ssl_app_id == SFTARGET_UNKNOWN_PROTOCOL)
693         {
694             ssl_app_id = _dpd.addProtocolReference("ssl");
695         }
696         _dpd.sessionAPI->register_service_handler( PP_SSL, ssl_app_id );
697 #endif
698     }
699 
700     sfPolicyUserPolicySet (ssl_config, policy_id);
701     pPolicyConfig = (SSLPP_config_t *)sfPolicyUserDataGetCurrent(ssl_config);
702     if (pPolicyConfig != NULL)
703     {
704         DynamicPreprocessorFatalMessage("SSL preprocessor can only be "
705                                         "configured once.\n");
706     }
707 
708     pPolicyConfig = (SSLPP_config_t *)calloc(1, sizeof(SSLPP_config_t));
709     if (pPolicyConfig == NULL)
710     {
711         DynamicPreprocessorFatalMessage("Could not allocate memory for the "
712                                         "SSL preprocessor configuration.\n");
713     }
714 
715     sfPolicyUserDataSetCurrent(ssl_config, pPolicyConfig);
716 
717     SSLPP_init_config(pPolicyConfig);
718 	SSLPP_config(pPolicyConfig, args);
719     SSLPP_print_config(pPolicyConfig);
720 
721     _dpd.preprocOptRegister(sc, "ssl_state", SSLPP_state_init, SSLPP_rule_eval,
722             free, NULL, NULL, NULL, NULL);
723     _dpd.preprocOptRegister(sc, "ssl_version", SSLPP_ver_init, SSLPP_rule_eval,
724             free, NULL, NULL, NULL, NULL);
725 
726 	_dpd.addPreproc( sc, SSLPP_process, PRIORITY_APPLICATION, PP_SSL, PROTO_BIT__TCP );
727 
728     registerPortsForDispatch( sc, pPolicyConfig );
729     registerPortsForReassembly( pPolicyConfig, SSN_DIR_FROM_SERVER | SSN_DIR_FROM_CLIENT );
730     _addPortsToStream5Filter(sc, pPolicyConfig, policy_id);
731 
732 #ifdef TARGET_BASED
733     _addServicesToStream5Filter(sc, policy_id);
734 #endif
735 
736 }
737 
SSLFreeConfigPolicy(tSfPolicyUserContextId config,tSfPolicyId policyId,void * pData)738 static int SSLFreeConfigPolicy(
739         tSfPolicyUserContextId config,
740         tSfPolicyId policyId,
741         void* pData
742         )
743 {
744     SSLPP_config_t *pPolicyConfig = (SSLPP_config_t *)pData;
745 
746     //do any housekeeping before freeing SSLPP_config_t
747     sfPolicyUserDataClear (config, policyId);
748 
749     if(pPolicyConfig->pki_dir)
750         free(pPolicyConfig->pki_dir);
751 
752     if(pPolicyConfig->ssl_rules_dir)
753         free(pPolicyConfig->ssl_rules_dir);
754 
755 
756     free(pPolicyConfig);
757 
758     return 0;
759 }
760 
SSLFreeConfig(tSfPolicyUserContextId config,bool full_cleanup)761 static void SSLFreeConfig(tSfPolicyUserContextId config, bool full_cleanup)
762 {
763     SSLPP_config_t *defaultConfig;
764     ssl_callback_interface_t *ssl_cb = (ssl_callback_interface_t *)_dpd.getSSLCallback();
765     if (config == NULL)
766         return;
767 
768    defaultConfig = (SSLPP_config_t *)sfPolicyUserDataGetDefault(config);
769 
770     if(defaultConfig && ssl_cb)
771     {
772         ssl_cb->policy_free(&(defaultConfig->current_handle), full_cleanup);
773 #ifdef ENABLE_HA
774         if(defaultConfig->ssl_ha_config)
775         {
776             SSLHAConfigFree(defaultConfig->ssl_ha_config);
777             defaultConfig->ssl_ha_config = NULL;
778         }
779 #endif
780     }
781 
782     sfPolicyUserDataFreeIterate (config, SSLFreeConfigPolicy);
783     sfPolicyConfigDelete(config);
784 }
785 
SSLCleanExit(int signal,void * data)786 static void SSLCleanExit(int signal, void *data)
787 {
788     if (ssl_config != NULL)
789     {
790 #ifdef ENABLE_HA
791         SSLCleanHA();
792 #endif
793         SSLFreeConfig(ssl_config, true);
794         ssl_config = NULL;
795     }
796 }
797 
SSLResetStats(int signal,void * data)798 static void SSLResetStats(int signal, void *data)
799 {
800     SSL_InitGlobals();
801 #ifdef ENABLE_HA
802     SSLResetHAStats();
803 #endif
804 }
805 
SSLPP_SetSSLPolicy(struct _SnortConfig * sc,tSfPolicyUserContextId config,tSfPolicyId policyId,void * pData)806 static int SSLPP_SetSSLPolicy(struct _SnortConfig *sc,
807                 tSfPolicyUserContextId config,
808                 tSfPolicyId policyId,
809                 void* pData
810                 )
811 {
812     _dpd.setSSLPolicyEnabled(sc, policyId, true);
813 
814     return 0;
815 }
816 
SSLPP_PolicyInit(struct _SnortConfig * sc,tSfPolicyUserContextId ssl_config,SSLPP_config_t * pPolicyConfig,tSfPolicyId policyId,bool reloading)817 static int SSLPP_PolicyInit(struct _SnortConfig *sc, tSfPolicyUserContextId ssl_config, SSLPP_config_t *pPolicyConfig, tSfPolicyId policyId, bool reloading)
818 {
819     ssl_callback_interface_t *ssl_cb = (ssl_callback_interface_t *)_dpd.getSSLCallback();
820     // Load SSL once for default policy
821     if (pPolicyConfig != NULL)
822     {
823         if(pPolicyConfig->pki_dir && pPolicyConfig->ssl_rules_dir && ssl_cb)
824         {
825             if ( ssl_cb->policy_initialize(pPolicyConfig, reloading) != 0 )
826             {
827                 _dpd.errMsg(
828                     "SSLPP_PolicyInit(): Failed to initialize ssl_rules_dir and pki_dir.\n");
829                 return -1;
830             }
831             else
832             {
833                 if((sfPolicyUserDataIterate (sc, ssl_config, SSLPP_SetSSLPolicy))!= 0)
834                 {
835                     _dpd.errMsg(
836                         "SSLPP_PolicyInit(): SetSSLpolicy failed.\n");
837                     return -1;
838                 }
839             }
840         }
841     }
842 
843     return 0;
844 }
845 
SSLPP_CheckPolicyConfig(struct _SnortConfig * sc,tSfPolicyUserContextId config,tSfPolicyId policyId,void * pData)846 static int SSLPP_CheckPolicyConfig(
847         struct _SnortConfig *sc,
848         tSfPolicyUserContextId config,
849         tSfPolicyId policyId,
850         void* pData
851         )
852 {
853     _dpd.setParserPolicy(sc, policyId);
854 
855     if (!_dpd.isPreprocEnabled(sc, PP_STREAM))
856     {
857         _dpd.errMsg(
858             "SSLPP_CheckPolicyConfig(): The Stream preprocessor must be enabled.\n");
859         return -1;
860     }
861 
862     return 0;
863 }
864 
865 
866 //  Enable SSL preproc for any policies that have inspection turned on.
SSLPP_CheckPolicyEnabled(struct _SnortConfig * sc,tSfPolicyUserContextId config,tSfPolicyId policyId,void * pData)867 static int SSLPP_CheckPolicyEnabled(
868         struct _SnortConfig *sc,
869         tSfPolicyUserContextId config,
870         tSfPolicyId policyId,
871         void* pData
872         )
873 {
874     if(_dpd.isSSLPolicyEnabled(sc))
875     {
876         //  Send packets to SSL preproc even when only doing Network Discovery.
877         _dpd.reenablePreprocBit(sc, PP_SSL);
878     }
879 
880     return 0;
881 }
882 
883 
SSLPP_CheckConfig(struct _SnortConfig * sc)884 static int SSLPP_CheckConfig(struct _SnortConfig *sc)
885 {
886 #ifdef ENABLE_HA
887     int haNotConfigured = 0;
888 #endif
889     int rval;
890     SSLPP_config_t *defaultConfig =
891                     (SSLPP_config_t *)sfPolicyUserDataGetDefault(ssl_config);
892 
893     if ((rval = sfPolicyUserDataIterate (sc, ssl_config, SSLPP_CheckPolicyConfig)))
894         return rval;
895 
896     // Load SSL once for default policy
897     if (defaultConfig)
898     {
899         if( SSLPP_PolicyInit(sc, ssl_config, defaultConfig, _dpd.getDefaultPolicy(), false) != 0 )
900             return -1;
901 
902 #ifdef ENABLE_HA
903         if (defaultConfig->enable_ssl_ha)
904         {
905             haNotConfigured = (SSLVerifyHAConfig(sc, defaultConfig->ssl_ha_config) != 0);
906             if (haNotConfigured)
907             {
908                 _dpd.errMsg("WARNING: SSL HA misconfigured.\n");
909                 return -1;
910             }
911         }
912 #endif
913     }
914 
915     if ((rval = sfPolicyUserDataIterate (sc, ssl_config, SSLPP_CheckPolicyEnabled)))
916         return rval;
917 
918     return 0;
919 }
920 
921 #ifdef SNORT_RELOAD
SSLReload(struct _SnortConfig * sc,char * args,void ** new_config)922 void SSLReload(struct _SnortConfig *sc, char *args, void **new_config)
923 {
924     tSfPolicyUserContextId ssl_swap_config = (tSfPolicyUserContextId)*new_config;
925     tSfPolicyId policy_id = _dpd.getParserPolicy(sc);
926     SSLPP_config_t * pPolicyConfig = NULL;
927 
928     if (ssl_swap_config == NULL)
929     {
930         //create a context
931         ssl_swap_config = sfPolicyConfigCreate();
932 
933         if (ssl_swap_config == NULL)
934         {
935             DynamicPreprocessorFatalMessage("Could not allocate memory for the "
936                                             "SSL preprocessor configuration.\n");
937         }
938 
939         if (_dpd.streamAPI == NULL)
940         {
941             DynamicPreprocessorFatalMessage(
942                                             "SSLPP_init(): The Stream preprocessor must be enabled.\n");
943         }
944         *new_config = (void *)ssl_swap_config;
945     }
946 
947     sfPolicyUserPolicySet (ssl_swap_config, policy_id);
948     pPolicyConfig = (SSLPP_config_t *)sfPolicyUserDataGetCurrent(ssl_swap_config);
949     if (pPolicyConfig != NULL)
950     {
951         DynamicPreprocessorFatalMessage("SSL preprocessor can only be "
952                                         "configured once.\n");
953     }
954 
955     pPolicyConfig = (SSLPP_config_t *)calloc(1, sizeof(SSLPP_config_t));
956     if (pPolicyConfig == NULL)
957     {
958         DynamicPreprocessorFatalMessage("Could not allocate memory for the "
959                                         "SSL preprocessor configuration.\n");
960     }
961 
962     sfPolicyUserDataSetCurrent(ssl_swap_config, pPolicyConfig);
963 
964     SSLPP_init_config(pPolicyConfig);
965 	SSLPP_config(pPolicyConfig, args);
966     SSLPP_print_config(pPolicyConfig);
967 
968     _dpd.preprocOptRegister(sc, "ssl_state", SSLPP_state_init, SSLPP_rule_eval,
969             free, NULL, NULL, NULL, NULL);
970     _dpd.preprocOptRegister(sc, "ssl_version", SSLPP_ver_init, SSLPP_rule_eval,
971             free, NULL, NULL, NULL, NULL);
972 
973 	_dpd.addPreproc(sc, SSLPP_process, PRIORITY_APPLICATION, PP_SSL, PROTO_BIT__TCP);
974 
975     registerPortsForDispatch( sc, pPolicyConfig );
976     registerPortsForReassembly( pPolicyConfig, SSN_DIR_FROM_SERVER | SSN_DIR_FROM_CLIENT );
977     _addPortsToStream5Filter(sc, pPolicyConfig, policy_id);
978 
979 #ifdef TARGET_BASED
980     _addServicesToStream5Filter(sc, policy_id);
981 #endif
982 }
983 
SSLReloadVerify(struct _SnortConfig * sc,void * swap_config)984 int SSLReloadVerify(struct _SnortConfig *sc, void *swap_config)
985 {
986     tSfPolicyUserContextId ssl_swap_config = (tSfPolicyUserContextId)swap_config;
987     SSLPP_config_t *reload_config = NULL;
988     SSLPP_config_t *start_config = NULL;
989     tSfPolicyId policyId = _dpd.getDefaultPolicy();
990     int ret = 0;
991     bool register_sfssl_preproc_reload_flag = false;
992     ssl_callback_interface_t *ssl_cb = (ssl_callback_interface_t *)_dpd.getSSLCallback();
993 
994     if (!_dpd.isPreprocEnabled(sc, PP_STREAM))
995     {
996         _dpd.errMsg("SSLPP_init(): The Stream preprocessor must be enabled.\n");
997         return -1;
998     }
999 
1000     if (!ssl_swap_config || !ssl_config)
1001         return 0;
1002 
1003     reload_config = (SSLPP_config_t *)sfPolicyUserDataGet(ssl_swap_config, policyId);
1004     start_config = (SSLPP_config_t *)sfPolicyUserDataGet(ssl_config, policyId);
1005 
1006     if( !reload_config || !start_config )
1007     {
1008         _dpd.errMsg("SSL reload: Turning on or off SSL preprocessor requires a restart.\n");
1009         return -1;
1010     }
1011 
1012     if (ssl_cb && ssl_cb->reload_mem_adjust_available())
1013     {
1014        _dpd.logMsg("SSL reload: SFSSL reload memcap adjust is available.\n");
1015        register_sfssl_preproc_reload_flag = true;
1016     }
1017 
1018     if (!register_sfssl_preproc_reload_flag &&
1019         reload_config->memcap != start_config->memcap)
1020     {
1021         /* Reload mem adjust not available, restart snort. */
1022         _dpd.errMsg("SSL reload: Changing the memcap requires a restart.\n");
1023         return -1;
1024     }
1025 
1026     if (!register_sfssl_preproc_reload_flag &&
1027         reload_config->decrypt_memcap != start_config->decrypt_memcap)
1028     {
1029       /* Reload mem adjust not available, restart snort. */
1030       _dpd.errMsg("SSL reload: Changing the decrypt_memcap requires a restart.\n");
1031       return -1;
1032     }
1033 
1034     if (reload_config->memcap != start_config->memcap)
1035     {
1036         /* reload mem adjust is available, any change in sfssl memcap, adjust the difference in sftls memcap */
1037         reload_config->decrypt_memcap += reload_config->memcap - start_config->memcap;
1038         _dpd.logMsg("SSL reload: Change in sfssl memcap:%d, sftls memcap:%d.\n", reload_config->memcap, reload_config->decrypt_memcap);
1039     }
1040 
1041     ret = SSLPP_PolicyInit(sc, ssl_swap_config, reload_config, policyId, true);
1042 
1043     if (!ret)
1044     {
1045         start_config->reload_handle = reload_config->current_handle;
1046     }
1047 
1048     if (register_sfssl_preproc_reload_flag)
1049     {
1050       /* Always register the SFSSL preproc reload, if sftls memcap adjuster is available
1051        * even in case where decrypt memcap doesn't change, may be we will add sftls_memcap in
1052        * ssl_tuning.conf file which might be differrent.
1053        */
1054       ssl_cb->register_reload_mem_adjust(sc, reload_config);
1055     }
1056 
1057     return ret;
1058 }
1059 
1060 
SSLReloadSwap(struct _SnortConfig * sc,void * swap_config)1061 void * SSLReloadSwap(struct _SnortConfig *sc, void *swap_config)
1062 {
1063     tSfPolicyUserContextId ssl_swap_config = (tSfPolicyUserContextId)swap_config;
1064     tSfPolicyUserContextId old_config = ssl_config;
1065 
1066     if (ssl_swap_config == NULL)
1067         return NULL;
1068 
1069     ssl_config = ssl_swap_config;
1070 
1071     return (void *)old_config;
1072 }
1073 
SSLReloadSwapFree(void * data)1074 void SSLReloadSwapFree(void *data)
1075 {
1076     if (data == NULL)
1077         return;
1078 
1079     SSLFreeConfig((tSfPolicyUserContextId)data, false);
1080 }
1081 #endif
1082