]> jfr.im git - irc/quakenet/qwebirc.git/commitdiff
Support asynchronous DNS resolution in webirc/None WEBIRC modes.
authorChris Porter <redacted>
Sat, 11 Apr 2009 23:07:26 +0000 (00:07 +0100)
committerChris Porter <redacted>
Sat, 11 Apr 2009 23:07:26 +0000 (00:07 +0100)
config.py.example
qwebirc/dns.py [new file with mode: 0644]
qwebirc/engines/ajaxengine.py
qwebirc/ircclient.py

index 42dbe68bc675d6500d629b0fbe9cc0fd4296831f..2d2b33611a61945422dd020e66ded9daa2c563a8 100644 (file)
@@ -21,13 +21,15 @@ HTTP_AJAX_REQUEST_TIMEOUT = 30
 NETWORK_NAME = "FooNet"
 APP_TITLE = "FooNet Web IRC"
 
 NETWORK_NAME = "FooNet"
 APP_TITLE = "FooNet Web IRC"
 
-# Possible types include "cgiirc", "hmac" and None
-WEBIRC_MODE = "cgiirc"
+DNS_TIMEOUT = 5
 
 
-# CGIIRC values
-CGIIRC_PASSWORD = "fish"
+# Possible types include "webirc" (CGIIRC style webirc config block),
+# "hmac" (quakenet specific) and None (passes ip and host in realname)
+WEBIRC_MODE = "webirc"
 
 
-# HMAC values
+# webirc mode values
+WEBIRC_PASSWORD = "fish"
+# hmac mode values
 HMACKEY = "mrmoo"
 HMACTEMPORAL = 30
 
 HMACKEY = "mrmoo"
 HMACTEMPORAL = 30
 
diff --git a/qwebirc/dns.py b/qwebirc/dns.py
new file mode 100644 (file)
index 0000000..9021c1d
--- /dev/null
@@ -0,0 +1,56 @@
+from twisted.names import client
+from twisted.internet import reactor, defer
+
+class LookupException(Exception): pass
+class VerificationException(Exception): pass
+TimeoutException = defer.TimeoutError
+
+def lookupPTR(ip, *args, **kwargs):
+  def callback(result):
+    answer, auth, add = result
+
+    if len(answer) == 0:
+      raise LookupException, "No ANSWERS in PTR response for %s." % repr(ip)
+    return str(answer[0].payload.name)
+
+  ptr = ".".join(ip.split(".")[::-1]) + ".in-addr.arpa."
+  return client.lookupPointer(ptr, **kwargs).addCallback(callback)
+
+def lookupAs(hostname, *args, **kwargs):
+  def callback(result):
+    answer, auth, add = result
+    if len(answer) == 0:
+      raise LookupException, "No ANSWERS in A response for %s." % repr(hostname)
+    return [x.payload.dottedQuad() for x in answer]
+
+  return client.lookupAddress(hostname, *args, **kwargs).addCallback(callback)
+
+def lookupAndVerifyPTR(ip, *args, **kwargs):
+  d = defer.Deferred()
+
+  def gotPTRResult(ptr):
+    def gotAResult(a_records):
+      if ip in a_records:
+        d.callback(ptr)
+      else:
+        raise VerificationException("IP mismatch: %s != %s%s" % (repr(ip), repr(ptr), repr(a_records)))
+    lookupAs(ptr, *args, **kwargs).addCallback(gotAResult).addErrback(d.errback)
+
+  lookupPTR(ip, *args, **kwargs).addCallback(gotPTRResult).addErrback(d.errback)
+  return d
+
+if __name__ == "__main__":
+  import sys
+
+  def callback(x):
+    print x
+    reactor.stop()
+
+  def errback(x):
+    x.printTraceback()
+    reactor.stop()
+
+  d = lookupAndVerifyPTR(sys.argv[1], timeout=[.001])
+  d.addCallbacks(callback, errback)
+
+  reactor.run()
index 6d4310e5e4b2ffabea72d6deea01490dd1cff6bb..6b0bf45b02fb8c3efa0bc146bb771f0d66db0e94 100644 (file)
@@ -6,7 +6,7 @@ import simplejson, md5, sys, os, time, config, weakref, traceback, socket
 import qwebirc.ircclient as ircclient
 from adminengine import AdminEngineAction
 from qwebirc.util import HitCounter
 import qwebirc.ircclient as ircclient
 from adminengine import AdminEngineAction
 from qwebirc.util import HitCounter
