"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/service_inspectors/wizard/curses.cc" between
snort3-3.1.29.0.tar.gz and snort3-3.1.30.0.tar.gz

About: Snort 3 is a network intrusion prevention and detection system (IDS/IPS) combining the benefits of signature, protocol and anomaly-based inspection.

curses.cc  (snort3-3.1.29.0):curses.cc  (snort3-3.1.30.0)
skipping to change at line 76 skipping to change at line 76
{ {
DCERPC_PROTO_MINOR_VERS__0 = 0, DCERPC_PROTO_MINOR_VERS__0 = 0,
DCERPC_PROTO_MINOR_VERS__1 = 1 DCERPC_PROTO_MINOR_VERS__1 = 1
}; };
static bool dce_udp_curse(const uint8_t* data, unsigned len, CurseTracker*) static bool dce_udp_curse(const uint8_t* data, unsigned len, CurseTracker*)
{ {
const uint8_t dcerpc_cl_hdr_len = 80; const uint8_t dcerpc_cl_hdr_len = 80;
const uint8_t cl_len_offset = 74; const uint8_t cl_len_offset = 74;
if (len >= dcerpc_cl_hdr_len) if ( len >= dcerpc_cl_hdr_len )
{ {
uint8_t version = data[0]; uint8_t version = data[0];
uint8_t pdu_type = data[1]; uint8_t pdu_type = data[1];
bool little_endian = ((data[4] & 0x10) >> 4) ? true : false; bool little_endian = ((data[4] & 0x10) >> 4) ? true : false;
uint16_t cl_len; uint16_t cl_len;
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
if (!little_endian) if ( !little_endian )
#else #else
if (little_endian) if ( little_endian )
#endif /* WORDS_BIGENDIAN */ #endif /* WORDS_BIGENDIAN */
cl_len = (data[cl_len_offset+1] << 8) | data[cl_len_offset]; cl_len = (data[cl_len_offset+1] << 8) | data[cl_len_offset];
else else
cl_len = (data[cl_len_offset] << 8) | data[cl_len_offset+1]; cl_len = (data[cl_len_offset] << 8) | data[cl_len_offset+1];
if ((version == DCERPC_PROTO_MAJOR_VERS__4) && if ( (version == DCERPC_PROTO_MAJOR_VERS__4) and
((pdu_type == DCERPC_PDU_TYPE__REQUEST) || ((pdu_type == DCERPC_PDU_TYPE__REQUEST) or
(pdu_type == DCERPC_PDU_TYPE__RESPONSE) || (pdu_type == DCERPC_PDU_TYPE__RESPONSE) or
(pdu_type == DCERPC_PDU_TYPE__FAULT) || (pdu_type == DCERPC_PDU_TYPE__FAULT) or
(pdu_type == DCERPC_PDU_TYPE__REJECT) || (pdu_type == DCERPC_PDU_TYPE__REJECT) or
(pdu_type == DCERPC_PDU_TYPE__FACK)) && (pdu_type == DCERPC_PDU_TYPE__FACK)) and
((cl_len != 0) && ((cl_len != 0) and
(cl_len + (unsigned)dcerpc_cl_hdr_len) <= len)) (cl_len + (unsigned)dcerpc_cl_hdr_len) <= len) )
return true; return true;
} }
return false; return false;
} }
static bool dce_tcp_curse(const uint8_t* data, unsigned len, CurseTracker* track er) static bool dce_tcp_curse(const uint8_t* data, unsigned len, CurseTracker* track er)
{ {
const uint8_t dce_rpc_co_hdr_len = 16; const uint8_t dce_rpc_co_hdr_len = 16;
CurseTracker::DCE& dce = tracker->dce; CurseTracker::DCE& dce = tracker->dce;
uint32_t n = 0; uint32_t n = 0;
while (n < len) while ( n < len )
{ {
switch (dce.state) switch ( dce.state )
{ {
case STATE_0: // check major version case STATE_0: // check major version
if (data[n] != DCERPC_PROTO_MAJOR_VERS__5) if ( data[n] != DCERPC_PROTO_MAJOR_VERS__5 )
{ {
// go to bad state // go to bad state
dce.state = STATE_10; dce.state = STATE_10;
return false; return false;
} }
dce.state = (DCE_State)((int)dce.state + 1); dce.state = (DCE_State)((int)dce.state + 1);
break; break;
case STATE_1: // check minor version case STATE_1: // check minor version
if (data[n] != DCERPC_PROTO_MINOR_VERS__0) if ( data[n] != DCERPC_PROTO_MINOR_VERS__0 )
{ {
// go to bad state // go to bad state
dce.state = STATE_10; dce.state = STATE_10;
return false; return false;
} }
dce.state = (DCE_State)((int)dce.state + 1); dce.state = (DCE_State)((int)dce.state + 1);
break; break;
case STATE_2: // pdu_type case STATE_2: // pdu_type
{ {
uint8_t pdu_type = data[n]; uint8_t pdu_type = data[n];
if ((pdu_type != DCERPC_PDU_TYPE__BIND) &&
(pdu_type != DCERPC_PDU_TYPE__BIND_ACK)) if ( (pdu_type != DCERPC_PDU_TYPE__BIND) and
(pdu_type != DCERPC_PDU_TYPE__BIND_ACK) )
{ {
// go to bad state // go to bad state
dce.state = STATE_10; dce.state = STATE_10;
return false; return false;
} }
dce.state = (DCE_State)((int)dce.state + 1); dce.state = (DCE_State)((int)dce.state + 1);
break; break;
} }
case STATE_4: //little endian case STATE_4: //little endian
dce.helper = (data[n] & 0x10) << 20; dce.helper = (data[n] & 0x10) << 20;
dce.state = (DCE_State)((int)dce.state + 1); dce.state = (DCE_State)((int)dce.state + 1);
break; break;
case STATE_8: case STATE_8:
dce.helper |= data[n]; dce.helper |= data[n];
dce.state = (DCE_State)((int)dce.state + 1); dce.state = (DCE_State)((int)dce.state + 1);
break; break;
case STATE_9: case STATE_9:
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
if (!(dce.helper >> 24)) if ( !(dce.helper >> 24) )
#else #else
if (dce.helper >> 24) if ( dce.helper >> 24 )
#endif /* WORDS_BIGENDIAN */ #endif /* WORDS_BIGENDIAN */
dce.helper = (data[n] << 8) | (dce.helper & 0XFF); dce.helper = (data[n] << 8) | (dce.helper & 0XFF);
else else
{ {
dce.helper <<=8; dce.helper <<=8;
dce.helper |= data[n]; dce.helper |= data[n];
} }
if (dce.helper >= dce_rpc_co_hdr_len) if ( dce.helper >= dce_rpc_co_hdr_len )
return true; return true;
dce.state = STATE_10; dce.state = STATE_10;
break; break;
case STATE_10: case STATE_10:
// no match // no match
return false; return false;
default: default:
dce.state = (DCE_State)((int)dce.state + 1); dce.state = (DCE_State)((int)dce.state + 1);
break; break;
} }
n++; n++;
} }
return false; return false;
} }
static bool dce_smb_curse(const uint8_t* data, unsigned len, CurseTracker* track er) static bool dce_smb_curse(const uint8_t* data, unsigned len, CurseTracker* track er)
{ {
const uint32_t dce_smb_id = 0xff534d42; /* \xffSMB */ const uint32_t dce_smb_id = 0xff534d42; /* \xffSMB */
const uint32_t dce_smb2_id = 0xfe534d42; /* \xfeSMB */ const uint32_t dce_smb2_id = 0xfe534d42; /* \xfeSMB */
const uint8_t session_request = 0x81, session_response = 0x82, const uint8_t session_request = 0x81, session_response = 0x82, session_messa
session_message = 0x00; ge = 0x00;
CurseTracker::DCE& dce = tracker->dce; CurseTracker::DCE& dce = tracker->dce;
uint32_t n = 0; uint32_t n = 0;
while (n < len) while ( n < len )
{ {
switch (dce.state) switch ( dce.state )
{ {
case STATE_0: case STATE_0:
if (data[n] == session_message) if ( data[n] == session_message )
{ {
dce.state = (DCE_State)((int)dce.state + 2); dce.state = (DCE_State)((int)dce.state + 2);
break; break;
} }
if (data[n] == session_request || data[n] == session_response) if ( data[n] == session_request or data[n] == session_response )
{ {
dce.state = (DCE_State)((int)dce.state + 1); dce.state = (DCE_State)((int)dce.state + 1);
return false; return false;
} }
dce.state = STATE_9; dce.state = STATE_9;
return false; return false;
case STATE_1: case STATE_1:
if (data[n] == session_message) if ( data[n] == session_message )
{ {
dce.state = (DCE_State)((int)dce.state + 1); dce.state = (DCE_State)((int)dce.state + 1);
break; break;
} }
dce.state = STATE_9; dce.state = STATE_9;
return false; return false;
case STATE_5: case STATE_5:
dce.helper = data[n]; dce.helper = data[n];
dce.state = (DCE_State)((int)dce.state + 1); dce.state = (DCE_State)((int)dce.state + 1);
break; break;
case STATE_6: case STATE_6:
case STATE_7: case STATE_7:
dce.helper <<= 8; dce.helper <<= 8;
dce.helper |= data[n]; dce.helper |= data[n];
dce.state = (DCE_State)((int)dce.state + 1); dce.state = (DCE_State)((int)dce.state + 1);
break; break;
case STATE_8: case STATE_8:
dce.helper <<= 8; dce.helper <<= 8;
dce.helper |= data[n]; dce.helper |= data[n];
if ((dce.helper == dce_smb_id) || (dce.helper == dce_smb2_id))
if ( (dce.helper == dce_smb_id) or (dce.helper == dce_smb2_id) )
return true; return true;
dce.state = (DCE_State)((int)dce.state + 1); dce.state = (DCE_State)((int)dce.state + 1);
break; break;
case STATE_9: case STATE_9:
// no match // no match
return false; return false;
default: default:
dce.state = (DCE_State)((int)dce.state + 1); dce.state = (DCE_State)((int)dce.state + 1);
break; break;
} }
n++; n++;
} }
return false; return false;
} }
static bool mms_curse(const uint8_t* data, unsigned len, CurseTracker* tracker) static bool mms_curse(const uint8_t* data, unsigned len, CurseTracker* tracker)
{ {
// peg the tracker to MMS // peg the tracker to MMS
CurseTracker::MMS& mms = tracker->mms; CurseTracker::MMS& mms = tracker->mms;
// if the state is set to MMS_STATE__SEARCH it means we most likely // if the state is set to MMS_STATE__SEARCH it means we most likely
// have a split pipelined message coming through and will need to // have a split pipelined message coming through and will need to
// reset the state // reset the state
if (mms.state == MMS_STATE__SEARCH) if ( mms.state == MMS_STATE__SEARCH )
{ {
mms.state = mms.last_state; mms.state = mms.last_state;
} }
// define all known MMS tags to check for // define all known MMS tags to check for
enum enum
{ {
MMS_CONFIRMED_REQUEST_TAG = 0xA0, MMS_CONFIRMED_REQUEST_TAG = 0xA0,
MMS_CONFIRMED_RESPONSE_TAG = 0xA1, MMS_CONFIRMED_RESPONSE_TAG = 0xA1,
MMS_CONFIRMED_ERROR_TAG = 0xA2, MMS_CONFIRMED_ERROR_TAG = 0xA2,
skipping to change at line 297 skipping to change at line 309
MMS_CANCEL_ERROR_TAG = 0xA7, MMS_CANCEL_ERROR_TAG = 0xA7,
MMS_INITIATE_REQUEST_TAG = 0xA8, MMS_INITIATE_REQUEST_TAG = 0xA8,
MMS_INITIATE_RESPONSE_TAG = 0xA9, MMS_INITIATE_RESPONSE_TAG = 0xA9,
MMS_INITIATE_ERROR_TAG = 0xAA, MMS_INITIATE_ERROR_TAG = 0xAA,
MMS_CONCLUDE_REQUEST_TAG = 0x8B, MMS_CONCLUDE_REQUEST_TAG = 0x8B,
MMS_CONCLUDE_RESPONSE_TAG = 0x8C, MMS_CONCLUDE_RESPONSE_TAG = 0x8C,
MMS_CONCLUDE_ERROR_TAG = 0xAD, MMS_CONCLUDE_ERROR_TAG = 0xAD,
}; };
uint32_t idx = 0; uint32_t idx = 0;
while (idx < len) while ( idx < len )
{ {
switch (mms.state) switch ( mms.state )
{ {
case MMS_STATE__TPKT_VER: case MMS_STATE__TPKT_VER:
{ {
mms.state = MMS_STATE__TPKT_RES; mms.state = MMS_STATE__TPKT_RES;
break; break;
} }
case MMS_STATE__TPKT_RES: case MMS_STATE__TPKT_RES:
{ {
mms.state = MMS_STATE__TPKT_LEN1; mms.state = MMS_STATE__TPKT_LEN1;
skipping to change at line 338 skipping to change at line 350
break; break;
} }
case MMS_STATE__COTP_PDU: case MMS_STATE__COTP_PDU:
{ {
// 7 6 5 4 3 2 1 0 // 7 6 5 4 3 2 1 0
// --------------- // ---------------
// . . . . x x x x Destination Reference // . . . . x x x x Destination Reference
// x x x x . . . . PDU Type // x x x x . . . . PDU Type
const uint32_t MMS_COTP_PDU_DT_DATA = 0x0F; const uint32_t MMS_COTP_PDU_DT_DATA = 0x0F;
if (data[idx] >> 0x04 != MMS_COTP_PDU_DT_DATA)
if ( data[idx] >> 0x04 != MMS_COTP_PDU_DT_DATA )
{ {
mms.state = MMS_STATE__NOT_FOUND; mms.state = MMS_STATE__NOT_FOUND;
break; break;
} }
mms.state = MMS_STATE__COTP_TPDU_NUM; mms.state = MMS_STATE__COTP_TPDU_NUM;
break; break;
} }
case MMS_STATE__COTP_TPDU_NUM: case MMS_STATE__COTP_TPDU_NUM:
{ {
mms.state = MMS_STATE__OSI_SESSION_SPDU; mms.state = MMS_STATE__OSI_SESSION_SPDU;
break; break;
} }
case MMS_STATE__OSI_SESSION_SPDU: case MMS_STATE__OSI_SESSION_SPDU:
{ {
// define all known OSI Session layer SPDU tags to check // define all known OSI Session layer SPDU tags to check
enum enum
{ {
MMS_OSI_SESSION_SPDU_GT_DT = 0x01, MMS_OSI_SESSION_SPDU_GT_DT = 0x01,
MMS_OSI_SESSION_SPDU_CN = 0x0D, MMS_OSI_SESSION_SPDU_CN = 0x0D,
MMS_OSI_SESSION_SPDU_AC = 0x0E, MMS_OSI_SESSION_SPDU_AC = 0x0E,
}; };
switch (data[idx]) switch ( data[idx] )
{ {
// check for a known MMS message tag in the event Session/Pr es/ACSE aren't used // check for a known MMS message tag in the event Session/Pr es/ACSE aren't used
case MMS_CONFIRMED_REQUEST_TAG: // fallthrough intentiona l case MMS_CONFIRMED_REQUEST_TAG: // fallthrough intentiona l
case MMS_CONFIRMED_RESPONSE_TAG: // fallthrough intentiona l case MMS_CONFIRMED_RESPONSE_TAG: // fallthrough intentiona l
case MMS_CONFIRMED_ERROR_TAG: // fallthrough intentiona l case MMS_CONFIRMED_ERROR_TAG: // fallthrough intentiona l
case MMS_UNCONFIRMED_TAG: // fallthrough intentiona l case MMS_UNCONFIRMED_TAG: // fallthrough intentiona l
case MMS_REJECT_TAG: // fallthrough intentiona l case MMS_REJECT_TAG: // fallthrough intentiona l
case MMS_CANCEL_REQUEST_TAG: // fallthrough intentiona l case MMS_CANCEL_REQUEST_TAG: // fallthrough intentiona l
case MMS_CANCEL_RESPONSE_TAG: // fallthrough intentiona l case MMS_CANCEL_RESPONSE_TAG: // fallthrough intentiona l
case MMS_CANCEL_ERROR_TAG: // fallthrough intentiona l case MMS_CANCEL_ERROR_TAG: // fallthrough intentiona l
skipping to change at line 409 skipping to change at line 423
mms.state = MMS_STATE__NOT_FOUND; mms.state = MMS_STATE__NOT_FOUND;
} }
} }
break; break;
} }
case MMS_STATE__MMS: case MMS_STATE__MMS:
{ {
// loop through the remaining bytes in the buffer checking for k nown MMS tags // loop through the remaining bytes in the buffer checking for k nown MMS tags
for (uint32_t i=idx; i < len; i++) for ( uint32_t i=idx; i < len; i++ )
{ {
// for each remaining byte check to see if it is in the know n tag map // for each remaining byte check to see if it is in the know n tag map
switch (data[i]) switch ( data[i] )
{ {
case MMS_CONFIRMED_REQUEST_TAG: // fallthrough intent ional case MMS_CONFIRMED_REQUEST_TAG: // fallthrough intent ional
case MMS_CONFIRMED_RESPONSE_TAG: // fallthrough intent ional case MMS_CONFIRMED_RESPONSE_TAG: // fallthrough intent ional
case MMS_CONFIRMED_ERROR_TAG: // fallthrough intent ional case MMS_CONFIRMED_ERROR_TAG: // fallthrough intent ional
case MMS_UNCONFIRMED_TAG: // fallthrough intent ional case MMS_UNCONFIRMED_TAG: // fallthrough intent ional
case MMS_REJECT_TAG: // fallthrough intent ional case MMS_REJECT_TAG: // fallthrough intent ional
case MMS_CANCEL_REQUEST_TAG: // fallthrough intent ional case MMS_CANCEL_REQUEST_TAG: // fallthrough intent ional
case MMS_CANCEL_RESPONSE_TAG: // fallthrough intent ional case MMS_CANCEL_RESPONSE_TAG: // fallthrough intent ional
case MMS_CANCEL_ERROR_TAG: // fallthrough intent ional case MMS_CANCEL_ERROR_TAG: // fallthrough intent ional
case MMS_INITIATE_REQUEST_TAG: // fallthrough intent ional case MMS_INITIATE_REQUEST_TAG: // fallthrough intent ional
skipping to change at line 439 skipping to change at line 453
// if an MMS tag exists in the remaining data, // if an MMS tag exists in the remaining data,
// hand off to the MMS service inspector // hand off to the MMS service inspector
mms.state = MMS_STATE__FOUND; mms.state = MMS_STATE__FOUND;
break; break;
} }
// no default here as it we don't know when we would hit // no default here as it we don't know when we would hit
// the first MMS tag without doing full parsing // the first MMS tag without doing full parsing
} }
// exit the loop when a state has been determined // exit the loop when a state has been determined
if (mms.state == MMS_STATE__NOT_FOUND if ( mms.state == MMS_STATE__NOT_FOUND
or mms.state == MMS_STATE__SEARCH or mms.state == MMS_STATE__SEARCH
or mms.state == MMS_STATE__FOUND) or mms.state == MMS_STATE__FOUND )
{ {
break; break;
} }
} }
break; break;
} }
case MMS_STATE__FOUND: case MMS_STATE__FOUND:
{ {
mms.state = MMS_STATE__TPKT_VER; mms.state = MMS_STATE__TPKT_VER;
return true; return true;
} }
case MMS_STATE__NOT_FOUND: case MMS_STATE__NOT_FOUND:
{ {
mms.state = MMS_STATE__TPKT_VER; mms.state = MMS_STATE__TPKT_VER;
return false; return false;
} }
default: default:
{ {
mms.state = MMS_STATE__NOT_FOUND; mms.state = MMS_STATE__NOT_FOUND;
assert(false); assert(false);
break; break;
} }
} }
idx++; idx++;
} }
mms.last_state = mms.state; mms.last_state = mms.state;
mms.state = MMS_STATE__SEARCH; mms.state = MMS_STATE__SEARCH;
return false; return false;
} }
namespace SSL_Const namespace SSL_Const
{ {
static constexpr uint8_t hdr_len = 9; static constexpr uint8_t hdr_len = 9;
static constexpr uint8_t sslv2_msb_set = 0x80; static constexpr uint8_t sslv2_msb_set = 0x80;
static constexpr uint8_t client_hello = 0x01; static constexpr uint8_t client_hello = 0x01;
static constexpr uint8_t sslv3_major_ver = 0x03; static constexpr uint8_t sslv3_major_ver = 0x03;
static constexpr uint8_t sslv3_max_minor_ver = 0x03; static constexpr uint8_t sslv3_max_minor_ver = 0x03;
} }
static bool ssl_v2_curse(const uint8_t* data, unsigned len, CurseTracker* tracke r) static bool ssl_v2_curse(const uint8_t* data, unsigned len, CurseTracker* tracke r)
{ {
CurseTracker::SSL& ssl = tracker->ssl; CurseTracker::SSL& ssl = tracker->ssl;
if (ssl.state == SSL_State::SSL_NOT_FOUND) if ( ssl.state == SSL_State::SSL_NOT_FOUND )
{
return false; return false;
} else if ( ssl.state == SSL_State::SSL_FOUND )
else if (ssl.state == SSL_State::SSL_FOUND)
{
return true; return true;
}
for (unsigned i = 0; i < len; ++i) for ( unsigned i = 0; i < len; ++i )
{ {
uint8_t val = data[i]; uint8_t val = data[i];
switch (ssl.state) switch ( ssl.state )
{ {
case SSL_State::BYTE_0_LEN_MSB: case SSL_State::BYTE_0_LEN_MSB:
if ((val & SSL_Const::sslv2_msb_set) == 0) if ( (val & SSL_Const::sslv2_msb_set) == 0 )
{ {
ssl.state = SSL_State::SSL_NOT_FOUND; ssl.state = SSL_State::SSL_NOT_FOUND;
return false; return false;
} }
ssl.total_len = (val & (~SSL_Const::sslv2_msb_set)) << 8; ssl.total_len = (val & (~SSL_Const::sslv2_msb_set)) << 8;
ssl.state = SSL_State::BYTE_1_LEN_LSB; ssl.state = SSL_State::BYTE_1_LEN_LSB;
break; break;
case SSL_State::BYTE_1_LEN_LSB: case SSL_State::BYTE_1_LEN_LSB:
ssl.total_len |= val; ssl.total_len |= val;
if (ssl.total_len < SSL_Const::hdr_len) if ( ssl.total_len < SSL_Const::hdr_len )
{ {
ssl.state = SSL_State::SSL_NOT_FOUND; ssl.state = SSL_State::SSL_NOT_FOUND;
return false; return false;
} }
ssl.total_len -= SSL_Const::hdr_len; ssl.total_len -= SSL_Const::hdr_len;
ssl.state = SSL_State::BYTE_2_CLIENT_HELLO; ssl.state = SSL_State::BYTE_2_CLIENT_HELLO;
break; break;
case SSL_State::BYTE_2_CLIENT_HELLO: case SSL_State::BYTE_2_CLIENT_HELLO:
if (val != SSL_Const::client_hello) if ( val != SSL_Const::client_hello )
{ {
ssl.state = SSL_State::SSL_NOT_FOUND; ssl.state = SSL_State::SSL_NOT_FOUND;
return false; return false;
} }
ssl.state = SSL_State::BYTE_3_MAX_MINOR_VER; ssl.state = SSL_State::BYTE_3_MAX_MINOR_VER;
break; break;
case SSL_State::BYTE_3_MAX_MINOR_VER: case SSL_State::BYTE_3_MAX_MINOR_VER:
if (val > SSL_Const::sslv3_max_minor_ver) if ( val > SSL_Const::sslv3_max_minor_ver )
{ {
ssl.state = SSL_State::SSL_NOT_FOUND; ssl.state = SSL_State::SSL_NOT_FOUND;
return false; return false;
} }
ssl.state = SSL_State::BYTE_4_V3_MAJOR; ssl.state = SSL_State::BYTE_4_V3_MAJOR;
break; break;
case SSL_State::BYTE_4_V3_MAJOR: case SSL_State::BYTE_4_V3_MAJOR:
if (val > SSL_Const::sslv3_major_ver) if ( val > SSL_Const::sslv3_major_ver )
{ {
ssl.state = SSL_State::SSL_NOT_FOUND; ssl.state = SSL_State::SSL_NOT_FOUND;
return false; return false;
} }
ssl.state = SSL_State::BYTE_5_SPECS_LEN_MSB; ssl.state = SSL_State::BYTE_5_SPECS_LEN_MSB;
break; break;
case SSL_State::BYTE_5_SPECS_LEN_MSB: case SSL_State::BYTE_5_SPECS_LEN_MSB:
ssl.specs_len = val << 8; ssl.specs_len = val << 8;
ssl.state = SSL_State::BYTE_6_SPECS_LEN_LSB; ssl.state = SSL_State::BYTE_6_SPECS_LEN_LSB;
break; break;
case SSL_State::BYTE_6_SPECS_LEN_LSB: case SSL_State::BYTE_6_SPECS_LEN_LSB:
ssl.specs_len |= val; ssl.specs_len |= val;
if (ssl.total_len < ssl.specs_len)
if ( ssl.total_len < ssl.specs_len )
{ {
ssl.state = SSL_State::SSL_NOT_FOUND; ssl.state = SSL_State::SSL_NOT_FOUND;
return false; return false;
} }
ssl.total_len -= ssl.specs_len; ssl.total_len -= ssl.specs_len;
ssl.state = SSL_State::BYTE_7_SSNID_LEN_MSB; ssl.state = SSL_State::BYTE_7_SSNID_LEN_MSB;
break; break;
case SSL_State::BYTE_7_SSNID_LEN_MSB: case SSL_State::BYTE_7_SSNID_LEN_MSB:
ssl.ssnid_len = val << 8; ssl.ssnid_len = val << 8;
ssl.state = SSL_State::BYTE_8_SSNID_LEN_LSB; ssl.state = SSL_State::BYTE_8_SSNID_LEN_LSB;
break; break;
case SSL_State::BYTE_8_SSNID_LEN_LSB: case SSL_State::BYTE_8_SSNID_LEN_LSB:
ssl.ssnid_len |= val; ssl.ssnid_len |= val;
if (ssl.total_len < ssl.ssnid_len)
if ( ssl.total_len < ssl.ssnid_len )
{ {
ssl.state = SSL_State::SSL_NOT_FOUND; ssl.state = SSL_State::SSL_NOT_FOUND;
return false; return false;
} }
ssl.total_len -= ssl.ssnid_len; ssl.total_len -= ssl.ssnid_len;
ssl.state = SSL_State::BYTE_9_CHLNG_LEN_MSB; ssl.state = SSL_State::BYTE_9_CHLNG_LEN_MSB;
break; break;
case SSL_State::BYTE_9_CHLNG_LEN_MSB: case SSL_State::BYTE_9_CHLNG_LEN_MSB:
ssl.chlng_len = val << 8; ssl.chlng_len = val << 8;
ssl.state = SSL_State::BYTE_10_CHLNG_LEN_LSB; ssl.state = SSL_State::BYTE_10_CHLNG_LEN_LSB;
break; break;
case SSL_State::BYTE_10_CHLNG_LEN_LSB: case SSL_State::BYTE_10_CHLNG_LEN_LSB:
ssl.chlng_len |= val; ssl.chlng_len |= val;
if (ssl.total_len < ssl.chlng_len)
if ( ssl.total_len < ssl.chlng_len )
{ {
ssl.state = SSL_State::SSL_NOT_FOUND; ssl.state = SSL_State::SSL_NOT_FOUND;
return false; return false;
} }
ssl.state = SSL_State::SSL_FOUND; ssl.state = SSL_State::SSL_FOUND;
return true; return true;
default: default:
return false; return false;
} }
} }
return false; return false;
} }
skipping to change at line 620 skipping to change at line 655
// name service alg is_tcp // name service alg is_tcp
{ "dce_udp", "dcerpc" , dce_udp_curse, false }, { "dce_udp", "dcerpc" , dce_udp_curse, false },
{ "dce_tcp", "dcerpc" , dce_tcp_curse, true }, { "dce_tcp", "dcerpc" , dce_tcp_curse, true },
{ "mms" , "mms" , mms_curse , true }, { "mms" , "mms" , mms_curse , true },
{ "dce_smb", "netbios-ssn", dce_smb_curse, true }, { "dce_smb", "netbios-ssn", dce_smb_curse, true },
{ "sslv2" , "ssl" , ssl_v2_curse , true } { "sslv2" , "ssl" , ssl_v2_curse , true }
}; };
bool CurseBook::add_curse(const char* key) bool CurseBook::add_curse(const char* key)
{ {
for (const CurseDetails& curse : curse_map) for ( const CurseDetails& curse : curse_map )
{ {
if (curse.name == key) if ( curse.name == key )
{ {
if (curse.is_tcp) if ( curse.is_tcp )
tcp_curses.emplace_back(&curse); tcp_curses.emplace_back(&curse);
else else
non_tcp_curses.emplace_back(&curse); non_tcp_curses.emplace_back(&curse);
return true; return true;
} }
} }
return false; return false;
} }
const vector<const CurseDetails*>& CurseBook::get_curses(bool tcp) const const vector<const CurseDetails*>& CurseBook::get_curses(bool tcp) const
{ {
if (tcp) if ( tcp )
return tcp_curses; return tcp_curses;
return non_tcp_curses; return non_tcp_curses;
} }
#ifdef CATCH_TEST_BUILD #ifdef CATCH_TEST_BUILD
#include "catch/catch.hpp" #include "catch/catch.hpp"
#include <cstring> #include <cstring>
//client hello with v2 header advertising sslv2 //client hello with v2 header advertising sslv2
static const uint8_t ssl_v2_ch[] = static const uint8_t ssl_v2_ch[] =
skipping to change at line 672 skipping to change at line 710
0xee,0xda,0xc1,0x9d,0xdc,0xd7,0xb8,0x86,0x51,0x10,0x5a }; 0xee,0xda,0xc1,0x9d,0xdc,0xd7,0xb8,0x86,0x51,0x10,0x5a };
TEST_CASE("sslv2 detect", "[SslV2Curse]") TEST_CASE("sslv2 detect", "[SslV2Curse]")
{ {
uint32_t max_detect = static_cast<uint32_t>(SSL_State::BYTE_10_CHLNG_LEN_LSB ); uint32_t max_detect = static_cast<uint32_t>(SSL_State::BYTE_10_CHLNG_LEN_LSB );
CurseTracker tracker{ }; CurseTracker tracker{ };
auto test = [&](uint32_t incr_by,const uint8_t* ch) auto test = [&](uint32_t incr_by,const uint8_t* ch)
{ {
uint32_t i = 0; uint32_t i = 0;
while (i <= max_detect) while ( i <= max_detect )
{ {
if ((i + incr_by - 1) < max_detect) if ( (i + incr_by - 1) < max_detect )
{ {
CHECK(tracker.ssl.state == static_cast<SSL_State>(i)); CHECK(tracker.ssl.state == static_cast<SSL_State>(i));
CHECK_FALSE(ssl_v2_curse(&ch[i],sizeof(uint8_t) * incr_by,&t racker)); CHECK_FALSE(ssl_v2_curse(&ch[i],sizeof(uint8_t) * incr_by,&t racker));
} }
else else
{ {
CHECK(ssl_v2_curse(&ch[i],sizeof(uint8_t) * incr_by,&tracker )); CHECK(ssl_v2_curse(&ch[i],sizeof(uint8_t) * incr_by,&tracker ));
CHECK(tracker.ssl.state == SSL_State::SSL_FOUND); CHECK(tracker.ssl.state == SSL_State::SSL_FOUND);
} }
i += incr_by; i += incr_by;
} }
//subsequent checks must return found //subsequent checks must return found
CHECK(ssl_v2_curse(&ch[max_detect + 1],sizeof(uint8_t),&tracker)); CHECK(ssl_v2_curse(&ch[max_detect + 1],sizeof(uint8_t),&tracker));
CHECK(tracker.ssl.state == SSL_State::SSL_FOUND); CHECK(tracker.ssl.state == SSL_State::SSL_FOUND);
}; };
//sslv2 with ssl version 2 //sslv2 with ssl version 2
SECTION("1 byte v2"){ test(1,ssl_v2_ch); } SECTION("1 byte v2"){ test(1,ssl_v2_ch); }
SECTION("2 bytes v2"){ test(2,ssl_v2_ch); } SECTION("2 bytes v2"){ test(2,ssl_v2_ch); }
skipping to change at line 730 skipping to change at line 769
uint32_t max_detect = static_cast<uint32_t>(SSL_State::BYTE_10_CHLNG_LEN_LSB ); uint32_t max_detect = static_cast<uint32_t>(SSL_State::BYTE_10_CHLNG_LEN_LSB );
CurseTracker tracker{}; CurseTracker tracker{};
uint8_t bad_data[] = {0x00,0x08,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }; uint8_t bad_data[] = {0x00,0x08,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff };
auto test = [&](uint32_t fail_at_byte) auto test = [&](uint32_t fail_at_byte)
{ {
uint8_t ch_data[sizeof(ssl_v2_ch)]; uint8_t ch_data[sizeof(ssl_v2_ch)];
memcpy(ch_data,ssl_v2_ch,sizeof(ssl_v2_ch)); memcpy(ch_data,ssl_v2_ch,sizeof(ssl_v2_ch));
ch_data[fail_at_byte] = bad_data[fail_at_byte]; ch_data[fail_at_byte] = bad_data[fail_at_byte];
for (uint32_t i = 0; i <= fail_at_byte; i++) for ( uint32_t i = 0; i <= fail_at_byte; i++ )
{ {
if (i < fail_at_byte) if ( i < fail_at_byte )
{ {
CHECK(tracker.ssl.state == static_cast<SSL_State>(i)); CHECK(tracker.ssl.state == static_cast<SSL_State>(i));
CHECK_FALSE(ssl_v2_curse(&ch_data[i],sizeof(uint8_t),&tracke r)); CHECK_FALSE(ssl_v2_curse(&ch_data[i],sizeof(uint8_t),&tracke r));
} }
else else
{ {
CHECK_FALSE(ssl_v2_curse(&ch_data[i],sizeof(uint8_t),&tracke r)); CHECK_FALSE(ssl_v2_curse(&ch_data[i],sizeof(uint8_t),&tracke r));
CHECK(tracker.ssl.state == SSL_State::SSL_NOT_FOUND); CHECK(tracker.ssl.state == SSL_State::SSL_NOT_FOUND);
} }
} }
 End of changes. 87 change blocks. 
61 lines changed or deleted 101 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)