zone is now a configuration variable
[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 ZONE = '.dyn.colgarra.priv.at'
16
17
18 # Just for debugging:
19 # import cgitb
20 # cgitb.enable()
21
22
23 fields = cgi.FieldStorage()
24
25 username = fields.getvalue('username')
26 password = fields.getvalue('password')
27 hostname = fields.getvalue('hostname')
28 myip     = fields.getvalue('myip')
29
30 # Strip zone
31 hostname = hostname.strip()
32 if hostname.endswith(ZONE):
33         hostname = hostname[:-len(ZONE)]
34
35 try:
36         # check username
37         user_info = pwd.getpwnam(username) # returns a key error if the user does not exist
38         if user_info.pw_uid < 1000:
39                 raise RuntimeError('Invalid user name')
40
41         # check password
42         if password != PASSWORD:
43                 raise RuntimeError('Invalid password')
44
45         # check hostname
46         if re.match(r'[-0-9a-z]+(\.[-0-9a-z]+)*$', hostname) is None:
47                 raise RuntimeError('Invalid host name')
48
49         # check IP address
50         ip = ipaddr.IPAddress(myip) # throws axception if the IP address is not valid
51         if isinstance(ip, ipaddr.IPv4Address):
52                 type = 'A'
53         elif isinstance(ip, ipaddr.IPv6Address):
54                 type = 'AAAA'
55         else:
56                 raise RuntimeError('Unknown IP address type')
57
58         # access granted
59         print "Content-Type: text/html"
60         print
61         call(['sudo', '/usr/local/bin/nsupdate_dyndns', hostname, myip, type])
62         print "OK"
63
64
65 except:
66         # access denied
67         print "Content-Type: text/html"
68         print "Status: 403 Forbidden"
69         print
70         print "Denied"
71