/* * report IP/User-Agent combo * * TODO: add support for IPv6 */ static void do_req_rep(const http_req *r, const parse_status *st) { #ifndef TEST if (st->frames >= 2) { /* assume [IPv4][TCP][HTTP] */ const struct head_kv *uah = http_header_find_key(&r->headers, "User-Agent"); if (uah) { const ptrlen *ua = uah->val.p; /* TODO: this IP/foo hint reporting is ugly and common, abstract it */ const parse_frame *fi = st->frame + st->frames - 2; if (PROT_IPv4 == fi->id) { char ipbuf[48]; const ipv4 *ip = fi->off; (void)ipv4_addr_format(ipbuf, sizeof ipbuf, ip->src); rep_hint("4", ipbuf, "HTTP.User-Agent", ua->start, ua->len); } } } #endif }
/** * given a SYN (not SYN+ACK) TCP packet, generate a p0f-style * fingerprint and report it */ void tcp_rep_syn(const parse_status *st, const tcp *t, size_t tcplen) { #ifndef TEST const parse_frame *fi = st->frame + st->frames - 1; if (PROT_IPv4 == fi->id) { char fpbuf[256], ipbuf[48]; const ipv4 *ip = fi->off; size_t fplen; (void)ipv4_addr_format(ipbuf, sizeof ipbuf, ip->src); /* generate and report fingerprint with literal MSS value */ fplen = p0f2str(fpbuf, sizeof fpbuf, t, tcplen, ip, fi->len, 0); if (fplen) rep_hint("4", ipbuf, "TCP.SYN.Fingerprint", fpbuf, fplen); /* generate and report fingerprint with "*" MSS value */ fplen = p0f2str(fpbuf, sizeof fpbuf, t, tcplen, ip, fi->len, 1); if (fplen) rep_hint("4", ipbuf, "TCP.SYN.Fingerprint", fpbuf, fplen); } #endif }
static void report(const parse_frame *f, const parse_status *st) { #ifndef TEST if (st->frames >= 3) { char ipbuf[48]; const parse_frame *fi = st->frame+st->frames-2; const ipv4 *ip = fi->off; const struct kv_list *l = f->pass; assert(PROT_IPv4 == fi->id); (void)ipv4_addr_format(ipbuf, sizeof ipbuf, ip->src); unsigned i; for (i = 0; i < l->cnt; i++) { if (8 == l->kv[i].key.len && 0 == memcmp("Hostname", l->kv[i].key.start, 8)) { rep_addr("4", ipbuf, "RAS", l->kv[i].val.start, Iface_RASADV.shortname, 1); } else if (6 == l->kv[i].key.len && 0 == memcmp("Domain", l->kv[i].key.start, 6)) { rep_hint("4", ipbuf, "RAS.Domain", l->kv[i].val.start, l->kv[i].val.len); } } } #endif }
static size_t dump_rr(enum DNS_RR rr, const parse_frame *f, const char *buf, size_t len, FILE *out) { char namebuf[256], targetbuf[256]; const char *name = buf; size_t namelen = dns_calc_len_name(name, len); const dns_answer *a = (dns_answer *)(buf + namelen); int bytes; (void)dump_chars_buf(namebuf, sizeof namebuf, name, namelen-1); bytes = fprintf(out, " %s name=%s type=%hu(%s) class=%hu(%s) ttl=%ld target=%s\n", RR[rr].name, namebuf, ntohs(a->type), type2str(ntohs(a->type)), a->class_, class2str(a->class_), (long)ntohl(a->ttl), addrformat(ntohs(a->type), targetbuf, sizeof targetbuf, (char *)a + sizeof *a, ntohs(a->rrlen))); #ifndef TEST /* TODO: split this block off to another function */ if (DNS_RR_AN == rr && DNS_Type_TXT == ntohs(a->type)) { /* is a TXT record answer; usually supplemental information that can * contain some interesting stuff */ const char *addrtype = NULL; char ipbuf[64]; const parse_frame *fi = f-2; if (PROT_IPv4 == fi->id) { const ipv4 *i = fi->off; addrtype = "4"; ipv4_addr_format(ipbuf, sizeof ipbuf, i->src); } else if (PROT_IPv6 == fi->id) { const ipv6 *i = fi->off; addrtype = "6"; ipv6_addr_format(ipbuf, sizeof ipbuf, i->src); } if (addrtype) { (void)dump_chars_buf(namebuf, sizeof namebuf, name, strip_c0(namebuf, namelen)); (void)dump_chars_buf(targetbuf, sizeof targetbuf, (char *)a + sizeof *a, strip_c0((char *)a + sizeof *a, ntohs(a->rrlen))); if ('\0' != namebuf[0]) rep_hint(addrtype, ipbuf, "DNS.TXT", namebuf, -1); if ('\0' != targetbuf[0]) rep_hint(addrtype, ipbuf, "DNS.TXT", targetbuf, -1); } } else if (DNS_RR_AN == rr && (DNS_Type_A == ntohs(a->type) || DNS_Type_AAAA == ntohs(a->type)) && str_endswith(namebuf, "\\x05local")) { /* we're looking for ".local" addresses; which may identify the machine */ char ipbuf[64]; const parse_frame *fi = f-2; const char *addrtype = NULL; if (PROT_IPv4 == fi->id) { const ipv4 *i = fi->off; addrtype = "4"; ipv4_addr_format(ipbuf, sizeof ipbuf, i->src); } else if (PROT_IPv6 == fi->id) { const ipv6 *i = fi->off; addrtype = "6"; ipv6_addr_format(ipbuf, sizeof ipbuf, i->src); } (void)dump_chars_buf(namebuf, sizeof namebuf, name, namelen-1); if ('\0' != namebuf[0]) { rep_hint(addrtype, ipbuf, "DNS.LOCAL", namebuf, -1); } { char localname[64]; /* first char is length of actual name */ if (name[0] > 0 && (unsigned)name[0] < sizeof localname) { strlcpy(localname, name+1, (size_t)name[0]+1); localname[(unsigned)name[0]] = '\0'; } else { strlcpy(localname, name+1, sizeof localname); } rep_addr(addrtype, ipbuf, "D", localname, "DNS.LOCAL", 1); } } #endif return (size_t)bytes; }
static size_t dump_ipv4_buf(char *dst, size_t dstlen, const char *src, size_t srclen) { return ipv4_addr_format(dst, dstlen, src); }