Projects STRLCPY Vault-8-Hive Commits ea327e4e
🤬
  • ■ ■ ■ ■ ■ ■
    server/decode_dns.c
     1 +#include "decode_dns.h"
     2 + 
     3 +char *extract_dns_name(void *, char *);
     4 +char dnsname[NS_MAXDNAME];
     5 + 
     6 +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     7 + 
     8 +/*!
     9 + * @brief decode_dns accepts a pointer to the start of the DNS header and returns a pointer to a character string that is the resolved IP address
     10 + *
     11 + * See RFC 1035 section 4 for details on DNS message formats
     12 + *
     13 + * @param dns pointer to the DNS response starting with the header
     14 + * @return a pointer the the resolved IP address (Note: This returns a pointer to allocated memory that must be freed after use.
     15 + */
     16 +char *decode_dns(void *dns)
     17 +{
     18 + void *dnsdata = NULL; // Pointer to start of DNS data
     19 + DNS_hdr *dnshdr = NULL; // Pointer to start of DNS header
     20 + char *resolved_address;
     21 + 
     22 + dnshdr = (DNS_hdr *) dns;
     23 + dnsdata = (void *)dnshdr + sizeof(DNS_hdr); // Pointer to start of DNS data
     24 + if ( DNS_QR(dnshdr)) { // Determine if it's a reply and, if so, decode it.
     25 + char *dnsname;
     26 + int i, type;
     27 + int q_records = ntohs(dnshdr->qdcount);
     28 + int a_records = ntohs(dnshdr->ancount);
     29 + 
     30 + // Process DNS Query Records
     31 + for (i = 0; i < q_records; i++) { // Process q_records query records
     32 + dnsname = dnsdata;
     33 + if (*((int8_t *)dnsdata) > 0) // Determine if dnsdata points to an encoded name or to a pointer
     34 + dnsdata += strlen(dnsname) + 1; // Skip over the name
     35 + else // Otherwise, skip over the pointer
     36 + dnsdata += 2; // dnsdata now points to query type
     37 + type = DNS_type(dnsdata);
     38 + 
     39 + switch(type) {
     40 + case ns_t_a: // IPv4 Address records
     41 + DLX(4, printf("\t DNS Response\tQ: %s\n", extract_dns_name(dns, dnsname)));
     42 + break;
     43 + 
     44 +#if 0 // No support for IPv6
     45 + case ns_t_aaaa: // IPv6 AAAA queries
     46 + DLX(6, printf("\t DNS Response\tIPv6 Q: %s\n", extract_dns_name(dns, dnsname)));
     47 + break;
     48 +#endif
     49 + default: //Return without action for all other record types
     50 + return NULL;
     51 + }
     52 + dnsdata += sizeof(ns_query_typeclass); // Reposition dnsdata
     53 + }
     54 + if ( DNS_RCODE(dnshdr) ) {
     55 + switch (DNS_RCODE(dnshdr)) {
     56 + case 1: DLX(4, printf("\t\t\tERROR: Name server unable to interpret query.\n")); break;
     57 + case 2: DLX(4, printf("\t\t\tERROR: Name server failure\n")); break;
     58 + case 3: if (DNS_AA(dnshdr)) DLX(6, printf("\t\t\tA: No such name\n")); break;
     59 + case 5: DLX(4, printf("\t\t\tERROR: Name server refused request.\n")); break;
     60 + 
     61 + default:
     62 + DLX(6, printf("\t\t\tERROR: Undefined response code %i returned.\n", (uint8_t)DNS_RCODE(dnshdr))); break;
     63 + }
     64 + }
     65 +#if 0
     66 + if ( DNS_ZERO(dnshdr) ) // Just checking...
     67 + DLX(6, printf("\t\t*** ALERT *** Normally zero reserved DNS header field contains data: %i\n", DNS_ZERO(dnshdr)));
     68 +#endif
     69 + 
     70 + // Process DNS Answer Records
     71 + for (i = 0; i < a_records; i++) { // Process a_records answer records
     72 + DNS_rr_data *rr;
     73 + void *rdata;
     74 + struct in_addr ipaddr;
     75 +// struct in6_addr ip6addr;
     76 + char addrbuf[INET6_ADDRSTRLEN] = {0};
     77 + 
     78 + dnsname = dnsdata;
     79 + if (*((int8_t *)dnsdata) > 0) // Determine if dnsdata points to an encoded name or to a pointer
     80 + dnsdata += strlen(dnsname) + 1; // Skip over the name
     81 + else // Otherwise, skip over the pointer
     82 + dnsdata += 2; // dnsdata now points to query type
     83 + type = ntohs(((ns_query_typeclass *)dnsdata)->type);
     84 + rr = (DNS_rr_data *) dnsdata;
     85 + rdata = (void *) rr + sizeof(struct _dns_rr_data);
     86 + switch (type) {
     87 + case ns_t_a: // IPv4 Address Record
     88 + memcpy(&ipaddr, rdata, ntohs(rr->rdlength));
     89 + if (inet_ntop(AF_INET, (const void *)&ipaddr, addrbuf, INET6_ADDRSTRLEN) == NULL)
     90 + perror("IPv4 address decode error");
     91 + else
     92 + DLX(6, printf("\t\t\t A: %s\tTTL: %i\n", addrbuf, ntohl(rr->ttl)));
     93 + if ((resolved_address = (char *)calloc(strlen(addrbuf)+1, 1)) == NULL) {
     94 + DLX(4, printf("ERROR: calloc failed\n"));
     95 + }
     96 + strcpy(resolved_address, addrbuf);
     97 + DLX(4, printf("\tResolved Address: %s\n", resolved_address));
     98 + return resolved_address;
     99 + break;
     100 + 
     101 +#if 0 // No support for IPv6
     102 + case ns_t_aaaa: // IPv6 Address Record
     103 + memcpy(&ip6addr, rdata, ntohs(rr->rdlength));
     104 + if (inet_ntop(AF_INET6, (const void *)&ip6addr, addrbuf, INET6_ADDRSTRLEN) == NULL)
     105 + perror("IPv6 address decode error");
     106 + else
     107 + DLX(6, printf("\t\t\t A: %s\tTTL: %i\n", addrbuf, ntohl(rr->ttl)));
     108 + if ((resolved_address = (char *)malloc(strlen(addrbuf)+1)) == NULL) {
     109 + DLX(4, printf("ERROR: malloc failed\n"));
     110 + }
     111 + strcpy(resolved_address, addrbuf);
     112 + return resolved_address;
     113 + break;
     114 +#endif
     115 + default: // Other record types not handled
     116 + DLX(4, printf("\t\t\tResource record data of type %d not decoded.\n", type));
     117 + break;
     118 + 
     119 + }
     120 + dnsdata = rdata + ntohs(rr->rdlength); // Reposition dnsdata pointer for next record
     121 + }
     122 + }
     123 + return NULL;
     124 +}
     125 + 
     126 +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     127 +//
     128 +// dnsname decodes the DNS name pointed to by namep and returns it in staticly allocated dnsname.
     129 +// Note that this name gets overwritten for each call.
     130 +/*!
     131 + * @brief Decode
     132 + * @param dns
     133 + * @param namep
     134 + * @return
     135 + */
     136 +char *extract_dns_name(void *dns, char *namep) {
     137 + char *p;
     138 + int8_t len;
     139 + uint16_t ptr;
     140 + 
     141 + p = dnsname;
     142 + len = (int8_t) *namep; // Use first byte as length
     143 + while (len) { // If 0, then stop
     144 + if (len < 0) { // If length is negative, then it's a pointer
     145 + ptr = ntohs(*((uint16_t *) namep)) & 0x3FFF; // Compute pointer as an offset into the DNS record
     146 + namep = dns + ptr;
     147 + len = (int8_t) *namep;
     148 + continue;
     149 + }
     150 + strncpy(p, ++namep, len);
     151 + p += len;
     152 + *p++ = '.';
     153 + namep += len;
     154 + len = (int8_t) *namep;
     155 + }
     156 + *--p='\0';
     157 + return dnsname;
     158 +}
     159 + 
  • ■ ■ ■ ■ ■ ■
    server/decode_dns.h
     1 +#ifndef _DECODE_DNS_
     2 +#define _DECODE_DNS_
     3 +#include <stdint.h>
     4 +#include <netinet/in.h>
     5 +#include <stdio.h>
     6 +#include <string.h>
     7 +#include <stdlib.h>
     8 +#include <arpa/inet.h>
     9 +#include "debug.h"
     10 +///////////////////////////////////////////////////////////////////////////////////////////////////
     11 +// DNS
     12 +///////
     13 +// Definitions in this section were taken from /usr/include/arpa/nameser.h and modified as needed.
     14 +// Many of the definitions found here may not actually be used.
     15 + 
     16 +/*
     17 + * Define constants based on RFC 883, RFC 1034, RFC 1035
     18 + */
     19 +#define NS_PACKETSZ 512 /* default UDP packet size */
     20 +#define NS_MAXDNAME 1025 /* maximum domain name */
     21 +#define NS_MAXMSG 65535 /* maximum message size */
     22 +#define NS_MAXCDNAME 255 /* maximum compressed domain name */
     23 +#define NS_MAXLABEL 63 /* maximum length of domain label */
     24 +#define NS_HFIXEDSZ 12 /* #/bytes of fixed data in header */
     25 +#define NS_QFIXEDSZ 4 /* #/bytes of fixed data in query */
     26 +#define NS_RRFIXEDSZ 10 /* #/bytes of fixed data in r record */
     27 +#define NS_INT32SZ 4 /* #/bytes of data in a uint32_t */
     28 +#define NS_INT16SZ 2 /* #/bytes of data in a uint16_t */
     29 +#define NS_INT8SZ 1 /* #/bytes of data in a uint8_t */
     30 +#define NS_INADDRSZ 4 /* IPv4 T_A */
     31 +#define NS_IN6ADDRSZ 16 /* IPv6 T_AAAA */
     32 +#define NS_CMPRSFLGS 0xc0 /* Flag bits indicating name compression. */
     33 +#define NS_DEFAULTPORT 53 /* For both TCP and UDP. */
     34 + 
     35 +// Message header
     36 +typedef struct {
     37 + uint16_t id; /* query identification number */
     38 + uint16_t flags; /* flags */
     39 + uint16_t qdcount; /* number of question entries */
     40 + uint16_t ancount; /* number of answer entries */
     41 + uint16_t nscount; /* number of authority entries */
     42 + uint16_t arcount; /* number of resource entries */
     43 +} DNS_hdr;
     44 + 
     45 +/*
     46 + * Macros for subfields of flag fields.
     47 + */
     48 +#define DNS_QR(np) (ntohs((np)->flags) & 0x8000) /* response flag */
     49 +#define DNS_OPCODE(np) ((ntohs((np)->flags) >> 11) & 0xF) /* purpose of message */
     50 +#define DNS_AA(np) (ntohs((np)->flags) & 0x0400) /* authoritative answer */
     51 +#define DNS_TC(np) (ntohs((np)->flags) & 0x0200) /* truncated message */
     52 +#define DNS_RD(np) (ntohs((np)->flags) & 0x0100) /* recursion desired */
     53 + 
     54 +#define DNS_RA(np) (ntohs((np)->flags) & 0x80) /* recursion available */
     55 +#define DNS_AD(np) (ntohs((np)->flags) & 0x20) /* authentic data from named */
     56 +#define DNS_CD(np) (ntohs((np)->flags) & 0x10) /* checking disabled by resolver */
     57 +#define DNS_ZERO(np) ((ntohs((np)->flags) >> 4) & 0x7) /* 3 bits should be zero */
     58 +#define DNS_RCODE(np) (ntohs((np)->flags) & 0xF) /* response code */
     59 + 
     60 +// Resource record data structure
     61 +struct _dns_rr_data {
     62 + uint16_t type;
     63 + uint16_t rr_class;
     64 + uint32_t ttl;
     65 + uint16_t rdlength;
     66 +} __attribute__((packed));
     67 +typedef struct _dns_rr_data DNS_rr_data;
     68 + 
     69 +#if 0
     70 +// Broken code that isn't used anyway
     71 +typedef struct {
     72 + char name[NS_MAXDNAME]; // <--- this doesn't work here
     73 + DNS_rr_data rrmetadata;
     74 + const u_char *rdata;
     75 +} DNS_rr;
     76 +#endif
     77 + 
     78 +/* Accessor macros - this is part of the public interface. */
     79 +#define ns_rr_name(rr) (((rr).name[0] != '\0') ? (rr).name : ".")
     80 +#define ns_rr_type(rr) ((ns_type)((rr).type + 0))
     81 +#define ns_rr_class(rr) ((ns_class)((rr).rr_class + 0))
     82 +#define ns_rr_ttl(rr) ((rr).ttl + 0)
     83 +#define ns_rr_rdlen(rr) ((rr).rdlength + 0)
     84 +#define ns_rr_rdata(rr) ((rr).rdata + 0)
     85 + 
     86 +/*%
     87 + * These don't have to be in the same order as in the packet flags word,
     88 + * and they can even overlap in some cases, but they will need to be kept
     89 + * in synch with ns_parse.c:ns_flagdata[].
     90 + */
     91 +typedef enum __ns_flag {
     92 + ns_f_qr, /*%< Question/Response. */
     93 + ns_f_opcode, /*%< Operation code. */
     94 + ns_f_aa, /*%< Authoritative Answer. */
     95 + ns_f_tc, /*%< Truncation occurred. */
     96 + ns_f_rd, /*%< Recursion Desired. */
     97 + ns_f_ra, /*%< Recursion Available. */
     98 + ns_f_z, /*%< MBZ. */
     99 + ns_f_ad, /*%< Authentic Data (DNSSEC). */
     100 + ns_f_cd, /*%< Checking Disabled (DNSSEC). */
     101 + ns_f_rcode, /*%< Response code. */
     102 + ns_f_max
     103 +} ns_flag;
     104 + 
     105 +/*%
     106 + * Currently defined opcodes.
     107 + */
     108 +typedef enum __ns_opcode {
     109 + ns_o_query = 0, /*%< Standard query. */
     110 + ns_o_iquery = 1, /*%< Inverse query (deprecated/unsupported). */
     111 + ns_o_status = 2, /*%< Name server status query (unsupported). */
     112 + /* Opcode 3 is undefined/reserved. */
     113 + ns_o_notify = 4, /*%< Zone change notification. */
     114 + ns_o_update = 5, /*%< Zone update message. */
     115 + ns_o_max = 6
     116 +} ns_opcode;
     117 + 
     118 +/*%
     119 + * Currently defined response codes.
     120 + */
     121 +typedef enum __ns_rcode {
     122 + ns_r_noerror = 0, /*%< No error occurred. */
     123 + ns_r_formerr = 1, /*%< Format error. */
     124 + ns_r_servfail = 2, /*%< Server failure. */
     125 + ns_r_nxdomain = 3, /*%< Name error. */
     126 + ns_r_notimpl = 4, /*%< Unimplemented. */
     127 + ns_r_refused = 5, /*%< Operation refused. */
     128 + /* these are for BIND_UPDATE */
     129 + ns_r_yxdomain = 6, /*%< Name exists */
     130 + ns_r_yxrrset = 7, /*%< RRset exists */
     131 + ns_r_nxrrset = 8, /*%< RRset does not exist */
     132 + ns_r_notauth = 9, /*%< Not authoritative for zone */
     133 + ns_r_notzone = 10, /*%< Zone of record different from zone section */
     134 + ns_r_max = 11,
     135 + /* The following are EDNS extended rcodes */
     136 + ns_r_badvers = 16,
     137 + /* The following are TSIG errors */
     138 + ns_r_badsig = 16,
     139 + ns_r_badkey = 17,
     140 + ns_r_badtime = 18
     141 +} ns_rcode;
     142 + 
     143 + 
     144 +/*
     145 + * Currently defined type values for resources and queries.
     146 + */
     147 +typedef enum __ns_type {
     148 + ns_t_invalid = 0, /* Cookie. */
     149 + ns_t_a = 1, /* Host address. */
     150 + ns_t_ns = 2, /* Authoritative server. */
     151 + ns_t_md = 3, /* Mail destination. */
     152 + ns_t_mf = 4, /* Mail forwarder. */
     153 + ns_t_cname = 5, /* Canonical name. */
     154 + ns_t_soa = 6, /* Start of authority zone. */
     155 + ns_t_mb = 7, /* Mailbox domain name. */
     156 + ns_t_mg = 8, /* Mail group member. */
     157 + ns_t_mr = 9, /* Mail rename name. */
     158 + ns_t_null = 10, /* Null resource record. */
     159 + ns_t_wks = 11, /* Well known service. */
     160 + ns_t_ptr = 12, /* Domain name pointer. */
     161 + ns_t_hinfo = 13, /* Host information. */
     162 + ns_t_minfo = 14, /* Mailbox information. */
     163 + ns_t_mx = 15, /* Mail routing information. */
     164 + ns_t_txt = 16, /* Text strings. */
     165 + ns_t_rp = 17, /* Responsible person. */
     166 + ns_t_afsdb = 18, /* AFS cell database. */
     167 + ns_t_x25 = 19, /* X_25 calling address. */
     168 + ns_t_isdn = 20, /* ISDN calling address. */
     169 + ns_t_rt = 21, /* Router. */
     170 + ns_t_nsap = 22, /* NSAP address. */
     171 + ns_t_nsap_ptr = 23, /* Reverse NSAP lookup (deprecated). */
     172 + ns_t_sig = 24, /* Security signature. */
     173 + ns_t_key = 25, /* Security key. */
     174 + ns_t_px = 26, /* X.400 mail mapping. */
     175 + ns_t_gpos = 27, /* Geographical position (withdrawn). */
     176 + ns_t_aaaa = 28, /* Ip6 Address. */
     177 + ns_t_loc = 29, /* Location Information. */
     178 + ns_t_nxt = 30, /* Next domain (security). */
     179 + ns_t_eid = 31, /* Endpoint identifier. */
     180 + ns_t_nimloc = 32, /* Nimrod Locator. */
     181 + ns_t_srv = 33, /* Server Selection. */
     182 + ns_t_atma = 34, /* ATM Address */
     183 + ns_t_naptr = 35, /* Naming Authority PoinTeR */
     184 + ns_t_kx = 36, /* Key Exchange */
     185 + ns_t_cert = 37, /* Certification record */
     186 + ns_t_a6 = 38, /* IPv6 address (deprecated, use ns_t_aaaa) */
     187 + ns_t_dname = 39, /* Non-terminal DNAME (for IPv6) */
     188 + ns_t_sink = 40, /* Kitchen sink (experimentatl) */
     189 + ns_t_opt = 41, /* EDNS0 option (meta-RR) */
     190 + ns_t_apl = 42, /* Address prefix list (RFC3123) */
     191 + ns_t_tkey = 249, /* Transaction key */
     192 + ns_t_tsig = 250, /* Transaction signature. */
     193 + ns_t_ixfr = 251, /* Incremental zone transfer. */
     194 + ns_t_axfr = 252, /* Transfer zone of authority. */
     195 + ns_t_mailb = 253, /* Transfer mailbox records. */
     196 + ns_t_maila = 254, /* Transfer mail agent records. */
     197 + ns_t_any = 255, /* Wildcard match. */
     198 + ns_t_zxfr = 256, /* BIND-specific, nonstandard. */
     199 + ns_t_max = 65536
     200 +} ns_type;
     201 + 
     202 +#define DNS_type(p) (ntohs(((ns_query_typeclass *)p)->type))
     203 +typedef struct __ns_query_typeclass {
     204 + uint16_t type;
     205 + uint16_t class;
     206 +} ns_query_typeclass;
     207 +#endif
     208 + 
     209 +char *decode_dns(void *dns);
     210 + 
Please wait...
Page is in error, reload to recover