wm: dnsparser

ref: 16d016b87e7783cecedb1078c1327fa1244da4d7
dir: /common.h/

View raw version
#include <openssl/x509v3.h>
#include <pcap.h>

/*
 * each parser have at least these two
 * they may have more functions internally and externally
 */
typedef struct
{
	char *name;
	int (*parse)();
	void (*print)();
	void (*free)();
}Parser;

extern pcap_t *handle;
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];
	uint16_t type;
}Ether;

char* etherTypeToStr(uint16_t frame);
int parseEther(const u_char *pkt, Ether *e);
void printEther(Ether e);

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;
	uint8_t len;
	uint16_t id;
	uint8_t flags;
	uint16_t fragoffset;
	uint8_t ttl;
	uint8_t proto; /* UDP, TCP */
	uint16_t sum; /* checksum of packet */

	uint32_t srcip;
	uint32_t dstip;
}Pkt;

#define IP4_HL(octet)	(octet & 0x0f)
#define IP4_V(octet)	(octet >> 4) 

int parsePkt(const u_char *pkt, Pkt *p);
char* pktTypeToStr(const u_char pkt);
void printPkt(Pkt p);

extern Parser pktParser;

/* udp.c */
enum
{
	/* 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;

int parseUdp(const u_char *pkt, Udp *udp);
void printUdp(Udp udp);

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
{
	uint32_t start;
	
	uint16_t src;
	uint16_t dst;

	uint32_t seq;
	uint32_t ack;
	
	uint16_t offset;
	uint16_t flags;
	
	uint16_t winsize;
	uint8_t sum;
	
	uint16_t urgentptr;
	/* we don't care about options */
}Tcp;

int parseTcp(const u_char *pkt, Tcp *tcp);
void printTcp(Tcp tcp);

extern Parser tcpParser;

/*
 * 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;
	
	/* count(s) */
	uint16_t nQueries;
	uint16_t nAnswers;
	uint16_t nAuthRR;
	uint16_t nAddRR;
	
	char domain[DNS_MAX_LEN+1];
	
	uint16_t type;
	uint16_t class;
	uint32_t ttl;
	uint32_t len;
	union
	{
		/* A */
		uint8_t ip[4];

		/* AAAA */
		uint16_t ip6[8];

		/* CNAME */
		u_char cname[DNS_MAX_LEN+1];
	};
}Dns;

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;
}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[TLS_HANDSHAKE_RANDOM];
	
	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
{
	uint32_t start;
	
	uint8_t type;
	uint16_t version; /* record version */
	uint16_t len;
	
	uint8_t nHandshakes;
	TlsHandshake *handshakes;
}Tls;

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;