-
+import qwebirc.dns as qdns
 Sessions = {}
 
 def get_session_id():
 Sessions = {}
 
 def get_session_id():
@@ -137,6 +137,10 @@ class IRCSession:
 
     reactor.callLater(5, cleanupSession, self.id)
 
 
     reactor.callLater(5, cleanupSession, self.id)
 
+# DANGER! Breach of encapsulation!
+def connect_notice(line):
+  return "c", "NOTICE", "", ("AUTH", "*** (qwebirc) %s" % line)
+
 class Channel:
   def __init__(self, request):
     self.request = request
 class Channel:
   def __init__(self, request):
     self.request = request
@@ -173,9 +177,6 @@ class AJAXEngine(resource.Resource):
         
     raise PassthruException, http_error.NoResource().render(request)
 
         
     raise PassthruException, http_error.NoResource().render(request)
 
-  #def render_GET(self, request):
-    #return self.render_POST(request)
-  
   def newConnection(self, request):
     ticket = login_optional(request)
     
   def newConnection(self, request):
     ticket = login_optional(request)
     
@@ -208,9 +209,24 @@ class AJAXEngine(resource.Resource):
       ident = socket.inet_aton(ip).encode("hex")
 
     self.__connect_hit()
       ident = socket.inet_aton(ip).encode("hex")
 
     self.__connect_hit()
-    client = ircclient.createIRC(session, nick=nick, ident=ident, ip=ip, realname=realname, perform=perform, hostname=ip)
-    session.client = client
-    
+
+    def proceed(hostname):
+      client = ircclient.createIRC(session, nick=nick, ident=ident, ip=ip, realname=realname, perform=perform, hostname=hostname)
+      session.client = client
+
+    if config.WEBIRC_MODE != "hmac":
+      notice = lambda x: session.event(connect_notice(x))
+      notice("Looking up your hostname...")
+      def callback(hostname):
+        notice("Found your hostname.")
+        proceed(hostname)
+      def errback(failure):
+        notice("Couldn't look up your hostname!")
+        proceed(ip)
+      qdns.lookupAndVerifyPTR(ip, timeout=[config.DNS_TIMEOUT]).addCallbacks(callback, errback)
+    else:
+      proceed(None) # hmac doesn't care
+
     Sessions[id] = session
     
     return id
     Sessions[id] = session
     
     return id
index 8ef8211102827174fbd860755fa1d8ad5eddae76..43f5665bc29650c30d14267fa47bd2939124332a 100644 (file)
@@ -79,8 +79,8 @@ class QWebIRCClient(basic.LineReceiver):
     if config.WEBIRC_MODE == "hmac":
       hmac = hmacfn(ident, ip)
       self.write("USER %s bleh bleh %s %s :%s" % (ident, ip, hmac, realname))
     if config.WEBIRC_MODE == "hmac":
       hmac = hmacfn(ident, ip)
       self.write("USER %s bleh bleh %s %s :%s" % (ident, ip, hmac, realname))
-    elif config.WEBIRC_MODE == "cgiirc":
-      self.write("WEBIRC %s cgiirc %s %s" % (config.WEBIRC_PASSWORD, ip, hostname))
+    elif config.WEBIRC_MODE == "webirc":
+      self.write("WEBIRC %s qwebirc %s %s" % (config.WEBIRC_PASSWORD, ip, hostname))
       self.write("USER %s bleh %s :%s" % (ident, ip, realname))
     else:
       if ip == hostname:
       self.write("USER %s bleh %s :%s" % (ident, ip, realname))
     else:
       if ip == hostname:
@@ -88,7 +88,7 @@ class QWebIRCClient(basic.LineReceiver):
       else:
         dispip = "%s/%s" % (hostname, ip)
 
       else:
         dispip = "%s/%s" % (hostname, ip)
 
-      self.write("USER %s bleh bleh :%s -- %s" % (ident, dispip, realname))
+      self.write("USER %s bleh bleh :%s - %s" % (ident, dispip, realname))
 
     self.write("NICK %s" % nick)
     
 
     self.write("NICK %s" % nick)