Example #1
0
    def register(self, log, hostname, ip, options):
        """Implement ServicePlugin.register()."""
        if not ip:
            raise ServiceError("IP must be defined.")

        self._init_auth()
        opts = dict_of_opts(options)

        if 'zone' not in opts:
            raise ServiceError('Required option zone= missing, giving up.')

        session = Session()

        opts['zone_id'] = self._get_zoneid(session, opts)

        dnsrecords = self._get_dnsrecords(session, hostname, opts)
        ipv4_id, ipv4 = _get_ipv4_from_dnsrecords(dnsrecords)
        ipv6_id, ipv6 = _get_ipv6_from_dnsrecords(dnsrecords)
        log.debug("host=%s existing_ipv4=%s existing_ipv6=%s", hostname, ipv4,
                  ipv6)

        if ip.v4:
            if ipv4 != ip.v4:
                record = {'type': 'A', 'name': hostname, 'content': ip.v4}
                if ipv4_id:
                    log.debug(
                        "method=update_A host=%s existing=%s expected=%s",
                        hostname, ipv4, ip.v4)
                    ipv4_id, ipv4 = self._update_dnsrecord(
                        session, ipv4_id, record, opts)
                else:
                    log.debug(
                        "method=create_A host=%s existing=%s expected=%s",
                        hostname, ipv4, ip.v4)
                    ipv4_id, ipv4 = self._create_dnsrecord(
                        session, record, opts)
                log.debug("ipv4_id=%s updated_ipv4=%s", ipv4_id, ipv4)
            else:
                log.info("Existing ipv4 record matches, skipping update")

        if ip.v6:
            if ipv6 != ip.v6:
                record = {'type': 'AAAA', 'name': hostname, 'content': ip.v6}
                if ipv6_id:
                    log.debug(
                        "method=update_AAAA host=%s existing=%s expected=%s",
                        hostname, ipv6, ip.v6)
                    ipv6_id, ipv6 = self._update_dnsrecord(
                        session, ipv6_id, record, opts)
                else:
                    log.debug(
                        "method=create_AAAA host=%s existing=%s expected=%s",
                        hostname, ipv6, ip.v6)
                    ipv6_id, ipv6 = self._create_dnsrecord(
                        session, record, opts)
                log.debug("ipv6_id=%s updated_ipv6=%s", ipv6_id, ipv6)
            else:
                log.info("Existing ipv6 record matches, skipping update")
Example #2
0
 def register(self, log, hostname, ip, options):
     """Implement ServicePlugin.register."""
     url = self._url.format(hostname)
     http_basic_auth_setup(url)
     html = get_response(log, url)
     if html.split()[0] not in ['nochg', 'good']:
         raise ServiceError("Bad update reply: " + html)
Example #3
0
    def register(self, log, hostname, ip, options):
        """
        Based on http://freedns.afraid.org/api/, needs _url below  to update.

        The sha parameter is sha1sum of login|password.  This returns a list
        of host|currentIP|updateURL lines.  Pick the line that matches myhost,
        and fetch the URL.  word 'Updated' for success, 'fail' for failure.
        """
        def build_shasum():
            """Compute sha1sum('user|password') used in url."""
            user, password = get_netrc_auth('freedns.afraid.org')
            token = "{0}|{1}".format(user, password)
            return hashlib.sha1(token.encode()).hexdigest()

        shasum = build_shasum()
        url = self._url.format(shasum)
        if ip and ip.v6:
            url += "&address=" + str(ip.v6)
        elif ip and ip.v4:
            url += "&address=" + str(ip.v4)
        html = get_response(log, url)
        update_url = None
        for line in html.split("\n"):
            log.debug("Got line: " + line)
            tokens = line.split("|")
            if tokens[0] == hostname:
                update_url = tokens[2]
                break
        if not update_url:
            raise ServiceError("Cannot see %s being set up at this account" %
                               hostname)
        log.debug("Contacting freedns for update on %s", update_url)
        get_response(log, update_url)
