You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1175 lines
40 KiB

4 years ago
  1. # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
  2. # Copyright (C) 2001-2017 Nominum, Inc.
  3. #
  4. # Permission to use, copy, modify, and distribute this software and its
  5. # documentation for any purpose with or without fee is hereby granted,
  6. # provided that the above copyright notice and this permission notice
  7. # appear in all copies.
  8. #
  9. # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
  10. # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  11. # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
  12. # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13. # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  14. # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
  15. # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16. """DNS Messages"""
  17. from __future__ import absolute_import
  18. from io import StringIO
  19. import struct
  20. import time
  21. import dns.edns
  22. import dns.exception
  23. import dns.flags
  24. import dns.name
  25. import dns.opcode
  26. import dns.entropy
  27. import dns.rcode
  28. import dns.rdata
  29. import dns.rdataclass
  30. import dns.rdatatype
  31. import dns.rrset
  32. import dns.renderer
  33. import dns.tsig
  34. import dns.wiredata
  35. from ._compat import long, xrange, string_types
  36. class ShortHeader(dns.exception.FormError):
  37. """The DNS packet passed to from_wire() is too short."""
  38. class TrailingJunk(dns.exception.FormError):
  39. """The DNS packet passed to from_wire() has extra junk at the end of it."""
  40. class UnknownHeaderField(dns.exception.DNSException):
  41. """The header field name was not recognized when converting from text
  42. into a message."""
  43. class BadEDNS(dns.exception.FormError):
  44. """An OPT record occurred somewhere other than the start of
  45. the additional data section."""
  46. class BadTSIG(dns.exception.FormError):
  47. """A TSIG record occurred somewhere other than the end of
  48. the additional data section."""
  49. class UnknownTSIGKey(dns.exception.DNSException):
  50. """A TSIG with an unknown key was received."""
  51. #: The question section number
  52. QUESTION = 0
  53. #: The answer section number
  54. ANSWER = 1
  55. #: The authority section number
  56. AUTHORITY = 2
  57. #: The additional section number
  58. ADDITIONAL = 3
  59. class Message(object):
  60. """A DNS message."""
  61. def __init__(self, id=None):
  62. if id is None:
  63. self.id = dns.entropy.random_16()
  64. else:
  65. self.id = id
  66. self.flags = 0
  67. self.question = []
  68. self.answer = []
  69. self.authority = []
  70. self.additional = []
  71. self.edns = -1
  72. self.ednsflags = 0
  73. self.payload = 0
  74. self.options = []
  75. self.request_payload = 0
  76. self.keyring = None
  77. self.keyname = None
  78. self.keyalgorithm = dns.tsig.default_algorithm
  79. self.request_mac = b''
  80. self.other_data = b''
  81. self.tsig_error = 0
  82. self.fudge = 300
  83. self.original_id = self.id
  84. self.mac = b''
  85. self.xfr = False
  86. self.origin = None
  87. self.tsig_ctx = None
  88. self.had_tsig = False
  89. self.multi = False
  90. self.first = True
  91. self.index = {}
  92. def __repr__(self):
  93. return '<DNS message, ID ' + repr(self.id) + '>'
  94. def __str__(self):
  95. return self.to_text()
  96. def to_text(self, origin=None, relativize=True, **kw):
  97. """Convert the message to text.
  98. The *origin*, *relativize*, and any other keyword
  99. arguments are passed to the RRset ``to_wire()`` method.
  100. Returns a ``text``.
  101. """
  102. s = StringIO()
  103. s.write(u'id %d\n' % self.id)
  104. s.write(u'opcode %s\n' %
  105. dns.opcode.to_text(dns.opcode.from_flags(self.flags)))
  106. rc = dns.rcode.from_flags(self.flags, self.ednsflags)
  107. s.write(u'rcode %s\n' % dns.rcode.to_text(rc))
  108. s.write(u'flags %s\n' % dns.flags.to_text(self.flags))
  109. if self.edns >= 0:
  110. s.write(u'edns %s\n' % self.edns)
  111. if self.ednsflags != 0:
  112. s.write(u'eflags %s\n' %
  113. dns.flags.edns_to_text(self.ednsflags))
  114. s.write(u'payload %d\n' % self.payload)
  115. for opt in self.options:
  116. s.write(u'option %s\n' % opt.to_text())
  117. is_update = dns.opcode.is_update(self.flags)
  118. if is_update:
  119. s.write(u';ZONE\n')
  120. else:
  121. s.write(u';QUESTION\n')
  122. for rrset in self.question:
  123. s.write(rrset.to_text(origin, relativize, **kw))
  124. s.write(u'\n')
  125. if is_update:
  126. s.write(u';PREREQ\n')
  127. else:
  128. s.write(u';ANSWER\n')
  129. for rrset in self.answer:
  130. s.write(rrset.to_text(origin, relativize, **kw))
  131. s.write(u'\n')
  132. if is_update:
  133. s.write(u';UPDATE\n')
  134. else:
  135. s.write(u';AUTHORITY\n')
  136. for rrset in self.authority:
  137. s.write(rrset.to_text(origin, relativize, **kw))
  138. s.write(u'\n')
  139. s.write(u';ADDITIONAL\n')
  140. for rrset in self.additional:
  141. s.write(rrset.to_text(origin, relativize, **kw))
  142. s.write(u'\n')
  143. #
  144. # We strip off the final \n so the caller can print the result without
  145. # doing weird things to get around eccentricities in Python print
  146. # formatting
  147. #
  148. return s.getvalue()[:-1]
  149. def __eq__(self, other):
  150. """Two messages are equal if they have the same content in the
  151. header, question, answer, and authority sections.
  152. Returns a ``bool``.
  153. """
  154. if not isinstance(other, Message):
  155. return False
  156. if self.id != other.id:
  157. return False
  158. if self.flags != other.flags:
  159. return False
  160. for n in self.question:
  161. if n not in other.question:
  162. return False
  163. for n in other.question:
  164. if n not in self.question:
  165. return False
  166. for n in self.answer:
  167. if n not in other.answer:
  168. return False
  169. for n in other.answer:
  170. if n not in self.answer:
  171. return False
  172. for n in self.authority:
  173. if n not in other.authority:
  174. return False
  175. for n in other.authority:
  176. if n not in self.authority:
  177. return False
  178. return True
  179. def __ne__(self, other):
  180. return not self.__eq__(other)
  181. def is_response(self, other):
  182. """Is this message a response to *other*?
  183. Returns a ``bool``.
  184. """
  185. if other.flags & dns.flags.QR == 0 or \
  186. self.id != other.id or \
  187. dns.opcode.from_flags(self.flags) != \
  188. dns.opcode.from_flags(other.flags):
  189. return False
  190. if dns.rcode.from_flags(other.flags, other.ednsflags) != \
  191. dns.rcode.NOERROR:
  192. return True
  193. if dns.opcode.is_update(self.flags):
  194. return True
  195. for n in self.question:
  196. if n not in other.question:
  197. return False
  198. for n in other.question:
  199. if n not in self.question:
  200. return False
  201. return True
  202. def section_number(self, section):
  203. """Return the "section number" of the specified section for use
  204. in indexing. The question section is 0, the answer section is 1,
  205. the authority section is 2, and the additional section is 3.
  206. *section* is one of the section attributes of this message.
  207. Raises ``ValueError`` if the section isn't known.
  208. Returns an ``int``.
  209. """
  210. if section is self.question:
  211. return QUESTION
  212. elif section is self.answer:
  213. return ANSWER
  214. elif section is self.authority:
  215. return AUTHORITY
  216. elif section is self.additional:
  217. return ADDITIONAL
  218. else:
  219. raise ValueError('unknown section')
  220. def section_from_number(self, number):
  221. """Return the "section number" of the specified section for use
  222. in indexing. The question section is 0, the answer section is 1,
  223. the authority section is 2, and the additional section is 3.
  224. *section* is one of the section attributes of this message.
  225. Raises ``ValueError`` if the section isn't known.
  226. Returns an ``int``.
  227. """
  228. if number == QUESTION:
  229. return self.question
  230. elif number == ANSWER:
  231. return self.answer
  232. elif number == AUTHORITY:
  233. return self.authority
  234. elif number == ADDITIONAL:
  235. return self.additional
  236. else:
  237. raise ValueError('unknown section')
  238. def find_rrset(self, section, name, rdclass, rdtype,
  239. covers=dns.rdatatype.NONE, deleting=None, create=False,
  240. force_unique=False):
  241. """Find the RRset with the given attributes in the specified section.
  242. *section*, an ``int`` section number, or one of the section
  243. attributes of this message. This specifies the
  244. the section of the message to search. For example::
  245. my_message.find_rrset(my_message.answer, name, rdclass, rdtype)
  246. my_message.find_rrset(dns.message.ANSWER, name, rdclass, rdtype)
  247. *name*, a ``dns.name.Name``, the name of the RRset.
  248. *rdclass*, an ``int``, the class of the RRset.
  249. *rdtype*, an ``int``, the type of the RRset.
  250. *covers*, an ``int`` or ``None``, the covers value of the RRset.
  251. The default is ``None``.
  252. *deleting*, an ``int`` or ``None``, the deleting value of the RRset.
  253. The default is ``None``.
  254. *create*, a ``bool``. If ``True``, create the RRset if it is not found.
  255. The created RRset is appended to *section*.
  256. *force_unique*, a ``bool``. If ``True`` and *create* is also ``True``,
  257. create a new RRset regardless of whether a matching RRset exists
  258. already. The default is ``False``. This is useful when creating
  259. DDNS Update messages, as order matters for them.
  260. Raises ``KeyError`` if the RRset was not found and create was
  261. ``False``.
  262. Returns a ``dns.rrset.RRset object``.
  263. """
  264. if isinstance(section, int):
  265. section_number = section
  266. section = self.section_from_number(section_number)
  267. else:
  268. section_number = self.section_number(section)
  269. key = (section_number, name, rdclass, rdtype, covers, deleting)
  270. if not force_unique:
  271. if self.index is not None:
  272. rrset = self.index.get(key)
  273. if rrset is not None:
  274. return rrset
  275. else:
  276. for rrset in section:
  277. if rrset.match(name, rdclass, rdtype, covers, deleting):
  278. return rrset
  279. if not create:
  280. raise KeyError
  281. rrset = dns.rrset.RRset(name, rdclass, rdtype, covers, deleting)
  282. section.append(rrset)
  283. if self.index is not None:
  284. self.index[key] = rrset
  285. return rrset
  286. def get_rrset(self, section, name, rdclass, rdtype,
  287. covers=dns.rdatatype.NONE, deleting=None, create=False,
  288. force_unique=False):
  289. """Get the RRset with the given attributes in the specified section.
  290. If the RRset is not found, None is returned.
  291. *section*, an ``int`` section number, or one of the section
  292. attributes of this message. This specifies the
  293. the section of the message to search. For example::
  294. my_message.get_rrset(my_message.answer, name, rdclass, rdtype)
  295. my_message.get_rrset(dns.message.ANSWER, name, rdclass, rdtype)
  296. *name*, a ``dns.name.Name``, the name of the RRset.
  297. *rdclass*, an ``int``, the class of the RRset.
  298. *rdtype*, an ``int``, the type of the RRset.
  299. *covers*, an ``int`` or ``None``, the covers value of the RRset.
  300. The default is ``None``.
  301. *deleting*, an ``int`` or ``None``, the deleting value of the RRset.
  302. The default is ``None``.
  303. *create*, a ``bool``. If ``True``, create the RRset if it is not found.
  304. The created RRset is appended to *section*.
  305. *force_unique*, a ``bool``. If ``True`` and *create* is also ``True``,
  306. create a new RRset regardless of whether a matching RRset exists
  307. already. The default is ``False``. This is useful when creating
  308. DDNS Update messages, as order matters for them.
  309. Returns a ``dns.rrset.RRset object`` or ``None``.
  310. """
  311. try:
  312. rrset = self.find_rrset(section, name, rdclass, rdtype, covers,
  313. deleting, create, force_unique)
  314. except KeyError:
  315. rrset = None
  316. return rrset
  317. def to_wire(self, origin=None, max_size=0, **kw):
  318. """Return a string containing the message in DNS compressed wire
  319. format.
  320. Additional keyword arguments are passed to the RRset ``to_wire()``
  321. method.
  322. *origin*, a ``dns.name.Name`` or ``None``, the origin to be appended
  323. to any relative names.
  324. *max_size*, an ``int``, the maximum size of the wire format
  325. output; default is 0, which means "the message's request
  326. payload, if nonzero, or 65535".
  327. Raises ``dns.exception.TooBig`` if *max_size* was exceeded.
  328. Returns a ``binary``.
  329. """
  330. if max_size == 0:
  331. if self.request_payload != 0:
  332. max_size = self.request_payload
  333. else:
  334. max_size = 65535
  335. if max_size < 512:
  336. max_size = 512
  337. elif max_size > 65535:
  338. max_size = 65535
  339. r = dns.renderer.Renderer(self.id, self.flags, max_size, origin)
  340. for rrset in self.question:
  341. r.add_question(rrset.name, rrset.rdtype, rrset.rdclass)
  342. for rrset in self.answer:
  343. r.add_rrset(dns.renderer.ANSWER, rrset, **kw)
  344. for rrset in self.authority:
  345. r.add_rrset(dns.renderer.AUTHORITY, rrset, **kw)
  346. if self.edns >= 0:
  347. r.add_edns(self.edns, self.ednsflags, self.payload, self.options)
  348. for rrset in self.additional:
  349. r.add_rrset(dns.renderer.ADDITIONAL, rrset, **kw)
  350. r.write_header()
  351. if self.keyname is not None:
  352. r.add_tsig(self.keyname, self.keyring[self.keyname],
  353. self.fudge, self.original_id, self.tsig_error,
  354. self.other_data, self.request_mac,
  355. self.keyalgorithm)
  356. self.mac = r.mac
  357. return r.get_wire()
  358. def use_tsig(self, keyring, keyname=None, fudge=300,
  359. original_id=None, tsig_error=0, other_data=b'',
  360. algorithm=dns.tsig.default_algorithm):
  361. """When sending, a TSIG signature using the specified keyring
  362. and keyname should be added.
  363. See the documentation of the Message class for a complete
  364. description of the keyring dictionary.
  365. *keyring*, a ``dict``, the TSIG keyring to use. If a
  366. *keyring* is specified but a *keyname* is not, then the key
  367. used will be the first key in the *keyring*. Note that the
  368. order of keys in a dictionary is not defined, so applications
  369. should supply a keyname when a keyring is used, unless they
  370. know the keyring contains only one key.
  371. *keyname*, a ``dns.name.Name`` or ``None``, the name of the TSIG key
  372. to use; defaults to ``None``. The key must be defined in the keyring.
  373. *fudge*, an ``int``, the TSIG time fudge.
  374. *original_id*, an ``int``, the TSIG original id. If ``None``,
  375. the message's id is used.
  376. *tsig_error*, an ``int``, the TSIG error code.
  377. *other_data*, a ``binary``, the TSIG other data.
  378. *algorithm*, a ``dns.name.Name``, the TSIG algorithm to use.
  379. """
  380. self.keyring = keyring
  381. if keyname is None:
  382. self.keyname = list(self.keyring.keys())[0]
  383. else:
  384. if isinstance(keyname, string_types):
  385. keyname = dns.name.from_text(keyname)
  386. self.keyname = keyname
  387. self.keyalgorithm = algorithm
  388. self.fudge = fudge
  389. if original_id is None:
  390. self.original_id = self.id
  391. else:
  392. self.original_id = original_id
  393. self.tsig_error = tsig_error
  394. self.other_data = other_data
  395. def use_edns(self, edns=0, ednsflags=0, payload=1280, request_payload=None,
  396. options=None):
  397. """Configure EDNS behavior.
  398. *edns*, an ``int``, is the EDNS level to use. Specifying
  399. ``None``, ``False``, or ``-1`` means "do not use EDNS", and in this case
  400. the other parameters are ignored. Specifying ``True`` is
  401. equivalent to specifying 0, i.e. "use EDNS0".
  402. *ednsflags*, an ``int``, the EDNS flag values.
  403. *payload*, an ``int``, is the EDNS sender's payload field, which is the
  404. maximum size of UDP datagram the sender can handle. I.e. how big
  405. a response to this message can be.
  406. *request_payload*, an ``int``, is the EDNS payload size to use when
  407. sending this message. If not specified, defaults to the value of
  408. *payload*.
  409. *options*, a list of ``dns.edns.Option`` objects or ``None``, the EDNS
  410. options.
  411. """
  412. if edns is None or edns is False:
  413. edns = -1
  414. if edns is True:
  415. edns = 0
  416. if request_payload is None:
  417. request_payload = payload
  418. if edns < 0:
  419. ednsflags = 0
  420. payload = 0
  421. request_payload = 0
  422. options = []
  423. else:
  424. # make sure the EDNS version in ednsflags agrees with edns
  425. ednsflags &= long(0xFF00FFFF)
  426. ednsflags |= (edns << 16)
  427. if options is None:
  428. options = []
  429. self.edns = edns
  430. self.ednsflags = ednsflags
  431. self.payload = payload
  432. self.options = options
  433. self.request_payload = request_payload
  434. def want_dnssec(self, wanted=True):
  435. """Enable or disable 'DNSSEC desired' flag in requests.
  436. *wanted*, a ``bool``. If ``True``, then DNSSEC data is
  437. desired in the response, EDNS is enabled if required, and then
  438. the DO bit is set. If ``False``, the DO bit is cleared if
  439. EDNS is enabled.
  440. """
  441. if wanted:
  442. if self.edns < 0:
  443. self.use_edns()
  444. self.ednsflags |= dns.flags.DO
  445. elif self.edns >= 0:
  446. self.ednsflags &= ~dns.flags.DO
  447. def rcode(self):
  448. """Return the rcode.
  449. Returns an ``int``.
  450. """
  451. return dns.rcode.from_flags(self.flags, self.ednsflags)
  452. def set_rcode(self, rcode):
  453. """Set the rcode.
  454. *rcode*, an ``int``, is the rcode to set.
  455. """
  456. (value, evalue) = dns.rcode.to_flags(rcode)
  457. self.flags &= 0xFFF0
  458. self.flags |= value
  459. self.ednsflags &= long(0x00FFFFFF)
  460. self.ednsflags |= evalue
  461. if self.ednsflags != 0 and self.edns < 0:
  462. self.edns = 0
  463. def opcode(self):
  464. """Return the opcode.
  465. Returns an ``int``.
  466. """
  467. return dns.opcode.from_flags(self.flags)
  468. def set_opcode(self, opcode):
  469. """Set the opcode.
  470. *opcode*, an ``int``, is the opcode to set.
  471. """
  472. self.flags &= 0x87FF
  473. self.flags |= dns.opcode.to_flags(opcode)
  474. class _WireReader(object):
  475. """Wire format reader.
  476. wire: a binary, is the wire-format message.
  477. message: The message object being built
  478. current: When building a message object from wire format, this
  479. variable contains the offset from the beginning of wire of the next octet
  480. to be read.
  481. updating: Is the message a dynamic update?
  482. one_rr_per_rrset: Put each RR into its own RRset?
  483. ignore_trailing: Ignore trailing junk at end of request?
  484. zone_rdclass: The class of the zone in messages which are
  485. DNS dynamic updates.
  486. """
  487. def __init__(self, wire, message, question_only=False,
  488. one_rr_per_rrset=False, ignore_trailing=False):
  489. self.wire = dns.wiredata.maybe_wrap(wire)
  490. self.message = message
  491. self.current = 0
  492. self.updating = False
  493. self.zone_rdclass = dns.rdataclass.IN
  494. self.question_only = question_only
  495. self.one_rr_per_rrset = one_rr_per_rrset
  496. self.ignore_trailing = ignore_trailing
  497. def _get_question(self, qcount):
  498. """Read the next *qcount* records from the wire data and add them to
  499. the question section.
  500. """
  501. if self.updating and qcount > 1:
  502. raise dns.exception.FormError
  503. for i in xrange(0, qcount):
  504. (qname, used) = dns.name.from_wire(self.wire, self.current)
  505. if self.message.origin is not None:
  506. qname = qname.relativize(self.message.origin)
  507. self.current = self.current + used
  508. (rdtype, rdclass) = \
  509. struct.unpack('!HH',
  510. self.wire[self.current:self.current + 4])
  511. self.current = self.current + 4
  512. self.message.find_rrset(self.message.question, qname,
  513. rdclass, rdtype, create=True,
  514. force_unique=True)
  515. if self.updating:
  516. self.zone_rdclass = rdclass
  517. def _get_section(self, section, count):
  518. """Read the next I{count} records from the wire data and add them to
  519. the specified section.
  520. section: the section of the message to which to add records
  521. count: the number of records to read
  522. """
  523. if self.updating or self.one_rr_per_rrset:
  524. force_unique = True
  525. else:
  526. force_unique = False
  527. seen_opt = False
  528. for i in xrange(0, count):
  529. rr_start = self.current
  530. (name, used) = dns.name.from_wire(self.wire, self.current)
  531. absolute_name = name
  532. if self.message.origin is not None:
  533. name = name.relativize(self.message.origin)
  534. self.current = self.current + used
  535. (rdtype, rdclass, ttl, rdlen) = \
  536. struct.unpack('!HHIH',
  537. self.wire[self.current:self.current + 10])
  538. self.current = self.current + 10
  539. if rdtype == dns.rdatatype.OPT:
  540. if section is not self.message.additional or seen_opt:
  541. raise BadEDNS
  542. self.message.payload = rdclass
  543. self.message.ednsflags = ttl
  544. self.message.edns = (ttl & 0xff0000) >> 16
  545. self.message.options = []
  546. current = self.current
  547. optslen = rdlen
  548. while optslen > 0:
  549. (otype, olen) = \
  550. struct.unpack('!HH',
  551. self.wire[current:current + 4])
  552. current = current + 4
  553. opt = dns.edns.option_from_wire(
  554. otype, self.wire, current, olen)
  555. self.message.options.append(opt)
  556. current = current + olen
  557. optslen = optslen - 4 - olen
  558. seen_opt = True
  559. elif rdtype == dns.rdatatype.TSIG:
  560. if not (section is self.message.additional and
  561. i == (count - 1)):
  562. raise BadTSIG
  563. if self.message.keyring is None:
  564. raise UnknownTSIGKey('got signed message without keyring')
  565. secret = self.message.keyring.get(absolute_name)
  566. if secret is None:
  567. raise UnknownTSIGKey("key '%s' unknown" % name)
  568. self.message.keyname = absolute_name
  569. (self.message.keyalgorithm, self.message.mac) = \
  570. dns.tsig.get_algorithm_and_mac(self.wire, self.current,
  571. rdlen)
  572. self.message.tsig_ctx = \
  573. dns.tsig.validate(self.wire,
  574. absolute_name,
  575. secret,
  576. int(time.time()),
  577. self.message.request_mac,
  578. rr_start,
  579. self.current,
  580. rdlen,
  581. self.message.tsig_ctx,
  582. self.message.multi,
  583. self.message.first)
  584. self.message.had_tsig = True
  585. else:
  586. if ttl < 0:
  587. ttl = 0
  588. if self.updating and \
  589. (rdclass == dns.rdataclass.ANY or
  590. rdclass == dns.rdataclass.NONE):
  591. deleting = rdclass
  592. rdclass = self.zone_rdclass
  593. else:
  594. deleting = None
  595. if deleting == dns.rdataclass.ANY or \
  596. (deleting == dns.rdataclass.NONE and
  597. section is self.message.answer):
  598. covers = dns.rdatatype.NONE
  599. rd = None
  600. else:
  601. rd = dns.rdata.from_wire(rdclass, rdtype, self.wire,
  602. self.current, rdlen,
  603. self.message.origin)
  604. covers = rd.covers()
  605. if self.message.xfr and rdtype == dns.rdatatype.SOA:
  606. force_unique = True
  607. rrset = self.message.find_rrset(section, name,
  608. rdclass, rdtype, covers,
  609. deleting, True, force_unique)
  610. if rd is not None:
  611. rrset.add(rd, ttl)
  612. self.current = self.current + rdlen
  613. def read(self):
  614. """Read a wire format DNS message and build a dns.message.Message
  615. object."""
  616. l = len(self.wire)
  617. if l < 12:
  618. raise ShortHeader
  619. (self.message.id, self.message.flags, qcount, ancount,
  620. aucount, adcount) = struct.unpack('!HHHHHH', self.wire[:12])
  621. self.current = 12
  622. if dns.opcode.is_update(self.message.flags):
  623. self.updating = True
  624. self._get_question(qcount)
  625. if self.question_only:
  626. return
  627. self._get_section(self.message.answer, ancount)
  628. self._get_section(self.message.authority, aucount)
  629. self._get_section(self.message.additional, adcount)
  630. if not self.ignore_trailing and self.current != l:
  631. raise TrailingJunk
  632. if self.message.multi and self.message.tsig_ctx and \
  633. not self.message.had_tsig:
  634. self.message.tsig_ctx.update(self.wire)
  635. def from_wire(wire, keyring=None, request_mac=b'', xfr=False, origin=None,
  636. tsig_ctx=None, multi=False, first=True,
  637. question_only=False, one_rr_per_rrset=False,
  638. ignore_trailing=False):
  639. """Convert a DNS wire format message into a message
  640. object.
  641. *keyring*, a ``dict``, the keyring to use if the message is signed.
  642. *request_mac*, a ``binary``. If the message is a response to a
  643. TSIG-signed request, *request_mac* should be set to the MAC of
  644. that request.
  645. *xfr*, a ``bool``, should be set to ``True`` if this message is part of
  646. a zone transfer.
  647. *origin*, a ``dns.name.Name`` or ``None``. If the message is part
  648. of a zone transfer, *origin* should be the origin name of the
  649. zone.
  650. *tsig_ctx*, a ``hmac.HMAC`` objext, the ongoing TSIG context, used
  651. when validating zone transfers.
  652. *multi*, a ``bool``, should be set to ``True`` if this message
  653. part of a multiple message sequence.
  654. *first*, a ``bool``, should be set to ``True`` if this message is
  655. stand-alone, or the first message in a multi-message sequence.
  656. *question_only*, a ``bool``. If ``True``, read only up to
  657. the end of the question section.
  658. *one_rr_per_rrset*, a ``bool``. If ``True``, put each RR into its
  659. own RRset.
  660. *ignore_trailing*, a ``bool``. If ``True``, ignore trailing
  661. junk at end of the message.
  662. Raises ``dns.message.ShortHeader`` if the message is less than 12 octets
  663. long.
  664. Raises ``dns.messaage.TrailingJunk`` if there were octets in the message
  665. past the end of the proper DNS message, and *ignore_trailing* is ``False``.
  666. Raises ``dns.message.BadEDNS`` if an OPT record was in the
  667. wrong section, or occurred more than once.
  668. Raises ``dns.message.BadTSIG`` if a TSIG record was not the last
  669. record of the additional data section.
  670. Returns a ``dns.message.Message``.
  671. """
  672. m = Message(id=0)
  673. m.keyring = keyring
  674. m.request_mac = request_mac
  675. m.xfr = xfr
  676. m.origin = origin
  677. m.tsig_ctx = tsig_ctx
  678. m.multi = multi
  679. m.first = first
  680. reader = _WireReader(wire, m, question_only, one_rr_per_rrset,
  681. ignore_trailing)
  682. reader.read()
  683. return m
  684. class _TextReader(object):
  685. """Text format reader.
  686. tok: the tokenizer.
  687. message: The message object being built.
  688. updating: Is the message a dynamic update?
  689. zone_rdclass: The class of the zone in messages which are
  690. DNS dynamic updates.
  691. last_name: The most recently read name when building a message object.
  692. """
  693. def __init__(self, text, message):
  694. self.message = message
  695. self.tok = dns.tokenizer.Tokenizer(text)
  696. self.last_name = None
  697. self.zone_rdclass = dns.rdataclass.IN
  698. self.updating = False
  699. def _header_line(self, section):
  700. """Process one line from the text format header section."""
  701. token = self.tok.get()
  702. what = token.value
  703. if what == 'id':
  704. self.message.id = self.tok.get_int()
  705. elif what == 'flags':
  706. while True:
  707. token = self.tok.get()
  708. if not token.is_identifier():
  709. self.tok.unget(token)
  710. break
  711. self.message.flags = self.message.flags | \
  712. dns.flags.from_text(token.value)
  713. if dns.opcode.is_update(self.message.flags):
  714. self.updating = True
  715. elif what == 'edns':
  716. self.message.edns = self.tok.get_int()
  717. self.message.ednsflags = self.message.ednsflags | \
  718. (self.message.edns << 16)
  719. elif what == 'eflags':
  720. if self.message.edns < 0:
  721. self.message.edns = 0
  722. while True:
  723. token = self.tok.get()
  724. if not token.is_identifier():
  725. self.tok.unget(token)
  726. break
  727. self.message.ednsflags = self.message.ednsflags | \
  728. dns.flags.edns_from_text(token.value)
  729. elif what == 'payload':
  730. self.message.payload = self.tok.get_int()
  731. if self.message.edns < 0:
  732. self.message.edns = 0
  733. elif what == 'opcode':
  734. text = self.tok.get_string()
  735. self.message.flags = self.message.flags | \
  736. dns.opcode.to_flags(dns.opcode.from_text(text))
  737. elif what == 'rcode':
  738. text = self.tok.get_string()
  739. self.message.set_rcode(dns.rcode.from_text(text))
  740. else:
  741. raise UnknownHeaderField
  742. self.tok.get_eol()
  743. def _question_line(self, section):
  744. """Process one line from the text format question section."""
  745. token = self.tok.get(want_leading=True)
  746. if not token.is_whitespace():
  747. self.last_name = dns.name.from_text(token.value, None)
  748. name = self.last_name
  749. token = self.tok.get()
  750. if not token.is_identifier():
  751. raise dns.exception.SyntaxError
  752. # Class
  753. try:
  754. rdclass = dns.rdataclass.from_text(token.value)
  755. token = self.tok.get()
  756. if not token.is_identifier():
  757. raise dns.exception.SyntaxError
  758. except dns.exception.SyntaxError:
  759. raise dns.exception.SyntaxError
  760. except Exception:
  761. rdclass = dns.rdataclass.IN
  762. # Type
  763. rdtype = dns.rdatatype.from_text(token.value)
  764. self.message.find_rrset(self.message.question, name,
  765. rdclass, rdtype, create=True,
  766. force_unique=True)
  767. if self.updating:
  768. self.zone_rdclass = rdclass
  769. self.tok.get_eol()
  770. def _rr_line(self, section):
  771. """Process one line from the text format answer, authority, or
  772. additional data sections.
  773. """
  774. deleting = None
  775. # Name
  776. token = self.tok.get(want_leading=True)
  777. if not token.is_whitespace():
  778. self.last_name = dns.name.from_text(token.value, None)
  779. name = self.last_name
  780. token = self.tok.get()
  781. if not token.is_identifier():
  782. raise dns.exception.SyntaxError
  783. # TTL
  784. try:
  785. ttl = int(token.value, 0)
  786. token = self.tok.get()
  787. if not token.is_identifier():
  788. raise dns.exception.SyntaxError
  789. except dns.exception.SyntaxError:
  790. raise dns.exception.SyntaxError
  791. except Exception:
  792. ttl = 0
  793. # Class
  794. try:
  795. rdclass = dns.rdataclass.from_text(token.value)
  796. token = self.tok.get()
  797. if not token.is_identifier():
  798. raise dns.exception.SyntaxError
  799. if rdclass == dns.rdataclass.ANY or rdclass == dns.rdataclass.NONE:
  800. deleting = rdclass
  801. rdclass = self.zone_rdclass
  802. except dns.exception.SyntaxError:
  803. raise dns.exception.SyntaxError
  804. except Exception:
  805. rdclass = dns.rdataclass.IN
  806. # Type
  807. rdtype = dns.rdatatype.from_text(token.value)
  808. token = self.tok.get()
  809. if not token.is_eol_or_eof():
  810. self.tok.unget(token)
  811. rd = dns.rdata.from_text(rdclass, rdtype, self.tok, None)
  812. covers = rd.covers()
  813. else:
  814. rd = None
  815. covers = dns.rdatatype.NONE
  816. rrset = self.message.find_rrset(section, name,
  817. rdclass, rdtype, covers,
  818. deleting, True, self.updating)
  819. if rd is not None:
  820. rrset.add(rd, ttl)
  821. def read(self):
  822. """Read a text format DNS message and build a dns.message.Message
  823. object."""
  824. line_method = self._header_line
  825. section = None
  826. while 1:
  827. token = self.tok.get(True, True)
  828. if token.is_eol_or_eof():
  829. break
  830. if token.is_comment():
  831. u = token.value.upper()
  832. if u == 'HEADER':
  833. line_method = self._header_line
  834. elif u == 'QUESTION' or u == 'ZONE':
  835. line_method = self._question_line
  836. section = self.message.question
  837. elif u == 'ANSWER' or u == 'PREREQ':
  838. line_method = self._rr_line
  839. section = self.message.answer
  840. elif u == 'AUTHORITY' or u == 'UPDATE':
  841. line_method = self._rr_line
  842. section = self.message.authority
  843. elif u == 'ADDITIONAL':
  844. line_method = self._rr_line
  845. section = self.message.additional
  846. self.tok.get_eol()
  847. continue
  848. self.tok.unget(token)
  849. line_method(section)
  850. def from_text(text):
  851. """Convert the text format message into a message object.
  852. *text*, a ``text``, the text format message.
  853. Raises ``dns.message.UnknownHeaderField`` if a header is unknown.
  854. Raises ``dns.exception.SyntaxError`` if the text is badly formed.
  855. Returns a ``dns.message.Message object``
  856. """
  857. # 'text' can also be a file, but we don't publish that fact
  858. # since it's an implementation detail. The official file
  859. # interface is from_file().
  860. m = Message()
  861. reader = _TextReader(text, m)
  862. reader.read()
  863. return m
  864. def from_file(f):
  865. """Read the next text format message from the specified file.
  866. *f*, a ``file`` or ``text``. If *f* is text, it is treated as the
  867. pathname of a file to open.
  868. Raises ``dns.message.UnknownHeaderField`` if a header is unknown.
  869. Raises ``dns.exception.SyntaxError`` if the text is badly formed.
  870. Returns a ``dns.message.Message object``
  871. """
  872. str_type = string_types
  873. opts = 'rU'
  874. if isinstance(f, str_type):
  875. f = open(f, opts)
  876. want_close = True
  877. else:
  878. want_close = False
  879. try:
  880. m = from_text(f)
  881. finally:
  882. if want_close:
  883. f.close()
  884. return m
  885. def make_query(qname, rdtype, rdclass=dns.rdataclass.IN, use_edns=None,
  886. want_dnssec=False, ednsflags=None, payload=None,
  887. request_payload=None, options=None):
  888. """Make a query message.
  889. The query name, type, and class may all be specified either
  890. as objects of the appropriate type, or as strings.
  891. The query will have a randomly chosen query id, and its DNS flags
  892. will be set to dns.flags.RD.
  893. qname, a ``dns.name.Name`` or ``text``, the query name.
  894. *rdtype*, an ``int`` or ``text``, the desired rdata type.
  895. *rdclass*, an ``int`` or ``text``, the desired rdata class; the default
  896. is class IN.
  897. *use_edns*, an ``int``, ``bool`` or ``None``. The EDNS level to use; the
  898. default is None (no EDNS).
  899. See the description of dns.message.Message.use_edns() for the possible
  900. values for use_edns and their meanings.
  901. *want_dnssec*, a ``bool``. If ``True``, DNSSEC data is desired.
  902. *ednsflags*, an ``int``, the EDNS flag values.
  903. *payload*, an ``int``, is the EDNS sender's payload field, which is the
  904. maximum size of UDP datagram the sender can handle. I.e. how big
  905. a response to this message can be.
  906. *request_payload*, an ``int``, is the EDNS payload size to use when
  907. sending this message. If not specified, defaults to the value of
  908. *payload*.
  909. *options*, a list of ``dns.edns.Option`` objects or ``None``, the EDNS
  910. options.
  911. Returns a ``dns.message.Message``
  912. """
  913. if isinstance(qname, string_types):
  914. qname = dns.name.from_text(qname)
  915. if isinstance(rdtype, string_types):
  916. rdtype = dns.rdatatype.from_text(rdtype)
  917. if isinstance(rdclass, string_types):
  918. rdclass = dns.rdataclass.from_text(rdclass)
  919. m = Message()
  920. m.flags |= dns.flags.RD
  921. m.find_rrset(m.question, qname, rdclass, rdtype, create=True,
  922. force_unique=True)
  923. # only pass keywords on to use_edns if they have been set to a
  924. # non-None value. Setting a field will turn EDNS on if it hasn't
  925. # been configured.
  926. kwargs = {}
  927. if ednsflags is not None:
  928. kwargs['ednsflags'] = ednsflags
  929. if use_edns is None:
  930. use_edns = 0
  931. if payload is not None:
  932. kwargs['payload'] = payload
  933. if use_edns is None:
  934. use_edns = 0
  935. if request_payload is not None:
  936. kwargs['request_payload'] = request_payload
  937. if use_edns is None:
  938. use_edns = 0
  939. if options is not None:
  940. kwargs['options'] = options
  941. if use_edns is None:
  942. use_edns = 0
  943. kwargs['edns'] = use_edns
  944. m.use_edns(**kwargs)
  945. m.want_dnssec(want_dnssec)
  946. return m
  947. def make_response(query, recursion_available=False, our_payload=8192,
  948. fudge=300):
  949. """Make a message which is a response for the specified query.
  950. The message returned is really a response skeleton; it has all
  951. of the infrastructure required of a response, but none of the
  952. content.
  953. The response's question section is a shallow copy of the query's
  954. question section, so the query's question RRsets should not be
  955. changed.
  956. *query*, a ``dns.message.Message``, the query to respond to.
  957. *recursion_available*, a ``bool``, should RA be set in the response?
  958. *our_payload*, an ``int``, the payload size to advertise in EDNS
  959. responses.
  960. *fudge*, an ``int``, the TSIG time fudge.
  961. Returns a ``dns.message.Message`` object.
  962. """
  963. if query.flags & dns.flags.QR:
  964. raise dns.exception.FormError('specified query message is not a query')
  965. response = dns.message.Message(query.id)
  966. response.flags = dns.flags.QR | (query.flags & dns.flags.RD)
  967. if recursion_available:
  968. response.flags |= dns.flags.RA
  969. response.set_opcode(query.opcode())
  970. response.question = list(query.question)
  971. if query.edns >= 0:
  972. response.use_edns(0, 0, our_payload, query.payload)
  973. if query.had_tsig:
  974. response.use_tsig(query.keyring, query.keyname, fudge, None, 0, b'',
  975. query.keyalgorithm)
  976. response.request_mac = query.mac
  977. return response