Пример #1
0
int mysql_parser(MolochSession_t *session, void *uw, const unsigned char *data, int len) 
{
    Info_t *info = uw;
    if (session->which != 0) {
        return 0;
    }

    if (len < 37 || data[1] != 0 || data[2] != 0 || data[3] != 1) {
        moloch_parsers_unregister(session, info);
        return 0;
    }

    unsigned char *ptr = (unsigned char*)data + 36;
    unsigned char *end = (unsigned char*)data + len;

    while (ptr < end) {
        if (*ptr == 0)
            break;
        if (!isprint(*ptr)) {
            moloch_parsers_unregister(session, info);
            return 0;
        }
        ptr++;
    }

    moloch_nids_add_protocol(session, "mysql");
    moloch_field_string_add(versionField, session, info->version, info->versionLen, FALSE);
    info->version = 0;

    char *lower = g_ascii_strdown((char *)data+36, ptr - (data + 36));
    moloch_field_string_add(userField, session, lower, ptr - (data + 36), FALSE);

    moloch_parsers_unregister(session, info);
    return 0;
}
Пример #2
0
void oracle_classify(MolochSession_t *session, const unsigned char *data, int len, int which, void *UNUSED(uw))
{
    if (which != 0 || len <= 27 || len != data[1] || (data[25] + data[27] != len))
        return;

    char *buf;  // can't be more then 1 byte big
    int  blen;

    buf = oracle_get_item((const char *)data, "HOST=", 5, &blen);
    if (buf && !moloch_field_string_add(hostField, session, buf, blen, FALSE)) {
        g_free(buf);
    }

    buf = oracle_get_item((const char *)data, "USER="******"SERVICE_NAME=", 13, &blen);
    if (buf && !moloch_field_string_add(serviceField, session, buf, blen, FALSE)) {
        g_free(buf);
    }

    moloch_session_add_protocol(session, "oracle");
}
Пример #3
0
void
moloch_http_parse_authorization(MolochSession_t *session, char *str)
{
    gsize olen;

    while (isspace(*str)) str++;

    char *space = strchr(str, ' ');

    if (!space)
        return;

    char *lower = g_ascii_strdown(str, space-str);
    if (!moloch_field_string_add(atField, session, lower, space-str, FALSE)) {
        g_free(lower);
    }

    if (strncasecmp("basic", str, 5) == 0) {
        str += 5;
        while (isspace(*str)) str++;

        // Yahoo reused Basic
        if (memcmp("token=", str, 6) != 0) {
            g_base64_decode_inplace(str, &olen);
            char *colon = strchr(str, ':');
            if (colon)
                *colon = 0;
            moloch_field_string_add(userField, session, str, -1, TRUE);
        }
    } else if (strncasecmp("digest", str, 6) == 0) {
        str += 5;
        while (isspace(*str)) str++;

        char *username = strstr(str, "username");
        if (!username) return;
        str = username + 8;
        while (isspace(*str)) str++;
        if (*str != '=') return;
        str++; // equal
        while (isspace(*str)) str++;

        int quote = 0;
        if (*str == '"') {
            quote = 1;
            str++;
        }
        char *end = str;
        while (*end && (*end != '"' || !quote) && (*end != ',' || quote)) {
            end++;
        }
        moloch_field_string_add(userField, session, str, end - str, TRUE);
    }
}
Пример #4
0
LOCAL int irc_parser(MolochSession_t *session, void *uw, const unsigned char *data, int remaining, int which)
{
    IRCInfo_t *irc = uw;

    if (which == 1)
        return 0;

    while (remaining) {
        if (irc->ircState & 0x1) {
            unsigned char *newline = memchr(data, '\n', remaining);
            if (newline) {
                irc->ircState &= ~ 0x1;
                remaining -= (newline - data) +1;
                data = newline+1;
                while (remaining > 0 && *data == 0) { // Some irc clients have 0's after new lines
                    remaining--;
                    data++;
                }
            } else {
                return 0;
            }
        }

        if (remaining > 5 && memcmp("JOIN ", data, 5) == 0) {
            const unsigned char *end = data + remaining;
            const unsigned char *ptr = data + 5;

            while (ptr < end && *ptr != ' ' && *ptr != '\r' && *ptr != '\n') {
                ptr++;
            }

            moloch_field_string_add(channelsField, session, (char*)data + 5, ptr - data - 5, TRUE);
        }

        if (remaining > 5 && memcmp("NICK ", data, 5) == 0) {
            const unsigned char *end = data + remaining;
            const unsigned char *ptr = data + 5;

            while (ptr < end && *ptr != ' ' && *ptr != '\r' && *ptr != '\n') {
                ptr++;
            }

            moloch_field_string_add(nickField, session, (char*)data + 5, ptr - data - 5, TRUE);
        }

        if (remaining > 0) {
            irc->ircState |=  0x1;
        }
    }

    return 0;
}
Пример #5
0
LOCAL int quic_chlo_parser(MolochSession_t *session, BSB dbsb) {

    guchar *tag = 0;
    int     tagLen = 0;
    BSB_LIMPORT_ptr(dbsb, tag, 4);
    BSB_LIMPORT_u16(dbsb, tagLen);
    BSB_LIMPORT_skip(dbsb, 2);

    if (BSB_IS_ERROR(dbsb)) {
        return 0;
    }

    moloch_session_add_protocol(session, "quic");

    if (!tag || memcmp(tag, "CHLO", 4) != 0) {
        return 0;
    }

    guchar *tagDataStart = dbsb.buf + tagLen*8 + 8;
    uint32_t dlen = BSB_REMAINING(dbsb);

    uint32_t start = 0;
    while (!BSB_IS_ERROR(dbsb) && BSB_REMAINING(dbsb) && tagLen > 0) {
        guchar   *subTag = 0;
        uint32_t  endOffset = 0;

        BSB_LIMPORT_ptr(dbsb, subTag, 4);
        BSB_LIMPORT_u32(dbsb, endOffset);

        if (endOffset > dlen || start > dlen || start > endOffset)
            return 1;

        if (!subTag)
            return 1;

        if (memcmp(subTag, "SNI\x00", 4) == 0) {
            moloch_field_string_add(hostField, session, (char *)tagDataStart+start, endOffset-start, TRUE);
        } else if (memcmp(subTag, "UAID", 4) == 0) {
            moloch_field_string_add(uaField, session, (char *)tagDataStart+start, endOffset-start, TRUE);
        } else if (memcmp(subTag, "VER\x00", 4) == 0) {
            moloch_field_string_add(versionField, session, (char *)tagDataStart+start, endOffset-start, TRUE);
        } else {
            //LOG("Subtag: %4.4s len: %d %.*s", subTag, endOffset-start, endOffset-start, tagDataStart+start);
        }
        start = endOffset;
        tagLen--;
    }
    return 1;
}
Пример #6
0
Файл: irc.c Проект: abpin/moloch
int irc_parser(MolochSession_t *session, void *uw, const unsigned char *data, int remaining)
{
    IRCInfo_t *irc = uw;

    if (session->which == 1)
        return 0;

    while (remaining) {
        if (irc->ircState & 0x1) {
            unsigned char *newline = memchr(data, '\n', remaining);
            if (newline) {
                remaining -= (newline - data) +1;
                data = newline+1;
                irc->ircState &= ~ 0x1;
            } else {
                return 0;
            }
        }

        if (remaining > 5 && memcmp("JOIN ", data, 5) == 0) {
            const unsigned char *end = data + remaining;
            const unsigned char *ptr = data + 5;

            while (ptr < end && *ptr != ' ' && *ptr != '\r' && *ptr != '\n') {
                ptr++;
            }

            moloch_field_string_add(MOLOCH_FIELD_IRC_CHANNELS, session, (char*)data + 5, ptr - data - 5, TRUE);
        }

        if (remaining > 5 && memcmp("NICK ", data, 5) == 0) {
            const unsigned char *end = data + remaining;
            const unsigned char *ptr = data + 5;

            while (ptr < end && *ptr != ' ' && *ptr != '\r' && *ptr != '\n') {
                ptr++;
            }

            moloch_field_string_add(MOLOCH_FIELD_IRC_NICK, session, (char*)data + 5, ptr - data - 5, TRUE);
        }

        if (remaining > 0) {
            irc->ircState |=  0x1;
        }
    }

    return 0;
}
Пример #7
0
/* wireshark: k5.asn which based on http://www.h5l.org/dist/src/heimdal-1.2.tar.gz
--KDC-REQ-BODY ::= SEQUENCE {
--      kdc-options[0]          KDCOptions,
--      cname[1]                PrincipalName OPTIONAL, - - Used only in AS-REQ
--      realm[2]                Realm,  - - Server's realm
                                        -- Also client's in AS-REQ
--      sname[3]                PrincipalName OPTIONAL,
--      from[4]                 KerberosTime OPTIONAL,
--      till[5]                 KerberosTime OPTIONAL,
--      rtime[6]                KerberosTime OPTIONAL,
--      nonce[7]                Krb5int32,
--      etype[8]                SEQUENCE OF ENCTYPE, - - EncryptionType,
                                        -- in preference order
--      addresses[9]            HostAddresses OPTIONAL,
--      enc-authorization-data[10] EncryptedData OPTIONAL,
                                        -- Encrypted AuthorizationData encoding
--      additional-tickets[11]  SEQUENCE OF Ticket OPTIONAL
--}
*/
LOCAL void krb5_parse_req_body(MolochSession_t *session, const unsigned char *data, int len)
{
    MolochASNSeq_t seq[12];

    int num = moloch_parsers_asn_get_sequence(seq, 12, data, len, TRUE);
    if (num < 2)
        return;
    int i;
    int vlen;
    const char *value;
    for (i = 0; i < num; i++) {
        switch (seq[i].tag) {
        case 1:
            krb5_parse_principal_name(session, cnameField, seq[i].value, seq[i].len);
            break;
        case 2:
            value = moloch_parsers_asn_sequence_to_string(&seq[i], &vlen);
            moloch_field_string_add(realmField, session, value, vlen, TRUE);
            break;
        case 3:
            krb5_parse_principal_name(session, snameField, seq[i].value, seq[i].len);
            break;
        }
    }
}
Пример #8
0
void wise_process_ops(MolochSession_t *session, WiseItem_t *wi)
{
    int i;
    for (i = 0; i < wi->numOps; i++) {
        WiseOp_t *op = &(wi->ops[i]);
        switch (config.fields[op->fieldPos]->type) {
        case  MOLOCH_FIELD_TYPE_INT_HASH:
            if (op->fieldPos == tagsField) {
                moloch_nids_add_tag(session, op->str);
                continue;
            }
            // Fall Thru
        case  MOLOCH_FIELD_TYPE_INT:
        case  MOLOCH_FIELD_TYPE_INT_ARRAY:
        case  MOLOCH_FIELD_TYPE_IP:
        case  MOLOCH_FIELD_TYPE_IP_HASH:
            moloch_field_int_add(op->fieldPos, session, op->strLenOrInt);
            break;
        case  MOLOCH_FIELD_TYPE_STR:
        case  MOLOCH_FIELD_TYPE_STR_ARRAY:
        case  MOLOCH_FIELD_TYPE_STR_HASH:
            moloch_field_string_add(op->fieldPos, session, op->str, op->strLenOrInt, TRUE);
            break;
        }
    }
}
Пример #9
0
void
http_add_value(MolochSession_t *session, HTTPInfo_t *http)
{
    int                    pos  = http->pos[session->which];
    char                  *s    = http->valueString[session->which]->str;
    int                    l    = http->valueString[session->which]->len;

    while (isspace(*s)) {
        s++;
        l--;
    }


    switch (config.fields[pos]->type) {
    case MOLOCH_FIELD_TYPE_INT:
    case MOLOCH_FIELD_TYPE_INT_ARRAY:
    case MOLOCH_FIELD_TYPE_INT_HASH:
        moloch_field_int_add(pos, session, atoi(s));
        g_string_free(http->valueString[session->which], TRUE);
        break;
    case MOLOCH_FIELD_TYPE_STR:
    case MOLOCH_FIELD_TYPE_STR_ARRAY:
    case MOLOCH_FIELD_TYPE_STR_HASH:
        moloch_field_string_add(pos, session, s, l, TRUE);
        g_string_free(http->valueString[session->which], TRUE);
        break;
    case MOLOCH_FIELD_TYPE_IP_HASH:
    {
        int i;
        gchar **parts = g_strsplit(http->valueString[session->which]->str, ",", 0);

        for (i = 0; parts[i]; i++) {
            gchar *ip = parts[i];
            while (*ip == ' ')
                ip++;

            in_addr_t ia = inet_addr(ip);
            if (ia == 0 || ia == 0xffffffff) {
                moloch_nids_add_tag(session, "http:bad-xff");
                LOG("ERROR - Didn't understand ip: %s %s %d", http->valueString[session->which]->str, ip, ia);
                continue;
            }

            moloch_field_int_add(pos, session, ia);
        }

        g_strfreev(parts);
        g_string_free(http->valueString[session->which], TRUE);
        break;
    }
    } /* SWITCH */


    http->valueString[session->which] = 0;
    http->pos[session->which] = 0;
}
Пример #10
0
void tls_process_server_hello(MolochSession_t *session, const unsigned char *data, int len)
{
    BSB bsb;
    BSB_INIT(bsb, data, len);

    unsigned char *ver;
    BSB_IMPORT_ptr(bsb, ver, 2);

    BSB_IMPORT_skip(bsb, 32);     // Random

    int skiplen = 0;
    BSB_IMPORT_u08(bsb, skiplen);   // Session Id Length
    BSB_IMPORT_skip(bsb, skiplen);  // Session Id

    unsigned char *cipher;
    BSB_IMPORT_ptr(bsb, cipher, 2);

    if (!BSB_IS_ERROR(bsb)) {
        char str[100];
        if (ver[0] == 3) {
            switch (ver[1]) {
            case 0:
                moloch_field_string_add(verField, session, "SSLv3", 5, TRUE);
                break;
            case 1:
                moloch_field_string_add(verField, session, "TLSv1", 5, TRUE);
                break;
            case 2:
                moloch_field_string_add(verField, session, "TLSv1.1", 7, TRUE);
                break;
            case 3:
                moloch_field_string_add(verField, session, "TLSv1.2", 7, TRUE);
                break;
            default:
                snprintf(str, sizeof(str), "0x%02x.%02x", ver[0], ver[1]);
                moloch_field_string_add(verField, session, str, 6, TRUE);
            }
        } else {
            snprintf(str, sizeof(str), "0x%02x.%02x", ver[0], ver[1]);
            moloch_field_string_add(verField, session, str, 7, TRUE);
        }


        char *cipherStr = ciphers[cipher[0]][cipher[1]];
        if (cipherStr)
            moloch_field_string_add(cipherField, session, cipherStr, -1, TRUE);
        else {
            snprintf(str, sizeof(str), "%02X%02X", cipher[0], cipher[1]);
            moloch_field_string_add(cipherField, session, str, 4, TRUE);
        }
    }
}
Пример #11
0
int socks4_parser(MolochSession_t *session, void *uw, const unsigned char *data, int remaining)
{
    SocksInfo_t            *socks          = uw;

    switch(socks->state4) {
    case SOCKS4_STATE_REPLY:
        if (session->which == socks->which)
            return 0;
        if (remaining >= 8 && data[0] == 0 && data[1] >= 0x5a && data[1] <= 0x5d) {
            if (socks->ip)
                moloch_field_int_add(ipField, session, socks->ip);
            moloch_field_int_add(portField, session, socks->port);
            moloch_nids_add_tag(session, "protocol:socks");
            moloch_nids_add_protocol(session, "socks");

            if (socks->user) {
                if (!moloch_field_string_add(userField, session, socks->user, socks->userlen, FALSE)) {
                    g_free(socks->user);
                }
                socks->user = 0;
            }
            if (socks->host) {
                if (!moloch_field_string_add(hostField, session, socks->host, socks->hostlen, FALSE)) {
                    g_free(socks->host);
                }
                socks->host = 0;
            }
            moloch_parsers_classify_tcp(session, data+8, remaining-8);
            socks->state4 = SOCKS4_STATE_DATA;
            return 8;
        }
        break;
    case SOCKS4_STATE_DATA:
        if (session->which != socks->which)
            return 0;
        moloch_parsers_classify_tcp(session, data, remaining);
        moloch_parsers_unregister(session, uw);
        break;
    }

    return 0;
}
Пример #12
0
int
moloch_hp_cb_on_headers_complete (http_parser *parser)
{
    HTTPInfo_t            *http = parser->data;
    MolochSession_t       *session = http->session;
    char                   tag[200];
    char                   version[20];


#ifdef HTTPDEBUG
    LOG("HTTPDEBUG: which: %d code: %d method: %d", session->which, parser->status_code, parser->method);
#endif

    int len = snprintf(version, sizeof(version), "%d.%d", parser->http_major, parser->http_minor);

    if (parser->status_code == 0) {
#ifndef REMOVEOLD
        snprintf(tag, sizeof(tag), "http:method:%s", http_method_str(parser->method));
        moloch_nids_add_tag(session, tag);
#endif
        moloch_field_string_add(methodField, session, http_method_str(parser->method), -1, TRUE);
        moloch_field_string_add(verReqField, session, version, len, TRUE);
    } else {
#ifndef REMOVEOLD
        snprintf(tag, sizeof(tag), "http:statuscode:%d", parser->status_code);
        moloch_nids_add_tag(session, tag);
#endif
        moloch_field_int_add(statuscodeField, session, parser->status_code);
        moloch_field_string_add(verResField, session, version, len, TRUE);
    }

    if (http->inValue & (1 << session->which) && http->pos[session->which]) {
        http_add_value(session, http);
    }

    if (pluginsCbs & MOLOCH_PLUGIN_HP_OHC)
        moloch_plugins_cb_hp_ohc(session, parser);

    return 0;
}
Пример #13
0
void moloch_session_add_tag(MolochSession_t *session, const char *tag) {
    moloch_session_incr_outstanding(session);
    moloch_db_get_tag(session, config.tagsField, tag, moloch_session_get_tag_cb);
    moloch_field_string_add(config.tagsStringField, session, tag, -1, TRUE);

    if (session->stopSaving == 0 && HASH_COUNT(s_, config.dontSaveTags)) {
        MolochString_t *tstring;

        HASH_FIND(s_, config.dontSaveTags, tag, tstring);
        if (tstring) {
            session->stopSaving = (int)(long)tstring->uw;
        }
    }
}
Пример #14
0
/* wireshark: k5.asn which based on http://www.h5l.org/dist/src/heimdal-1.2.tar.gz
--PrincipalName ::= SEQUENCE {
--      name-type[0]            NAME-TYPE,
--      name-string[1]          SEQUENCE OF GeneralString
--}
 */