Example #4
0
 def register(self, log, hostname, ip, options):
     """Implement ServicePlugin.register."""
     opts = dict_of_opts(options)
     log.debug(opts)
     if 'server' not in opts:
         log.error("Required server option missing, giving up")
         sys.exit(2)
     args = ('nsupdate', )
     if 'key' in opts:
         args += ('-k', opts['key'].encode('ascii'))
     p = Popen(args, stdout=PIPE, stdin=PIPE)
     p.stdin.write(b'server ' + opts['server'].encode('ascii') + b'\n')
     try:
         p.stdin.write(b'zone ' + opts['zone'].encode('ascii') + b'\n')
     except KeyError:
         pass
     hostname = hostname.encode('ascii')
     if ip:
         if ip.v4:
             addr = ip.v4.encode('ascii')
             p.stdin.write(b'update delete ' + hostname + b' A\n')
             p.stdin.write(b'update add ' + hostname + b' 60 A ' + addr +
                           b'\n')
         if ip.v6:
             addr = ip.v6.encode('ascii')
             p.stdin.write(b'update delete ' + hostname + b' AAAA\n')
             p.stdin.write(b'update add ' + hostname + b' 60 AAAA ' + addr +
                           b'\n')
     p.stdin.write(b'send\n')
     stdout, err = p.communicate()
     if not (err is None):
         raise ServiceError("Bad update reply: " + stdout.decode('ascii'))
Example #5
0
def _call(session, request):
    """Call Cloudflare V4 API."""
    try:
        prepped = session.prepare_request(request)
        res = session.send(prepped)

        if res.status_code / 100 != 2:
            raise ServiceError("Error retrieving %s: status %d" %
                               (request.url, res.status_code))
        json = res.json()
        if not json['success']:
            raise ServiceError("Error retrieving %s: errors %s" %
                               (request.url, json['errors']))
        return json['result']
    except ValueError as err:
        raise ServiceError("Error parsing response %s: %s" %
                           (request.url, err))
Example #6
0
 def register(self, log, hostname, ip, options):
     """Implement AddressPlugin.get_ip()."""
     if not ip:
         log.warn(self._ip_warning)
     user, password = get_netrc_auth('update.dnsexit.com')
     url = self._url.format(self._api_host, user, password, hostname)
     if ip:
         url += "&myip=" + ip.v4
     # if debugging:
     #     url += "&force=Y" # override 8 minutes server limit
     html = get_response(log, url).split('\n')
     if '200' not in html[0]:
         raise ServiceError("Bad HTML response: " + html)
     code = html[1].split('=')[0]
     if int(code) > 1:
         raise ServiceError("Bad update response: " + html[1])
     log.info("Response: " + html[1])
Example #7
0
 def register(self, log, hostname, ip, options):
     """Implement ServicePlugin.register."""
     url = self._url.format(hostname)
     if ip:
         url += "&ip=" + ip.v4
     http_basic_auth_setup(url)
     html = get_response(log, url)
     if 'uccessful' not in html:
         raise ServiceError("Bad update reply: " + html)
Example #8
0
 def register(self, log, hostname, ip, options):
     """Implement ServicePlugin.register()."""
     url = self._url.format(hostname)
     if ip:
         url += '&myip=' + ip.v4
     http_basic_auth_setup(url)
     html = get_response(log, request)
     if html not in ['good', 'nochg']:
         raise ServiceError('Bad server reply: ' + html)
Example #9
0
 def register(self, log, hostname, ip, options):
     """Implement ServicePlugin.register()."""
     url = self._url.format(hostname)
     if ip and ip.v4:
         url += "&ip=" + ip.v4
     http_basic_auth_setup(url)
     reply = get_response(log, url).strip()
     if reply not in ['ok', 'nochange']:
         raise ServiceError("Unexpected update reply: " + reply)
Example #10
0
 def register(self, log, hostname, ip, options):
     """Implement ServicePlugin.register()."""
     password = get_netrc_auth('dynv6.com')[1]
     query = {"hostname": hostname, "token": password}
     query['ipv4'] = ip.v4 if ip and ip.v4 else "auto"
     query['ipv6'] = ip.v6 if ip and ip.v6 else "auto"
     html = get_response(log, self._url + urllib.parse.urlencode(query))
     if not ('updated' in html or 'unchanged' in html):
         raise ServiceError("Update error, got: " + html)
Example #11
0
 def register(self, log, hostname, ip, options):
     """Implement ServicePlugin.register()."""
     password = get_netrc_auth('dynv6.com')[1]
     url = self._url.format(hostname, password)
     if ip and ip.v4:
         url += "&ipv4=" + ip.v4
     if ip and ip.v6:
         url += "&ipv6=" + ip.v6
     html = get_response(log, url)
     if not ('updated' in html or 'unchanged' in html):
         raise ServiceError("Update error, got: " + html)
