You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
suricata/src/app-layer-smb2.c

691 lines
24 KiB
C

/* Copyright (C) 2007-2010 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
* Software Foundation.
*
* 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
* version 2 along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
/**
* \file
16 years ago
*
* \author Kirby Kuehl <kkuehl@gmail.com>
*
* SMBv2 parser/decoder
16 years ago
*/
#include "suricata-common.h"
16 years ago
#include "debug.h"
#include "decode.h"
#include "threads.h"
#include "util-print.h"
#include "util-pool.h"
#include "stream-tcp-private.h"
#include "stream-tcp-reassemble.h"
#include "stream-tcp.h"
16 years ago
#include "stream.h"
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
#include "app-layer.h"
16 years ago
#include "app-layer-protos.h"
#include "app-layer-parser.h"
#include "util-spm.h"
16 years ago
#include "util-unittest.h"
#include "util-debug.h"
#include "util-memcmp.h"
16 years ago
#include "app-layer-smb2.h"
enum {
SMB2_FIELD_NONE = 0,
SMB2_PARSE_NBSS_HEADER,
SMB2_PARSE_SMB_HEADER,
/* must be last */
SMB_FIELD_MAX,
};
static uint32_t NBSSParseHeader(void *smb2_state, AppLayerParserState *pstate,
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
uint8_t *input, uint32_t input_len)
{
SCEnter();
16 years ago
SMB2State *sstate = (SMB2State *) smb2_state;
uint8_t *p = input;
if (input_len && sstate->bytesprocessed < NBSS_HDR_LEN - 1) {
switch (sstate->bytesprocessed) {
case 0:
/* Initialize */
16 years ago
if (input_len >= NBSS_HDR_LEN) {
sstate->nbss.type = *p;
sstate->nbss.length = (*(p + 1) & 0x01) << 16;
sstate->nbss.length |= *(p + 2) << 8;
sstate->nbss.length |= *(p + 3);
sstate->bytesprocessed += NBSS_HDR_LEN;
SCReturnUInt(4U);
16 years ago
} else {
sstate->nbss.type = *(p++);
if (!(--input_len))
break;
16 years ago
}
/* fall through */
16 years ago
case 1:
sstate->nbss.length = (*(p++) & 0x01) << 16;
if (!(--input_len))
break;
/* fall through */
16 years ago
case 2:
sstate->nbss.length |= *(p++) << 8;
if (!(--input_len))
break;
/* fall through */
16 years ago
case 3:
sstate->nbss.length |= *(p++);
--input_len;
break;
}
sstate->bytesprocessed += (p - input);
}
SCReturnUInt((uint32_t)(p - input));
16 years ago
}
static uint32_t SMB2ParseHeader(void *smb2_state, AppLayerParserState *pstate,
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
uint8_t *input, uint32_t input_len)
{
SCEnter();
16 years ago
SMB2State *sstate = (SMB2State *) smb2_state;
uint8_t *p = input;
16 years ago
if (input_len) {
switch (sstate->bytesprocessed) {
case 4:
// fallthrough
/* above statement to prevent coverity FPs from the switch
* fall through */
16 years ago
if (input_len >= SMB2_HDR_LEN) {
if (SCMemcmp(p, "\xfe\x53\x4d\x42", 4) != 0) {
//printf("SMB2 Header did not validate\n");
16 years ago
return 0;
}
sstate->smb2.StructureSize = *(p + 4);
sstate->smb2.StructureSize |= *(p + 5) << 8;
sstate->smb2.CreditCharge = *(p + 6);
sstate->smb2.CreditCharge |= *(p + 7) << 8;
sstate->smb2.Status = *(p + 8);
sstate->smb2.Status |= *(p + 9) << 8;
sstate->smb2.Status |= *(p + 10) << 16;
sstate->smb2.Status |= *(p + 11) << 24;
sstate->smb2.Command = *(p + 12);
sstate->smb2.Command |= *(p + 13) << 8;
sstate->smb2.CreditRequestResponse = *(p + 14);
sstate->smb2.CreditRequestResponse |= *(p + 15) << 8;
sstate->smb2.Flags = *(p + 16);
sstate->smb2.Flags |= *(p + 17) << 8;
sstate->smb2.Flags |= *(p + 18) << 16;
sstate->smb2.Flags |= *(p + 19) << 24;
sstate->smb2.NextCommand = *(p + 20);
sstate->smb2.NextCommand |= *(p + 21) << 8;
sstate->smb2.NextCommand |= *(p + 22) << 16;
sstate->smb2.NextCommand |= *(p + 23) << 24;
sstate->smb2.MessageId = *(p + 24);
sstate->smb2.MessageId |= *(p + 25) << 8;
sstate->smb2.MessageId |= *(p + 26) << 16;
sstate->smb2.MessageId |= (uint64_t) *(p + 27) << 24;
16 years ago
sstate->smb2.MessageId |= (uint64_t) *(p + 28) << 32;
sstate->smb2.MessageId |= (uint64_t) *(p + 29) << 40;
sstate->smb2.MessageId |= (uint64_t) *(p + 30) << 48;
sstate->smb2.MessageId |= (uint64_t) *(p + 31) << 56;
sstate->smb2.ProcessId = *(p + 32);
sstate->smb2.ProcessId |= *(p + 33) << 8;
sstate->smb2.ProcessId |= *(p + 34) << 16;
sstate->smb2.ProcessId |= *(p + 35) << 24;
sstate->smb2.TreeId = *(p + 36);
sstate->smb2.TreeId |= *(p + 37) << 8;
sstate->smb2.TreeId |= *(p + 38) << 16;
sstate->smb2.TreeId |= *(p + 39) << 24;
sstate->smb2.SessionId = *(p + 40);
sstate->smb2.SessionId |= *(p + 41) << 8;
sstate->smb2.SessionId |= *(p + 42) << 16;
sstate->smb2.SessionId |= (uint64_t) *(p + 43) << 24;
16 years ago
sstate->smb2.SessionId |= (uint64_t) *(p + 44) << 32;
sstate->smb2.SessionId |= (uint64_t) *(p + 45) << 40;
sstate->smb2.SessionId |= (uint64_t) *(p + 46) << 48;
sstate->smb2.SessionId |= (uint64_t) *(p + 47) << 56;
sstate->smb2.Signature[0] = *(p + 48);
sstate->smb2.Signature[1] = *(p + 49);
sstate->smb2.Signature[2] = *(p + 50);
sstate->smb2.Signature[3] = *(p + 51);
sstate->smb2.Signature[4] = *(p + 52);
sstate->smb2.Signature[5] = *(p + 53);
sstate->smb2.Signature[6] = *(p + 54);
sstate->smb2.Signature[7] = *(p + 55);
sstate->smb2.Signature[8] = *(p + 56);
sstate->smb2.Signature[9] = *(p + 57);
sstate->smb2.Signature[10] = *(p + 58);
sstate->smb2.Signature[11] = *(p + 59);
sstate->smb2.Signature[12] = *(p + 60);
sstate->smb2.Signature[13] = *(p + 61);
sstate->smb2.Signature[14] = *(p + 62);
sstate->smb2.Signature[15] = *(p + 63);
sstate->bytesprocessed += SMB2_HDR_LEN;
SCReturnUInt(64U);
16 years ago
break;
} else {
//sstate->smb2.protocol[0] = *(p++);
if (*(p++) != 0xfe)
return 0;
if (!(--input_len))
break;
/* We fall through to the next case if we still have input.
* Same applies for other cases as well */
16 years ago
}
/* fall through */
16 years ago
case 5:
//sstate->smb2.protocol[1] = *(p++);
if (*(p++) != 'S')
return 0;
if (!(--input_len))
break;
/* fall through */
16 years ago
case 6:
//sstate->smb2.protocol[2] = *(p++);
if (*(p++) != 'M')
return 0;
if (!(--input_len))
break;
/* fall through */
16 years ago
case 7:
//sstate->smb2.protocol[3] = *(p++);
if (*(p++) != 'B')
return 0;
if (!(--input_len))
break;
/* fall through */
16 years ago
case 8:
sstate->smb2.StructureSize = *(p++);
if (!(--input_len))
break;
/* fall through */
16 years ago
case 9:
sstate->smb2.StructureSize |= *(p++) << 8;
if (!(--input_len))
break;
/* fall through */
16 years ago
case 10:
sstate->smb2.CreditCharge = *(p++);
if (!(--input_len))
break;
/* fall through */
16 years ago
case 11:
sstate->smb2.CreditCharge |= *(p++) << 8;
if (!(--input_len))
break;
/* fall through */
16 years ago
case 12:
sstate->smb2.Status = *(p++);
if (!(--input_len))
break;
/* fall through */
16 years ago
case 13:
sstate->smb2.Status |= *(p++) << 8;
if (!(--input_len))
break;
/* fall through */
16 years ago
case 14:
sstate->smb2.Status |= *(p++) << 16;
if (!(--input_len))
break;
/* fall through */
16 years ago
case 15:
sstate->smb2.Status |= *(p++) << 24;
if (!(--input_len))
break;
/* fall through */
16 years ago
case 16:
sstate->smb2.Command = *(p++);
if (!(--input_len))
break;
/* fall through */
16 years ago
case 17:
sstate->smb2.Command |= *(p++) << 8;
if (!(--input_len))
break;
/* fall through */
16 years ago
case 18:
sstate->smb2.CreditRequestResponse = *(p++);
if (!(--input_len))
break;
/* fall through */
16 years ago
case 19:
sstate->smb2.CreditRequestResponse |= *(p++) << 8;
if (!(--input_len))
break;
/* fall through */
16 years ago
case 20:
sstate->smb2.Flags = *(p++);
if (!(--input_len))
break;
/* fall through */
16 years ago
case 21:
sstate->smb2.Flags |= *(p++) << 8;
if (!(--input_len))
break;
/* fall through */
16 years ago
case 22:
sstate->smb2.Flags |= *(p++) << 16;
if (!(--input_len))
break;
/* fall through */
16 years ago
case 23:
sstate->smb2.Flags |= *(p++) << 24;
if (!(--input_len))
break;
/* fall through */
16 years ago
case 24:
sstate->smb2.NextCommand = *(p++);
if (!(--input_len))
break;
/* fall through */
16 years ago
case 25:
sstate->smb2.NextCommand |= *(p++) << 8;
if (!(--input_len))
break;
/* fall through */
16 years ago
case 26:
sstate->smb2.NextCommand |= *(p++) << 16;
if (!(--input_len))
break;
/* fall through */
16 years ago
case 27:
sstate->smb2.NextCommand |= *(p++) << 24;
if (!(--input_len))
break;
/* fall through */
16 years ago
case 28:
sstate->smb2.MessageId = *(p++);
if (!(--input_len))
break;
/* fall through */
16 years ago
case 29:
sstate->smb2.MessageId = *(p++) << 8;
if (!(--input_len))
break;
/* fall through */
16 years ago
case 30:
sstate->smb2.MessageId = *(p++) << 16;
if (!(--input_len))
break;
/* fall through */
16 years ago
case 31:
sstate->smb2.MessageId = (uint64_t) *(p++) << 24;
if (!(--input_len))
break;
/* fall through */
16 years ago
case 32:
sstate->smb2.MessageId = (uint64_t) *(p++) << 32;
if (!(--input_len))
break;
/* fall through */
16 years ago
case 33:
sstate->smb2.MessageId = (uint64_t) *(p++) << 40;
if (!(--input_len))
break;
/* fall through */
16 years ago
case 34:
sstate->smb2.MessageId = (uint64_t) *(p++) << 48;
if (!(--input_len))
break;
/* fall through */
16 years ago
case 35:
sstate->smb2.MessageId = (uint64_t) *(p++) << 56;
if (!(--input_len))
break;
/* fall through */
16 years ago
case 36:
sstate->smb2.ProcessId = *(p++);
if (!(--input_len))
break;
/* fall through */
16 years ago
case 37:
sstate->smb2.ProcessId |= *(p++) << 8;
if (!(--input_len))
break;
/* fall through */
16 years ago
case 38:
sstate->smb2.ProcessId |= *(p++) << 16;
if (!(--input_len))
break;
/* fall through */
16 years ago
case 39:
sstate->smb2.ProcessId |= *(p++) << 24;
if (!(--input_len))
break;
/* fall through */
16 years ago
case 40:
sstate->smb2.TreeId = *(p++);
if (!(--input_len))
break;
/* fall through */
16 years ago
case 41:
sstate->smb2.TreeId |= *(p++) << 8;
if (!(--input_len))
break;
/* fall through */
16 years ago
case 42:
sstate->smb2.TreeId |= *(p++) << 16;
if (!(--input_len))
break;
/* fall through */
16 years ago
case 43:
sstate->smb2.TreeId |= *(p++) << 24;
if (!(--input_len))
break;
/* fall through */
16 years ago
case 44:
sstate->smb2.SessionId = *(p++);
if (!(--input_len))
break;
/* fall through */
16 years ago
case 45:
sstate->smb2.SessionId |= *(p++) << 8;
if (!(--input_len))
break;
/* fall through */
16 years ago
case 46:
sstate->smb2.SessionId |= *(p++) << 16;
if (!(--input_len))
break;
/* fall through */
16 years ago
case 47:
sstate->smb2.SessionId |= (uint64_t) *(p++) << 24;
if (!(--input_len))
break;
/* fall through */
16 years ago
case 48:
sstate->smb2.SessionId |= (uint64_t) *(p++) << 32;
if (!(--input_len))
break;
/* fall through */
16 years ago
case 49:
sstate->smb2.SessionId |= (uint64_t) *(p++) << 40;
if (!(--input_len))
break;
/* fall through */
16 years ago
case 50:
sstate->smb2.SessionId |= (uint64_t) *(p++) << 48;
if (!(--input_len))
break;
/* fall through */
16 years ago
case 51:
sstate->smb2.SessionId |= (uint64_t) *(p++) << 56;
if (!(--input_len))
break;
/* fall through */
16 years ago
case 52:
sstate->smb2.Signature[0] = *(p++);
if (!(--input_len))
break;
/* fall through */
16 years ago
case 53:
sstate->smb2.Signature[1] = *(p++);
if (!(--input_len))
break;
/* fall through */
16 years ago
case 54:
sstate->smb2.Signature[2] = *(p++);
if (!(--input_len))
break;
/* fall through */
16 years ago
case 55:
sstate->smb2.Signature[3] = *(p++);
if (!(--input_len))
break;
/* fall through */
16 years ago
case 56:
sstate->smb2.Signature[4] = *(p++);
if (!(--input_len))
break;
/* fall through */
16 years ago
case 57:
sstate->smb2.Signature[5] = *(p++);
if (!(--input_len))
break;
/* fall through */
16 years ago
case 58:
sstate->smb2.Signature[6] = *(p++);
if (!(--input_len))
break;
/* fall through */
16 years ago
case 59:
sstate->smb2.Signature[7] = *(p++);
if (!(--input_len))
break;
/* fall through */
16 years ago
case 60:
sstate->smb2.Signature[8] = *(p++);
if (!(--input_len))
break;
/* fall through */
16 years ago
case 61:
sstate->smb2.Signature[9] = *(p++);
if (!(--input_len))
break;
/* fall through */
16 years ago
case 62:
sstate->smb2.Signature[10] = *(p++);
if (!(--input_len))
break;
/* fall through */
16 years ago
case 63:
sstate->smb2.Signature[11] = *(p++);
if (!(--input_len))
break;
/* fall through */
16 years ago
case 64:
sstate->smb2.Signature[12] = *(p++);
if (!(--input_len))
break;
/* fall through */
16 years ago
case 65:
sstate->smb2.Signature[13] = *(p++);
if (!(--input_len))
break;
/* fall through */
16 years ago
case 66:
sstate->smb2.Signature[14] = *(p++);
if (!(--input_len))
break;
/* fall through */
16 years ago
case 67:
sstate->smb2.Signature[15] = *(p++);
--input_len;
16 years ago
break;
/* fall through */
16 years ago
}
}
sstate->bytesprocessed += (p - input);
SCReturnUInt((uint32_t)(p - input));
16 years ago
}
static int SMB2Parse(Flow *f, void *smb2_state, AppLayerParserState *pstate,
uint8_t *input, uint32_t input_len,
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
void *local_data)
{
SCEnter();
16 years ago
SMB2State *sstate = (SMB2State *) smb2_state;
uint32_t retval = 0;
uint32_t parsed = 0;
if (pstate == NULL)
return -1;
if (input == NULL && AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF)) {
SCReturnInt(1);
} else if (input == NULL || input_len == 0) {
SCReturnInt(-1);
}
while (sstate->bytesprocessed < NBSS_HDR_LEN && input_len) {
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
retval = NBSSParseHeader(smb2_state, pstate, input, input_len);
if (retval <= input_len) {
parsed += retval;
input_len -= retval;
} else {
return -1;
}
SCLogDebug("NBSS Header (%u/%u) Type 0x%02x Length 0x%04x parsed %u input_len %u",
sstate->bytesprocessed, NBSS_HDR_LEN, sstate->nbss.type,
sstate->nbss.length, parsed, input_len);
16 years ago
}
switch(sstate->nbss.type) {
case NBSS_SESSION_MESSAGE:
while (input_len && (sstate->bytesprocessed >= NBSS_HDR_LEN &&
sstate->bytesprocessed < NBSS_HDR_LEN + SMB2_HDR_LEN)) {
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
retval = SMB2ParseHeader(smb2_state, pstate, input + parsed, input_len);
if (retval <= input_len) {
parsed += retval;
input_len -= retval;
} else {
return -1;
}
SCLogDebug("SMB2 Header (%u/%u) Command 0x%04x parsed %u input_len %u",
sstate->bytesprocessed, NBSS_HDR_LEN + SMB2_HDR_LEN,
sstate->smb2.Command, parsed, input_len);
}
break;
default:
break;
16 years ago
}
SCReturnInt(1);
16 years ago
}
static void *SMB2StateAlloc(void)
{
void *s = SCMalloc(sizeof(SMB2State));
if (unlikely(s == NULL))
16 years ago
return NULL;
memset(s, 0, sizeof(SMB2State));
return s;
}
static void SMB2StateFree(void *s)
{
16 years ago
if (s) {
SCFree(s);
16 years ago
s = NULL;
}
}
void RegisterSMB2Parsers(void)
{
/** SMB2 */
char *proto_name = "smb2";
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
if (AppLayerProtoDetectConfProtoDetectionEnabled("tcp", proto_name)) {
AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_SMB2, STREAM_TOSERVER, SMB2Parse);
AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_SMB2, STREAM_TOCLIENT, SMB2Parse);
AppLayerParserRegisterStateFuncs(IPPROTO_TCP, ALPROTO_SMB2, SMB2StateAlloc, SMB2StateFree);
} else {
SCLogInfo("Parsed disabled for %s protocol. Protocol detection"
"still on.", proto_name);
}
#ifdef UNITTESTS
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
AppLayerParserRegisterProtocolUnittests(IPPROTO_TCP, ALPROTO_SMB2, SMB2ParserRegisterTests);
#endif
return;
16 years ago
}
/* UNITTESTS */
#ifdef UNITTESTS
int SMB2ParserTest01(void)
{
16 years ago
int result = 1;
Flow f;
uint8_t smb2buf[] =
"\x00\x00\x00\x66" // NBSS
"\xfe\x53\x4d\x42\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00" // SMB2
"\x3f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x24\x00\x01\x00x00\x00\x00\x00\x00\x00\x0\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x02";
16 years ago
uint32_t smb2len = sizeof(smb2buf) - 1;
TcpSession ssn;
AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
16 years ago
memset(&f, 0, sizeof(f));
memset(&ssn, 0, sizeof(ssn));
f.protoctx = (void *)&ssn;
StreamTcpInitConfig(TRUE);
SCMutexLock(&f.m);
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
int r = AppLayerParserParse(alp_tctx, &f, ALPROTO_SMB2, STREAM_TOSERVER|STREAM_EOF, smb2buf, smb2len);
16 years ago
if (r != 0) {
printf("smb2 header check returned %" PRId32 ", expected 0: ", r);
result = 0;
SCMutexUnlock(&f.m);
16 years ago
goto end;
}
SCMutexUnlock(&f.m);
16 years ago
SMB2State *smb2_state = f.alstate;
16 years ago
if (smb2_state == NULL) {
printf("no smb2 state: ");
result = 0;
goto end;
}
if (smb2_state->nbss.type != NBSS_SESSION_MESSAGE) {
printf("expected nbss type 0x%02x , got 0x%02x : ", NBSS_SESSION_MESSAGE, smb2_state->nbss.type);
result = 0;
goto end;
}
16 years ago
if (smb2_state->nbss.length != 102) {
printf("expected nbss length 0x%02x , got 0x%02x : ", 102, smb2_state->nbss.length);
16 years ago
result = 0;
goto end;
}
if (smb2_state->smb2.Command != SMB2_NEGOTIATE) {
printf("expected SMB2 command 0x%04x , got 0x%04x : ", SMB2_NEGOTIATE, smb2_state->smb2.Command);
result = 0;
goto end;
}
end:
App layer API rewritten. The main files in question are: app-layer.[ch], app-layer-detect-proto.[ch] and app-layer-parser.[ch]. Things addressed in this commit: - Brings out a proper separation between protocol detection phase and the parser phase. - The dns app layer now is registered such that we don't use "dnstcp" and "dnsudp" in the rules. A user who previously wrote a rule like this - "alert dnstcp....." or "alert dnsudp....." would now have to use, alert dns (ipproto:tcp;) or alert udp (app-layer-protocol:dns;) or alert ip (ipproto:udp; app-layer-protocol:dns;) The same rules extend to other another such protocol, dcerpc. - The app layer parser api now takes in the ipproto while registering callbacks. - The app inspection/detection engine also takes an ipproto. - All app layer parser functions now take direction as STREAM_TOSERVER or STREAM_TOCLIENT, as opposed to 0 or 1, which was taken by some of the functions. - FlowInitialize() and FlowRecycle() now resets proto to 0. This is needed by unittests, which would try to clean the flow, and that would call the api, AppLayerParserCleanupParserState(), which would try to clean the app state, but the app layer now needs an ipproto to figure out which api to internally call to clean the state, and if the ipproto is 0, it would return without trying to clean the state. - A lot of unittests are now updated where if they are using a flow and they need to use the app layer, we would set a flow ipproto. - The "app-layer" section in the yaml conf has also been updated as well.
12 years ago
if (alp_tctx != NULL)
AppLayerParserThreadCtxFree(alp_tctx);
StreamTcpFreeConfig(TRUE);
16 years ago
return result;
}
void SMB2ParserRegisterTests(void)
{
16 years ago
UtRegisterTest("SMB2ParserTest01", SMB2ParserTest01, 1);
}
#endif