LOCAL void krb5_parse_principal_name(MolochSession_t *session, int field, const unsigned char *data, int len)
{
    MolochASNSeq_t seq[10];

    int num = moloch_parsers_asn_get_sequence(seq, 2, data, len, TRUE);

    if (num < 2 || seq[1].tag != 1)
        return;

    num = moloch_parsers_asn_get_sequence(seq, 2, seq[1].value, seq[1].len, TRUE);

    int len0, len1;
    const char *value0, *value1;
    if (num == 1) {
        value0 = moloch_parsers_asn_sequence_to_string(&seq[0], &len0);
        moloch_field_string_add(field, session, value0, len0, TRUE);
    } else if (num == 2) {
        char str[255];
        value0 = moloch_parsers_asn_sequence_to_string(&seq[0], &len0);
        value1 = moloch_parsers_asn_sequence_to_string(&seq[1], &len1);
        snprintf(str, 255, "%.*s/%.*s", len0, value0, len1, value1);
        moloch_field_string_add(field, session, str, len0 + 1 + len1, TRUE);
    }
}
Пример #15
0
LOCAL int mysql_parser(MolochSession_t *session, void *uw, const unsigned char *data, int len, int which)
{
    Info_t *info = uw;
    if (which != 0) {
        return 0;
    }

    if (info->ssl) {
        moloch_parsers_classify_tcp(session, data, len, which);
        moloch_parsers_unregister(session, info);
        return 0;
    }

    if (len < 35 || data[1] != 0 || data[2] != 0 || data[3] > 2) {
        moloch_parsers_unregister(session, info);
        return 0;
    }

    unsigned char *ptr = (unsigned char*)data + 36;
    unsigned char *end = (unsigned char*)data + len;

    while (ptr < end) {
        if (*ptr == 0)
            break;
        if (!isprint(*ptr)) {
            moloch_parsers_unregister(session, info);
            return 0;
        }
        ptr++;
    }

    moloch_session_add_protocol(session, "mysql");
    moloch_field_string_add(versionField, session, info->version, info->versionLen, FALSE);
    info->version = 0;

    if (ptr > data + 36) {
        moloch_field_string_add_lower(userField, session, (char*)data+36, ptr - (data + 36));
    }

    if (data[5] & 0x08) { //CLIENT_SSL
        info->ssl = 1;
    } else {
        moloch_parsers_unregister(session, info);
    }
    return 0;
}
Пример #16
0
int
moloch_hp_cb_on_message_complete (http_parser *parser)
{
    HTTPInfo_t            *http = parser->data;
    MolochSession_t       *session = http->session;

#ifdef HTTPDEBUG
    LOG("HTTPDEBUG: which: %d", http->which);
#endif

    if (pluginsCbs & MOLOCH_PLUGIN_HP_OMC)
        moloch_plugins_cb_hp_omc(session, parser);

    if (http->inBody & (1 << http->which)) {
        const char *md5 = g_checksum_get_string(http->checksum[http->which]);
        moloch_field_string_add(md5Field, session, (char*)md5, 32, TRUE);
    }

    return 0;
}
Пример #17
0
static int MS_add_string(lua_State *L)
{
    if (config.debug > 2)
        molua_stackDump(L);

    if (lua_gettop(L) != 3 || !lua_isuserdata(L, 1) || !(lua_isstring(L, 2) || lua_isinteger(L, 2)) || !lua_isstring(L, 3)) {
        return luaL_error(L, "usage: <session> <field string or field num(faster)> <string>");
    }

    MolochSession_t *session = checkMolochSession(L, 1);
    const char      *string  = lua_tostring(L, 3);
    int              len     = lua_rawlen(L, 3);
    int              pos;
    if (lua_isinteger(L, 2)) {
        pos = lua_tointeger(L, 2);
    } else {
        pos = moloch_field_by_exp(lua_tostring(L, 2));
    }
    gboolean result;
    result = moloch_field_string_add(pos, session, string, len, TRUE);
    lua_pushboolean(L, result);

    return 1;
}
Пример #18
0
int socks5_parser(MolochSession_t *session, void *uw, const unsigned char *data, int remaining, int which)
{
    SocksInfo_t            *socks          = uw;
    int                     consumed;

    //LOG("%d %d %d", which, socks->which, socks->state5[which]);
    //moloch_print_hex_string(data, remaining);

    switch(socks->state5[which]) {
    case SOCKS5_STATE_VER_REQUEST:
        if (data[2] == 0) {
            socks->state5[which] = SOCKS5_STATE_CONN_REQUEST;
        } else {
            socks->state5[which] = SOCKS5_STATE_USER_REQUEST;
        }
        socks->state5[(which+1)%2] = SOCKS5_STATE_VER_REPLY;
        break;
    case SOCKS5_STATE_VER_REPLY:
        if (remaining != 2 || data[0] != 5 || data[1] > 2) {
            moloch_parsers_unregister(session, uw);
            return 0;
        }

        moloch_nids_add_protocol(session, "socks");

        if (socks->state5[socks->which] == SOCKS5_STATE_CONN_DATA) {
            // Other side of connection already in data state
            socks->state5[which] = SOCKS5_STATE_CONN_REPLY;
        } else if (data[1] == 0) {
            socks->state5[socks->which] = SOCKS5_STATE_CONN_REQUEST;
            socks->state5[which] = SOCKS5_STATE_CONN_REPLY;
        } else if (data[1] == 2) {
            socks->state5[socks->which] = SOCKS5_STATE_USER_REQUEST;
            socks->state5[which] = SOCKS5_STATE_USER_REPLY;
        } else {
            // We don't handle other auth methods
            moloch_parsers_unregister(session, uw);
        }


        return 2;
    case SOCKS5_STATE_USER_REQUEST:
        if ((2 + data[1] > (int)remaining) || (2 + data[1] + 1 + data[data[1]+2]  > (int)remaining)) {
            moloch_parsers_unregister(session, uw);
            return 0;
        }

        moloch_field_string_add(userField, session, (char *)data + 2, data[1], TRUE);
        moloch_nids_add_tag(session, "socks:password");
        socks->state5[which] = SOCKS5_STATE_CONN_REQUEST;
        return data[1] + 1 + data[data[1]+2];
    case SOCKS5_STATE_USER_REPLY:
        socks->state5[which] = SOCKS5_STATE_CONN_REPLY;
        return 2;
    case SOCKS5_STATE_CONN_REQUEST:
        if (remaining < 6 || data[0] != 5 || data[1] != 1 || data[2] != 0) {
            moloch_parsers_unregister(session, uw);
            return 0;
        }

        socks->state5[which] = SOCKS5_STATE_CONN_DATA;
        if (data[3] == 1) { // IPV4
            socks->port = (data[8]&0xff) << 8 | (data[9]&0xff);
            memcpy(&socks->ip, data+4, 4);
            moloch_field_int_add(ipField, session, socks->ip);
            moloch_field_int_add(portField, session, socks->port);
            consumed = 4 + 4 + 2;
        } else if (data[3] == 3) { // Domain Name
            socks->port = (data[5+data[4]]&0xff) << 8 | (data[6+data[4]]&0xff);
            char *lower = g_ascii_strdown((char*)data+5, data[4]);
            if (!moloch_field_string_add(hostField, session, lower, data[4], FALSE)) {
                g_free(lower);
            }
            moloch_field_int_add(portField, session, socks->port);
            consumed = 4 + 1 + data[4] + 2;
        } else if (data[3] == 4) { // IPV6
            consumed = 4 + 16 + 2;
        } else {
            break;
        }

        moloch_parsers_classify_tcp(session, data+consumed, remaining-consumed, which);
        return consumed;
    case SOCKS5_STATE_CONN_REPLY: {
        if (remaining < 6) {
            moloch_parsers_unregister(session, uw);
            return 0;
        }

        socks->state5[which] = SOCKS5_STATE_CONN_DATA;
        if (data[3] == 1) { // IPV4
            consumed = 4 + 4 + 2;
        } else if (data[3] == 3) { // Domain Name
            consumed = 4 + 1 + data[4] + 2;
        } else if (data[3] == 4) { // IPV6
            consumed = 4 + 16 + 2;
        } else {
            break;
        }
        moloch_parsers_classify_tcp(session, data+consumed, remaining-consumed, which);
        return consumed;
    }
    case SOCKS5_STATE_CONN_DATA:
        moloch_parsers_classify_tcp(session, data, remaining, which);
        moloch_parsers_unregister(session, uw);
        return 0;
    default:
        moloch_parsers_unregister(session, uw);
    }

    return 0;
}
Пример #19
0
void
tls_process_client(MolochSession_t *session, const unsigned char *data, int len)
{
    BSB sslbsb;

    BSB_INIT(sslbsb, data, len);

    if (BSB_REMAINING(sslbsb) > 5) {
        unsigned char *ssldata = BSB_WORK_PTR(sslbsb);
        int            ssllen = MIN(BSB_REMAINING(sslbsb) - 5, ssldata[3] << 8 | ssldata[4]);

        BSB pbsb;
        BSB_INIT(pbsb, ssldata+5, ssllen);

        if (BSB_REMAINING(pbsb) > 7) {
            unsigned char *pdata = BSB_WORK_PTR(pbsb);
            int            plen = MIN(BSB_REMAINING(pbsb) - 4, pdata[2] << 8 | pdata[3]);

            BSB cbsb;
            BSB_INIT(cbsb, pdata+6, plen-2); // The - 4 for plen is done above, confusing

            if(BSB_REMAINING(cbsb) > 32) {
                BSB_IMPORT_skip(cbsb, 32);     // Random

                int skiplen = 0;
                BSB_IMPORT_u08(cbsb, skiplen);   // Session Id Length
                BSB_IMPORT_skip(cbsb, skiplen);  // Session Id

                BSB_IMPORT_u16(cbsb, skiplen);   // Ciper Suites Length
                BSB_IMPORT_skip(cbsb, skiplen);  // Ciper Suites

                BSB_IMPORT_u08(cbsb, skiplen);   // Compression Length
                BSB_IMPORT_skip(cbsb, skiplen);  // Compressions

                if (BSB_REMAINING(cbsb) > 2) {
                    int etotlen = 0;
                    BSB_IMPORT_u16(cbsb, etotlen);  // Extensions Length

                    etotlen = MIN(etotlen, BSB_REMAINING(cbsb));

                    BSB ebsb;
                    BSB_INIT(ebsb, BSB_WORK_PTR(cbsb), etotlen);

                    while (BSB_REMAINING(ebsb) > 0) {
                        int etype = 0, elen = 0;

                        BSB_IMPORT_u16 (ebsb, etype);
                        BSB_IMPORT_u16 (ebsb, elen);
                        if (etype != 0) {
                            BSB_IMPORT_skip (ebsb, elen);
                            continue;
                        }

                        if (elen > BSB_REMAINING(ebsb))
                            break;

                        BSB snibsb;
                        BSB_INIT(snibsb, BSB_WORK_PTR(ebsb), elen);
                        BSB_IMPORT_skip (ebsb, elen);

                        int sni = 0;
                        BSB_IMPORT_u16(snibsb, sni); // list len
                        if (sni != BSB_REMAINING(snibsb))
                            continue;

                        BSB_IMPORT_u08(snibsb, sni); // type
                        if (sni != 0)
                            continue;

                        BSB_IMPORT_u16(snibsb, sni); // len
                        if (sni != BSB_REMAINING(snibsb))
                            continue;

                        moloch_field_string_add(hostField, session, (char *)BSB_WORK_PTR(snibsb), sni, TRUE);
                    }
                }
            }
        }

        BSB_IMPORT_skip(sslbsb, ssllen + 5);
    }
}
Пример #20
0
void moloch_session_add_protocol(MolochSession_t *session, const char *protocol)
{
    moloch_field_string_add(protocolField, session, protocol, -1, TRUE);
}
Пример #21
0
int
moloch_hp_cb_on_headers_complete (http_parser *parser)
{
    HTTPInfo_t            *http = parser->data;
    MolochSession_t       *session = http->session;
    char                   tag[200];
    char                   version[20];


#ifdef HTTPDEBUG
    LOG("HTTPDEBUG: which: %d code: %d method: %d", http->which, parser->status_code, parser->method);
#endif

    int len = snprintf(version, sizeof(version), "%d.%d", parser->http_major, parser->http_minor);

    if (parser->status_code == 0) {
#ifndef REMOVEOLD
        snprintf(tag, sizeof(tag), "http:method:%s", http_method_str(parser->method));
        moloch_nids_add_tag(session, tag);
#endif
        moloch_field_string_add(methodField, session, http_method_str(parser->method), -1, TRUE);
        moloch_field_string_add(verReqField, session, version, len, TRUE);
    } else {
#ifndef REMOVEOLD
        snprintf(tag, sizeof(tag), "http:statuscode:%d", parser->status_code);
        moloch_nids_add_tag(session, tag);
#endif
        moloch_field_int_add(statuscodeField, session, parser->status_code);
        moloch_field_string_add(verResField, session, version, len, TRUE);
    }

    if (http->inValue & (1 << http->which) && http->pos[http->which]) {
        http_add_value(session, http);
    }

    http->header[0][0] = http->header[1][0] = 0;

    if (http->urlString) {
        char *ch = http->urlString->str;
        while (*ch) {
            if (*ch < 32) {
                moloch_nids_add_tag(session, "http:control-char");
                break;
            }
            ch++;
        }
    }

    if (http->cookieString && http->cookieString->str[0]) {
        char *start = http->cookieString->str;
        while (1) {
            while (isspace(*start)) start++;
            char *equal = strchr(start, '=');
            if (!equal)
                break;
            moloch_field_string_add(cookieKeyField, session, start, equal-start, TRUE);
            start = strchr(equal+1, ';');
            if(!start)
                break;
            start++;
        }
        g_string_truncate(http->cookieString, 0);
    }

    if (http->authString && http->authString->str[0]) {
        moloch_http_parse_authorization(session, http->authString->str);
        g_string_truncate(http->authString, 0);
    }

    if (http->hostString) {
        g_string_ascii_down(http->hostString);
    }

    if (http->urlString && http->hostString) {
        char *colon = strchr(http->hostString->str+2, ':');
        if (colon) {
            moloch_field_string_add(hostField, session, http->hostString->str+2, colon - http->hostString->str-2, TRUE);
        } else {
            moloch_field_string_add(hostField, session, http->hostString->str+2, http->hostString->len-2, TRUE);
        }

        char *question = strchr(http->urlString->str, '?');
        if (question) {
            moloch_field_string_add(pathField, session, http->urlString->str, question - http->urlString->str, TRUE);
            char *start = question+1;
            char *ch;
            int   field = keyField;
            for (ch = start; *ch; ch++) {
                if (*ch == '&') {
                    if (ch != start && (config.parseQSValue || field == keyField)) {
                        char *str = g_uri_unescape_segment(start, ch, NULL);
                        if (!str) {
                            moloch_field_string_add(field, session, start, ch-start, TRUE);
                        } else if (!moloch_field_string_add(field, session, str, strlen(str), FALSE)) {
                            g_free(str);
                        }
                    }
                    start = ch+1;
                    field = keyField;
                    continue;
                } else if (*ch == '=') {
                    if (ch != start && (config.parseQSValue || field == keyField)) {
                        char *str = g_uri_unescape_segment(start, ch, NULL);
                        if (!str) {
                            moloch_field_string_add(field, session, start, ch-start, TRUE);
                        } else if (!moloch_field_string_add(field, session, str, strlen(str), FALSE)) {
                            g_free(str);
                        }
                    }
                    start = ch+1;
                    field = valueField;
                }
            }
            if (config.parseQSValue && field == valueField && ch > start) {
                char *str = g_uri_unescape_segment(start, ch, NULL);
                if (!str) {
                    moloch_field_string_add(field, session, start, ch-start, TRUE);
                } else if (!moloch_field_string_add(field, session, str, strlen(str), FALSE)) {
                    g_free(str);
                }
            }
        } else {
            moloch_field_string_add(pathField, session, http->urlString->str, http->urlString->len, TRUE);
        }

        if (http->urlString->str[0] != '/') {
            char *result = strstr(http->urlString->str, http->hostString->str+2);

            /* If the host header is in the first 8 bytes of url then just use the url */
            if (result && result - http->urlString->str <= 8) {
                moloch_field_string_add(urlsField, session, http->urlString->str, http->urlString->len, FALSE);
                g_string_free(http->urlString, FALSE);
                g_string_free(http->hostString, TRUE);
            } else {
                /* Host header doesn't match the url */
                g_string_append(http->hostString, ";");
                g_string_append(http->hostString, http->urlString->str);
                moloch_field_string_add(urlsField, session, http->hostString->str, http->hostString->len, FALSE);
                g_string_free(http->urlString, TRUE);
                g_string_free(http->hostString, FALSE);
            }
        } else {
            /* Normal case, url starts with /, so no extra host in url */
            g_string_append(http->hostString, http->urlString->str);
            moloch_field_string_add(urlsField, session, http->hostString->str, http->hostString->len, FALSE);
            g_string_free(http->urlString, TRUE);
            g_string_free(http->hostString, FALSE);
        }

        http->urlString = NULL;
        http->hostString = NULL;
    } else if (http->urlString) {
        moloch_field_string_add(urlsField, session, http->urlString->str, http->urlString->len, FALSE);
        g_string_free(http->urlString, FALSE);


        http->urlString = NULL;
    } else if (http->hostString) {
        char *colon = strchr(http->hostString->str+2, ':');
        if (colon) {
            moloch_field_string_add(hostField, session, http->hostString->str+2, colon - http->hostString->str-2, TRUE);
        } else {
            moloch_field_string_add(hostField, session, http->hostString->str+2, http->hostString->len-2, TRUE);
        }

        g_string_free(http->hostString, TRUE);
        http->hostString = NULL;
    }

    moloch_nids_add_tag(session, "protocol:http");
    moloch_nids_add_protocol(session, "http");

    if (pluginsCbs & MOLOCH_PLUGIN_HP_OHC)
        moloch_plugins_cb_hp_ohc(session, parser);

    return 0;
}
Пример #22
0
int radius_udp_parser(MolochSession_t *session, void *UNUSED(uw), const unsigned char *data, int len, int UNUSED(which))
{
    BSB bsb;

    BSB_INIT(bsb, data, len);

    BSB_IMPORT_skip(bsb, 20);

    unsigned char type = 0, length = 0;
    unsigned char *value;
    char str[256];
    struct in_addr in;
    int i;

    while (BSB_REMAINING(bsb) > 2) {
        BSB_IMPORT_u08(bsb, type);
        BSB_IMPORT_u08(bsb, length);
        length -= 2; // length includes the type/length
        BSB_IMPORT_ptr(bsb, value, length);
        if (BSB_IS_ERROR(bsb)) {
            break;
        }
        switch (type) {
        case 1:
            moloch_field_string_add(userField, session, (char *)value, length, TRUE);
            break;
    /*    case 4:
            LOG("NAS-IP-Address: %d %d %u.%u.%u.%u", type, length, value[0], value[1], value[2], value[3]);
            break;*/
        case 8:
            memcpy(&in.s_addr, value, 4);
            moloch_field_int_add(framedIpField, session, in.s_addr);
            break;
        case 31:
            if (length == 12) {
                snprintf(str, sizeof(str), "%c%c:%c%c:%c%c:%c%c:%c%c:%c%c",
                        value[0], value[1],
                        value[2], value[3],
                        value[4], value[5],
                        value[6], value[7],
                        value[8], value[9],
                        value[10], value[11]);
                for (i = 0; i < 17; i++) {
                    if (isupper (str[i]))
                      str[i] = tolower (str[i]);
                }
                moloch_field_string_add(macField, session, str, 17, TRUE);
            }
            break;
        case 66:
            memcpy(str, value, length);
            str[length] = 0;
            inet_aton(str, &in);
            moloch_field_int_add(endpointIpField, session, in.s_addr);
            break;

/*        default:
            LOG("%d %d %.*s", type, length, length, value);*/
        }
    }
    return 0;
}
Пример #23
0
int
moloch_hp_cb_on_message_complete (http_parser *parser)
{
    HTTPInfo_t            *http = parser->data;
    MolochSession_t       *session = http->session;

#ifdef HTTPDEBUG
    LOG("HTTPDEBUG: which: %d", session->which);
#endif

    if (pluginsCbs & MOLOCH_PLUGIN_HP_OMC)
        moloch_plugins_cb_hp_omc(session, parser);

    http->header[0][0] = http->header[1][0] = 0;

    if (http->urlString) {
        char *ch = http->urlString->str;
        while (*ch) {
            if (*ch < 32) {
                moloch_nids_add_tag(session, "http:control-char");
                break;
            }
            ch++;
        }
    }

    if (http->hostString) {
        g_string_ascii_down(http->hostString);
    }

    if (http->urlString && http->hostString) {
        char *colon = strchr(http->hostString->str+2, ':');
        if (colon) {
            moloch_field_string_add(hostField, session, http->hostString->str+2, colon - http->hostString->str-2, TRUE);
        } else {
            moloch_field_string_add(hostField, session, http->hostString->str+2, http->hostString->len-2, TRUE);
        }

        char *question = strchr(http->urlString->str, '?');
        if (question) {
            moloch_field_string_add(pathField, session, http->urlString->str, question - http->urlString->str, TRUE);
            char *start = question+1;
            char *ch;
            int   field = keyField;
            for (ch = start; *ch; ch++) {
                if (*ch == '&') {
                    if (ch != start && (config.parseQSValue || field == keyField)) {
                        char *str = g_uri_unescape_segment(start, ch, NULL);
                        if (!str) {
                            moloch_field_string_add(field, session, start, ch-start, TRUE);
                        } else if (!moloch_field_string_add(field, session, str, strlen(str), FALSE)) {
                            g_free(str);
                        }
                    }
                    start = ch+1;
                    field = keyField;
                    continue;
                } else if (*ch == '=') {
                    if (ch != start && (config.parseQSValue || field == keyField)) {
                        char *str = g_uri_unescape_segment(start, ch, NULL);
                        if (!str) {
                            moloch_field_string_add(field, session, start, ch-start, TRUE);
                        } else if (!moloch_field_string_add(field, session, str, strlen(str), FALSE)) {
                            g_free(str);
                        }
                    }
                    start = ch+1;
                    field = valueField;
                }
            }
            if (config.parseQSValue && field == valueField && ch > start) {
                char *str = g_uri_unescape_segment(start, ch, NULL);
                if (!str) {
                    moloch_field_string_add(field, session, start, ch-start, TRUE);
                } else if (!moloch_field_string_add(field, session, str, strlen(str), FALSE)) {
                    g_free(str);
                }
            }
        } else {
            moloch_field_string_add(pathField, session, http->urlString->str, http->urlString->len, TRUE);
        }

        if (http->urlString->str[0] != '/') {
            char *result = strstr(http->urlString->str, http->hostString->str+2);

            /* If the host header is in the first 8 bytes of url then just use the url */
            if (result && result - http->urlString->str <= 8) {
                moloch_field_string_add(urlsField, session, http->urlString->str, http->urlString->len, FALSE);
                g_string_free(http->urlString, FALSE);
                g_string_free(http->hostString, TRUE);
            } else {
                /* Host header doesn't match the url */
                g_string_append(http->hostString, ";");
                g_string_append(http->hostString, http->urlString->str);
                moloch_field_string_add(urlsField, session, http->hostString->str, http->hostString->len, FALSE);
                g_string_free(http->urlString, TRUE);
                g_string_free(http->hostString, FALSE);
            }
        } else {
            /* Normal case, url starts with /, so no extra host in url */
            g_string_append(http->hostString, http->urlString->str);
            moloch_field_string_add(urlsField, session, http->hostString->str, http->hostString->len, FALSE);
            g_string_free(http->urlString, TRUE);
            g_string_free(http->hostString, FALSE);
        }

        moloch_nids_add_tag(session, "protocol:http");
        moloch_nids_add_protocol(session, "http");

        http->urlString = NULL;
        http->hostString = NULL;
    } else if (http->urlString) {
        moloch_field_string_add(urlsField, session, http->urlString->str, http->urlString->len, FALSE);
        g_string_free(http->urlString, FALSE);

        moloch_nids_add_tag(session, "protocol:http");
        moloch_nids_add_protocol(session, "http");

        http->urlString = NULL;
    } else if (http->hostString) {
        char *colon = strchr(http->hostString->str+2, ':');
        if (colon) {
            moloch_field_string_add(hostField, session, http->hostString->str+2, colon - http->hostString->str-2, TRUE);
        } else {
            moloch_field_string_add(hostField, session, http->hostString->str+2, http->hostString->len-2, TRUE);
        }

        g_string_free(http->hostString, TRUE);
        http->hostString = NULL;
    }

    if (http->inBody & (1 << session->which)) {
        const char *md5 = g_checksum_get_string(http->checksum[session->which]);
        moloch_field_string_add(md5Field, session, (char*)md5, 32, TRUE);
    }

    return 0;
}
Пример #24
0
// SSH Parsing currently assumes the parts we want from a SSH Packet will be
// in a single TCP packet.  Kind of sucks.
int ssh_parser(MolochSession_t *session, void *uw, const unsigned char *data, int remaining, int which)
{
    SSHInfo_t *ssh = uw;

    if (memcmp("SSH", data, 3) == 0) {
        unsigned char *n = memchr(data, 0x0a, remaining);
        if (n && *(n-1) == 0x0d)
            n--;

        if (n) {
            int len = (n - data);

            char *str = g_ascii_strdown((char *)data, len);

            if (!moloch_field_string_add(verField, session, str, len, FALSE)) {
                g_free(str);
            }
        }
        return 0;
    }

    if (which != 1)
        return 0;

    BSB bsb;
    BSB_INIT(bsb, data, remaining);

    while (BSB_REMAINING(bsb) > 6) {
        uint32_t loopRemaining = BSB_REMAINING(bsb);

        // If 0 looking for a ssh packet, otherwise in the middle of ssh packet
        if (ssh->sshLen == 0) {
            BSB_IMPORT_u32(bsb, ssh->sshLen);

            // Can't have a ssh packet > 35000 bytes.
            if (ssh->sshLen >= 35000) {
                moloch_parsers_unregister(session, uw);
                return 0;
            }
            ssh->sshLen += 4;

            uint8_t    sshCode = 0;
            BSB_IMPORT_skip(bsb, 1); // padding length
            BSB_IMPORT_u08(bsb, sshCode);

            if (sshCode == 33) {
                moloch_parsers_unregister(session, uw);

                uint32_t keyLen = 0;
                BSB_IMPORT_u32(bsb, keyLen);

                if (!BSB_IS_ERROR(bsb) && BSB_REMAINING(bsb) >= keyLen) {
                    char *str = g_base64_encode(BSB_WORK_PTR(bsb), keyLen);
                    if (!moloch_field_string_add(keyField, session, str, (keyLen/3+1)*4, FALSE)) {
                        g_free(str);
                    }
                }
                break;
            }
        }

        if (loopRemaining > ssh->sshLen) {
            // Processed all, looking for another packet
            BSB_IMPORT_skip(bsb, loopRemaining);
            ssh->sshLen = 0;
            continue;
        } else {
            // Waiting on more data then in this callback
            ssh->sshLen -= loopRemaining;
            break;
        }
    }
    return 0;
}
Пример #25
0
void dns_parser(MolochSession_t *session, const unsigned char *data, int len) 
{

    if (len < 18)
        return;

    int qr      = (data[2] >> 7) & 0x1;
    int opcode  = (data[2] >> 3) & 0xf;

    if (opcode != 0)
        return;

    int qdcount = (data[4] << 8) | data[5];
    int ancount = (data[6] << 8) | data[7];

    if (qdcount > 10 || qdcount <= 0)
        return;

    BSB bsb;
    BSB_INIT(bsb, data + 12, len - 12);

    /* QD Section */
    int i;
    for (i = 0; BSB_NOT_ERROR(bsb) && i < qdcount; i++) {
        int namelen;
        unsigned char *name = dns_name(data, len, &bsb, &namelen);

        if (BSB_IS_ERROR(bsb))
            break;

        if (!namelen) {
            name = (unsigned char*)"<root>";
            namelen = 6;
        }

        unsigned short qtype = 0 , qclass = 0 ;
        BSB_IMPORT_u16(bsb, qtype);
        BSB_IMPORT_u16(bsb, qclass);

        char *lower = g_ascii_strdown((char*)name, namelen);

        if (qclass <= 255 && qclasses[qclass]) {
            moloch_field_string_add(queryClassField, session, qclasses[qclass], -1, TRUE);
        }

        if (qtype <= 255 && qtypes[qtype]) {
            moloch_field_string_add(queryTypeField, session, qtypes[qtype], -1, TRUE);
        }

        if (lower && !moloch_field_string_add(hostField, session, lower, namelen, FALSE)) {
            g_free(lower);
        }
    }
    moloch_nids_add_protocol(session, "dns");

    if (qr == 0)
        return;

    int rcode      = data[3] & 0xf;
    moloch_field_string_add(statusField, session, statuses[rcode], -1, TRUE);

    for (i = 0; BSB_NOT_ERROR(bsb) && i < ancount; i++) {
        int namelen;
        dns_name(data, len, &bsb, &namelen);

        if (BSB_IS_ERROR(bsb))
            break;

        uint16_t antype = 0;
        BSB_IMPORT_u16 (bsb, antype);
        uint16_t anclass = 0;
        BSB_IMPORT_u16 (bsb, anclass);
        BSB_IMPORT_skip(bsb, 4); // ttl
        uint16_t rdlength = 0;
        BSB_IMPORT_u16 (bsb, rdlength);

        if (BSB_REMAINING(bsb) < rdlength) {
            break;
        }

        if (anclass != 1) {
            BSB_IMPORT_skip(bsb, rdlength);
            continue;
        }

        switch (antype) {
        case 1: {
            if (rdlength != 4)
                break;
            struct in_addr in;
            unsigned char *ptr = BSB_WORK_PTR(bsb);
            in.s_addr = ptr[3] << 24 | ptr[2] << 16 | ptr[1] << 8 | ptr[0];

            moloch_field_int_add(ipField, session, in.s_addr);
            break;
        }
        case 5: {
            BSB rdbsb;
            BSB_INIT(rdbsb, BSB_WORK_PTR(bsb), rdlength);

            int namelen;
            unsigned char *name = dns_name(data, len, &rdbsb, &namelen);

            if (!namelen || BSB_IS_ERROR(rdbsb))
                continue;

            char *lower = g_ascii_strdown((char*)name, namelen);

            if (lower && !moloch_field_string_add(hostField, session, lower, namelen, FALSE)) {
                g_free(lower);
            }
            break;
        }
        case 15: {
            BSB rdbsb;
            BSB_INIT(rdbsb, BSB_WORK_PTR(bsb), rdlength);
            BSB_IMPORT_skip(rdbsb, 2); // preference

            int namelen;
            unsigned char *name = dns_name(data, len, &rdbsb, &namelen);

            if (!namelen || BSB_IS_ERROR(rdbsb))
                continue;

            char *lower = g_ascii_strdown((char*)name, namelen);

            if (lower && !moloch_field_string_add(hostField, session, lower, namelen, FALSE)) {
                g_free(lower);
            }
        }
        } /* switch */
        BSB_IMPORT_skip(bsb, rdlength);
    }
}