/* @data the data inside the record layer * @len the length of data inside record layer */ int tls_process_server_handshake_record(MolochSession_t *session, const unsigned char *data, int len) { BSB rbsb; BSB_INIT(rbsb, data, len); while (BSB_REMAINING(rbsb) >= 4) { unsigned char *hdata = BSB_WORK_PTR(rbsb); int hlen = MIN(BSB_REMAINING(rbsb), (hdata[1] << 16 | hdata[2] << 8 | hdata[3]) + 4); switch(hdata[0]) { case 2: tls_process_server_hello(session, hdata+4, hlen-4); break; case 11: tls_process_server_certificate(session, hdata + 4, hlen - 4); break; case 14: return 1; } BSB_IMPORT_skip(rbsb, hlen); } return 0; }
void wise_load_fields() { char key[500]; int key_len; memset(fieldsMap, -1, sizeof(fieldsMap)); key_len = snprintf(key, sizeof(key), "/fields"); size_t data_len; unsigned char *data = moloch_http_send_sync(wiseService, "GET", key, key_len, NULL, 0, NULL, &data_len);; BSB bsb; BSB_INIT(bsb, data, data_len); int ver, cnt = 0; BSB_IMPORT_u32(bsb, fieldsTS); BSB_IMPORT_u32(bsb, ver); BSB_IMPORT_u08(bsb, cnt); int i; for (i = 0; i < cnt; i++) { int len = 0; BSB_IMPORT_u16(bsb, len); // len includes NULL terminated fieldsMap[i] = moloch_field_define_text((char*)BSB_WORK_PTR(bsb), NULL); if (fieldsMap[i] == -1) fieldsTS = 0; if (config.debug) LOG("%d %d %s", i, fieldsMap[i], BSB_WORK_PTR(bsb)); BSB_IMPORT_skip(bsb, len); } }
LOCAL void krb5_parse(MolochSession_t *session, const unsigned char *data, int len) { BSB obsb; uint32_t opc, msgType, olen; unsigned char *ovalue; BSB_INIT(obsb, data, len); ovalue = moloch_parsers_asn_get_tlv(&obsb, &opc, &msgType, &olen); #ifdef KRB5_DEBUG LOG("DEBUG1 - opc:%uumsgType:%u olen:%u", opc, msgType, olen); #endif if (!opc) return; switch (msgType) { case 10: case 12: krb5_parse_req(session, ovalue, olen); break; case 11: case 13: krb5_parse_rep(session, ovalue, olen); break; case 30: krb5_parse_error(session, ovalue, olen); break; } }
unsigned char *dns_name(const unsigned char *full, int fulllen, BSB *inbsb, int *namelen) { static unsigned char name[8000]; BSB nbsb; int didPointer = 0; BSB tmpbsb; BSB *curbsb; BSB_INIT(nbsb, name, sizeof(name)); curbsb = inbsb; while (BSB_REMAINING(*curbsb)) { unsigned char ch = 0; BSB_IMPORT_u08(*curbsb, ch); if (ch == 0) break; BSB_EXPORT_rewind(*curbsb, 1); if (ch & 0xc0) { if (didPointer > 5) return 0; didPointer++; int tpos = 0; BSB_IMPORT_u16(*curbsb, tpos); tpos &= 0x3fff; BSB_INIT(tmpbsb, full+tpos, fulllen - tpos); curbsb = &tmpbsb; continue; } if (BSB_LENGTH(nbsb)) { BSB_EXPORT_u08(nbsb, '.'); } if (dns_name_element(&nbsb, curbsb) && BSB_LENGTH(nbsb)) BSB_EXPORT_rewind(nbsb, 1); // Remove last . } *namelen = BSB_LENGTH(nbsb); BSB_EXPORT_u08(nbsb, 0); return name; }
void netflow_send() { BSB hbsb; BSB_INIT(hbsb, buf, headerSize); uint32_t sys_uptime = (bufTime.tv_sec - initialPacket.tv_sec)*1000; /*+ (bufTIme.tv_usec - initialPacket.tv_usec)/1000;*/ /* Header */ BSB_EXPORT_u16(hbsb, netflowVersion); BSB_EXPORT_u16(hbsb, bufCount); // count BSB_EXPORT_u32(hbsb, sys_uptime); // sys_uptime BSB_EXPORT_u32(hbsb, bufTime.tv_sec); BSB_EXPORT_u32(hbsb, bufTime.tv_usec); switch (netflowVersion) { case 5: BSB_EXPORT_u32(hbsb, totalFlows); // flow_sequence BSB_EXPORT_u08(hbsb, 0); // engine_type BSB_EXPORT_u08(hbsb, 0); // engine_id BSB_EXPORT_u16(hbsb, 0); // mode/interval break; case 7: BSB_EXPORT_u32(hbsb, totalFlows); // flow_sequence BSB_EXPORT_u32(hbsb, 0); // reserved break; } int i; for (i = 0; i < numDests; i++) { int rc; if ((rc = send(dests[i].fd, buf, BSB_LENGTH(bsb)+headerSize, 0)) < BSB_LENGTH(bsb)+headerSize) { LOG("Failed to send rc=%d size=%ld", rc, BSB_LENGTH(bsb)+headerSize); } } totalFlows += bufCount; BSB_INIT(bsb, buf + headerSize, sizeof(buf) - headerSize); bufCount = 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); } } }
void tls_alt_names(MolochCertsInfo_t *certs, BSB *bsb, char *lastOid) { int apc, atag, alen; while (BSB_REMAINING(*bsb) >= 2) { unsigned char *value = moloch_parsers_asn_get_tlv(bsb, &apc, &atag, &alen); if (!value) return; if (apc) { BSB tbsb; BSB_INIT(tbsb, value, alen); tls_alt_names(certs, &tbsb, lastOid); if (certs->alt.s_count > 0) { return; } } else if (atag == 6) { moloch_parsers_asn_decode_oid(lastOid, 100, value, alen); if (strcmp(lastOid, "2.5.29.17") != 0) lastOid[0] = 0; } else if (lastOid[0] && atag == 4) { BSB tbsb; BSB_INIT(tbsb, value, alen); tls_alt_names(certs, &tbsb, lastOid); return; } else if (lastOid[0] && atag == 2) { MolochString_t *element = MOLOCH_TYPE_ALLOC0(MolochString_t); element->str = g_ascii_strdown((char*)value, alen); element->len = alen; DLL_PUSH_TAIL(s_, &certs->alt, element); } } lastOid[0] = 0; return; }
LOCAL void krb5_udp_classify(MolochSession_t *session, const unsigned char *data, int len, int UNUSED(which), void *UNUSED(uw)) { if (moloch_session_has_protocol(session, "krb5")) return; BSB obsb; uint32_t opc, otag, olen; BSB_INIT(obsb, data, len); moloch_parsers_asn_get_tlv(&obsb, &opc, &otag, &olen); #ifdef KRB5_DEBUG LOG("enter %u %u %u", opc, otag, olen); #endif if (opc && (otag == 10 || otag == 12 || otag == 30) && len >= (int)olen) { moloch_parsers_register(session, krb5_udp_parser, 0, 0); } }
void tls_certinfo_process(MolochCertInfo_t *ci, BSB *bsb) { int apc, atag, alen; char lastOid[1000]; lastOid[0] = 0; while (BSB_REMAINING(*bsb)) { unsigned char *value = moloch_parsers_asn_get_tlv(bsb, &apc, &atag, &alen); if (!value) return; if (apc) { BSB tbsb; BSB_INIT(tbsb, value, alen); tls_certinfo_process(ci, &tbsb); } else if (atag == 6) { moloch_parsers_asn_decode_oid(lastOid, sizeof(lastOid), value, alen); } else if (lastOid[0] && (atag == 20 || atag == 19 || atag == 12)) { /* 20 == BER_UNI_TAG_TeletexString * 19 == BER_UNI_TAG_PrintableString * 12 == BER_UNI_TAG_UTF8String */ if (strcmp(lastOid, "2.5.4.3") == 0) { MolochString_t *element = MOLOCH_TYPE_ALLOC(MolochString_t); element->utf8 = atag == 12; if (element->utf8) element->str = g_utf8_strdown((char*)value, alen); else element->str = g_ascii_strdown((char*)value, alen); DLL_PUSH_TAIL(s_, &ci->commonName, element); } else if (strcmp(lastOid, "2.5.4.10") == 0) { if (ci->orgName) { LOG("Multiple orgName %s => %.*s", ci->orgName, alen, value); free(ci->orgName); } ci->orgUtf8 = atag == 12; ci->orgName = g_strndup((char*)value, alen); } } } }
// 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; }
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); } }
void tls_process_server_certificate(MolochSession_t *session, const unsigned char *data, int len) { BSB cbsb; BSB_INIT(cbsb, data, len); BSB_IMPORT_skip(cbsb, 3); // Length again while(BSB_REMAINING(cbsb) > 3) { int badreason = 0; unsigned char *cdata = BSB_WORK_PTR(cbsb); int clen = MIN(BSB_REMAINING(cbsb) - 3, (cdata[0] << 16 | cdata[1] << 8 | cdata[2])); MolochCertsInfo_t *certs = MOLOCH_TYPE_ALLOC0(MolochCertsInfo_t); DLL_INIT(s_, &certs->alt); DLL_INIT(s_, &certs->subject.commonName); DLL_INIT(s_, &certs->issuer.commonName); int atag, alen, apc; unsigned char *value; BSB bsb; BSB_INIT(bsb, cdata + 3, clen); /* Certificate */ if (!(value = moloch_parsers_asn_get_tlv(&bsb, &apc, &atag, &alen))) {badreason = 1; goto bad_cert;} BSB_INIT(bsb, value, alen); /* signedCertificate */ if (!(value = moloch_parsers_asn_get_tlv(&bsb, &apc, &atag, &alen))) {badreason = 2; goto bad_cert;} BSB_INIT(bsb, value, alen); /* serialNumber or version*/ if (!(value = moloch_parsers_asn_get_tlv(&bsb, &apc, &atag, &alen))) {badreason = 3; goto bad_cert;} if (apc) { if (!(value = moloch_parsers_asn_get_tlv(&bsb, &apc, &atag, &alen))) {badreason = 4; goto bad_cert;} } certs->serialNumberLen = alen; certs->serialNumber = malloc(alen); memcpy(certs->serialNumber, value, alen); /* signature */ if (!(value = moloch_parsers_asn_get_tlv(&bsb, &apc, &atag, &alen))) {badreason = 5; goto bad_cert;} /* issuer */ if (!(value = moloch_parsers_asn_get_tlv(&bsb, &apc, &atag, &alen))) {badreason = 6; goto bad_cert;} BSB tbsb; BSB_INIT(tbsb, value, alen); tls_certinfo_process(&certs->issuer, &tbsb); /* validity */ if (!(value = moloch_parsers_asn_get_tlv(&bsb, &apc, &atag, &alen))) {badreason = 7; goto bad_cert;} /* subject */ if (!(value = moloch_parsers_asn_get_tlv(&bsb, &apc, &atag, &alen))) {badreason = 8; goto bad_cert;} BSB_INIT(tbsb, value, alen); tls_certinfo_process(&certs->subject, &tbsb); /* subjectPublicKeyInfo */ if (!(value = moloch_parsers_asn_get_tlv(&bsb, &apc, &atag, &alen))) {badreason = 9; goto bad_cert;} /* extensions */ if (BSB_REMAINING(bsb)) { if (!(value = moloch_parsers_asn_get_tlv(&bsb, &apc, &atag, &alen))) {badreason = 10; goto bad_cert;} BSB tbsb; BSB_INIT(tbsb, value, alen); char lastOid[100]; lastOid[0] = 0; tls_alt_names(certs, &tbsb, lastOid); } if (!moloch_field_certsinfo_add(certsField, session, certs, clen*2)) { moloch_field_certsinfo_free(certs); } BSB_IMPORT_skip(cbsb, clen + 3); continue; bad_cert: if (config.debug) LOG("bad cert %d - %d", badreason, clen); moloch_field_certsinfo_free(certs); break; } }
void wise_cb(unsigned char *data, int data_len, gpointer uw) { BSB bsb; WiseRequest_t *request = uw; int i; inflight -= request->numItems; BSB_INIT(bsb, data, data_len); uint32_t fts = 0, ver = 0; BSB_IMPORT_u32(bsb, fts); BSB_IMPORT_u32(bsb, ver); if (BSB_IS_ERROR(bsb) || ver != 0) { for (i = 0; i < request->numItems; i++) { wise_free_item(request->items[i]); } MOLOCH_TYPE_FREE(WiseRequest_t, request); return; } if (fts != fieldsTS) wise_load_fields(); struct timeval currentTime; gettimeofday(¤tTime, NULL); for (i = 0; i < request->numItems; i++) { WiseItem_t *wi = request->items[i]; BSB_IMPORT_u08(bsb, wi->numOps); if (wi->numOps > 0) { wi->ops = malloc(wi->numOps * sizeof(WiseOp_t)); int i; for (i = 0; i < wi->numOps; i++) { WiseOp_t *op = &(wi->ops[i]); int rfield = 0; BSB_IMPORT_u08(bsb, rfield); op->fieldPos = fieldsMap[rfield]; int len = 0; BSB_IMPORT_u08(bsb, len); char *str = (char*)BSB_WORK_PTR(bsb); BSB_IMPORT_skip(bsb, len); switch (config.fields[op->fieldPos]->type) { case MOLOCH_FIELD_TYPE_INT_HASH: if (op->fieldPos == tagsField) { moloch_db_get_tag(NULL, tagsField, str, NULL); // Preload the tagname -> tag mapping op->str = g_strdup(str); op->strLenOrInt = len - 1; continue; } // Fall thru case MOLOCH_FIELD_TYPE_INT: case MOLOCH_FIELD_TYPE_INT_ARRAY: op->str = 0; op->strLenOrInt = atoi(str); break; case MOLOCH_FIELD_TYPE_STR: case MOLOCH_FIELD_TYPE_STR_ARRAY: case MOLOCH_FIELD_TYPE_STR_HASH: op->str = g_strdup(str); op->strLenOrInt = len - 1; break; case MOLOCH_FIELD_TYPE_IP: case MOLOCH_FIELD_TYPE_IP_HASH: op->str = 0; op->strLenOrInt = inet_addr(str); break; default: LOG("WARNING - Unsupported expression type for %s", str); continue; } } } wi->loadTime = currentTime.tv_sec; int s; for (s = 0; s < wi->numSessions; s++) { wise_process_ops(wi->sessions[s], wi); moloch_nids_decr_outstanding(wi->sessions[s]); } g_free(wi->sessions); wi->sessions = 0; wi->numSessions = 0; DLL_PUSH_HEAD(wil_, &itemList[(int)wi->type], wi); // Cache needs to be reduced if (itemList[(int)wi->type].wil_count > maxCache) { DLL_POP_TAIL(wil_, &itemList[(int)wi->type], wi); wise_free_item(wi); } } MOLOCH_TYPE_FREE(WiseRequest_t, request); }
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); } }
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; }
LOCAL int quic_udp_parser(MolochSession_t *session, void *UNUSED(uw), const unsigned char *data, int len, int UNUSED(which)) { int version = -1; int offset = 1; // PUBLIC_FLAG_RESET if (data[0] & 0x02) { return 0; } // CID if (data[0] & 0x08) { offset += 8; } // Get version if (data[0] & 0x01 && data[offset] == 'Q') { version = (data[offset+1] - '0') * 100 + (data[offset+2] - '0') * 10 + (data[offset+3] - '0'); offset += 4; } // Unsupported version if (version < 24) { moloch_parsers_unregister(session, uw); return 0; } // Diversification only is from server to client, so we can ignore // Packet number size if ((data[0] & 0x30) == 0) { offset++; } else { offset += ((data[0] & 0x30) >> 4) * 2; } // Hash offset += 12; // Private Flags if (version < 34) offset++; if (offset > len) return 0; BSB bsb; BSB_INIT(bsb, data+offset, len-offset); while (!BSB_IS_ERROR(bsb) && BSB_REMAINING(bsb)) { uint8_t type = 0; BSB_LIMPORT_u08(bsb, type); //1fdooossB if ((type & 0x80) == 0) { return 0; } int offsetLen = 0; if (type & 0x1C) { offsetLen = ((type & 0x1C) >> 2) + 1; } int streamLen = (type & 0x03) + 1; BSB_LIMPORT_skip(bsb, streamLen + offsetLen); int dataLen = BSB_REMAINING(bsb); if (type & 0x20) { BSB_LIMPORT_u16(bsb, dataLen); } if (BSB_IS_ERROR(bsb)) return 0; BSB dbsb; BSB_INIT(dbsb, BSB_WORK_PTR(bsb), MIN(dataLen, BSB_REMAINING(bsb))); BSB_IMPORT_skip(bsb, dataLen); quic_chlo_parser(session,dbsb); moloch_parsers_unregister(session, uw); return 0; }