}
static uint32_t SSL_decode_v3(const uint8_t* pkt, int size, uint32_t pkt_flags,
- uint8_t* alert_flags, uint16_t* partial_rec_len, int max_hb_len)
+ uint8_t* alert_flags, uint16_t* partial_rec_len, int max_hb_len, uint32_t* info_flags)
{
uint32_t retval = 0;
uint16_t hblen;
break;
case SSL_ALERT_REC:
+ if (reclen == sizeof(SSL_alert_t))
+ {
+ const SSL_alert_t* ssl_alert = (const SSL_alert_t*)pkt;
+ if (ssl_alert->level == SSL_ALERT_LEVEL_FATAL && info_flags)
+ *info_flags |= SSL_ALERT_LVL_FATAL_FLAG;
+ }
retval |= SSL_ALERT_FLAG;
ccs = 0;
break;
{
uint32_t SSL_decode(
const uint8_t* pkt, int size, uint32_t pkt_flags, uint32_t prev_flags,
- uint8_t* alert_flags, uint16_t* partial_rec_len, int max_hb_len)
+ uint8_t* alert_flags, uint16_t* partial_rec_len, int max_hb_len, uint32_t* info_flags)
{
if (!pkt || !size)
return SSL_ARG_ERROR_FLAG;
* SSLv2 as TLS,the decoder will either catch a bad type, bad version, or
* indicate that it is truncated. */
if (size == 5)
- return SSL_decode_v3(pkt, size, pkt_flags, alert_flags, partial_rec_len, max_hb_len);
+ return SSL_decode_v3(pkt, size, pkt_flags, alert_flags, partial_rec_len, max_hb_len, info_flags);
/* At this point, 'size' has to be > 5 */
}
}
- return SSL_decode_v3(pkt, size, pkt_flags, alert_flags, partial_rec_len, max_hb_len);
+ return SSL_decode_v3(pkt, size, pkt_flags, alert_flags, partial_rec_len, max_hb_len, info_flags);
}
/* very simplistic - just enough to say this is binary data - the rules will make a final
bool IsSSL(const uint8_t* ptr, int len, int pkt_flags)
{
- uint32_t ssl_flags = SSL_decode(ptr, len, pkt_flags, 0, nullptr, nullptr, 0);
+ uint32_t ssl_flags = SSL_decode(ptr, len, pkt_flags, 0, nullptr, nullptr, 0, nullptr);
if ((ssl_flags != SSL_ARG_ERROR_FLAG) &&
!(ssl_flags & SSL_ERROR_FLAGS))
* #define SSL_HS_FINISHED_FLAG Ignored for our purposes
*/
+/* Flags for additional info */
+#define SSL_ALERT_LVL_FATAL_FLAG 0x00000001
+
/* The constants used below are from RFC 2246 */
/* SSLv3 & TLS Record types */
#define SSL_REC_PAYLOAD_OFFSET (sizeof(uint8_t) * 5)
+#define SSL_ALERT_LEVEL_WARNING 1
+#define SSL_ALERT_LEVEL_FATAL 2
+
+struct SSL_alert_t
+{
+ uint8_t level;
+ uint8_t description;
+};
+
struct SSL_heartbeat
{
uint8_t type;
namespace snort
{
-SO_PUBLIC uint32_t SSL_decode(
+uint32_t SSL_decode(
const uint8_t* pkt, int size, uint32_t pktflags, uint32_t prevflags,
- uint8_t* alert_flags, uint16_t* partial_rec_len, int hblen);
+ uint8_t* alert_flags, uint16_t* partial_rec_len, int hblen, uint32_t* info_flags = nullptr);
SO_PUBLIC bool IsTlsClientHello(const uint8_t* ptr, const uint8_t* end);
SO_PUBLIC bool IsTlsServerHello(const uint8_t* ptr, const uint8_t* end);
}
static inline uint32_t SSLPP_process_alert(
- SSL_PROTO_CONF*, uint32_t ssn_flags, uint32_t new_flags, Packet* packet)
+ SSL_PROTO_CONF*, uint32_t ssn_flags, uint32_t new_flags, Packet* packet, uint32_t info_flags)
{
ssn_flags |= new_flags;
if (SSL_IS_HANDSHAKE(ssn_flags) &&
!SSL_IS_HANDSHAKE(new_flags) &&
!(new_flags & SSL_CHANGE_CIPHER_FLAG) &&
- !(new_flags & SSL_HEARTBEAT_SEEN))
+ !(new_flags & SSL_HEARTBEAT_SEEN) &&
+ info_flags & SSL_ALERT_LVL_FATAL_FLAG)
{
DetectionEngine::disable_content(packet);
sslstats.disabled++;
uint8_t index = (p->packet_flags & PKT_REBUILT_STREAM) ? 2 : 0;
uint8_t heartbleed_type = 0;
+ uint32_t info_flags = 0;
uint32_t new_flags = SSL_decode(p->data, (int)p->dsize, p->packet_flags, sd->ssn_flags,
- &heartbleed_type, &(sd->partial_rec_len[dir+index]), config->max_heartbeat_len);
+ &heartbleed_type, &(sd->partial_rec_len[dir+index]), config->max_heartbeat_len, &info_flags);
if (heartbleed_type & SSL_HEARTBLEED_REQUEST)
{
if (SSL_IS_ALERT(new_flags))
{
- sd->ssn_flags = SSLPP_process_alert(config, sd->ssn_flags, new_flags, p);
+ sd->ssn_flags = SSLPP_process_alert(config, sd->ssn_flags, new_flags, p, info_flags);
}
else if (SSL_IS_HANDSHAKE(new_flags))
{