Initial check-in: This is currently working but needs improvements.
[toast/tdyndns.git] / cgi-bin / dyndns.py
1 #!/usr/bin/python2.7
2 """Dynamic DNS script. Expects URLs from routers in the form
3 https://info.colgarra.priv.at/dyndns/dyndns.py?username=<username>&password=<pass>&hostname=<domain>&myip=<ipaddr>
4 """
5
6 import re
7 import cgi
8 import pwd
9 from subprocess import call
10 import ipaddr
11
12
13 # Configuration
14 PASSWORD = 'hygCithOrs5'
15
16
17 # Just for debugging:
18 # import cgitb
19 # cgitb.enable()
20
21
22 fields = cgi.FieldStorage()
23
24 username = fields.getvalue('username')
25 password = fields.getvalue('password')
26 hostname = fields.getvalue('hostname')
27 myip     = fields.getvalue('myip')
28
29 # Strip zone
30 hostname = re.sub('\.dyn\.colgarra\.priv\.at\s*$', '', hostname)
31
32 try:
33         # check username
34         user_info = pwd.getpwnam(username) # returns a key error if the user does not exist
35         if user_info.pw_uid < 1000:
36                 raise RuntimeError('Invalid user name')
37
38         # check password
39         if password != PASSWORD:
40                 raise RuntimeError('Invalid password')
41
42         # check hostname
43         if re.match(r'[-0-9a-z]+(\.[-0-9a-z]+)*$', hostname) is None:
44                 raise RuntimeError('Invalid host name')
45
46         # check IP address
47         ip = ipaddr.IPAddress(myip) # throws axception if the IP address is not valid
48         if isinstance(ip, ipaddr.IPv4Address):
49                 type = 'A'
50         elif isinstance(ip, ipaddr.IPv6Address):
51                 type = 'AAAA'
52         else:
53                 raise RuntimeError('Unknown IP address type')
54
55         # access granted
56         print "Content-Type: text/html"
57         print
58         call(['sudo', '/usr/local/bin/nsupdate_dyndns', hostname, myip, type])
59         print "OK"
60
61
62 except:
63         # access denied
64         print "Content-Type: text/html"
65         print "Status: 403 Forbidden"
66         print
67         print "Denied"
68