1# Copyright (c) 2003-2016 CORE Security Technologies 2# 3# This software is provided under under a slightly modified version 4# of the Apache Software License. See the accompanying LICENSE file 5# for more information. 6# 7# Author: 8# Andres Blanco 9# Gustavo Moreira 10 11# 12# RFCs for the DNS Server service 13# 14# 1034 - Domain Names -- Concepts and Facilities [http://www.faqs.org/rfcs/rfc1034.html] 15# 1035 - Domain Names -- Implementation and Specification [http://www.faqs.org/rfcs/rfc1035.html] 16# 1123 - Requirements for Internet Hosts -- Application and Support [http://www.faqs.org/rfcs/rfc1123.html] 17# 1886 - DNS Extensions to Support IP Version 6 [http://www.faqs.org/rfcs/rfc1886.html] 18# 1995 - Incremental Zone Transfer in DNS [http://www.faqs.org/rfcs/rfc1995.html] 19# 1996 - A Mechanism for Prompt Notification of Zone Changes (DNS NOTIFY) [http://www.faqs.org/rfcs/rfc1996.html] 20# 2136 - Dynamic Updates in the Domain Name System (DNS UPDATE) [http://www.faqs.org/rfcs/rfc2136.html] 21# 2181 - Clarifications to the DNS Specification [http://www.faqs.org/rfcs/rfc2181.html] 22# 2308 - Negative Caching of DNS Queries (DNS NCACHE) [http://www.faqs.org/rfcs/rfc2308.html] 23# 2535 - Domain Name System Security Extensions (DNSSEC) [http://www.faqs.org/rfcs/rfc2535.html] 24# 2671 - Extension Mechanisms for DNS (EDNS0) [http://www.faqs.org/rfcs/rfc2671.html] 25# 2782 - A DNS RR for specifying the location of services (DNS SRV) [http://www.faqs.org/rfcs/rfc2782.html] 26# 2930 - Secret Key Establishment for DNS (TKEY RR) [http://www.faqs.org/rfcs/rfc2930.html] 27# 3645 - Generic Security Service Algorithm for Secret Key Transaction Authentication for DNS (GSS-TSIG) [http://www.faqs.org/rfcs/rfc3645.html] 28# 3646 - DNS Configuration options for Dynamic Host Configuration Protocol for IPv6 (DHCPv6) [http://www.faqs.org/rfcs/rfc3646.html] 29# 30 31import socket 32import struct 33 34from ImpactPacket import ProtocolPacket 35 36 37class DNSFlags(): 38 'Bitmap with the flags of a dns packet.' 39 # QR - Query/Response - 1 bit 40 QR_QUERY = int("0000000000000000", 2) 41 QR_RESPONSE = int("1000000000000000", 2) 42 # OP - Opcode - 4 bits 43 OP_STANDARD_QUERY = int("0000000000000000", 2) # Standard query. 44 OP_INVERSE_QUERY = int("0100000000000000", 2) # Inverse query. 45 OP_STATUS_QUERY = int("0010000000000000", 2) # Server status request. 46 OP_NOTIFY = int("0000100000000000", 2) # Notify. 47 OP_UPDATE = int("0100100000000000", 2) # Update. 48 # AA - Authority Answer - 1 bit 49 AA_NOT_AUTH_ANSWER = int("0000000000000000", 2) # Not authoritative. 50 AA_AUTH_ANSWER = int("0000010000000000", 2) # Is authoritative. 51 # TC - Truncated - 1 bit 52 TC_NOT_TRUNCATED = int("0000000000000000", 2) # Not truncated. 53 TC_TRUNCATED = int("0000001000000000", 2) # Message truncated. 54 # RD - Recursion Desired - 1 bit 55 RD_NOT_RECURSIVE_QUERY = int("0000000000000000", 2) # Recursion not desired. 56 RD_RECURSIVE_QUERY = int("0000000100000000", 2) # Recursion desired. 57 # RA - Recursion Available - 1 bit 58 RA_NOT_AVAILABLE = int("0000000000000000", 2) # Recursive query support not available. 59 RA_AVAILABLE = int("0000000010000000", 2) # Recursive query support available. 60 # Z - 3 bits 61 Z = int("0000000000000000", 2) 62 # AD - Authenticated Data - 1 bit 63 AUTHENTICATED_DATA = int("0000000000100000", 2) 64 # CD - Checking Disabled - 1 bit 65 CHECKING_DISABLED = int("0000000000010000", 2) 66 # RCODE - 4 bits 67 RCODE_NO_ERROR = int("0000000000000000", 2) # The request completed successfully. 68 RCODE_FORMAT_ERROR = int("0000000000001000", 2) # The name server was unable to interpret the query. 69 RCODE_SERVER_FAILURE = int("0000000000000100", 2) # The name server was unable to process this query due to a problem with the name server. 70 RCODE_NAME_ERROR = int("0000000000001100", 2) # Meaningful only for responses from an authoritative name server, this code signifies that the domain name referenced in the query does not exist. 71 RCODE_NOT_IMPLEMENTED = int("0000000000000010", 2) # Not Implemented. The name server does not support the requested kind of query. 72 RCODE_REFUSED = int("0000000000001010", 2) # The name server refuses to perform the specified operation for policy reasons. 73 RCODE_YXDOMAIN = int("0000000000000110", 2) # Name Exists when it should not. 74 RCODE_YXRRSET = int("0000000000001110", 2) # RR Set Exists when it should not. 75 RCODE_NXRRSET = int("0000000000000001", 2) # RR Set that should exist does not. 76 RCODE_NOAUTH = int("0000000000001001", 2) # Server Not Authoritative for zone. 77 RCODE_NOTZONE = int("0000000000000101", 2) # Name not contained in zone. 78 79class DNSType(): 80 A = 1 # IPv4 address. 81 NS = 2 # Authoritative name server. 82 MD = 3 # Mail destination. Obsolete use MX instead. 83 MF = 4 # Mail forwarder. Obsolete use MX instead. 84 CNAME = 5 # Canonical name for an alias. 85 SOA = 6 # Marks the start of a zone of authority. 86 MB = 7 # Mailbox domain name. 87 MG = 8 # Mail group member. 88 MR = 9 # Mail rename domain name. 89 NULL = 10 # Null resource record. 90 WKS = 11 # Well known service description. 91 PTR = 12 # Domain name pointer. 92 HINFO = 13 # Host information. 93 MINFO = 14 # Mailbox or mail list information. 94 MX = 15 # Mail exchange. 95 TXT = 16 # Text strings. 96 RP = 17 # Responsible Person. 97 AFSDB = 18 # AFS Data Base location. 98 X25 = 19 # X.25 PSDN address. 99 ISDN = 20 # ISDN address. 100 RT = 21 # Route Through. 101 NSAP = 22 # NSAP address. NSAP style A record. 102 NSAP_PTR = 23 # NSAP pointer. 103 SIG = 24 # Security signature. 104 KEY = 25 # Security key. 105 PX = 26 # X.400 mail mapping information. 106 GPOS = 27 # Geographical Position. 107 AAAA = 28 # IPv6 Address. 108 LOC = 29 # Location Information. 109 NXT = 30 # Next Domain (obsolete). 110 EID = 31 # Endpoint Identifier. 111 NB = 32 # NetBIOS general Name Service. 112 NBSTAT = 33 # NetBIOS NODE STATUS. 113 ATMA = 34 # ATM Address. 114 NAPTR = 35 # Naming Authority Pointer. 115 KX = 36 # Key Exchanger. 116 CERT = 37 117 A6 = 38 118 DNAME = 39 119 SINK = 40 120 OPT = 41 121 APL = 42 122 DS = 43 # Delegation Signer. 123 SSHFP = 44 # SSH Key Fingerprint. 124 IPSECKEY = 45 125 RRSIG = 46 126 NSEC = 47 # NextSECure. 127 DNSKEY = 48 128 DHCID = 49 # DHCP identifier. 129 NSEC3 = 50 130 NSEC3PARAM = 51 131 132 HIP = 55 # Host Identity Protocol. 133 NINFO = 56 134 RKEY = 57 135 136 SPF = 99 # Sender Policy Framework. 137 UINFO = 100 138 UID = 101 139 GID = 102 140 UNSPEC = 103 141 142 TKEY = 249 143 TSIG = 250 # Transaction Signature. 144 IXFR = 251 # Incremental transfer. 145 AXFR = 252 # A request for a transfer of an entire zone. 146 MAILB = 253 # A request for mailbox-related records (MB, MG or MR). 147 MAILA = 254 # A request for mail agent RRs. Obsolete. 148 ALL = 255 # A request for all records. 149 150 DNSSEC = 32768 # Trust Authorities. 151 DNSSEC = 32769 # DNSSEC Lookaside Validation. 152 153 @staticmethod 154 def getTypeName(type): 155 for item, value in DNSType.__dict__.items(): 156 if value == type: 157 return item 158 159 160class DNSClass(): 161 RESERVED = 0 162 IN = 1 # Internet. 163 CH = 3 # Chaos. 164 HS = 4 # Hesiod. 165 166 NONE = 254 167 ANY = 255 # QCLASS only 168 169 @staticmethod 170 def getClassName(type): 171 for item, value in DNSClass.__dict__.items(): 172 if value == type: 173 return item 174 175class DNS(ProtocolPacket): 176 '''The Message Header is present in all messages. Never empty. 177 Contains various flags and values which control the transaction.''' 178 179 __TYPE_LEN = 2 # Unsigned 16 bit value. 180 __CLASS_LEN = 2 # Unsigned 16 bit value. 181 __POINTER_LEN = 2 # A pointer is an unsigned 16-bit value. 182 __TTL_LEN = 4 # Unsigned 32 bit value. The time in seconds that the record may be cached. 183 __RDLENGTH_LEN = 2 # Unsigned 16-bit value that defines the length in bytes (octets) of the RDATA record. 184 __TYPE_A_LEN = 4 # Unsigned 32-bit value representing the IP address. 185 __SERIAL_LEN = 4 # Serial Number Unsigned 32-bit integer. 186 __REFRESH_LEN = 4 # Refresh interval Unsigned 32-bit integer. 187 __RETRY_LEN = 4 # Retry Interval Unsigned 32-bit integer. 188 __EXPIRATION_LEN = 4 # Expiration Limit Unsigned 32-bit integer. 189 __MINTTL_LEN = 4 # Minimum TTL Unsigned 32-bit integer. 190 __PREF_LEN = 2 # Preference Unsigned 16-bit integer. 191 __IS_POINTER = int("11000000", 2) 192 __OFFSETMASK = int("00111111", 2) 193 194 def __init__(self, aBuffer = None): 195 self.__HEADER_BASE_SIZE = 12 196 self.__TAIL_SIZE = 0 197 ProtocolPacket.__init__(self, self.__HEADER_BASE_SIZE, self.__TAIL_SIZE) 198 if aBuffer: 199 self.load_packet(aBuffer) 200 201 def get_transaction_id(self): 202 'Get 16 bit message ID.' 203 return self.header.get_word(0) 204 205 def set_transaction_id(self, value): 206 'Set 16 bit message ID.' 207 self.header.set_word(0, value) 208 209 def get_transaction_id_tcp(self): 210 'Get 16 bit message ID.' 211 return self.header.get_word(2) 212 213 def set_transaction_id_tcp(self, value): 214 'Set 16 bit message ID.' 215 self.header.set_word(2, value) 216 217 def get_flags(self): 218 'Get 16 bit flags.' 219 return self.header.get_word(2) 220 221 def set_flags(self, value): 222 'Set 16 bit flags.' 223 self.header.set_word(2, value) 224 225 def get_flags_tcp(self): 226 'Get 16 bit flags.' 227 return self.header.get_word(4) 228 229 def set_flags_tcp(self, value): 230 'Set 16 bit flags.' 231 self.header.set_word(4, value) 232 233 def get_qdcount(self): 234 'Get Unsigned 16 bit integer specifying the number of entries in the question section.' 235 return self.header.get_word(4) 236 237 def set_qdcount(self, value): 238 'Set Unsigned 16 bit integer specifying the number of entries in the question section.' 239 self.header.set_word(4, value) 240 241 def get_qdcount_tcp(self): 242 'Get Unsigned 16 bit integer specifying the number of entries in the question section.' 243 return self.header.get_word(6) 244 245 def set_qdcount_tcp(self, value): 246 'Set Unsigned 16 bit integer specifying the number of entries in the question section.' 247 self.header.set_word(6, value) 248 249 def get_ancount(self): 250 'Get Unsigned 16 bit integer specifying the number of resource records in the answer section' 251 return self.header.get_word(6) 252 253 def set_ancount(self, value): 254 'Set Unsigned 16 bit integer specifying the number of resource records in the answer section' 255 self.header.set_word(6, value) 256 257 def get_nscount(self): 258 'Get Unsigned 16 bit integer specifying the number of name server resource records in the authority section.' 259 return self.header.get_word(8) 260 261 def set_nscount(self, value): 262 'Set Unsigned 16 bit integer specifying the number of name server resource records in the authority section.' 263 self.header.set_word(8, value) 264 265 def get_arcount(self): 266 'Get Unsigned 16 bit integer specifying the number of resource records in the additional records section.' 267 return self.header.get_word(10) 268 269 def set_arcount(self, value): 270 'Set Unsigned 16 bit integer specifying the number of resource records in the additional records section.' 271 self.header.set_word(10, value) 272 273 def get_questions(self): 274 'Get a list of the DNS Question.' 275 return self.__get_questions()[0] 276 277 def __get_questions(self): 278 aux = [] 279 offset = 0 280 qdcount = self.get_qdcount() 281 data = self.get_body_as_string() 282 for _ in range(qdcount): # number of questions 283 offset, qname = self.parseCompressedMessage(data, offset) 284 qtype = data[offset:offset+self.__TYPE_LEN] 285 offset += self.__TYPE_LEN 286 qclass = data[offset:offset+self.__CLASS_LEN] 287 offset += self.__CLASS_LEN 288 qtype = struct.unpack("!H", qtype)[0] 289 qclass = struct.unpack("!H", qclass)[0] 290 aux.append((qname, qtype, qclass)) 291 return (aux, offset) 292 293 def get_questions_tcp(self): 294 'Get a list of the DNS Question.' 295 return self.__get_questions_tcp()[0] 296 297 def __get_questions_tcp(self): 298 aux = [] 299 offset = 2 300 qdcount = self.get_qdcount_tcp() 301 data = self.get_body_as_string() 302 for _ in range(qdcount): # number of questions 303 offset, qname = self.parseCompressedMessage(data, offset) 304 qtype = data[offset:offset+self.__TYPE_LEN] 305 offset += self.__TYPE_LEN 306 qclass = data[offset:offset+self.__CLASS_LEN] 307 offset += self.__CLASS_LEN 308 qtype = struct.unpack("!H", qtype)[0] 309 qclass = struct.unpack("!H", qclass)[0] 310 aux.append((qname, qtype, qclass)) 311 return (aux, offset) 312 313 def parseCompressedMessage(self, buf, offset=0): 314 'Parse compressed message defined on rfc1035 4.1.4.' 315 if offset >= len(buf): 316 raise Exception("No more data to parse. Offset is bigger than length of buffer.") 317 byte = struct.unpack("B", buf[offset])[0] 318 # if the first two bits are ones (11000000=0xC0), the next bits are the offset 319 if byte & 0xC0 == 0xC0: 320 # It's a pointer 321 pointer = struct.unpack("!H", buf[offset:offset+2])[0] # network unsigned short 322 pointer = (pointer & 0x3FFF) - self.__HEADER_BASE_SIZE 323 offset += 2 324 name = self.parseCompressedMessage(buf, pointer)[1] 325 return (offset, name) 326 else: 327 # It's a label 328 if byte == 0x00: 329 offset += 1 330 return (offset, '') 331 offset += 1 332 name = buf[offset:offset+byte] 333 offset += byte 334 offset, unnamed = self.parseCompressedMessage(buf, offset) 335 if not unnamed: 336 return (offset, name) 337 else: 338 return (offset, name + "." + unnamed) 339 340 def get_answers(self): 341 return self.__get_answers()[0] 342 343 def get_authoritative(self): 344 return self.__get_authoritative()[0] 345 346 def get_additionals(self): 347 return self.__get_additionals()[0] 348 349 def __get_answers(self): 350 offset = self.__get_questions()[1] # get the initial offset 351 ancount = self.get_ancount() 352 return self.__process_answer_structure(offset, ancount) 353 354 def __get_authoritative(self): 355 'Get a list of the DNS Authoritative.' 356 offset = self.__get_answers()[1] # get the initial offset 357 nscount = self.get_nscount() 358 return self.__process_answer_structure(offset, nscount) 359 360 def __get_additionals(self): 361 'Get a list of the DNS Additional Records.' 362 offset = self.__get_authoritative()[1] # get the initial offset 363 arcount = self.get_arcount() 364 return self.__process_answer_structure(offset, arcount) 365 366 def __process_answer_structure(self, offset, num): 367 aux = [] 368 data = self.get_body_as_string() 369 for _ in range(num): 370 offset, qname = self.parseCompressedMessage(data, offset) 371 qtype = data[offset:offset+self.__TYPE_LEN] 372 qtype = struct.unpack("!H", qtype)[0] 373 offset += self.__TYPE_LEN 374 375 qclass = data[offset:offset+self.__CLASS_LEN] 376 qclass = struct.unpack("!H", qclass)[0] 377 offset += self.__CLASS_LEN 378 379 qttl_raw = data[offset:offset+self.__TTL_LEN] 380 qttl = struct.unpack("!L", qttl_raw)[0] 381 offset += self.__TTL_LEN 382 383 qrdlength = data[offset:offset+self.__RDLENGTH_LEN] 384 qrdlength = struct.unpack("!H", qrdlength)[0] 385 offset += self.__RDLENGTH_LEN 386 387 qrdata = {} 388 if qtype == DNSType.A: 389 # IP Address Unsigned 32-bit value representing the IP address 390 qrdata["IPAddress"] = socket.inet_ntoa(data[offset:offset+qrdlength]) 391 offset += self.__TYPE_A_LEN 392 elif qtype == DNSType.SOA: 393 # Primary NS Variable length. The name of the Primary Master for the domain. May be a label, pointer or any combination. 394 offset, primaryNs = self.parseCompressedMessage(data, offset) 395 qrdata["PrimaryNS"] = primaryNs 396 # Admin MB Variable length. The administrator's mailbox. May be a label, pointer or any combination. 397 offset, adminMb = self.parseCompressedMessage(data, offset) 398 qrdata["AdminMB"] = adminMb 399 # Serial Number Unsigned 32-bit integer. 400 qrdata["SerialNumber"] = struct.unpack("!L", data[offset:offset+self.__SERIAL_LEN])[0] 401 offset += self.__SERIAL_LEN 402 # Refresh interval Unsigned 32-bit integer. 403 qrdata["RefreshInterval"] = struct.unpack("!L", data[offset:offset+self.__REFRESH_LEN])[0] 404 offset += self.__REFRESH_LEN 405 # Retry Interval Unsigned 32-bit integer. 406 qrdata["RetryInterval"] = struct.unpack("!L", data[offset:offset+self.__RETRY_LEN])[0] 407 offset += self.__RETRY_LEN 408 # Expiration Limit Unsigned 32-bit integer. 409 qrdata["ExpirationLimit"] = struct.unpack("!L", data[offset:offset+self.__EXPIRATION_LEN])[0] 410 offset += self.__EXPIRATION_LEN 411 # Minimum TTL Unsigned 32-bit integer. 412 qrdata["MinimumTTL"] = struct.unpack("!L", data[offset:offset+self.__MINTTL_LEN])[0] 413 offset += self.__MINTTL_LEN 414 elif qtype == DNSType.MX: 415 # Preference Unsigned 16-bit integer. 416 qrdata["Preference"] = struct.unpack("!H", data[offset:offset+self.__PREF_LEN])[0] 417 # Mail Exchanger The name host name that provides the service. May be a label, pointer or any combination. 418 offset, mailExch = self.parseCompressedMessage(data, offset) 419 qrdata["MailExchanger"] = mailExch 420 elif qtype == DNSType.PTR or qtype == DNSType.NS or qtype == DNSType.CNAME: 421 # Name The host name that represents the supplied IP address (in the case of a PTR) or the NS name for the supplied domain (in the case of NS). May be a label, pointer or any combination. 422 offset, name = self.parseCompressedMessage(data, offset) 423 qrdata["Name"] = name 424 elif qtype == DNSType.OPT: 425 # rfc2671 4.3 426 #NAME domain name empty (root domain) 427 #TYPE u_int16_t OPT 428 #CLASS u_int16_t sender's UDP payload size 429 #TTL u_int32_t extended RCODE and flags 430 #RDLEN u_int16_t describes RDATA 431 #RDATA octet stream {attribute,value} pairs 432 #udp_payload = qclass 433 udp_payload_size = qclass 434 ext_rcode = struct.unpack("B", qttl_raw[0])[0] 435 version = struct.unpack("B", qttl_raw[1])[0] 436 flags = struct.unpack("!H", qttl_raw[2:4])[0] 437 qrdata["RDATA"] = data[offset:offset+qrdlength] 438 offset += qrdlength 439 aux.append((qname, qtype, udp_payload_size, ext_rcode, version, flags, qrdata)) 440 continue 441 else: 442 # We don't know how to parse it, just skip it 443 offset += qrdlength 444 445 aux.append((qname, qtype, qclass, qttl, qrdata)) 446 return (aux, offset) 447 448 def get_header_size(self): 449 return self.__HEADER_BASE_SIZE 450 451 def __str__(self): 452 res = "" 453 454 id = self.get_transaction_id() 455 flags = self.get_flags() 456 qdcount = self.get_qdcount() 457 ancount = self.get_ancount() 458 nscount = self.get_nscount() 459 arcount = self.get_arcount() 460 461 res += "DNS " 462 if flags & DNSFlags.QR_RESPONSE: 463 res += "RESPONSE\n" 464 else: 465 res += "QUERY\n" 466 467 res += " - Transaction ID -- [0x%04x] %d\n" % (id, id) 468 res += " - Flags ----------- [0x%04x] %d\n" % (flags, flags) 469 res += " - QdCount --------- [0x%04x] %d\n" % (qdcount, qdcount) 470 res += " - AnCount --------- [0x%04x] %d\n" % (ancount, ancount) 471 res += " - NsCount --------- [0x%04x] %d\n" % (nscount, nscount) 472 res += " - ArCount --------- [0x%04x] %d\n" % (arcount, arcount) 473 474 if qdcount > 0: 475 res += " - Questions:\n" 476 questions = self.get_questions() 477 questions.reverse() 478 while(questions): 479 qname, qtype, qclass = questions.pop() 480 format = (qname, DNSType.getTypeName(qtype), qtype, DNSClass.getClassName(qclass), qclass) 481 res += " * Domain: %s - Type: %s [0x%04x] - Class: %s [0x%04x]\n" % format 482 483 if ancount > 0: 484 res += " - Answers:\n" 485 answers = self.get_answers() 486 answers.reverse() 487 while(answers): 488 qname, qtype, qclass, qttl, qrdata = answers.pop() 489 format = (qname, DNSType.getTypeName(qtype), qtype, DNSClass.getClassName(qclass), qclass, qttl, repr(qrdata)) 490 res += " * Domain: %s - Type: %s [0x%04x] - Class: %s [0x%04x] - TTL: %d seconds - %s\n" % format 491 492 if nscount > 0: 493 res += " - Authoritative:\n" 494 authoritative = self.get_authoritative() 495 authoritative.reverse() 496 while(authoritative): 497 qname, qtype, qclass, qttl, qrdata = authoritative.pop() 498 format = (qname, DNSType.getTypeName(qtype), qtype, DNSClass.getClassName(qclass), qclass, qttl, repr(qrdata)) 499 res += " * Domain: %s - Type: %s [0x%04x] - Class: %s [0x%04x] - TTL: %d seconds - %s\n" % format 500 501 if arcount > 0: 502 res += " - Additionals:\n" 503 additionals = self.get_additionals() 504 for additional in additionals: 505 qtype = additional[1] 506 if qtype == DNSType.OPT: 507 508 qname, qtype, udp_payload_size, ext_rcode, version, flags, qrdata = additional 509 format = (DNSType.getTypeName(qtype), qtype, udp_payload_size, ext_rcode, version, flags, repr(qrdata['RDATA'])) 510 res += " * Name: <Root> - Type: %s [0x%04x] - udp payload size: [%d] - extended RCODE: [0x%02x] - EDNS0 version: [0x%02x] - Z Flags: [0x%02x] - RDATA: [%s]\n" % format 511 else: 512 qname, qtype, qclass, qttl, qrdata = additional 513 format = (qname, DNSType.getTypeName(qtype), qtype, DNSClass.getClassName(qclass), qclass, qttl, repr(qrdata)) 514 res += " * Domain: %s - Type: %s [0x%04x] - Class: %s [0x%04x] - TTL: %d seconds - %s\n" % format 515 516 return res 517 518 def __get_questions_raw(self): 519 if self.get_qdcount() == 0: 520 return '' 521 questions_offset = self.__get_questions()[1] 522 raw_data = self.get_body_as_string()[:questions_offset] 523 return raw_data 524 525 def __get_answers_raw(self): 526 if self.get_ancount() == 0: 527 return '' 528 questions_offset = self.__get_questions()[1] 529 answers_offset = self.__get_answers()[1] 530 raw_data = self.get_body_as_string()[questions_offset: answers_offset] 531 return raw_data 532 533 def __get_authoritative_raw(self): 534 if self.get_nscount() == 0: 535 return '' 536 answers_offset = self.__get_answers()[1] 537 authoritative_offset = self.__get_authoritative()[1] 538 raw_data = self.get_body_as_string()[answers_offset:authoritative_offset] 539 return raw_data 540 541 def __get_additionals_raw(self): 542 if self.get_arcount() == 0: 543 return '' 544 authoritative_offset = self.__get_authoritative()[1] 545 raw_data = self.get_body_as_string()[authoritative_offset:] 546 return raw_data 547 548 def add_answer(self, answer_raw): 549 '''Add a raw answer''' 550 questions_raw = self.__get_questions_raw() 551 answers_raw = self.__get_answers_raw() 552 authoritative_raw = self.__get_authoritative_raw() 553 additionals_raw = self.__get_additionals_raw() 554 555 answers_raw += answer_raw 556 557 body = questions_raw + answers_raw + authoritative_raw + additionals_raw 558 self.load_body(body) # It breaks children hierarchy 559 560 # Increment the answer count 561 cur_answer_count = self.get_ancount()+1 562 self.set_ancount(cur_answer_count) 563 564 def is_edns0(self): 565 additionals = self.get_additionals() 566 for item in additionals: 567 response_type = item[1] 568 if response_type == DNSType.OPT: 569 return True 570 return False 571 572if __name__ == "__main__": 573 pkts = [ 574 "\x6a\x8c\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x03\x77\x77\x77" \ 575 "\x05\x74\x61\x72\x74\x61\x03\x63\x6f\x6d\x00\x00\x01\x00\x01", 576 "\x6a\x8c\x81\x80\x00\x01\x00\x02\x00\x02\x00\x00\x03\x77\x77\x77" \ 577 "\x05\x74\x61\x72\x74\x61\x03\x63\x6f\x6d\x00\x00\x01\x00\x01\xc0" \ 578 "\x0c\x00\x05\x00\x01\x00\x00\x07\x08\x00\x02\xc0\x10\xc0\x10\x00" \ 579 "\x01\x00\x01\x00\x00\x07\x08\x00\x04\x45\x59\x1f\xc7\xc0\x10\x00" \ 580 "\x02\x00\x01\x00\x02\xa3\x00\x00\x0f\x03\x6e\x73\x31\x08\x62\x6c" \ 581 "\x75\x65\x68\x6f\x73\x74\xc0\x16\xc0\x10\x00\x02\x00\x01\x00\x02" \ 582 "\xa3\x00\x00\x06\x03\x6e\x73\x32\xc0\x4d", 583 "\x82\x75\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x03\x77\x77\x77" \ 584 "\x04\x6a\x68\x6f\x6e\x03\x63\x6f\x6d\x00\x00\x01\x00\x01", 585 "\x82\x75\x81\x80\x00\x01\x00\x01\x00\x02\x00\x02\x03\x77\x77\x77" \ 586 "\x04\x6a\x68\x6f\x6e\x03\x63\x6f\x6d\x00\x00\x01\x00\x01\xc0\x0c" \ 587 "\x00\x01\x00\x01\x00\x00\x00\x05\x00\x04\xd1\x3b\xc3\x14\xc0\x10" \ 588 "\x00\x02\x00\x01\x00\x00\x06\xf8\x00\x0f\x03\x6e\x73\x31\x08\x74" \ 589 "\x72\x61\x66\x66\x69\x63\x7a\xc0\x15\xc0\x10\x00\x02\x00\x01\x00" \ 590 "\x00\x06\xf8\x00\x06\x03\x6e\x73\x32\xc0\x3e\xc0\x3a\x00\x01\x00" \ 591 "\x01\x00\x00\x00\x0d\x00\x04\xd1\x3b\xc2\xf6\xc0\x55\x00\x01\x00" \ 592 "\x01\x00\x00\x00\x85\x00\x04\xd1\x3b\xc3\xf6", 593 "\xef\x55\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x04\x6d\x61\x69" \ 594 "\x6c\x06\x67\x6f\x6f\x67\x6c\x65\x03\x63\x6f\x6d\x00\x00\x01\x00" \ 595 "\x01", 596 "\xef\x55\x81\x80\x00\x01\x00\x04\x00\x04\x00\x04\x04\x6d\x61\x69" \ 597 "\x6c\x06\x67\x6f\x6f\x67\x6c\x65\x03\x63\x6f\x6d\x00\x00\x01\x00" \ 598 "\x01\xc0\x0c\x00\x05\x00\x01\x00\x00\x06\x79\x00\x0f\x0a\x67\x6f" \ 599 "\x6f\x67\x6c\x65\x6d\x61\x69\x6c\x01\x6c\xc0\x11\xc0\x2d\x00\x01" \ 600 "\x00\x01\x00\x00\x00\x77\x00\x04\xd1\x55\xc3\x53\xc0\x2d\x00\x01" \ 601 "\x00\x01\x00\x00\x00\x77\x00\x04\xd1\x55\xc3\x12\xc0\x2d\x00\x01" \ 602 "\x00\x01\x00\x00\x00\x77\x00\x04\xd1\x55\xc3\x13\xc0\x11\x00\x02" \ 603 "\x00\x01\x00\x00\x00\x5d\x00\x06\x03\x6e\x73\x33\xc0\x11\xc0\x11" \ 604 "\x00\x02\x00\x01\x00\x00\x00\x5d\x00\x06\x03\x6e\x73\x34\xc0\x11" \ 605 "\xc0\x11\x00\x02\x00\x01\x00\x00\x00\x5d\x00\x06\x03\x6e\x73\x31" \ 606 "\xc0\x11\xc0\x11\x00\x02\x00\x01\x00\x00\x00\x5d\x00\x06\x03\x6e" \ 607 "\x73\x32\xc0\x11\xc0\x9c\x00\x01\x00\x01\x00\x00\x04\x4e\x00\x04" \ 608 "\xd8\xef\x20\x0a\xc0\xae\x00\x01\x00\x01\x00\x00\x06\x64\x00\x04" \ 609 "\xd8\xef\x22\x0a\xc0\x78\x00\x01\x00\x01\x00\x00\x00\x05\x00\x04" \ 610 "\xd8\xef\x24\x0a\xc0\x8a\x00\x01\x00\x01\x00\x00\x00\x08\x00\x04" \ 611 "\xd8\xef\x26\x0a" 612 ] 613 614 for pkt in pkts: 615 d = DNS(pkt) 616 print d 617