tsig issue bytes to str (python3)

105 views
Skip to first unread message

Scott Strattner

unread,
May 31, 2016, 4:39:45 PM5/31/16
to dnspython-users
I created a very simple script to demonstrate the problem. I have verified that the key works (can use it with nsupdate). I am showing the real key since it's just for testing anyway.

The code:

$ cat dnstest.py
import dns.tsigkeyring
import dns.update
import dns.reversename
import dns.query
import dns.rdatatype

dnsserver = '192.168.40.21'
ipaddress = '192.168.253.55'
keyring = dns.tsigkeyring.from_text({'ddns-test' : 'gwHzfofiiSJeh+cYTl/nUKMi8EzHWmnC+xV0IwG+EKF1LO/BTuZ/byDjscT9hXsxuQjyCpyiWZCYv7PxMI07JQ=='})
update = dns.update.Update('dynamic.domain.com.', keyring=keyring)
update.replace('testname', 300, dns.rdatatype.A, ipaddress)
response = dns.query.udp(update, dnsserver)
print(response)


I cannot use dns.tsigkeyring.from_text as is shown in the Example page. I get the following error:

$ python dnstest.py
Traceback (most recent call last):
  File "/home/sstrattn/dnstools/lib/python3.4/base64.py", line 519, in _input_type_check
    m = memoryview(s)
TypeError: memoryview: str object does not have the buffer interface

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "dnstest.py", line 9, in <module>
    keyring = dns.tsigkeyring.from_text({'ddns-test' : 'gwHzfofiiSJeh+cYTl/nUKMi8EzHWmnC+xV0IwG+EKF1LO/BTuZ/byDjscT9hXsxuQjyCpyiWZCYv7PxMI07JQ=='})
  File "/home/sstrattn/dnstools/lib/python3.4/site-packages/dns/tsigkeyring.py", line 31, in from_text
    secret = base64.decodestring(textring[keytext])
  File "/home/sstrattn/dnstools/lib/python3.4/base64.py", line 561, in decodestring
    return decodebytes(s)
  File "/home/sstrattn/dnstools/lib/python3.4/base64.py", line 553, in decodebytes
    _input_type_check(s)
  File "/home/sstrattn/dnstools/lib/python3.4/base64.py", line 522, in _input_type_check
    raise TypeError(msg) from err
TypeError: expected bytes-like object, not str

I can get around this error by forcing the key string to be a byte (prepend with 'b'). But then I get an error when trying to do an update.

Change in script:

keyring = dns.tsigkeyring.from_text({'ddns-test' : b'gwHzfofiiSJeh+cYTl/nUKMi8EzHWmnC+xV0IwG+EKF1LO/BTuZ/byDjscT9hXsxuQjyCpyiWZCYv7PxMI07JQ=='})

New error message:

$ python dnstest.py
Traceback (most recent call last):
  File "dnstest.py", line 12, in <module>
    response = dns.query.udp(update, dnsserver)
  File "/home/sstrattn/dnstools/lib/python3.4/site-packages/dns/query.py", line 223, in udp
    wire = q.to_wire()
  File "/home/sstrattn/dnstools/lib/python3.4/site-packages/dns/update.py", line 249, in to_wire
    return super(Update, self).to_wire(origin, max_size)
  File "/home/sstrattn/dnstools/lib/python3.4/site-packages/dns/message.py", line 437, in to_wire
    self.keyalgorithm)
  File "/home/sstrattn/dnstools/lib/python3.4/site-packages/dns/renderer.py", line 292, in add_tsig
    algorithm=algorithm)
  File "/home/sstrattn/dnstools/lib/python3.4/site-packages/dns/tsig.py", line 121, in sign
    post_mac = struct.pack('!HH', error, ol) + other_data
TypeError: can't concat bytes to str

My environment information (using virtualenv):

$ python --version
Python 3.4.3
(dnstools) sstrattn@puppet:~/dnstools$ pip list
dnspython (1.14.0)
pip (8.1.2)
setuptools (21.2.2)
wheel (0.29.0)

A coworker who was also playing with dnspython didn't run into any issues. When I asked him he said he installed dnspython via apt-get, not pip. The version that apt-get has is 1.11.1-1...when I try to install that with pip, I can get 1.11.1 but then I get another error, and I'd rather not get it working on an older version anyway.


Bob Halley

unread,
May 31, 2016, 7:34:13 PM5/31/16
to dnspython-users
This is a bug from the recent Python 2 and Python 3 unification.  It's fixed on github [issue #171] and will be in the 1.14.1 release when it comes out.  (Don't expect that for a few weeks at least.)

Scott Strattner

unread,
Jun 1, 2016, 9:39:55 AM6/1/16
to dnspython-users
I uninstalled the pip version of dnspython, downloaded the github code and installed it in my virtualenv, but I still get a bytes to str error. The initial tsig keyring issue is fixed, in that I no longer need to explicitly convert the string to a byte. But I still get the failure when performing the update to the DNS server.


$ python dnstest.py
Traceback (most recent call last):
  File "dnstest.py", line 13, in <module>
    response = dns.query.udp(update, dnsserver)
  File "/home/sstrattn/dnstools/lib/python3.5/site-packages/dnspython-1.15.0-py3.5.egg/dns/query.py", line 226, in udp
  File "/home/sstrattn/dnstools/lib/python3.5/site-packages/dnspython-1.15.0-py3.5.egg/dns/update.py", line 249, in to_wire
  File "/home/sstrattn/dnstools/lib/python3.5/site-packages/dnspython-1.15.0-py3.5.egg/dns/message.py", line 437, in to_wire
  File "/home/sstrattn/dnstools/lib/python3.5/site-packages/dnspython-1.15.0-py3.5.egg/dns/renderer.py", line 292, in add_tsig
  File "/home/sstrattn/dnstools/lib/python3.5/site-packages/dnspython-1.15.0-py3.5.egg/dns/tsig.py", line 121, in sign

TypeError: can't concat bytes to str


Code:

import dns.tsigkeyring
import dns.update

import dns.query
import dns.rdatatype

dnsserver = '192.168.40.21'
ipaddress = '192.168.253.55'
keyring = dns.tsigkeyring.from_text({'ddns-test' : 'gwHzfofiiSJeh+cYTl/nUKMi8EzHWmnC+xV0IwG+EKF1LO/BTuZ/byDjscT9hXsxuQjyCpyiWZCYv7PxMI07JQ=='})
update = dns.update.Update('dynamic.domain.com.', keyring=keyring)
update.replace('testname', 300, dns.rdatatype.A, ipaddress)
response = dns.query.udp(update, dnsserver)
print(response)


$ python --version
Python 3.5.1

Bob Halley

unread,
Jun 1, 2016, 9:50:56 AM6/1/16
to dnspython-users
Please try again with github source, I pushed a fix for the second problem.

Scott Strattner

unread,
Jun 1, 2016, 2:31:50 PM6/1/16
to dnspython-users
Thank you, it looks like that worked.

$ python dnstest.py
id 48311
opcode UPDATE
rcode NOERROR
flags QR RA
;ZONE
dynamic.domain.com. IN SOA
;PREREQ
;UPDATE
;ADDITIONAL

$ nslookup testname.dynamic.domain.com 192.168.40.21
Server:        192.168.40.21
Address:    192.168.40.21#53

Name:    testname.dynamic.domain.com
Address: 192.168.253.55
Reply all
Reply to author
Forward
0 new messages