📄 spp_ssl.c
字号:
/*** Copyright (C) 2007-2008 Sourcefire, Inc.**** This program is free software; you can redistribute it and/or modify** it under the terms of the GNU General Public License Version 2 as** published by the Free Software Foundation. You may not use, modify or** distribute this program under any other version of the GNU General** Public License.**** This program is distributed in the hope that it will be useful,** but WITHOUT ANY WARRANTY; without even the implied warranty of** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the** GNU General Public License for more details.**** You should have received a copy of the GNU General Public License** along with this program; if not, write to the Free Software** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*//* * Adam Keeton * SSLPP Preprocessor * 10/10/07 **/#ifdef HAVE_CONFIG_H#include "config.h"#endif /* HAVE_CONFIG_H */#include "sf_snort_packet.h"#include "sf_dynamic_preprocessor.h"#include "sf_snort_plugin_api.h"#include "debug.h"#include "preprocids.h"#include "spp_ssl.h"#include <stdio.h>#include <syslog.h>#include <string.h>#ifndef WIN32#include <strings.h>#include <sys/time.h>#endif#include <stdlib.h>#include <ctype.h>#include "profiler.h"#ifdef PERF_PROFILINGPreprocStats sslpp_perf_stats;#endif#define GENERATOR_SPP_SSLPP 133/* Ultimately calls SnortEventqAdd *//* Arguments are: gid, sid, rev, classification, priority, message, rule_info */#define ALERT(x,y) { _dpd.alertAdd(GENERATOR_SPP_SSLPP, x, 1, 0, 3, y, 0 ); }/* Wraps disabling detect with incrementing the counter */#define DISABLE_DETECT() { _dpd.disableDetect(packet); counts.disabled++; }extern DynamicPreprocessorData _dpd;static SSLPP_config_t config;static SSLPP_counters_t counts;static INLINE int SSLPP_is_encrypted(u_int32_t ssl_flags, SFSnortPacket *packet) { if(SSL_IS_CLEAN(ssl_flags)) { if((ssl_flags & SSLPP_ENCRYPTED_FLAGS) == SSLPP_ENCRYPTED_FLAGS) { counts.completed_hs++; return SSLPP_TRUE; } /* Check if we're either midstream or if packets were missed after the * connection was established */ else if( (_dpd.streamAPI->get_session_flags( packet->stream_session_ptr) & SSNFLAG_MIDSTREAM ) || _dpd.streamAPI->missed_packets( packet->stream_session_ptr, SSN_DIR_BOTH) ) { /* If we're trusting the server, check if it trusts * the handshake */ if( config.flags & SSLPP_TRUSTSERVER_FLAG ) { if(ssl_flags & SSL_SAPP_FLAG) return SSLPP_TRUE; } else if( (ssl_flags & (SSL_CAPP_FLAG | SSL_SAPP_FLAG)) == (SSL_CAPP_FLAG | SSL_SAPP_FLAG) ) { return SSLPP_TRUE; } } } /* Bad flags were set. If we're trusting the server, check if it trusts * the handshake */ else if( config.flags & SSLPP_TRUSTSERVER_FLAG ) { if(ssl_flags & SSL_SAPP_FLAG) return SSLPP_TRUE; } return SSLPP_FALSE;}static INLINE u_int32_t SSLPP_process_alert( u_int32_t ssn_flags, u_int32_t new_flags, SFSnortPacket *packet){ counts.alerts++; ssn_flags |= new_flags; /* Check if we've seen a handshake, that this isn't it, * that the cipher flags is not set, and that we are disabling detection */ if(SSL_IS_HANDSHAKE(ssn_flags) && !SSL_IS_HANDSHAKE(new_flags) && !(new_flags & SSL_CHANGE_CIPHER_FLAG) && (config.flags & SSLPP_DISABLE_FLAG)) { DISABLE_DETECT(); } /* Need to negate the application flags from the opposing side. */ if(packet->flags & FLAG_FROM_CLIENT) return ssn_flags & ~SSL_SAPP_FLAG; else if(packet->flags & FLAG_FROM_SERVER) return ssn_flags & ~SSL_CAPP_FLAG; return ssn_flags;}static INLINE u_int32_t SSLPP_process_hs(u_int32_t ssl_flags, u_int32_t new_flags){ counts.handshakes++; if(!SSL_BAD_HS(new_flags)) ssl_flags |= new_flags & (SSL_CLIENT_HELLO_FLAG | SSL_SERVER_HELLO_FLAG | SSL_CLIENT_KEYX_FLAG | SSL_SFINISHED_FLAG); else counts.bad_handshakes++; return ssl_flags;}static INLINE u_int32_t SSLPP_process_app( u_int32_t ssn_flags, u_int32_t new_flags, SFSnortPacket *packet) { if(!(config.flags & SSLPP_DISABLE_FLAG)) return ssn_flags | new_flags; if(SSLPP_is_encrypted(ssn_flags | new_flags, packet) ) { ssn_flags |= SSL_ENCRYPTED_FLAG; _dpd.streamAPI->stop_inspection(packet->stream_session_ptr, packet, SSN_DIR_BOTH, -1, 0); counts.stopped++; } else if(SSL_IS_HANDSHAKE(ssn_flags) && (new_flags & SSL_CHANGE_CIPHER_FLAG)) { DISABLE_DETECT(); } return ssn_flags | new_flags;}static INLINE void SSLPP_process_other( u_int32_t ssn_flags, u_int32_t new_flags, SFSnortPacket *packet) { if(new_flags & SSL_CHANGE_CIPHER_FLAG) { counts.cipher_change++; } /* Encrypted SSLv2 will appear unrecognizable. Check if the handshake was * seen and stop inspecting if so. */ else if((ssn_flags & SSL_VER_SSLV2_FLAG) && /* Check for an existing handshake from both sides */ SSL_IS_CHELLO(ssn_flags) && SSL_IS_SHELLO(ssn_flags) && (config.flags & SSLPP_DISABLE_FLAG)) { ssn_flags |= SSL_ENCRYPTED_FLAG | new_flags; _dpd.streamAPI->stop_inspection(packet->stream_session_ptr, packet, SSN_DIR_BOTH, -1, 0); } else { counts.unrecognized++; /* Special handling for SSLv2 */ if(new_flags & SSL_VER_SSLV2_FLAG) ssn_flags |= new_flags; if(new_flags & SSL_UNKNOWN_FLAG) ssn_flags |= new_flags;/* The following block is intentionally disabled. *//* If we were unable to decode the packet, and previous packets had been * missed, we will not assume it is encrypted SSLv2. */#if 0 /* More special handling for SSLv2. * If both server-side and client-side data was missed, and it has not * been identified it as TLS, it is possibly encrypted SSLv2. */ if( !(ssn_flags & ( SSL_VER_SSLV3_FLAG | SSL_VER_TLS10_FLAG | SSL_VER_TLS11_FLAG | SSL_VER_TLS12_FLAG)) ) { if(packet->stream_session_ptr && _dpd.streamAPI->missed_packets( packet->stream_session_ptr, SSN_DIR_SERVER) && _dpd.streamAPI->missed_packets( packet->stream_session_ptr, SSN_DIR_CLIENT) ) ssn_flags |= SSL_VER_SSLV2_FLAG; }#endif } /* Still need to set application data here because some of the ssn_flags * flags were cleared in SSL_CLEAR_TEMPORARY_FLAGS */ _dpd.streamAPI->set_application_data( packet->stream_session_ptr, PP_SSL, (void*)(uintptr_t)ssn_flags, NULL);}/* SSL Preprocessor process callback. */static void SSLPP_process(void *raw_packet, void *context){ SFSnortPacket *packet; u_int32_t ssn_flags; u_int32_t new_flags; PROFILE_VARS; PREPROC_PROFILE_START(sslpp_perf_stats); packet = (SFSnortPacket*)raw_packet; if(!packet || !packet->payload || !packet->payload_size || !packet->tcp_header || !packet->stream_session_ptr) { PREPROC_PROFILE_END(sslpp_perf_stats); return; } /* Make sure the packet is on the right port */ if(!config.ports[ PORT_INDEX(packet->src_port) ] && !config.ports[ PORT_INDEX(packet->dst_port) ]) { PREPROC_PROFILE_END(sslpp_perf_stats); return; } ssn_flags = (u_int32_t)(uintptr_t)_dpd.streamAPI->get_application_data( packet->stream_session_ptr, PP_SSL); SSL_CLEAR_TEMPORARY_FLAGS(ssn_flags); new_flags = SSL_decode(packet->payload, packet->payload_size, packet->flags); counts.decoded++; /* Note, there can be multiple record types in each SSL packet. * Processing them in this order is intentional. If there is an * Alert, we don't care about the other records */ if(SSL_IS_ALERT(new_flags)) { ssn_flags = SSLPP_process_alert(ssn_flags, new_flags, packet); } else if(SSL_IS_HANDSHAKE(new_flags)) { ssn_flags = SSLPP_process_hs(ssn_flags, new_flags); } else if(SSL_IS_APP(new_flags)) { ssn_flags = SSLPP_process_app(ssn_flags, new_flags, packet);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -