]> jfr.im git - irc/rizon/acid.git/blobdiff - pyva/pyva/src/main/python/moo/requests.py
et lifetime=timeout=1 for dns resolver
[irc/rizon/acid.git] / pyva / pyva / src / main / python / moo / requests.py
index eead77638da233733a6bfecd954ed32ed3dc74d5..1d8b879cfc4a0408a3b1632306ff370a340559dd 100644 (file)
@@ -4,6 +4,10 @@ from fnmatch import fnmatch
 from operator import itemgetter
 from socket import getaddrinfo, gaierror
 import moo_utils
+import dns.resolver
+import dns.exception
+
+import pyva_net_rizon_acid_core_User as User
 
 class Ban(object):
        def __init__(self, row):
@@ -92,7 +96,7 @@ class RequestManager(object):
                        last_req = self.__get_last_request(main)
                        acceptable, rating, internal = self.__verify(nick, vhost, main)
                else: # only for requests missed during downtime
-                       userinfo = self.module.inter.findUser(nick)
+                       userinfo = User.findUser(nick)
                        if userinfo and userinfo['su']:
                                main = userinfo['su']
                                last_req = self.__get_last_request(main)
@@ -128,12 +132,13 @@ class RequestManager(object):
                suspicious = self.__is_suspicious(vhost)
                date = datetime.now()
                self.list[nick.lower()] = {'id': id, 'vhost': vhost, 'rating': rating, 'date': date, 'main': main, 'nick': nick, 'last': last_req, 'suspicious': suspicious}
-               self.module.msg(self.module.chan, moo_utils.format_last_req(last_req, '[new] %(id)d.@o %(nick)s @sep %(vhost)s%(susp)s @sep%(lastreq)s' % {
+               self.module.msg(self.module.chan, moo_utils.format_last_req(last_req, '[new] %(id)d.@o %(nick)s @sep %(vhost)s%(susp)s @sep%(lastreq)s %(extra)s' % {
                                'id'     : id,
                                'nick'   : nick,
                                'vhost'  : vhost if not suspicious else '@c10@b[!]@o ' + vhost,
                                'susp'   : ' @sep @bSuspicious@b %s' % suspicious if suspicious else '',
-                               'lastreq': ' @bLast request@b %s ago as %s @sep' % (utils.get_timespan(last_req.date), last_req.nickname) if last_req else ''}))
+                               'lastreq': ' @bLast request@b %s ago as %s @sep' % (utils.get_timespan(last_req.date), last_req.nickname) if last_req else '',
+                               'extra'  : 'vHost resolved but its ownership was verified by the existence of a DNS TXT record' if internal == 'TXT record' else ''}))
        
        def add_blacklist(self, vhost, by, reason=None):
                b = (vhost, by, reason, datetime.now())
@@ -340,21 +345,43 @@ class RequestManager(object):
                is_blacklisted, reason, int = self.__is_blacklisted(vhost)
                if is_blacklisted:
                        return (False, reason, int)
-               
-               is_resolvable, resolved, host = self.__is_resolvable(vhost)
-               if is_resolvable:
-                       return (False, 
-                               'Your vHost resolves. %s' % RULES, 
-                               'vHost resolves (%s => %s)' % (host, resolved))
-               
+                       
                for req in self.list.values():
                        if main == req['main'] and nick != req['nick']:
                                return (False,
                                        'You already have a pending vHost request for a grouped nickname. Please wait for it to be reviewed before requesting a new one.',
                                        'Has a pending request with grouped nick %s' % req['nick'])
+
+               if vhost.replace(".", "").isdigit() and not self.__is_numeric_ip(vhost):
+                       return (True, '@c9Acceptable@c', None)
                
+               is_resolvable, resolved, host = self.__is_resolvable(vhost)
+               if is_resolvable:
+                       (txt_record_exists, resolving_error) = self.check_nick_in_TXT_records(vhost, nick)
+
+                       if resolving_error == "timeout":
+                               return (False, "Rejected vHost", "DNS Timeout when trying to check TXT record for vhost @b{}@b requested by @b{}@b.".format(
+                                       vhost, nick))
+                       elif resolving_error:
+                               return (False, "Unkown error", "The following error occured when checking TXT record for vhost @b{}@b requested by @b{}@b @sep {}.".format(
+                                       vhost, nick, resolving_error))
+
+                       if not txt_record_exists:
+                               return (False, 
+                                       'Your vHost resolves. You can add a particular DNS TXT record to confirm the ownership of the domain and request again. %s' % RULES, 
+                                       'vHost resolves (%s => %s)' % (host, resolved)) 
+                       else:
+                               return (True, '@c9Acceptable@c', 'TXT record')
+
                return (True, '@c9Acceptable@c', None)
-       
+
+       def __is_numeric_ip(self, host):
+               try:
+                       parts = host.split(".")
+                       return len(parts) == len([x for x in parts if 0 <= int(x) <= 255]) == 4
+               except:
+                       return False
+
        def __is_resolvable(self, host):
                try:
                        res = getaddrinfo(host, 80)
@@ -389,3 +416,24 @@ class RequestManager(object):
                                return 'matches @c10%s@c%s' % (b.vhost, ' (%s)' % b.reason if b.reason else '')
                
                return False
+
+       def check_nick_in_TXT_records(self, host, nick):
+               try:
+                       resolver = dns.resolver.Resolver()
+                       resolver.timeout = 1
+                       resolver.lifetime = 1
+                       answers = resolver.query(host, 'TXT')
+                       for answer in answers:
+                               for ans in answer.strings:
+                                       parts = ans.split('=')
+                                       if len(parts) > 1 and parts[0].lower().strip() == 'rizon_vhost':
+                                               if parts[1].strip() == '*':
+                                                       return (True, "")
+                                               nicks = [n.lower().strip() for n in parts[1].split(',')]
+                                               if nick.lower() in nicks:
+                                                       return (True, "")
+                       return (False, "")
+               except dns.exception.Timeout, e:
+                       return (False, "timeout")
+               except Exception, e:
+                       return (False, str(e))