summaryrefslogtreecommitdiff
path: root/duo_openvpn.py
diff options
context:
space:
mode:
Diffstat (limited to 'duo_openvpn.py')
-rwxr-xr-xduo_openvpn.py55
1 files changed, 39 insertions, 16 deletions
diff --git a/duo_openvpn.py b/duo_openvpn.py
index a82839a..cb01827 100755
--- a/duo_openvpn.py
+++ b/duo_openvpn.py
@@ -8,12 +8,14 @@ __version__ = '2.2'
import base64
import email.utils
-import httplib
import os
import socket
import sys
import syslog
-import urllib
+
+import six
+from six.moves import http_client
+from six.moves.urllib.parse import quote, urlencode
def log(msg):
msg = 'Duo OpenVPN: %s' % msg
@@ -24,7 +26,7 @@ try:
import hmac
import json
from https_wrapper import CertValidatingHTTPSConnection
-except ImportError, e:
+except ImportError as e:
log('ImportError: %s' % e)
log('Please make sure you\'re running Python 2.6 or newer')
raise
@@ -44,8 +46,8 @@ def canon_params(params):
# http://tools.ietf.org/html/rfc5849#section-3.4.1.3.2
args = []
for (key, vals) in sorted(
- (urllib.quote(key, '~'), vals) for (key, vals) in params.items()):
- for val in sorted(urllib.quote(val, '~') for val in vals):
+ (quote(key, '~'), vals) for (key, vals) in params.items()):
+ for val in sorted(quote(val, '~') for val in vals):
args.append('%s=%s' % (key, val))
return '&'.join(args)
@@ -73,11 +75,24 @@ def sign(ikey, skey, method, host, uri, date, sig_version, params):
Return basic authorization header line with a Duo Web API signature.
"""
canonical = canonicalize(method, host, uri, params, date, sig_version)
- if isinstance(skey, unicode):
+
+ if isinstance(skey, six.text_type):
skey = skey.encode('utf-8')
+ if isinstance(canonical, six.text_type):
+ canonical = canonical.encode('utf-8')
+
sig = hmac.new(skey, canonical, hashlib.sha1)
auth = '%s:%s' % (ikey, sig.hexdigest())
- return 'Basic %s' % base64.b64encode(auth)
+
+ if isinstance(auth, six.text_type):
+ auth = auth.encode('utf-8')
+
+ b64 = base64.b64encode(auth)
+ if not isinstance(b64, six.text_type):
+ b64 = b64.decode('utf-8')
+
+ return 'Basic %s' % b64
+
def normalize_params(params):
"""
@@ -87,16 +102,19 @@ def normalize_params(params):
# urllib cannot handle unicode strings properly. quote() excepts,
# and urlencode() replaces them with '?'.
def encode(value):
- if isinstance(value, unicode):
+ if isinstance(value, six.text_type):
return value.encode("utf-8")
return value
+
def to_list(value):
- if value is None or isinstance(value, basestring):
+ if value is None or isinstance(value, six.string_types):
return [value]
return value
+
return dict(
(encode(key), [encode(v) for v in to_list(value)])
- for (key, value) in params.items())
+ for (key, value) in list(params.items()))
+
class Client(object):
sig_version = 1
@@ -163,11 +181,11 @@ class Client(object):
if method in ['POST', 'PUT']:
headers['Content-type'] = 'application/x-www-form-urlencoded'
- body = urllib.urlencode(params, doseq=True)
+ body = urlencode(params, doseq=True)
uri = path
else:
body = None
- uri = path + '?' + urllib.urlencode(params, doseq=True)
+ uri = path + '?' + urlencode(params, doseq=True)
return self._make_request(method, uri, body, headers)
@@ -192,9 +210,9 @@ class Client(object):
# Create outer HTTP(S) connection.
if self.ca_certs == 'HTTP':
- conn = httplib.HTTPConnection(host, port)
+ conn = http_client.HTTPConnection(host, port)
elif self.ca_certs == 'DISABLE':
- conn = httplib.HTTPSConnection(host, port)
+ conn = http_client.HTTPSConnection(host, port)
else:
conn = CertValidatingHTTPSConnection(host,
port,
@@ -255,6 +273,10 @@ class Client(object):
error.reason = response.reason
error.data = data
raise error
+
+ if not isinstance(data, six.text_type):
+ data = data.decode('utf-8')
+
if response.status != 200:
try:
data = json.loads(data)
@@ -391,7 +413,7 @@ def main(Client=Client, environ=os.environ):
try:
default_factor = preauth(client, control, username, ipaddr)
- except Exception, e:
+ except Exception as e:
log(str(e))
failure(control)
@@ -404,11 +426,12 @@ def main(Client=Client, environ=os.environ):
try:
auth(client, control, username, password, ipaddr)
- except Exception, e:
+ except Exception as e:
log(str(e))
failure(control)
failure(control)
+
if __name__ == '__main__':
main()