Example #12
0
 def register(self, log, hostname, ip, options):
     """Implement ServicePlugin.register()."""
     password = get_netrc_auth('system-ns.com')[1]
     url = self._url.format(self._apihost, hostname, password)
     if ip:
         url += "&ip=" + ip.v4
     html = get_response(log, url)
     reply = json.loads(html)
     if reply['code'] > 2:
         raise ServiceError('Bad reply code {0}, message: {1}'.format(
             reply['code'], reply['msg']))
     log.info("Server reply: " + reply['msg'])
Example #13
0
 def register(self, log, hostname, ip, options):
     """Implement ServicePlugin.register()."""
     password = get_netrc_auth('www.duckdns.org')[1]
     host = hostname.split('.duckdns.org')[0]
     url = self._url.format(host, password)
     if ip and ip.v4:
         url += "&ip=" + ip.v4
     if ip and ip.v6:
         url += "&ipv6=" + ip.v6
     html = get_response(log, url)
     if html.strip() != "OK":
         raise ServiceError("Update error, got: " + html)
Example #14
0
 def register(self, log, hostname, ip, options):
     """Implement ServicePlugin.register()."""
     url = self._url.format(hostname)
     if ip.v4:
         url += "&myipv4=" + ip.v4
     if ip.v6:
         url += "&myipv6=" + ip.v6
     password = get_netrc_auth(hostname)[1]
     hdr = ('Authorization', 'Token ' + password)
     reply = get_response(log, url, header=hdr)
     if not ('good' in reply or 'throttled' in reply):
         raise ServiceError("Cannot update address: " + reply)
Example #15
0
 def _get_zoneid(self, session, opts):
     """Retrieve an identifier for a given zone name."""
     zone = opts['zone']
     params = {'name': zone, 'per_page': 1}
     request = Request('GET',
                       self._url + "/zones",
                       params=params,
                       auth=self._auth)
     res = _call(session, request)
     if res and len(res) == 1 and 'id' in res[0] and res[0]['id']:
         return res[0]['id']
     raise ServiceError("Zone %s not found" % zone)
Example #16
0
 def register(self, log, hostname, ip, options):
     """Implement ServicePlugin.register()."""
     url = self._url.format(hostname)
     if ip and ip.v4:
         url += "&ip=" + ip.v4
     if ip and ip.v6:
         url += "&ip6=" + ip.v6
     http_basic_auth_setup(url)
     html = get_response(log, url)
     key = html.split()[0]
     if key not in ['OK', 'good', 'nochg']:
         raise ServiceError("Bad server reply: " + html)
     log.info("Server reply: " + html)
Example #17
0
 def register(self, log, hostname, ip, options):
     """Implement ServicePlugin.register()."""
     url = self._url.format(hostname)
     if ip:
         url += '&myip=' + ip.v4
     api_host = urlparse(url).hostname
     username, password = get_netrc_auth(api_host)
     user_pw = ('%s:%s' % (username, password))
     credentials = base64.b64encode(user_pw.encode('ascii'))
     auth_header = ('Authorization', 'Basic ' + credentials.decode("ascii"))
     reply = get_response(log, url, header=auth_header)
     if not ('good' in reply or 'nochg' in reply):
         raise ServiceError('Bad server reply: ' + reply)
Example #18
0
 def register(self, log, hostname, ip, options):
     """
     Based on http://freedns.afraid.org/api/, needs _url below  to update.
     """
     user, password = get_netrc_auth('freedns.afraid.org')
     url = self._url.format(user, password, hostname)
     if ip and ip.v6:
         url += "&ip=" + str(ip.v6)
     elif ip and ip.v4:
         url += "&ip=" + str(ip.v4)
     html = get_response(log, url)
     if not ('Updated' in html or 'skipping' in html):
         raise ServiceError("Error updating %s" % hostname)
Example #19
0
 def register(self, log, hostname, ip, options):
     """Implement ServicePlugin.register()."""
     url = self._url.format(hostname)
     if ip:
         url += '&myip=' + ip.v4
     user, password = get_netrc_auth('now-dns.com')
     credentials = '%s:%s' % (user, password)
     encoded_credentials = base64.b64encode(credentials.encode('ascii'))
     req = urllib.request.Request(url)
     req.add_header('Authorization',
                    'Basic %s' % encoded_credentials.decode("ascii"))
     try:
         with urllib.request.urlopen(req) as response:
             code = response.getcode()
             html = response.read().decode('ascii').strip()
     except urllib.error.HTTPError as err:
         raise ServiceError("Error reading %s :%s" % (url, err))
     if code != 200:
         raise ServiceError('Bad server reply code: ' + code)
     if html not in ['good', 'nochg']:
         raise ServiceError('Bad server reply: ' + html)
     log.info("Server reply: " + html)
