From e52db4420fb6756ad2c61bd7647a8e35be08c57c Mon Sep 17 00:00:00 2001 From: Philipp Spitzer Date: Tue, 25 Mar 2014 21:46:17 +0100 Subject: [PATCH] Implemented Auth Basic --- cgi-bin/dyndns.py | 74 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 56 insertions(+), 18 deletions(-) diff --git a/cgi-bin/dyndns.py b/cgi-bin/dyndns.py index 04e18f9..b2d33a7 100755 --- a/cgi-bin/dyndns.py +++ b/cgi-bin/dyndns.py @@ -2,10 +2,11 @@ """Dynamic DNS script. Expects URLs from routers in the form http://dyndns.colgarra.priv.at/nic/update??username=&password=&hostname=&myip= """ - +import os import re import cgi import pwd +import base64 from subprocess import call import ipaddr @@ -22,22 +23,6 @@ if DEBUG: cgitb.enable() -fields = cgi.FieldStorage() - -# the following fields are supported by most dyndns providers -# if a parameter is not provided, the .getvalue method returns None -username = fields.getvalue('username') -password = fields.getvalue('password') -hostname = fields.getvalue('hostname') -myip = fields.getvalue('myip') -wildcard = fields.getvalue('wildcard') -mx = fields.getvalue('mx') -backmx = fields.getvalue('backmx') -offline = fields.getvalue('offline') -system = fields.getvalue('system') -url = fields.getvalue('url') - - # Base class for our exceptions class DynDnsError(Exception): pass @@ -45,6 +30,9 @@ class DynDnsError(Exception): class AuthError(DynDnsError): returncode = 'badauth' +class CredentialsMissing(AuthError): + pass + class UsernameMissing(AuthError): pass @@ -57,6 +45,12 @@ class PasswordMissing(AuthError): class PasswordWrong(AuthError): pass +class AuthWrongMethod(AuthError): + returncode = 'wrongauthmethod' # not documented at dyn.com + +class AuthBasicError(AuthError): + returncode = 'authbasicerror' # not documented at dyn.com + class HostnameError(DynDnsError): returncode = 'notfqdn' @@ -78,7 +72,45 @@ class MyipInvalid(MyipError): class OfflineInvalid(DynDnsError): returncode = 'badparam' # not documented at dyn.com + +fields = cgi.FieldStorage() + +# the following fields are supported by most dyndns providers +# if a parameter is not provided, the .getvalue method returns None +username = fields.getvalue('username') +password = fields.getvalue('password') +hostname = fields.getvalue('hostname') +myip = fields.getvalue('myip') +wildcard = fields.getvalue('wildcard') +mx = fields.getvalue('mx') +backmx = fields.getvalue('backmx') +offline = fields.getvalue('offline') +system = fields.getvalue('system') +url = fields.getvalue('url') + + +# Optional Auth Basic +auth = os.environ.get('HTTP_AUTHORIZATION') # auth == 'Basic cGhpbGlwcDpka2ZhamRrZg==' +if auth: # empty string if HTTP_AUTHORIZATION not present + auth_parts = auth.split(' ') + auth_method = 'Basic' + if len(auth_parts) != 2 or auth_parts[0] != auth_method: + raise AuthWrongMethod() + try: + auth_decoded = base64.b64decode(auth_parts[1]) # auth_decoded == 'philipp:dkfajdkf' + except TypeError: + raise AuthBasicError() + auth_decoded_parts = auth_decoded.split(':') + if len(auth_decoded_parts) != 2: + raise AuthBasicError() + username, password = auth_decoded_parts + + try: + # check username and password + if username is None and password is None: + raise CredentialsMissing() + # check username if username is None: raise UsernameMissing() @@ -143,9 +175,15 @@ try: # Note: we should return 'nochg' in case the IP has not changed, however we don't know yet. +except CredentialsMissing as error: + print "Content-Type: text/html" + print "Status: 401 Unauthorized" + print "WWW-Authenticate: Basic realm='tdyndns'" + print + except DynDnsError as error: print "Content-Type: text/html" - print "Status: 200" + print "Status: 200 OK" print print error.returncode -- 2.39.5