/* smb_parser.c * * This file contains functions to parse SMB (version 2 and 3) headers. * * File begun on 2018-11-13 * * Created by: * - Théo Bertin (theo.bertin@advens.fr) * * With: * - François Bernard (francois.bernard@isen.yncrea.fr) * - Tianyu Geng (tianyu.geng@isen.yncrea.fr) * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "parsers.h" /* SMB2 opCodes */ #define SMB2_NEGOTIATE 0x00 #define SMB2_SESSIONSET 0x01 #define SMB2_SESSIONLOGOFF 0x02 #define SMB2_TREECONNECT 0x03 #define SMB2_TREEDISCONNECT 0x04 #define SMB2_CREATE 0x05 #define SMB2_CLOSE 0x06 #define SMB2_FLUSH 0x07 #define SMB2_READ 0x08 #define SMB2_WRITE 0x09 #define SMB2_LOCK 0x0a #define SMB2_IOCTL 0x0b #define SMB2_CANCEL 0x0c #define SMB2_KEEPALIVE 0x0d #define SMB2_FIND 0x0e #define SMB2_NOTIFY 0x0f #define SMB2_GETINFO 0x10 #define SMB2_SETINFO 0x11 #define SMB2_BREAK 0x12 struct smb_header_s { uint32_t version; uint16_t headerLength; uint16_t padding1; uint32_t ntStatus; uint16_t opCode; uint16_t padding2; uint32_t flags; uint32_t chainOffset; uint32_t comSeqNumber[2]; uint32_t processID; uint32_t treeID; uint32_t userID[2]; uint32_t signature[4]; }; typedef struct smb_header_s smb_header_t; static char flagCodes[5] = "RPCS"; /* * This function parses the bytes in the received packet to extract SMB2 metadata. * * its parameters are: * - a pointer on the list of bytes representing the packet * the beginning of the header will be checked by the function * - the size of the list passed as first parameter * - a pointer on a json_object, containing all the metadata recovered so far * this is also where SMB2 metadata will be added * * This function returns a structure containing the data unprocessed by this parser * or the ones after (as a list of bytes), and the length of this data. */ data_ret_t *smb_parse(const uchar *packet, int pktSize, struct json_object *jparent) { DBGPRINTF("smb_parse\n"); DBGPRINTF("packet size %d\n", pktSize); int pktSizeCpy = pktSize; const uchar *packetCpy = packet; while (pktSizeCpy > 0) { /* don't check packetCpy[0] to include SMB version byte at the beginning */ if (packetCpy[1] == 'S') { if (packetCpy[2] == 'M') { if (packetCpy[3] == 'B') { break; } } } packetCpy++, pktSizeCpy--; } if ((int)pktSizeCpy < 64) { DBGPRINTF("SMB packet too small : %d\n", pktSizeCpy); RETURN_DATA_AFTER(0) } /* Union to prevent cast from uchar to smb_header_t */ union { const uchar *pck; smb_header_t *hdr; } smb_header_to_char; smb_header_to_char.pck = packetCpy; smb_header_t *smb_header = smb_header_to_char.hdr; char flags[5] = {0}; uint64_t seqNum, userID; uint8_t version; version = (smb_header->version == 0xFF) ? 1 : 2; seqNum = smb_header->comSeqNumber[0] | smb_header->comSeqNumber[1] << 16; userID = smb_header->userID[0] | smb_header->userID[1] << 16; uint8_t i, pos = 0; for (i = 0; i < 4; ++i) { if (smb_header->flags & (0x01 << i)) flags[pos++] = flagCodes[i]; } json_object_object_add(jparent, "SMB_version", json_object_new_int(version)); json_object_object_add(jparent, "SMB_NTstatus", json_object_new_int64(smb_header->ntStatus)); json_object_object_add(jparent, "SMB_operation", json_object_new_int(smb_header->opCode)); json_object_object_add(jparent, "SMB_flags", json_object_new_string(flags)); json_object_object_add(jparent, "SMB_seqNumber", json_object_new_int64(seqNum)); json_object_object_add(jparent, "SMB_processID", json_object_new_int64(smb_header->processID)); json_object_object_add(jparent, "SMB_treeID", json_object_new_int64(smb_header->treeID)); json_object_object_add(jparent, "SMB_userID", json_object_new_int64(userID)); RETURN_DATA_AFTER(0) }