Example #20
0
 def register(self, log, hostname, ip, options):
     """Implement ServicePlugin.register()."""
     password = get_netrc_auth('ip.duiadns.net')[1]
     url = self._url.format(hostname, password)
     if not ip:
         log.warn("This plugin requires an ip address.")
     if ip and ip.v4:
         url += "&ip4=" + ip.v4
     if ip and ip.v6:
         url += "&ip6=" + ip.v6
     try:
         html = get_response(log, url)
     except ServiceError:
         resp = requests.get(url, verify=False)
         if resp.status_code != 200:
             raise ServiceError("Cannot access update url: " + url) \
                 from None
         html = resp.content.decode('ascii')
     parser = DuiadnsParser()
     parser.feed(html)
     if 'error' in parser.data or 'Ipv4' not in parser.data:
         raise ServiceError('Cannot parse server reply (see debug log)')
     log.info('New ip address: ' + parser.data['Ipv4'])
Example #21
0
 def register(self, log, hostname, ip, options):
     """Implement ServicePlugin.register()."""
     user, password = get_netrc_auth('www.dtdns.com')
     url = self._url.format(hostname, password)
     if ip:
         url += "&ip=" + ip.v4
     try:
         html = get_response(log, url)
     except TimeoutError:
         # one more try...
         html = get_response(log, url)
     if 'points to' not in html:
         raise ServiceError("Bad update reply: " + html)
     log.info("Update completed: " + html)
Example #22
0
 def register(self, log, hostname, ip, options):
     """Implement ServicePlugin.register()."""
     password = get_netrc_auth('ip.duiadns.net')[1]
     url = self._url.format(hostname, password)
     if not ip:
         log.warn("This plugin requires an ip address.")
     if ip and ip.v4:
         url += "&ip4=" + ip.v4
     if ip and ip.v6:
         url += "&ip6=" + ip.v6
     html = get_response(log, url)
     parser = DuiadnsParser()
     parser.feed(html)
     if 'error' in parser.data or 'Ipv4' not in parser.data:
         raise ServiceError('Cannot parse server reply (see debug log)')
     log.info('New ip address: ' + parser.data['Ipv4'])
Example #23
0
 def register(self, log, hostname, ip, options):
     """Implement ServicePlugin.register()."""
     url = self._url.format(hostname)
     api_host = urlparse(url).hostname
     username, password = get_netrc_auth(api_host)
     user_pw = ('%s:%s' % (username, password))
     credentials = base64.b64encode(user_pw.encode('ascii'))
     auth_header = ('Authorization', 'Basic ' + credentials.decode("ascii"))
     url = self._url.format(hostname)
     if ip and ip.v4:
         url += "&ip=" + ip.v4
     if ip and ip.v6:
         url += "&ip6=" + ip.v6
     html = get_response(log, url, header=auth_header)
     key = html.split()[0]
     if key not in ['OK', 'good', 'nochg']:
         raise ServiceError("Bad server reply: " + html)
     log.info("Server reply: " + html)
Example #24
0
    def register(self, log, hostname, ip, options):
        """Implement ServicePlugin.register()."""
        query = {
            'hostname': hostname,
        }

        # IP address is optional for IPv4
        if ip:
            query['myip'] = ip.v6 or ip.v4

        url = "{}?{}".format(self._url, urllib.parse.urlencode(query))
        http_basic_auth_setup(url)
        request = urllib.request.Request(url=url, method='POST')
        html = get_response(log, request)

        code = html.split()[0]
        if code not in ['good', 'nochg']:
            raise ServiceError("Bad server reply: " + html)
Example #25
0
    def register(self, log: Logger, hostname: str, ip: IpAddr, options):
        """Implement ServicePlugin.register.

        Expects the `ip` to be filtered already according to the _global_
        `--ip-version` option.
        """
        url = self._url.format(hostname)

        if ip:
            if ip.v4:
                url += '&ip=' + ip.v4
            if ip.v6:
                url += '&ip6=' + ip.v6

        http_basic_auth_setup(url)

        body = get_response(log, url)  # Get ASCII encoded body-content
        if not DeDnsHomeAddressPlugin.is_success(body):
            raise ServiceError("Bad update reply.\nMessage: " + body)
Example #26
0
 def error(self, message):
     """Implement HTMLParser.error()."""
     raise ServiceError("HTML parser error: " + message)
Example #27
0
def error(message):
    """Just a shorthand."""
    raise ServiceError("HTML parser error: " + message)