2013-06-16 14:41:29 +02:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
2013-07-06 09:42:26 +02:00
|
|
|
""" License
|
|
|
|
|
|
|
|
Copyright (C) 2013 YunoHost
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU Affero General Public License as published
|
|
|
|
by the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU Affero General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Affero General Public License
|
|
|
|
along with this program; if not, see http://www.gnu.org/licenses
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
""" yunohost_dyndns.py
|
2013-07-06 10:17:16 +02:00
|
|
|
|
|
|
|
Subscribe and Update DynDNS Hosts
|
2013-07-06 09:42:26 +02:00
|
|
|
"""
|
2013-06-16 14:41:29 +02:00
|
|
|
import os
|
|
|
|
import sys
|
|
|
|
import requests
|
2013-06-16 14:33:00 +02:00
|
|
|
import json
|
|
|
|
import glob
|
2013-07-07 12:30:00 +02:00
|
|
|
import base64
|
2014-02-05 02:01:03 +01:00
|
|
|
|
2014-03-04 12:31:04 +01:00
|
|
|
from moulinette.helpers import YunoHostError, YunoHostLDAP, validate, colorize, win_msg
|
2013-06-16 14:41:29 +02:00
|
|
|
|
|
|
|
def dyndns_subscribe(subscribe_host="dyndns.yunohost.org", domain=None, key=None):
|
|
|
|
"""
|
|
|
|
Subscribe to a DynDNS service
|
|
|
|
|
2013-07-06 10:17:16 +02:00
|
|
|
Keyword argument:
|
|
|
|
domain -- Full domain to subscribe with
|
2013-07-06 12:59:06 +02:00
|
|
|
key -- Public DNS key
|
2013-10-31 11:21:59 +01:00
|
|
|
subscribe_host -- Dynette HTTP API to subscribe to
|
2013-06-16 14:41:29 +02:00
|
|
|
|
|
|
|
"""
|
|
|
|
if domain is None:
|
|
|
|
with open('/etc/yunohost/current_host', 'r') as f:
|
|
|
|
domain = f.readline().rstrip()
|
|
|
|
|
2013-12-10 16:26:05 +01:00
|
|
|
# Verify if domain is available
|
|
|
|
if requests.get('http://'+ subscribe_host +'/test/'+ domain).status_code != 200:
|
|
|
|
raise YunoHostError(17, _("DynDNS domain is already taken"))
|
|
|
|
|
2013-06-16 14:41:29 +02:00
|
|
|
if key is None:
|
2013-06-16 14:33:00 +02:00
|
|
|
if len(glob.glob('/etc/yunohost/dyndns/*.key')) == 0:
|
2013-06-16 14:41:29 +02:00
|
|
|
os.makedirs('/etc/yunohost/dyndns')
|
2013-07-08 14:41:44 +02:00
|
|
|
print(_("DNS key is being generated, it may take a while..."))
|
2013-06-16 14:33:00 +02:00
|
|
|
os.system('cd /etc/yunohost/dyndns && dnssec-keygen -a hmac-md5 -b 128 -n USER '+ domain)
|
|
|
|
os.system('chmod 600 /etc/yunohost/dyndns/*.key /etc/yunohost/dyndns/*.private')
|
|
|
|
|
|
|
|
key_file = glob.glob('/etc/yunohost/dyndns/*.key')[0]
|
|
|
|
with open(key_file) as f:
|
|
|
|
key = f.readline().strip().split(' ')[-1]
|
2013-06-16 14:41:29 +02:00
|
|
|
|
|
|
|
# Send subscription
|
2013-07-07 12:30:00 +02:00
|
|
|
r = requests.post('http://'+ subscribe_host +'/key/'+ base64.b64encode(key), data={ 'subdomain': domain })
|
2013-06-16 14:33:00 +02:00
|
|
|
if r.status_code != 201:
|
2013-07-07 12:55:04 +02:00
|
|
|
try: error = json.loads(r.text)['error']
|
|
|
|
except: error = "Server error"
|
2013-06-16 14:33:00 +02:00
|
|
|
raise YunoHostError(1, _("An error occured during DynDNS registration: "+ error))
|
2013-06-16 14:41:29 +02:00
|
|
|
|
|
|
|
win_msg(_("Subscribed to DynDNS"))
|
|
|
|
|
|
|
|
dyndns_installcron()
|
|
|
|
|
|
|
|
|
|
|
|
def dyndns_update(dyn_host="dynhost.yunohost.org", domain=None, key=None, ip=None):
|
|
|
|
"""
|
2013-07-06 10:17:16 +02:00
|
|
|
Update IP on DynDNS platform
|
2013-06-16 14:41:29 +02:00
|
|
|
|
2013-07-06 10:17:16 +02:00
|
|
|
Keyword argument:
|
2013-07-06 12:59:06 +02:00
|
|
|
domain -- Full domain to subscribe with
|
2013-10-31 11:21:59 +01:00
|
|
|
dyn_host -- Dynette DNS server to inform
|
2013-07-06 10:17:16 +02:00
|
|
|
key -- Public DNS key
|
2013-10-31 11:21:59 +01:00
|
|
|
ip -- IP address to send
|
2013-06-16 14:41:29 +02:00
|
|
|
|
|
|
|
"""
|
|
|
|
if domain is None:
|
|
|
|
with open('/etc/yunohost/current_host', 'r') as f:
|
|
|
|
domain = f.readline().rstrip()
|
|
|
|
|
|
|
|
if ip is None:
|
|
|
|
new_ip = requests.get('http://ip.yunohost.org').text
|
|
|
|
else:
|
|
|
|
new_ip = ip
|
|
|
|
|
|
|
|
try:
|
|
|
|
with open('/etc/yunohost/dyndns/old_ip', 'r') as f:
|
|
|
|
old_ip = f.readline().rstrip()
|
|
|
|
except IOError:
|
|
|
|
old_ip = '0.0.0.0'
|
|
|
|
|
|
|
|
if old_ip != new_ip:
|
|
|
|
host = domain.split('.')[1:]
|
|
|
|
host = '.'.join(host)
|
|
|
|
lines = [
|
|
|
|
'server '+ dyn_host,
|
|
|
|
'zone '+ host,
|
|
|
|
'update delete '+ domain +'. A',
|
|
|
|
'update delete '+ domain +'. MX',
|
|
|
|
'update delete '+ domain +'. TXT',
|
|
|
|
'update delete pubsub.'+ domain +'. A',
|
|
|
|
'update delete muc.'+ domain +'. A',
|
|
|
|
'update delete vjud.'+ domain +'. A',
|
|
|
|
'update delete _xmpp-client._tcp.'+ domain +'. SRV',
|
|
|
|
'update delete _xmpp-server._tcp.'+ domain +'. SRV',
|
2013-07-07 13:35:13 +02:00
|
|
|
'update add '+ domain +'. 1800 A '+ new_ip,
|
2013-06-16 14:41:29 +02:00
|
|
|
'update add '+ domain +'. 14400 MX 5 '+ domain +'.',
|
2013-10-30 17:34:43 +01:00
|
|
|
'update add '+ domain +'. 14400 TXT "v=spf1 a mx -all"',
|
2013-07-07 13:35:13 +02:00
|
|
|
'update add pubsub.'+ domain +'. 1800 A '+ new_ip,
|
|
|
|
'update add muc.'+ domain +'. 1800 A '+ new_ip,
|
|
|
|
'update add vjud.'+ domain +'. 1800 A '+ new_ip,
|
2013-06-16 14:41:29 +02:00
|
|
|
'update add _xmpp-client._tcp.'+ domain +'. 14400 SRV 0 5 5222 '+ domain +'.',
|
|
|
|
'update add _xmpp-server._tcp.'+ domain +'. 14400 SRV 0 5 5269 '+ domain +'.',
|
|
|
|
'show',
|
|
|
|
'send'
|
|
|
|
]
|
|
|
|
with open('/etc/yunohost/dyndns/zone', 'w') as zone:
|
2013-06-16 14:33:00 +02:00
|
|
|
for line in lines:
|
2013-06-16 14:41:29 +02:00
|
|
|
zone.write(line + '\n')
|
|
|
|
|
2013-06-16 14:33:00 +02:00
|
|
|
if key is None:
|
|
|
|
private_key_file = glob.glob('/etc/yunohost/dyndns/*.private')[0]
|
|
|
|
else:
|
|
|
|
private_key_file = key
|
|
|
|
if os.system('/usr/bin/nsupdate -k '+ private_key_file +' /etc/yunohost/dyndns/zone') == 0:
|
2013-06-16 14:41:29 +02:00
|
|
|
win_msg(_("IP successfully updated"))
|
2013-07-08 14:41:44 +02:00
|
|
|
with open('/etc/yunohost/dyndns/old_ip', 'w') as f:
|
|
|
|
f.write(new_ip)
|
2013-06-16 14:41:29 +02:00
|
|
|
else:
|
2013-11-22 16:15:48 +01:00
|
|
|
os.remove('/etc/yunohost/dyndns/old_ip')
|
2013-06-16 14:41:29 +02:00
|
|
|
raise YunoHostError(1, _("An error occured during DynDNS update"))
|
|
|
|
|
|
|
|
|
2013-06-16 14:33:00 +02:00
|
|
|
def dyndns_installcron():
|
2013-06-16 14:41:29 +02:00
|
|
|
"""
|
|
|
|
Install IP update cron
|
|
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
os.system("touch /etc/cron.d/yunohost-dyndns")
|
2013-11-21 19:08:53 +01:00
|
|
|
os.system("echo '*/2 * * * * root yunohost dyndns update --no-ldap >> /dev/null' >/etc/cron.d/yunohost-dyndns")
|
2013-06-16 14:41:29 +02:00
|
|
|
win_msg(_("DynDNS cron installed"))
|
|
|
|
|
|
|
|
|
2013-06-16 14:33:00 +02:00
|
|
|
def dyndns_removecron():
|
2013-06-16 14:41:29 +02:00
|
|
|
"""
|
|
|
|
Remove IP update cron
|
|
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
try:
|
|
|
|
os.remove("/etc/cron.d/yunohost-dyndns")
|
|
|
|
except:
|
|
|
|
raise YunoHostError(167,_("DynDNS cron was not installed!"))
|
|
|
|
|
|
|
|
win_msg(_("DynDNS cron removed"))
|