Exemple #1
0
static enum proto_parse_status netbios_parse(struct parser *parser, struct proto_layer *parent, unsigned way, uint8_t const *packet, size_t cap_len, size_t wire_len, struct timeval const *now, proto_okfn_t *okfn)
{
    /* Sanity checks */
    if (wire_len < NETBIOS_HEADER_SIZE) return PROTO_PARSE_ERR;
    if (cap_len < NETBIOS_HEADER_SIZE) return PROTO_TOO_SHORT;

    if (! packet_is_netbios(packet, cap_len)) return PROTO_PARSE_ERR;

    /* Parse */
    struct netbios_proto_info info;
    netbios_proto_info_ctor(&info, NETBIOS_HEADER_SIZE, wire_len - NETBIOS_HEADER_SIZE);

    struct proto_layer layer;
    proto_layer_ctor(&layer, parent, parser, &info.info);

    uint8_t const *next_packet = packet + NETBIOS_HEADER_SIZE;
    struct parser *subparser = proto_cifs->ops->parser_new(proto_cifs, now);
    if (! subparser) goto fallback;

    /* List of protocols above NetBios: CIFS, SMB, ... */
    int err = proto_parse(subparser, parent, way, next_packet, cap_len - NETBIOS_HEADER_SIZE, wire_len - NETBIOS_HEADER_SIZE, now, okfn);
    parser_unref(subparser);
    if (err) goto fallback;
    return PROTO_OK;

fallback:
    (void)proto_parse(NULL, parent, way, next_packet, cap_len - NETBIOS_HEADER_SIZE, wire_len - NETBIOS_HEADER_SIZE, now, okfn);
    return PROTO_OK;
}
Exemple #2
0
static enum proto_parse_status netbios_parse_frame(struct netbios_parser *netbios_parser,
        struct proto_info *parent, unsigned way, uint8_t const *packet, size_t cap_len, size_t wire_len,
        struct timeval const *now, size_t tot_cap_len, uint8_t const *tot_packet, size_t *pos)
{
    if (cap_len == 0 && netbios_parser->sbuf.dir[way].cap_len == 0) {
        // Ignore pure gap start
        timeval_reset(netbios_parser->first_packet_tv + way);
        return PROTO_PARSE_ERR;
    }
    if (cap_len > 0 && !timeval_is_set(&netbios_parser->first_packet_tv[way])) {
        SLOG(LOG_DEBUG, "Set first packet ts for way %d to %s", way, timeval_2_str(now));
        netbios_parser->first_packet_tv[way] = *now;
    }
    if (wire_len < NETBIOS_HEADER_SIZE + SMB_FLAG_SIZE) {
        streambuf_set_restart(&netbios_parser->sbuf, way, packet, NETBIOS_HEADER_SIZE + SMB_FLAG_SIZE);
        return PROTO_OK;
    }
    if (cap_len < NETBIOS_HEADER_SIZE + SMB_FLAG_SIZE) {
        SLOG(LOG_DEBUG, "Got a gap on neccessary bytes");
        timeval_reset(netbios_parser->first_packet_tv + way);
        return PROTO_PARSE_ERR;
    }
    if (packet[0] != 0) {
        SLOG(LOG_DEBUG, "Expected Session message type 0x00, got 0x%"PRIx8, packet[0]);
        timeval_reset(netbios_parser->first_packet_tv + way);
        return PROTO_PARSE_ERR;
    }

    uint32_t smb_version = READ_U32N(packet + NETBIOS_HEADER_SIZE);
    if (smb_version != CIFS_SMB_HEADER && smb_version != CIFS_SMB2_HEADER) {
        static unsigned char smb_header[SMB_FLAG_SIZE] = {0xff, 0x53, 0x4d, 0x42};
        static unsigned char smb2_header[SMB_FLAG_SIZE] = {0xfe, 0x53, 0x4d, 0x42};
        void *res = memmem(packet + NETBIOS_HEADER_SIZE, cap_len - NETBIOS_HEADER_SIZE, &smb_header,
                SMB_FLAG_SIZE);
        if (!res) {
            res = memmem(packet + NETBIOS_HEADER_SIZE, cap_len - NETBIOS_HEADER_SIZE, &smb2_header,
                    SMB_FLAG_SIZE);
        }
        if (!res) {
            SLOG(LOG_DEBUG, "Netbios payload does not expected header (expected %"PRIx32" or %"PRIx32"),"
                    " got %"PRIx32, CIFS_SMB_HEADER, CIFS_SMB2_HEADER, smb_version);
            return PROTO_PARSE_ERR;
        }
        SLOG(LOG_DEBUG, "Found a SMB header in payload, restarting there");
        timeval_reset(netbios_parser->first_packet_tv + way);
        streambuf_set_restart(&netbios_parser->sbuf, way, res - NETBIOS_HEADER_SIZE,
                NETBIOS_HEADER_SIZE + SMB_FLAG_SIZE);
        return PROTO_OK;
    }

    uint32_t len = READ_U32N((uint32_t*) packet) & 0x00ffffff;
    *pos = len;
    size_t current_payload = wire_len - NETBIOS_HEADER_SIZE;
    SLOG(LOG_DEBUG, "Found netbios payload of %"PRIu32", current payload %zu",
            len, current_payload);
    if (len > current_payload) {
        streambuf_set_restart(&netbios_parser->sbuf, way, packet, len + NETBIOS_HEADER_SIZE);
        return PROTO_OK;
    }

    /* Parse */
    struct netbios_proto_info info;
    netbios_proto_info_ctor(&info, &netbios_parser->parser, parent,
            NETBIOS_HEADER_SIZE, wire_len - NETBIOS_HEADER_SIZE, len,
            netbios_parser->first_packet_tv + way);
    timeval_reset(netbios_parser->first_packet_tv + way);

    SLOG(LOG_DEBUG, "Parsing netbios content");
    uint8_t const *next_packet = packet + NETBIOS_HEADER_SIZE;
    if (!netbios_parser->msg_parser) {
        netbios_parser->msg_parser = proto_cifs->ops->parser_new(proto_cifs);
    }

    enum proto_parse_status status = PROTO_OK;
    if (netbios_parser->msg_parser) {
        status = proto_parse(netbios_parser->msg_parser, &info.info,
                way, next_packet,
                cap_len - NETBIOS_HEADER_SIZE, wire_len - NETBIOS_HEADER_SIZE,
                now, tot_cap_len, tot_packet);
        if (status == PROTO_OK) return PROTO_OK;
    }
    (void)proto_parse(NULL, &info.info, way, next_packet, cap_len - NETBIOS_HEADER_SIZE, wire_len - NETBIOS_HEADER_SIZE, now, tot_cap_len, tot_packet);
    return status;
}