ref: 16d016b87e7783cecedb1078c1327fa1244da4d7
parent: 1766db24dfb733bd1f574bf0882527356f177397
author: mkf <mkf@cloud9p.org>
date: Sat Nov 16 09:57:36 EST 2024
very little changes
--- a/common.c
+++ b/common.c
@@ -2,7 +2,11 @@
#include <stdarg.h>
#include <stdlib.h>
#include <stdint.h>
+#include <string.h>
+ulong pos;
+ulong pktlen;
+
void
err(int fatal, char *fmt, ...)
{
@@ -33,4 +37,77 @@
get4(const u_char *octet)
{
return get2(octet) << 8 * 2 | get2(octet + 2);
-}
\ No newline at end of file
+}
+
+void*
+emalloc(ulong len)
+{
+ void *m;
+
+ m = malloc(len);
+
+ if(m == NULL)
+ err(1, "emalloc(%d): malloc failed, unable to allocate memory", len);
+
+ return m;
+}
+
+void*
+ecalloc(ulong len, ulong size)
+{
+ void *m;
+
+ m = calloc(len, size);
+
+ if(m == NULL)
+ err(1, "ecalloc(%d, %d): calloc failed, unable to allocate memory", len, size);
+
+ return m;
+}
+
+void*
+memdup(const void *src, ulong len)
+{
+ void *dst;
+
+ dst = emalloc(len);
+ memmove(dst, src, len);
+
+ return dst;
+}
+
+void
+get(const u_char *pkt, long size, ...)
+{
+ uint8_t *u8;
+ uint16_t *u16;
+ uint32_t *u32;
+
+ va_list args;
+ va_start(args, size);
+
+ switch(size)
+ {
+ case 1:
+ u8 = va_arg(args, u_char*);
+ *u8 = pkt[pos];
+ break;
+ case 2:
+ u16 = va_arg(args, uint16_t*);
+ *u16 = get2(pkt + pos);
+ break;
+ case 3:
+ u32 = va_arg(args, uint32_t*);
+ *u32 = get4(pkt + pos) >> 8;
+ // *u32 &= 0x00ffffff;
+ break;
+ case 4:
+ u32 = va_arg(args, uint32_t*);
+ *u32 = get4(pkt + pos);
+ break;
+ default:
+ err(1, "get(%p, %ld, ...): unsupported size", pkt, size);
+ }
+ pos += size;
+ va_end(args);
+}
--- a/common.h
+++ b/common.h
@@ -1,150 +1,6 @@
-#define debug 0
+#include <openssl/x509v3.h>
+#include <pcap.h>
-enum
-{
- /* sizes and stuff */
- ETHER_LEN = 14,
- ETHER_ADDR_LEN = 6,
-
- UDP_SIZE = 8,
-
- /* sizes of each field in header */
- ETHER_DST = ETHER_ADDR_LEN,
- ETHER_SRC = ETHER_ADDR_LEN,
- ETHER_TYPE = 2,
-
- PKT_VHL = 1,
- PKT_DSFIELD = 1,
- PKT_LEN = 2,
- PKT_ID = 2,
- // PKT_FLAGS = 1, /* 3 bits */
- PKT_FRAGOFFSET = 2, /* 12 bits */
- PKT_TTL = 1,
- PKT_PROTO = 1,
- PKT_SUM = 2,
- PKT_SRC = 4,
- PKT_DST = 4,
-
- /* udp stuff */
- UDP_SRCPORT = 2,
- UDP_DSTPORT = 2,
- UDP_LEN = 2,
- UDP_SUM = 2,
-
- /* tcp stuff */
- TCP_SRCPORT = 2,
- TCP_DSTPORT = 2,
- TCP_SEQNUM = 4,
- TCP_ACKNUM = 4,
- TCP_OFFSET = 1, /* half a byte is used */
- TCP_FLAGS = 1,
- TCP_WINSIZE = 2,
- TCP_SUM = 2,
- TCP_URGPTR = 2,
- TCP_OPTS = 2,
-
- /* tcp flags @ 13 */
- TCP_FLAG_ACK = 0x010,
- TCP_FLAG_PSH = 0x008,
- TCP_FLAG_SYN = 0x002,
- TCP_FLAG_FIN = 0x001,
-
- /* dns */
- DNS_ID = 2,
- DNS_FLAGS = 2,
- DNS_COUNT_QUERIES = 2,
- DNS_COUNT_ANSWERS = 2,
- DNS_COUNT_AUTH_RR = 2,
- DNS_COUNT_ADD_RR = 2,
- DNS_TYPE = 2,
- DNS_CLASS = 2,
- DNS_BACKREF = 2, /* that c0 ff thingi which back references */
- DNS_TTL = 4,
- DNS_LEN = 2,
-
- /* dns flags bits @ 2 */
- DNS_ISRESP = 0x8000,
- DNS_OPCODE = 0x7800,
-
- DNS_FLAGS_OPCODE_QUERY = 0x4000,
- DNS_FLAGS_OPCODE_IQUERY = 0x2000,
- DNS_FLAGS_OPCODE_STATUS = 0x1000, /* 2 bits */
- DNS_FLAGS_OPCODE_NOTIFY = 0x0800,
-
- DNS_AUTH = 0x0400,
- DNS_TRUNCATED = 0x0200,
- DNS_RD = 0x0100,
- DNS_RA = 0x0080,
- DNS_Z = 0x0040,
- DNS_AD = 0x0020,
- DNS_CD = 0x0010,
- DNS_RCODE = 0x000F,
-
- /* tls record */
- TLS_RECORD = 4,
- TLS_RECORD_CONTENTTYPE = 1,
- TLS_RECORD_VERSION = 1,
- TLS_RECORD_LEN = 2,
-
- /* tls record versions */
- TLS_RECORD_10 = 0x301,
- TLS_RECORD_11 = 0x302,
- TLS_RECORD_12 = 0x303,
- TLS_RECORD_13 = 0x304,
-
- /* tls 1.2 handshake */
- TLS_HANDSHAKE_TYPE = 1,
- TLS_HANDSHAKE_LEN = 3,
- TLS_HANDSHAKE_VERSION = 2,
- TLS_HANDSHAKE_RANDOM = 32,
- TLS_HANDSHAKE_SESSIONID_LEN = 1,
- TLS_HANDSHAKE_SESSIONID = 32,
- TLS_HANDSHAKE_CIPHERS_LEN = 2,
- TLS_HANDSHAKE_CIPHERS = 54,
- TLS_HANDSHAKE_COMP_LEN = 1,
- TLS_HANDSHAKE_COMPS = 1,
- TLS_HANDSHAKE_EXTS_LEN = 2, /* number of all extensions */
- TLS_HANDSHAKE_EXT_TYPE = 2,
- TLS_HANDSHAKE_EXT_LEN = 2, /* (data) length of a specfic extension */
-
- /* ether types */
- ETHER_IP4 = 0x800,
- ETHER_IP6 = 0x86dd,
-
- /* packet types */
- PKT_TCP = 6,
- PKT_UDP = 17,
-
- /* dns types */
- DNS_TYPE_A = 1,
- DNS_TYPE_CNAME = 5,
- DNS_TYPE_MX = 15,
- DNS_TYPE_TXT = 16,
- DNS_TYPE_AAAA = 28,
-
- /* dns classes */
- DNS_CLASS_IN = 1, /* lonely :( */
-
- /* tls handshake types */
- TLS_HELLO_REQ = 0,
- TLS_CLIENT_HELLO = 1,
- TLS_SERVER_HELLO = 2,
- TLS_NEW_TICKET = 4,
- TLS_END_OF_EARLY_DATA = 5,
- TLS_CERT = 11,
- TLS_CERT_REQ = 13,
- TLS_FINISHED = 20,
-
- /* tls content types */
- TLS_ALERT = 21,
- TLS_HANDSHAKE = 22,
- TLS_APPLICATION_DATA = 23,
- TLS_HEARTBEAT = 24,
- TLS_CID = 25, /* ? */
- TLS_ACK = 26,
- TLS_RTC = 27, /* ? */
-};
-
/*
* each parser have at least these two
* they may have more functions internally and externally
@@ -154,22 +10,49 @@
char *name;
int (*parse)();
void (*print)();
+ void (*free)();
}Parser;
extern pcap_t *handle;
-extern struct bpf_program dnsfilter;
+extern struct bpf_program filter;
+extern int debug;
/* common.c */
+extern unsigned long pos;
+extern const u_char *pkt;
+extern ulong pktlen;
+#define PKTHEAD pkt + pos
+
uint16_t get2(const u_char *octet);
uint32_t get4(const u_char *octet);
+void get(const u_char *pkt, int size, ...);
+
void err(int fatal, char *fmt, ...);
+void *emalloc(ulong size);
+void *memdup(const void *src, ulong len);
/* ether.c */
+enum
+{
+ ETHER_LEN = 14,
+ ETHER_ADDR_LEN = 6,
+
+ /* sizes of each field in header */
+ ETHER_DST = ETHER_ADDR_LEN,
+ ETHER_SRC = ETHER_ADDR_LEN,
+ ETHER_TYPE = 2,
+
+ /* ether types */
+ ETHER_IP4 = 0x800,
+ ETHER_IP6 = 0x86dd,
+};
+
typedef struct
{
+ uint32_t start;
uint8_t dst[ETHER_ADDR_LEN];
uint8_t src[ETHER_ADDR_LEN];
- int type;
+ uint16_t type;
}Ether;
char* etherTypeToStr(uint16_t frame);
@@ -179,8 +62,29 @@
extern Parser etherParser;
/* (ipv4) pkt.c */
+enum
+{
+ PKT_VHL = 1,
+ PKT_DSFIELD = 1,
+ PKT_LEN = 2,
+ PKT_ID = 2,
+ // PKT_FLAGS = 1, /* 3 bits */
+ PKT_FRAGOFFSET = 2, /* 12 bits */
+ PKT_TTL = 1,
+ PKT_PROTO = 1,
+ PKT_SUM = 2,
+ PKT_SRC = 4,
+ PKT_DST = 4,
+
+ /* packet types */
+ PKT_TCP = 6,
+ PKT_UDP = 17,
+};
+
typedef struct
{
+ uint32_t start;
+
uint8_t version;
uint8_t headerlen;
uint8_t dsfield;
@@ -206,11 +110,24 @@
extern Parser pktParser;
/* udp.c */
-typedef struct
+enum
{
- uint16_t srcport;
- uint16_t dstport;
+ /* udp stuff */
+ UDP_SIZE = 8,
+
+ UDP_SRCPORT = 2,
+ UDP_DSTPORT = 2,
+ UDP_LEN = 2,
+ UDP_SUM = 2,
+};
+typedef struct
+{
+ uint32_t start;
+
+ uint16_t src;
+ uint16_t dst;
+
uint16_t len;
uint16_t sum;
}Udp;
@@ -221,13 +138,36 @@
extern Parser udpParser;
/* tcp.c */
+enum
+{
+ /* tcp sizes */
+ TCP_SRCPORT = 2,
+ TCP_DSTPORT = 2,
+ TCP_SEQNUM = 4,
+ TCP_ACKNUM = 4,
+ TCP_OFFSET = 1, /* half a byte is used */
+ TCP_FLAGS = 1,
+ TCP_WINSIZE = 2,
+ TCP_SUM = 2,
+ TCP_URGPTR = 2,
+ TCP_OPTS = 2,
+
+ /* tcp flags @ 13 */
+ TCP_FLAG_ACK = 0x010,
+ TCP_FLAG_PSH = 0x008,
+ TCP_FLAG_SYN = 0x002,
+ TCP_FLAG_FIN = 0x001,
+};
+
typedef struct
{
- uint16_t srcport;
- uint16_t dstport;
+ uint32_t start;
+
+ uint16_t src;
+ uint16_t dst;
- uint32_t seqnum;
- uint32_t acknum;
+ uint32_t seq;
+ uint32_t ack;
uint16_t offset;
uint16_t flags;
@@ -248,8 +188,57 @@
* dns.c
* a maximum size of 255 for strings is assumed
*/
+enum
+{
+ /* dns */
+ DNS_ID = 2,
+ DNS_FLAGS = 2,
+ DNS_COUNT_QUERIES = 2,
+ DNS_COUNT_ANSWERS = 2,
+ DNS_COUNT_AUTH_RR = 2,
+ DNS_COUNT_ADD_RR = 2,
+ DNS_TYPE = 2,
+ DNS_CLASS = 2,
+ DNS_BACKREF = 2, /* that c0 ff thingi which back references */
+ DNS_TTL = 4,
+ DNS_LEN = 2,
+
+ /* dns flags bits @ 2 */
+ DNS_ISRESP = 0x8000,
+ DNS_OPCODE = 0x7800,
+
+ DNS_FLAGS_OPCODE_QUERY = 0x4000,
+ DNS_FLAGS_OPCODE_IQUERY = 0x2000,
+ DNS_FLAGS_OPCODE_STATUS = 0x1000, /* 2 bits */
+ DNS_FLAGS_OPCODE_NOTIFY = 0x0800,
+
+ DNS_AUTH = 0x0400,
+ DNS_TRUNCATED = 0x0200,
+ DNS_RD = 0x0100,
+ DNS_RA = 0x0080,
+ DNS_Z = 0x0040,
+ DNS_AD = 0x0020,
+ DNS_CD = 0x0010,
+ DNS_RCODE = 0x000F,
+
+ /* dns types */
+ DNS_TYPE_A = 1,
+ DNS_TYPE_CNAME = 5,
+ DNS_TYPE_SOA = 6,
+ DNS_TYPE_MX = 15,
+ DNS_TYPE_TXT = 16,
+ DNS_TYPE_AAAA = 28,
+
+ /* dns classes */
+ DNS_CLASS_IN = 1, /* lonely :( */
+
+ DNS_MAX_LEN = 255,
+};
+
typedef struct
{
+ uint32_t start;
+
/* is it response or request */
uint16_t id;
uint16_t flags;
@@ -260,10 +249,10 @@
uint16_t nAuthRR;
uint16_t nAddRR;
- char domain[255];
+ char domain[DNS_MAX_LEN+1];
- uint8_t type;
- uint8_t class;
+ uint16_t type;
+ uint16_t class;
uint32_t ttl;
uint32_t len;
union
@@ -275,46 +264,259 @@
uint16_t ip6[8];
/* CNAME */
- u_char cname[255];
+ u_char cname[DNS_MAX_LEN+1];
};
}Dns;
-int parseDnsCname(const u_char *pkt, u_char cname[255], uint pos, uint len);
+int parseDnsName(const u_char *pkt, char *buf, u_char len);
+int parseDnsCname(const u_char *pkt, Dns *d, uint len);
int parseDns(const u_char *pkt, Dns *dns);
char* dnsClassToStr(uint16_t class);
char* dnsTypeToStr(uint16_t type);
void printDns(Dns dns);
+
extern Parser dnsParser;
+/* der.c */
+enum
+{
+ /* der tags */
+ DER_TAG_INT = 0x2,
+ DER_TAG_BITSTR = 0x3,
+ DER_TAG_OCTSTR = 0x4,
+ DER_TAG_NULL = 0x5,
+ DER_TAG_OID = 0x6,
+ DER_TAG_UTF8STR = 0xc,
+ DER_TAG_SEQ = 0x10,
+ DER_TAG_SET = 0x11,
+ DER_TAG_PRINTSTR = 0x13,
+ DER_TAG_IA5STR = 0x16,
+ DER_TAG_UTCTIME = 0x17,
+ DER_TAG_GENERALTIME = 0x18,
+ DER_TAG_SEQOF = 0x30,
+ DER_TAG_SETOF = 0x31,
+
+ /* der tag classes */
+ DER_CLASS_UNIVERSAL = 0,
+ DER_CLASS_APPLICATION = 1,
+ DER_CLASS_CONTEXT = 2,
+ DER_CLASS_PRIVATE = 3,
+
+ DER_CN_MAX = 1024,
+};
+
+typedef struct
+{
+ uint32_t start;
+
+ uint64_t len; /* of cert */
+
+ X509 *cert;
+ char *subject;
+ char *issuer;
+
+ char *commonName[DER_CN_MAX];
+ uint16_t nCommonName;
+
+ uint8_t selfsigned;
+}Der;
+
+int parseDer(const u_char *pkt, Der *der);
+
+void printDer(Der der);
+
+extern Parser derParser;
+
/* tls.c */
+enum
+{
+ /* tls record */
+ TLS_RECORD = 5,
+ TLS_RECORD_CONTENTTYPE = 1,
+ TLS_RECORD_VERSION = 2,
+ TLS_RECORD_LEN = 2,
+
+ /* tls record versions */
+ SSL_30 = 0x300,
+ TLS_10 = 0x301,
+ TLS_11 = 0x302,
+ TLS_12 = 0x303,
+ TLS_13 = 0x304,
+
+ /* tls 1.2 (client) handshake */
+ TLS_HANDSHAKE_HEADER = 4,
+ TLS_HANDSHAKE_TYPE = 1,
+ TLS_HANDSHAKE_LEN = 3,
+ TLS_HANDSHAKE_VERSION = 2,
+ TLS_HANDSHAKE_RANDOM = 32,
+ TLS_HANDSHAKE_SESSIONID_LEN = 1,
+ /* TLS_HANDSHAKE_SESSIONID = ??, */
+ TLS_HANDSHAKE_CIPHERS_LEN = 2,
+ /* TLS_HANDSHAKE_CIPHERS = ?? , */
+ TLS_HANDSHAKE_CIPHER = 2,
+ TLS_HANDSHAKE_COMP_LEN = 1,
+ TLS_HANDSHAKE_COMP = 1,
+ /* TLS_HANDSHAKE_COMPS = 1?, */
+ TLS_HANDSHAKE_EXTS_LEN = 2, /* number of all extensions */
+ TLS_HANDSHAKE_EXT_TYPE = 2,
+ TLS_HANDSHAKE_EXT_LEN = 2, /* (data) length of a specfic extension */
+ TLS_HANDSHAKE_CERTS_LEN = 3,
+ TLS_HANDSHAKE_CERT_LEN = 3,
+
+ /* tls 1.2 (server) handshake */
+ TLS_HANDSHAKE_COMPS = 1,
+
+ /* tls SNI */
+ TLS_SNI_LISTLEN = 2,
+ TLS_SNI_TYPE = 1,
+ TLS_SNI_LEN = 2,
+
+ /* tls supported versions */
+ TLS_SV_LEN = 1,
+ TLS_SV_DATA = 2,
+
+ /* tls handshake types */
+ TLS_HELLO_REQ = 0,
+ TLS_CLIENT_HELLO = 1,
+ TLS_SERVER_HELLO = 2,
+ TLS_NEW_TICKET = 4,
+ TLS_END_OF_EARLY_DATA = 5,
+ TLS_CERT = 11,
+ TLS_SERVER_KEY_EXCH = 12,
+ TLS_SERVER_HELLO_DONE = 14,
+ TLS_CERT_REQ = 13,
+ TLS_CLIENT_KEY_EXCH = 16,
+ TLS_FINISHED = 20,
+ TLS_CERT_STATUS = 22,
+
+ /* tls content types */
+ TLS_CTYPE_ALERT = 21,
+ TLS_CTYPE_HANDSHAKE = 22,
+ TLS_CTYPE_APPLICATION_DATA = 23,
+ TLS_CTYPE_HEARTBEAT = 24,
+ TLS_CTYPE_CID = 25, /* ? */
+ TLS_CTYPE_ACK = 26,
+ TLS_CTYPE_RTC = 27, /* ? */
+
+ /* tls extensions */
+ TLS_EXT_SNI = 0,
+ TLS_EXT_PADDING = 21,
+ TLS_EXT_SUPPORTED_VERS = 43,
+};
+
typedef struct
{
+ uint32_t start;
+
+ char *name;
uint8_t len;
- uint8_t data[];
+ uint8_t *data;
}TlsTuple;
+/* supported versions */
typedef struct
{
+ uint8_t len;
+ uint16_t *vers;
+}TlsExtensionSv;
+
+/* server name */
+typedef struct
+{
+ uint16_t listLen;
uint8_t type;
+ uint16_t len;
+
+ char *name;
+}TlsExtensionSni;
+
+typedef struct
+{
+ uint32_t start;
+
+ uint16_t type;
+ uint16_t len;
+
+ union
+ {
+ TlsExtensionSv *sv;
+ TlsExtensionSni *sni;
+ u_char *data;
+ };
+}TlsExtension;
+
+typedef struct
+{
+ uint32_t start;
uint32_t len;
+ Der *der;
+}TlsCert;
+
+typedef struct
+{
+ uint32_t start;
+
+ uint8_t type;
+ uint32_t len;
uint16_t version;
- uint8_t random[32];
+ uint8_t random[TLS_HANDSHAKE_RANDOM];
- TlsTuple sessionId;
- TlsTuple cipherSuits;
- TlsTuple compressionMethods;
- TlsTuple extensions;
+ TlsTuple *sessionId;
+ union
+ {
+ /* client hello */
+ struct
+ {
+ TlsTuple *cipherSuits;
+ TlsTuple *compressionMethods;
+ };
+
+ /* server hello */
+ struct
+ {
+ uint16_t cipherSuit;
+ uint8_t compressionMethod;
+ };
+
+ /* cert */
+ struct
+ {
+ uint32_t certsLen;
+ uint32_t nCerts;
+ TlsCert *certs;
+ };
+ };
+
+ uint16_t extensionsLen; /* length of extentions in bytes */
+ uint16_t nExtensions; /* number of actual extentions */
+ TlsExtension *extensions;
}TlsHandshake;
typedef struct
{
- uint8_t contenttype;
- uint16_t rversion; /* record version */
+ uint32_t start;
+
+ uint8_t type;
+ uint16_t version; /* record version */
uint16_t len;
- TlsHandshake handshake;
+ uint8_t nHandshakes;
+ TlsHandshake *handshakes;
}Tls;
-extern Parser tlsParser;
+int parseTlsTuple(const u_char *pkt, TlsTuple *tuple);
+int parseTlsRecord(const u_char *pkt, Tls *tls);
+int parseTlsExtensions(const u_char *pkt, TlsHandshake *hs);
+int parseTlsHandshake(const u_char *pkt, TlsHandshake *hs);
+int parseTls(const u_char *pkt, Tls *tls);
+void printTlsTuple(TlsTuple tuple);
+void printTlsHandshake(TlsHandshake hs);
+void printTlsRecord(Tls tls);
+void printTls(Tls tls);
+void printTlsExtension(TlsExtension e);
+void printTlsExtensions(TlsHandshake hs);
+void freeTls(Tls *tls);
+
+extern Parser tlsParser;
--- a/dns.c
+++ b/dns.c
@@ -1,8 +1,3 @@
-/*
- * notes:
- * we dont parse compressed names very well.
- */
-
#include <stdio.h>
#include <stdint.h>
#include <string.h>
@@ -9,32 +4,68 @@
#include <pcap.h>
#include "common.h"
-/*
- * pos must be after data length, before size of first string
- * len must be dns.len
- */
int
-parseDnsCname(const u_char *pkt, u_char cname[255], uint pos, uint len)
+parseDnsName(const u_char *pkt, char *buf, u_char len)
{
- int section_header, cname_head = 0;
+ int section_header, i;
+
+ memset(buf, '\0', len);
+
+ /* skip first len byte, we can't replace it with '.' */
+ strncpy(buf, pkt+1, len);
+ for(i = 0 ; i < len ; i++)
+ {
+ section_header = pkt[i];
+
+ if(section_header == 0x0 || section_header == 0xc0)
+ break;
+ else
+ {
+ i += section_header;
+ buf[i] = '.';
+ }
+ }
+
+ buf[len] = '\0';
+ return 1;
+}
+
+/* len must be dns.len */
+int
+parseDnsCname(const u_char *pkt, Dns *d, uint len)
+{
+ int section_header;
const u_char *pkt_head;
+ u_char next_header, *cname_head, namebuf[DNS_MAX_LEN];
pkt_head = pkt + pos;
+ cname_head = d->cname;
for(int i = 0 ; i < len ; i++)
{
section_header = pkt_head[i];
-
- /* compressed, we'r too lazy to handle it */
- if(section_header == 0xc0 || section_header == 0x0)
+
+ /* compressed */
+ if(section_header == 0xc0)
+ {
+ next_header = pkt_head[i + 1];
+ parseDnsName(pkt + d->start + next_header, namebuf, DNS_MAX_LEN);
+ cname_head = strchr(cname_head, '\0');
+ *cname_head++ = '.';
+ strncpy(cname_head, namebuf, DNS_MAX_LEN - (cname_head - d->cname));
break;
-
- /* not compressed, regular size */
- strncpy(cname + cname_head, pkt_head + i + 1, section_header);
-
+ }
+ else if(section_header == 0x0)
+ break;
+ else
+ {
+ parseDnsName(pkt_head + i, namebuf, section_header);
+ cname_head = strchr(cname_head, '\0');
+ *cname_head++ = '.';
+ strncpy(cname_head, namebuf, section_header);
+ }
i += section_header;
- cname_head += section_header;
- cname[cname_head++] = '.';
}
+
return 1;
}
@@ -45,65 +76,36 @@
int
parseDns(const u_char *pkt, Dns *dns)
{
- int section_header;
- int pos = 0;
- int name_head = 0;
+ dns->start = pos;
+ get(pkt, DNS_ID, &dns->id);
+ get(pkt, DNS_FLAGS, &dns->flags);
- dns->id = get2(pkt + pos);
- pos += DNS_ID;
+ get(pkt, DNS_COUNT_QUERIES, &dns->nQueries);
+ get(pkt, DNS_COUNT_ANSWERS, &dns->nAnswers);
+ get(pkt, DNS_COUNT_AUTH_RR, &dns->nAuthRR);
+ get(pkt, DNS_COUNT_ADD_RR, &dns->nAddRR);
- dns->flags = get2(pkt + pos);
- pos += DNS_FLAGS;
-
- dns->nQueries = get2(pkt + pos);
- pos += DNS_COUNT_QUERIES;
-
- dns->nAnswers = get2(pkt + pos);
- pos += DNS_COUNT_ANSWERS;
-
- dns->nAuthRR = get2(pkt + pos);
- pos += DNS_COUNT_AUTH_RR;
-
- dns->nAddRR = get2(pkt + pos);
- pos += DNS_COUNT_ADD_RR;
-
- memset(dns->domain, '\0', sizeof(dns->domain));
- for(int i = 0 ; i < sizeof(dns->domain) ; i++)
- {
- section_header = pkt[pos];
- pos++;
+ parseDnsName(PKTHEAD, dns->domain, DNS_MAX_LEN);
+ /* first byte isn't counted. */
+ pos += strnlen(dns->domain, DNS_MAX_LEN) + 1;
+ get(pkt, DNS_TYPE, &dns->type);
+ get(pkt, DNS_CLASS, &dns->class);
- if(section_header == 0x0)
- break;
-
- strncpy(dns->domain + name_head, pkt + pos, section_header);
- name_head += section_header;
- dns->domain[name_head++] = '.';
- pos += section_header;
- }
-
- dns->type = get2(pkt + pos);
- pos += DNS_TYPE;
- dns->class = get2(pkt + pos);
- pos += DNS_CLASS;
-
if(dns->flags & DNS_ISRESP)
{
/* a resposnse, should have answers */
pos += DNS_BACKREF; /* skip domain name */
- pos += DNS_TYPE; /* skip type */
+ get(pkt, DNS_TYPE, &dns->type);
+
pos += DNS_CLASS; /* skip class */
/* we are in next packet */
- dns->ttl = get4(pkt + pos);
- pos += DNS_TTL;
-
- dns->len = get2(pkt + pos);
- pos += DNS_LEN;
+ get(pkt, DNS_TTL, &dns->ttl);
+ get(pkt, DNS_LEN, &dns->len);
}
else
return 1;
-
+
switch(dns->type)
{
case DNS_TYPE_A:
@@ -111,33 +113,26 @@
dns->ip[1] = pkt[pos++];
dns->ip[2] = pkt[pos++];
dns->ip[3] = pkt[pos++];
- break;
+ break;
case DNS_TYPE_AAAA:
- dns->ip6[0] = get2(pkt + pos);
- pos += 2;
- dns->ip6[1] = get2(pkt + pos);
- pos += 2;
- dns->ip6[2] = get2(pkt + pos);
- pos += 2;
- dns->ip6[3] = get2(pkt + pos);
- pos += 2;
- dns->ip6[4] = get2(pkt + pos);
- pos += 2;
- dns->ip6[5] = get2(pkt + pos);
- pos += 2;
- dns->ip6[6] = get2(pkt + pos);
- pos += 2;
- dns->ip6[7] = get2(pkt + pos);
- pos += 2;
+ get(pkt, 2, dns->ip6+0);
+ get(pkt, 2, dns->ip6+1);
+ get(pkt, 2, dns->ip6+2);
+ get(pkt, 2, dns->ip6+3);
+ get(pkt, 2, dns->ip6+4);
+ get(pkt, 2, dns->ip6+5);
+ get(pkt, 2, dns->ip6+6);
+ get(pkt, 2, dns->ip6+7);
break;
+ case DNS_TYPE_SOA:
case DNS_TYPE_CNAME:
- memset(dns->cname, '\0', sizeof(dns->domain));
- parseDnsCname(pkt, dns->cname, pos, dns->len);
+ memset(dns->cname, '\0', DNS_MAX_LEN);
+ parseDnsCname(pkt, dns, dns->len);
break;
case DNS_TYPE_MX:
break;
default:
- err(1, "parseDnsQuery(%d) unknown type", dns->type);
+ err(1, "parseDns(): unknown type: %d", dns->type);
}
return 1;
}
@@ -148,7 +143,7 @@
printf("dns query:\n"
"\tid: %d\tflags: %b (%x)\n"
"\tnQueries: %d\tnAnswers: %d\tnAuthRR: %d\tnAddRR: %d\n"
- "\tdomain: %s (%p)\n"
+ "\tdomain: %s (%p)\n\n"
"\ttype: %d (%s)\tclass: %s\n"
"\tttl: %x (%d)\tlen: %x (%d)\n",
@@ -174,6 +169,9 @@
case DNS_TYPE_CNAME:
printf("\tcname: %s\n", dns.cname);
break;
+ case DNS_TYPE_SOA:
+ printf("\tsoa: %s\n", dns.cname);
+ break;
case DNS_TYPE_MX:
break;
default:
@@ -204,6 +202,8 @@
return "A";
case DNS_TYPE_CNAME:
return "CNAME";
+ case DNS_TYPE_SOA:
+ return "SOA";
case DNS_TYPE_TXT:
return "TXT";
case DNS_TYPE_AAAA:
--- a/dnsparser.c
+++ b/dnsparser.c
@@ -12,13 +12,12 @@
struct bpf_program dnsfilter;
char errbuf[PCAP_ERRBUF_SIZE];
+int debug;
-/* magic happens here! */
void
-dns_reader(u_char *args, const struct pcap_pkthdr *header, const u_char *pkt)
+dnsReader(u_char *args, const struct pcap_pkthdr *header, const u_char *pkt)
{
static int packets = 1;
- int head = 0;
Ether e;
Pkt p;
Udp udp;
@@ -25,37 +24,31 @@
Tcp tcp;
Dns dns;
- printf("\n==================%3d ==================\n", packets++);
+ pos = 0;
- parseEther(pkt + head, &e);
- head += ETHER_LEN;
-
-
- parsePkt(pkt + head, &p);
- head += p.headerlen;
+ parseEther(pkt, &e);
+ parsePkt(pkt, &p);
if(p.proto == IPPROTO_UDP)
{
- parseUdp(pkt + head, &udp);
- head += UDP_SIZE;
+ parseUdp(pkt, &udp);
}
else if(p.proto == IPPROTO_TCP)
{
- parseTcp(pkt + head, &tcp);
+ parseTcp(pkt, &tcp);
/* reduce the noise */
if(tcp.flags & (TCP_FLAG_FIN|TCP_FLAG_SYN|TCP_FLAG_ACK) &&
!(tcp.flags & TCP_FLAG_PSH))
{
- printf("skipped noise\n");
+ // printf("skipped noise\n");
return;
}
- head += tcp.offset;
- head += 2; /* there is a dns-over-tcp len field we ignore */
+ pos += 2; /* there is a dns-over-tcp len field we ignore */
}
else
- err(1, "dns_reader(): unknown proto: %d", p.proto);
+ err(1, "dnsReader(): unknown proto: %#x (%d)", p.proto);
if(debug)
{
@@ -66,7 +59,9 @@
fprintf(stderr, "\n");
}
- parseDns(pkt + head, &dns);
+ parseDns(pkt, &dns);
+
+ printf("\n==================%3d ==================\n", packets++);
printf("frame info:\n"
"\tlen: %d\tcaplen: %d\n"
@@ -81,7 +76,7 @@
printUdp(udp);
else if(p.proto == IPPROTO_TCP)
printTcp(tcp);
-
+
printDns(dns);
}
@@ -106,7 +101,7 @@
err(1, "%s: failed to install filter: %s\n", argv[0], pcap_geterr(handle));
- pcap_loop(handle, -1, dns_reader, NULL);
+ pcap_loop(handle, -1, dnsReader, NULL);
pcap_freecode(&dnsfilter);
pcap_close(handle);
--- a/ether.c
+++ b/ether.c
@@ -1,6 +1,6 @@
#include <stdio.h>
#include <stdint.h>
-#include <pcap/pcap.h>
+#include <pcap.h>
#include "common.h"
char*
@@ -21,7 +21,7 @@
int
parseEther(const u_char *pkt, Ether *e)
{
- int pos = 0;
+ e->start = pos;
for(int i = 0 ; i < ETHER_ADDR_LEN ; i++)
e->dst[i] = pkt[i];
@@ -32,8 +32,8 @@
e->src[i] = pkt[i+ETHER_ADDR_LEN];
pos += ETHER_SRC;
- e->type = get2(pkt + pos);
-
+
+ get(pkt, ETHER_TYPE, &e->type);
return 1;
}
@@ -40,7 +40,7 @@
void
printEther(Ether e)
{
- printf("ether info:\n\tdst:");
+ printf("ether info:\n\tdst: ");
for(int i = 0 ; i < ETHER_ADDR_LEN ; i++)
printf("%x:", e.dst[i]);
--- a/pkt.c
+++ b/pkt.c
@@ -24,42 +24,31 @@
int
parsePkt(const u_char *pkt, Pkt *p)
{
- int pos = 0;
+ p->start = pos;
+
+ /* they'r both half a byte */
p->version = IP4_V(pkt[pos]);
p->headerlen = IP4_HL(pkt[pos]) * 4;
pos += PKT_VHL;
- p->dsfield = pkt[pos];
- pos += PKT_DSFIELD;
+ get(pkt, PKT_DSFIELD, &p->dsfield);
+ get(pkt, PKT_LEN, &p->len);
+ get(pkt, PKT_ID, &p->id);
- p->len = get2(pkt + pos);
- pos += PKT_LEN;
-
- p->id = get2(pkt + pos);
- pos += PKT_ID;
-
- p->flags = pkt[pos];
/* flags are just 3 bits, smaller than a byte */
-
+ p->flags = pkt[pos];
+
+ /* this one is 12 bits */
p->fragoffset = get2(pkt + pos);
p->fragoffset &= 0x1FFF;
pos += PKT_FRAGOFFSET;
- p->ttl = pkt[pos];
- pos += PKT_TTL;
+ get(pkt, PKT_TTL, &p->ttl);
+ get(pkt, PKT_PROTO, &p->proto);
+ get(pkt, PKT_SUM, &p->sum);
+ get(pkt, PKT_SRC, &p->srcip);
+ get(pkt, PKT_SRC, &p->dstip);
- p->proto = pkt[pos];
- pos += PKT_PROTO;
-
- p->sum = get2(pkt + pos);
- pos += PKT_SUM;
-
- p->srcip = get4(pkt + pos);
- pos += PKT_SRC;
-
- p->dstip = get4(pkt + pos);
- pos += PKT_DST;
-
return 1;
}
@@ -67,15 +56,19 @@
printPkt(Pkt p)
{
printf("ip packet info:\n"
- "\tversion: 0x%x\theaderlen: 0x%x\tdsfield: %b\n",
+ "\tversion: %#x\theaderlen: %#x\tdsfield: %b\n",
p.version, p.headerlen, p.dsfield);
- printf("\tlen: %d (%x)\tid: 0x%x (%d)\n",
+ printf("\tlen: %d (%#x)\tid: %#x (%d)\n",
p.len, p.len, p.id, p.id);
- printf("\tttl: 0%x (%d)\tproto 0%x (%s)\tsum: 0x%x\n",
+
+ printf("\tflags: %b\tfragment offset: %b\n",
+ p.flags, p.fragoffset);
+
+ printf("\tttl: %#x (%d)\tproto %#x (%s)\tsum: %#x\n",
p.ttl, p.ttl, p.proto, pktTypeToStr(p.proto), p.sum);
-
- printf("\tsrcip: 0x%x\tdstip: 0x%x\n", p.srcip, p.dstip);
+
+ printf("\tsrcip: %#x\tdstip: %#x\n", p.srcip, p.dstip);
}
Parser pktParser = {
--- a/tcp.c
+++ b/tcp.c
@@ -1,40 +1,40 @@
#include <stdio.h>
#include <stdint.h>
-#include <pcap.h>
#include "common.h"
int
parseTcp(const u_char *pkt, Tcp *tcp)
{
- int pos = 0;
+ tcp->start = pos;
- tcp->srcport = get2(pkt + pos);
- pos += TCP_SRCPORT;
+ get(pkt, TCP_SRCPORT, &tcp->src);
+ get(pkt, TCP_DSTPORT, &tcp->dst);
+ get(pkt, TCP_SEQNUM, &tcp->seq);
+ get(pkt, TCP_ACKNUM, &tcp->ack);
- tcp->dstport = get2(pkt + pos);
- pos += TCP_DSTPORT;
-
- tcp->seqnum = get4(pkt + pos);
- pos += TCP_SEQNUM;
-
- tcp->acknum = get4(pkt + pos);
- pos += TCP_ACKNUM;
-
/* offsets are multiplies of 4 (32-bit) values */
- tcp->offset = (pkt[pos] >> 4) * 4;
- pos += TCP_OFFSET;
+ get(pkt, TCP_OFFSET, &tcp->offset);
+ /* some(?) compilers may do logical shift */
+ tcp->offset = (tcp->offset >> 4) & 0xf;
+ tcp->offset *= 4;
- tcp->flags = pkt[pos];
- pos += TCP_FLAGS;
+ get(pkt, TCP_FLAGS, &tcp->flags);
+ get(pkt, TCP_WINSIZE, &tcp->winsize);
+ get(pkt, TCP_SUM, &tcp->sum);
+ get(pkt, TCP_URGPTR, &tcp->urgentptr);
- tcp->winsize = get2(pkt + pos);
- pos += TCP_WINSIZE;
-
- tcp->sum = pkt[pos];
- pos += TCP_SUM;
-
- tcp->urgentptr = get2(pkt + pos);
- pos += TCP_URGPTR;
+ /*
+ * we dont parse tcp options yet,
+ * offset alone shows size of tcp packet (options + headers)
+ * there is no need to add length of headers to pos twice.
+ *
+ * x--------x------------------------x------------x
+ * ^ pkt[0] ^ pkt[tcp.start] ^ pkt[pos] ^ pkt[tcp.offset]
+ *
+ * tcp.start < pos ≤ tcp.offset
+ */
+
+ pos += tcp->offset - (pos - tcp->start);
return 1;
}
@@ -42,13 +42,13 @@
printTcp(Tcp tcp)
{
printf("tcp pkt:\n"
- "\tsrcport: %d\tdstport: %d\n"
- "\tseqnum: %d\tacknum: %d\n"
+ "\tsrc port: %d\tdst port: %d\n"
+ "\tseq num: %u\tack num: %u\n"
"\toffset: %d\tflags: %b (%x)\n"
"\twinsize: %d (%x)\tsum: %d\n",
- tcp.srcport, tcp.dstport,
- tcp.seqnum, tcp.acknum,
+ tcp.src, tcp.dst,
+ tcp.seq, tcp.ack,
tcp.offset, tcp.flags, tcp.flags,
tcp.winsize, tcp.winsize, tcp.sum);
}
--- a/tls.c
+++ b/tls.c
@@ -1,57 +1,580 @@
#include <stdio.h>
#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
#include <pcap.h>
#include "common.h"
int
-parseTlsRecord(const u_char *pkt, Tls tls)
+parseTlsRecord(const u_char *pkt, Tls *tls)
{
- int pos = 0;
+ get(pkt, TLS_RECORD_CONTENTTYPE, &tls->type);
+ get(pkt, TLS_RECORD_VERSION, &tls->version);
+ get(pkt, TLS_RECORD_LEN, &tls->len);
+ return 1;
+}
+
+int
+parseTlsClientHello(const u_char *pkt, TlsHandshake *hs)
+{
+ get(pkt, TLS_HANDSHAKE_VERSION, &hs->version);
+ memmove(hs->random, PKTHEAD, TLS_HANDSHAKE_RANDOM);
+ pos += TLS_HANDSHAKE_RANDOM;
- tls.contenttype = pkt[pos];
- pos += TLS_RECORD_CONTENTTYPE;
+ hs->sessionId = emalloc(sizeof(TlsTuple));
+ hs->sessionId->name = "session id";
+ hs->sessionId->start = pos;
+ get(pkt, TLS_HANDSHAKE_SESSIONID_LEN, &hs->sessionId->len);
+ hs->sessionId->data = memdup(PKTHEAD, hs->sessionId->len);
+ pos += hs->sessionId->len;
- tls.rversion = pkt[pos];
- pos += TLS_RECORD_VERSION;
+ hs->cipherSuits = emalloc(sizeof(TlsTuple));
+ hs->cipherSuits->name = "cipher suits";
+ get(pkt, TLS_HANDSHAKE_CIPHERS_LEN, &hs->cipherSuits->len);
+ hs->cipherSuits->data = memdup(PKTHEAD, hs->cipherSuits->len);
+ pos += hs->cipherSuits->len;
- tls.len = get2(pkt + TLS_RECORD_LEN);
- pos += TLS_RECORD_LEN;
+ hs->compressionMethods = emalloc(sizeof(TlsTuple));
+ hs->compressionMethods->name = "compression methods";
+ get(pkt, TLS_HANDSHAKE_COMP_LEN, &hs->compressionMethods->len);
+ hs->compressionMethods->data = memdup(PKTHEAD, hs->compressionMethods->len);
+ pos += hs->compressionMethods->len;
+ get(pkt, TLS_HANDSHAKE_EXTS_LEN, &hs->extensionsLen);
+ parseTlsExtensions(pkt, hs);
+
return 1;
}
int
-parseTlsHandshake(const u_char *pkt, TlsHandshake hs)
+parseTlsServerHello(const u_char *pkt, TlsHandshake *hs)
{
+ get(pkt, TLS_HANDSHAKE_VERSION, &hs->version);
+ memmove(hs->random, PKTHEAD, TLS_HANDSHAKE_RANDOM);
+ pos += TLS_HANDSHAKE_RANDOM;
+ hs->sessionId = emalloc(sizeof(TlsTuple));
+ hs->sessionId->name = "session id";
+ hs->sessionId->start = pos;
+ get(pkt, TLS_HANDSHAKE_SESSIONID_LEN, &hs->sessionId->len);
+ hs->sessionId->data = memdup(PKTHEAD, hs->sessionId->len);
+ pos += hs->sessionId->len;
+
+ get(pkt, TLS_HANDSHAKE_CIPHER, &hs->cipherSuit);
+ get(pkt, TLS_HANDSHAKE_COMP, &hs->compressionMethod);
+
+ if(pos < hs->start + hs->len)
+ {
+ get(pkt, TLS_HANDSHAKE_EXTS_LEN, &hs->extensionsLen);
+ parseTlsExtensions(pkt, hs);
+ }
+ else
+ {
+ hs->extensionsLen = 0;
+ hs->nExtensions = 0;
+ pos = hs->start + hs->len;
+ pos += TLS_HANDSHAKE_TYPE + TLS_HANDSHAKE_LEN;
+ }
+
+ return 1;
}
int
-parseTls(const u_char *pkt, Tls tls)
+parseTlsCert(const u_char *pkt, TlsCert *cert)
{
- int pos = 0;
+ cert->start = pos;
+ get(pkt, TLS_HANDSHAKE_CERT_LEN, &cert->len);
+
+ cert->der = emalloc(sizeof(Der));
+ cert->der->len = cert->len;
+ parseDer(pkt, cert->der);
+ return 1;
+}
+
+int
+parseTlsCerts(const u_char *pkt, TlsHandshake *hs)
+{
+ get(pkt, TLS_HANDSHAKE_CERTS_LEN, &hs->certsLen);
- parseTlsRecord(pkt + pos, tls);
- parseTlsHandshake(pkt + TLS_RECORD, tls.handshake);
+ hs->certs = emalloc(sizeof(TlsCert) * hs->certsLen);
+ hs->nCerts = 0;
+ for(int tmp = pos ; tmp < hs->certsLen + pos ; hs->nCerts++)
+ {
+ tmp += get4(pkt + tmp) >> 8;
+ tmp += TLS_HANDSHAKE_CERT_LEN;
+ }
+
+ for(int i = 0 ; i < hs->nCerts ; i++)
+ {
+ parseTlsCert(pkt, hs->certs + i);
+ }
+
+ return 1;
}
+int
+parseExtensionData(const u_char *pkt, TlsExtension *e)
+{
+ switch(e->type)
+ {
+ case TLS_EXT_SNI:
+ e->sni = emalloc(sizeof(TlsExtensionSni));
+ get(pkt, TLS_SNI_LISTLEN, &e->sni->listLen);
+ get(pkt, TLS_SNI_TYPE, &e->sni->type);
+ get(pkt, TLS_SNI_LEN, &e->sni->len);
+
+ e->sni->name = emalloc(e->sni->len);
+ strncpy(e->sni->name, PKTHEAD, e->sni->len);
+ pos += e->sni->len;
+ break;
+
+ case TLS_EXT_SUPPORTED_VERS:
+ e->sv = emalloc(sizeof(TlsExtensionSv));
+ get(pkt, TLS_SV_LEN, &e->sv->len);
+
+ e->sv->vers = emalloc(e->sv->len);
+ for(int i = 0 ; i < e->sv->len / 2 ; i++)
+ {
+ get(pkt, TLS_SV_DATA, &e->sv->vers[i]);
+ }
+ break;
+
+ default:
+ e->data = memdup(PKTHEAD, e->len);
+ pos += e->len;
+ break;
+ }
+
+ return 1;
+}
+
+int
+parseTlsExtensions(const u_char *pkt, TlsHandshake *hs)
+{
+ hs->nExtensions = 0;
+
+ for(int tmp = pos ; tmp < hs->extensionsLen + pos ; hs->nExtensions++)
+ {
+ tmp += TLS_HANDSHAKE_EXT_TYPE;
+ tmp += get2(pkt + tmp);
+ tmp += TLS_HANDSHAKE_EXT_LEN;
+ }
+
+ hs->extensions = emalloc(hs->nExtensions * sizeof(TlsExtension));
+ for(int i = 0 ; i < hs->nExtensions ; i++)
+ {
+ hs->extensions[i].start = pos;
+ get(pkt, TLS_HANDSHAKE_EXT_TYPE, &hs->extensions[i].type);
+ get(pkt, TLS_HANDSHAKE_EXT_LEN, &hs->extensions[i].len);
+
+ if(hs->extensions[i].len > 0)
+ {
+ parseExtensionData(pkt, &hs->extensions[i]);
+ }
+ }
+
+ return 1;
+}
+
+int
+parseTlsHandshake(const u_char *pkt, TlsHandshake *hs)
+{
+ hs->start = pos;
+ get(pkt, TLS_HANDSHAKE_TYPE, &hs->type);
+
+ /* len is 3 bytes */
+ get(pkt, TLS_HANDSHAKE_LEN, &hs->len);
+
+ switch(hs->type)
+ {
+ case TLS_CLIENT_HELLO:
+ parseTlsClientHello(pkt, hs);
+ break;
+ case TLS_SERVER_HELLO:
+ parseTlsServerHello(pkt, hs);
+ break;
+ case TLS_CERT:
+ parseTlsCerts(pkt, hs);
+ break;
+ case TLS_NEW_TICKET:
+ case TLS_CLIENT_KEY_EXCH:
+ case TLS_CERT_STATUS:
+ default:
+ pos += hs->len;
+ }
+ return 1;
+}
+
+int
+parseTls(const u_char *pkt, Tls *tls)
+{
+ tls->start = pos;
+ parseTlsRecord(pkt, tls);
+
+ tls->nHandshakes = 0;
+ if(tls->type != TLS_CTYPE_HANDSHAKE || (pktlen < tls->len && pktlen))
+ return 0;
+
+ /* count number of handshakes */
+ for(int tmp = pos ; tmp < tls->len + tls->start + TLS_RECORD ; tls->nHandshakes++)
+ {
+ tmp += TLS_HANDSHAKE_TYPE;
+ tmp += get4(pkt + tmp) >> 8;
+ tmp += TLS_HANDSHAKE_LEN;
+ }
+
+ tls->handshakes = emalloc(tls->nHandshakes * sizeof(TlsHandshake));
+ for(int i = 0 ; i < tls->nHandshakes ; i++)
+ {
+ parseTlsHandshake(pkt, tls->handshakes + i);
+ }
+
+ return 1;
+}
+
+char*
+tlsVersionToStr(uint16_t ver)
+{
+ switch(ver)
+ {
+ case SSL_30:
+ return "SSL v3";
+ case TLS_10:
+ return "TLS v1.0";
+ case TLS_11:
+ return "TLS v1.1";
+ case TLS_12:
+ return "TLS v1.2";
+ case TLS_13:
+ return "TLS v1.3";
+ default:
+ return "Unknown";
+ }
+}
+
+char*
+tlsContentTypeToStr(uint8_t type)
+{
+ switch(type)
+ {
+ case TLS_CTYPE_ALERT:
+ return "Alert";
+ case TLS_CTYPE_HANDSHAKE:
+ return "Handshake";
+ case TLS_CTYPE_APPLICATION_DATA:
+ return "Application data";
+ case TLS_CTYPE_HEARTBEAT:
+ return "heart beat";
+ default:
+ return "Unkown";
+ }
+}
+
+char*
+tlsHandshakeTypeToStr(uint8_t type)
+{
+ switch(type)
+ {
+ case TLS_HELLO_REQ:
+ return "Hello Request";
+ case TLS_CLIENT_HELLO:
+ return "Client Hello ☺";
+ case TLS_SERVER_HELLO:
+ return "Server Hello ☺";
+ case TLS_NEW_TICKET:
+ return "New session ticket";
+ case TLS_CERT:
+ return "Certificate";
+ case TLS_SERVER_KEY_EXCH:
+ return "Server key exchange";
+ case TLS_SERVER_HELLO_DONE:
+ return "Server hello done";
+ case TLS_CLIENT_KEY_EXCH:
+ return "Client key exchange";
+ case TLS_CERT_STATUS:
+ return "OCSP";
+ default:
+ err(1, "tlsHandshakeTypeToStr(%d): unkown type", type);
+ return NULL;
+ }
+}
+
+char*
+tlsExtensionsTypeToStr(uint16_t type)
+{
+ switch(type)
+ {
+ case TLS_EXT_SNI:
+ return "SNI (Server name)";
+ case TLS_EXT_SUPPORTED_VERS:
+ return "Supported versions";
+ case TLS_EXT_PADDING:
+ return "Padding";
+ default:
+ return "Unkown";
+ }
+}
+
void
-printTls(Tcp tcp)
-{/*
- printf("tcp pkt:\n"
- "\tsrcport: %d\tdstport: %d\n"
- "\tseqnum: %d\tacknum: %d\n"
- "\toffset: %d\tflags: %b (%x)\n"
- "\twinsize: %d (%x)\tsum: %d\n",
+printTlsTuple(TlsTuple tuple)
+{
+ printf("\ttls tuple (%s):\n"
+ "\t\tlen: %d (%#x)\n",
+ tuple.name,
+ tuple.len, tuple.len);
- tcp.srcport, tcp.dstport,
- tcp.seqnum, tcp.acknum,
- tcp.offset, tcp.flags, tcp.flags,
- tcp.winsize, tcp.winsize, tcp.sum);
-*/}
+ printf("\t\tdata: ");
+ for(int i = 0 ; i < tuple.len ; i++)
+ printf("%0x", tuple.data[i]);
+
+ printf("\n");
+}
+void
+printTlsExtension(TlsExtension e)
+{
+ if(debug)
+ {
+ switch(e.type)
+ {
+ case TLS_EXT_SNI:
+ printf("list len: %d\ttype: %d\tlen: %d\tname: %s",
+ e.sni->listLen, e.sni->type, e.sni->len, e.sni->name);
+
+ break;
+ case TLS_EXT_SUPPORTED_VERS:
+ printf("len: %d (%#x)\tdata: ", e.sv->len, e.sv->len);
+ for(int i = 0 ; i < e.sv->len / 2; i++)
+ printf("%#x ", e.sv->vers[i]);
+ break;
+ default:
+ printf("data: ");
+ for(int i = 0 ; i < e.len ; i++)
+ printf("%x", e.data[i]);
+ break;
+ }
+ }
+ else
+ {
+ switch(e.type)
+ {
+ case TLS_EXT_SNI:
+ printf("name: %s", e.sni->name);
+ break;
+
+ case TLS_EXT_SUPPORTED_VERS:
+ for(int i = 0 ; i < e.sv->len / 2; i++)
+ printf("%s (%#x) ", tlsVersionToStr(e.sv->vers[i]), e.sv->vers[i]);
+ break;
+ default:
+ break;
+ }
+ }
+ printf("\n");
+}
+
+void
+printTlsExtensions(TlsHandshake hs)
+{
+ TlsExtension *e = hs.extensions;
+
+ if(debug)
+ {
+ printf("\t\ttls extensions:\n"
+ "\t\tlen: %d\tnExtensions: %d (%#x)\n",
+ hs.extensionsLen, hs.nExtensions, hs.nExtensions);
+
+ for(int i = 0 ; i < hs.nExtensions ; i++)
+ {
+ //if(strcmp("Unkown", tlsExtensionsTypeToStr(e->type)) && e->len > 0)
+ {
+ printf("\t\t\textension %i: start: %d (%#x)\n"
+ "\t\t\t\ttype: %d (%s)\tlen: %d (%#x)\n"
+ "\t\t\t\t",
+
+ i, e->start, e->start,
+ e->type, tlsExtensionsTypeToStr(e->type), e->len, e->len);
+
+ printTlsExtension(*e);
+ }
+ e++;
+ }
+ }
+ else
+ {
+ printf("\t\ttls extensions:\tnExtensions: %d\n",
+ hs.nExtensions);
+
+ for(int i = 0 ; i < hs.nExtensions ; i++)
+ {
+ if((e->type == TLS_EXT_SNI || e->type == TLS_EXT_SUPPORTED_VERS) && e->len > 0)
+ {
+ printf("\t\t\textension %i: type: %s\t",
+ i, tlsExtensionsTypeToStr(e->type));
+
+ printTlsExtension(*e);
+ }
+ e++;
+ }
+ }
+}
+
+void
+printTlsHandshake(TlsHandshake hs)
+{
+ if(debug)
+ {
+ printf("tls handshake:\n"
+ "\ttype: %s (%d)\tlen: %d (%#x)\tstart: %d (%#x)\n",
+
+ tlsHandshakeTypeToStr(hs.type), hs.type, hs.len, hs.len, hs.start, hs.start);
+ switch(hs.type)
+ {
+ case TLS_CLIENT_HELLO:
+
+ printf("\tversion: %#04x\n", hs.version);
+
+ printTlsTuple(*(hs.sessionId));
+
+ printf("\trandom: ");
+ for(int i = 0 ; i < TLS_HANDSHAKE_RANDOM ; i++)
+ printf("%x", hs.random[i]);
+
+ printTlsTuple(*hs.cipherSuits);
+ printTlsTuple(*hs.compressionMethods);
+ printTlsExtensions(hs);
+ break;
+
+ case TLS_SERVER_HELLO:
+ printf("\tversion: %#04x\n", hs.version);
+
+ printTlsTuple(*(hs.sessionId));
+
+ printf("\trandom: ");
+ for(int i = 0 ; i < TLS_HANDSHAKE_RANDOM ; i++)
+ printf("%x", hs.random[i]);
+
+ printf("\tcipherSuit: %#x\tcompressionMethod: %#x\n",
+ hs.cipherSuit, hs.compressionMethod);
+ printTlsExtensions(hs);
+ break;
+
+ case TLS_CERT:
+ printf("\tcertsLen: %d (%#x), nCerts: %d (%#x)\n",
+ hs.certsLen, hs.certsLen, hs.nCerts, hs.nCerts);
+
+ printf("\tcerts:\n");
+ for(int i = 0 ; i < hs.nCerts ; i++)
+ {
+ printf("\t\t cert %d:\n", i);
+ printf("\t\t\tstart: %d (%#x)\t len: %d (%#x)\n",
+ hs.certs->start, hs.certs->start, hs.certs->len, hs.certs->len);
+ printDer(*hs.certs[i].der);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ printf("tls handshake:\ttype: %s\n",
+ tlsHandshakeTypeToStr(hs.type));
+
+ switch(hs.type)
+ {
+ case TLS_CLIENT_HELLO:
+
+ printf("\n\tversion: %s\n", tlsVersionToStr(hs.version));
+ printTlsExtensions(hs);
+ break;
+
+ case TLS_SERVER_HELLO:
+ printf("\n\tversion: %s\n", tlsVersionToStr(hs.version));
+ printTlsExtensions(hs);
+ break;
+
+ case TLS_CERT:
+ printf("\tnCerts: %d\n",
+ hs.nCerts);
+
+ printf("\tcerts:\n");
+ for(int i = 0 ; i < hs.nCerts ; i++)
+ {
+ printf("\t\t***** cert %d:*****\n", i);
+ printDer(*hs.certs[i].der);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void
+printTlsRecord(Tls tls)
+{
+ if(debug)
+ {
+ printf("tls record:\n"
+ "\ttype: %d\t\tversion: %#x\t"
+ "len: %d (%#x), nHandshakes: %d\n",
+
+ tls.type, tls.version,
+ tls.len, tls.len, tls.nHandshakes);
+ }
+ else
+ {
+ printf("tls: content type: %s\tversion %s\n",
+ tlsContentTypeToStr(tls.type), tlsVersionToStr(tls.version));
+ }
+}
+
+void
+printTls(Tls tls)
+{
+
+ if(tls.type == TLS_CTYPE_HANDSHAKE)
+ {
+ printTlsRecord(tls);
+ for(int i = 0 ; i < tls.nHandshakes ; i++)
+ {
+ printTlsHandshake(tls.handshakes[i]);
+ }
+ }
+}
+
+/* keep this with sync with parsers */
+void
+freeTls(Tls *tls)
+{
+ TlsHandshake *hs;
+ TlsExtension *e;
+
+ for(int i = 0 ; i < tls->nHandshakes ; i++)
+ {
+ hs = tls->handshakes + i;
+ for(int j = 0 ; j < hs->nExtensions ; j++)
+ {
+ e = hs->extensions + j;
+ switch(e->type)
+ {
+ case TLS_EXT_SNI:
+ case TLS_EXT_SUPPORTED_VERS:
+ break;
+ default:
+ // free(e->data);
+ }
+ // free(e);
+ }
+ free(hs);
+ }
+ /* do not free tls! */
+}
+
Parser tlsParser = {
.name = "tls",
.parse = parseTls,
- .print = printTcp,
+ .print = printTls,
+ .free = freeTls,
};
\ No newline at end of file
--- a/udp.c
+++ b/udp.c
@@ -6,20 +6,13 @@
int
parseUdp(const u_char *pkt, Udp *udp)
{
- int pos = 0;
+ udp->start = pos;
- udp->srcport = get2(pkt + pos);
- pos += UDP_SRCPORT;
+ get(pkt, UDP_SRCPORT, &udp->src);
+ get(pkt, UDP_DSTPORT, &udp->dst);
+ get(pkt, UDP_LEN, &udp->len);
+ get(pkt, UDP_SUM, &udp->sum);
- udp->dstport = get2(pkt + pos);
- pos += UDP_DSTPORT;
-
- udp->len = get2(pkt + pos);
- pos += UDP_LEN;
-
- udp->sum = get2(pkt + pos);
- pos += UDP_SUM;
-
return 1;
}
@@ -28,8 +21,8 @@
{
printf("udp pkt:\n"
"\tsrcport: %d\tdstport: %d\n"
- "\tlen: %d\tsum 0x%x\n",
- udp.srcport, udp.dstport, udp.len, udp.sum);
+ "\tlen: %d\tsum 0x%#x\n",
+ udp.src, udp.dst, udp.len, udp.sum);
}
Parser udpParser = {