summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core.py64
-rw-r--r--model.py21
-rw-r--r--pywhoisd.conf6
-rwxr-xr-xpywhoisd.py35
4 files changed, 78 insertions, 48 deletions
diff --git a/core.py b/core.py
index 1ac7e4f..cdb5343 100644
--- a/core.py
+++ b/core.py
@@ -2,34 +2,33 @@ import socketserver
import ipaddr
class Daemon():
- def __init__(data):
+ def __init__(self, data):
self.data = data
- def query(q):
+ def query(self, q):
if self.is_ip(q):
- self.search_ip(q)
-
+ self.search_ip(q)
elif self.is_domain(q):
- self.search_domain(q)
-
+ self.search_domain(q)
else:
# Try to find a person with the given query
person = search_person(q)
if person:
return person
else:
- return self.show_help()
+ return self.get_help()
def search_ip(self, ip):
result = {}
# Iterate over all IP block elements
- for network in self.data.get_networks():
- for block in network.ip_blocks:
+ networks = self.data.get_networks()
+ for key in networks:
+ for block in networks[key].ip_blocks:
if ipaddr.IPAddress(ip) in ipaddr.IPNetwork(block):
- result['name'] = network.name
- for key in network.data:
- result[key] = network.data[key]
+ result['name'] = networks[key].name
+ for k in networks[key].data:
+ result[k] = networks[key].data[k]
return result
@@ -40,46 +39,57 @@ class Daemon():
def search_domain(self, domain):
pass
+ # TODO
+
def search_person(self, query):
pass
# TODO
def is_ip(self, query):
- pass
+ return True
# TODO
def is_domain(self, query):
pass
# TODO
- def show_help():
- pass
+ def get_help(self):
+ return "This will be the help"
+
+ # TODO
+ def get_footer(self):
+ return "This will be the footer"
+
+ # TODO
+ def get_header(self):
+ return "This will be the header"
class WhoisHandler(socketserver.BaseRequestHandler):
+ def setup(self):
+ self.daemon = self.server.daemon
+
def handle(self):
- daemon = self.server.daemon
- data = self.request.recv(100)
- cur_thread = threading.current_thread()
- response = daemon.get_header() + "\n" + daemon.query(data) + "\n" + daemon.get_footer()
+ data = str(self.request.recv(100), 'utf-8')[:-2]
+
+ response = self.daemon.get_header() + "\n"
+ response += self.daemon.query(data) + "\n"
+ response += self.daemon.get_footer()
self.request.sendall(response)
-class ClassicServer(socketserver.ThreadingTCPServer):
+class ClassicServer(socketserver.ThreadingTCPServer):
def __init__(self, config, daemon):
host = config['Servers']['classic_host']
- port = config['Servers']['classic_port']
+ port = int(config['Servers']['classic_port'])
self.daemon = daemon
- ThreadingTCPServer.__init__(self, (host, port), WhoisHandler)
-
- def start(self):
- pass
+ socketserver.ThreadingTCPServer.__init__(self, (host, port), WhoisHandler)
class WebServer(socketserver.ThreadingTCPServer):
def __init__(self, config, daemon):
self.host = config['Servers']['web_host']
- self.port = config['Servers']['web_port']
+ self.port = int(config['Servers']['web_port'])
self.daemon = daemon
- ThreadingTCPServer.__init__(self, (host, port), WhoisHandler)
+ socketserver.ThreadingTCPServer.__init__(self, (self.host, self.port), WhoisHandler)
diff --git a/model.py b/model.py
index 13bcfa8..99f368f 100644
--- a/model.py
+++ b/model.py
@@ -1,4 +1,4 @@
-from xml.etree import ElementTree
+from xml.etree.ElementTree import ElementTree
class Network():
"""A simple network definition"""
@@ -37,9 +37,9 @@ class Data():
def __init__(self, config):
self.config = config
- self.networks = []
- self.domains = []
- self.persons = []
+ self.networks = None
+ self.domains = None
+ self.persons = None
def parse_config(self):
"""Parse neccesary config params depending on the method used
@@ -79,7 +79,7 @@ class Data():
return self.persons
-class DataXML(model.Data):
+class DataXML(Data):
"""Reads network information from a XML file"""
def parse_config(self):
@@ -90,8 +90,13 @@ class DataXML(model.Data):
def load_data(self):
"""Parse XML for getting network information"""
+ self.parse_config()
root = ElementTree(file=self.data_file).getroot()
+ self.networks = {}
+ self.domains = {}
+ self.persons = {}
+
for elem in root:
if elem.tag == 'person':
self.add_person(elem)
@@ -105,7 +110,7 @@ class DataXML(model.Data):
def add_person(self, elem):
"""Adds a new person"""
- person = model.Person()
+ person = Person()
for e in elem:
if e.tag == 'name':
person.name = e.text
@@ -121,7 +126,7 @@ class DataXML(model.Data):
def add_domain(self, elem):
"""Adds a new domain"""
- domain = model.Domain()
+ domain = Domain()
for e in elem:
if e.tag == 'name':
domain.name == e.text
@@ -133,7 +138,7 @@ class DataXML(model.Data):
def add_network(self, elem):
"""Adds a new network"""
- network = model.Network()
+ network = Network()
for e in elem:
if e.tag == 'name':
network.name = e.text
diff --git a/pywhoisd.conf b/pywhoisd.conf
index b7d0662..b18da39 100644
--- a/pywhoisd.conf
+++ b/pywhoisd.conf
@@ -6,10 +6,10 @@ classic = yes
# Only makes sense when classic server is enabled
classic_host = localhost
-classic_port = 4343
+classic_port = 4344
# Run a web whois server?
-web = yes
+web = no
# Only makes sense when web server is enabled
web_host = localhost
@@ -20,4 +20,4 @@ web_port = 8080
mode = xml
# Only makes sense when xml storage mode is enabled
-xml_file = networks.xml \ No newline at end of file
+xml_file = examples/networks.xml \ No newline at end of file
diff --git a/pywhoisd.py b/pywhoisd.py
index 6572cac..11ad133 100755
--- a/pywhoisd.py
+++ b/pywhoisd.py
@@ -1,5 +1,6 @@
#!/usr/bin/python3
import configparser
+import concurrent.futures
import core
import model
@@ -9,10 +10,14 @@ class PyWhoisD():
def __init__(self):
self.config = configparser.ConfigParser()
- self.config.read('examples/pywhoisd.conf')
+ self.config.read('pywhoisd.conf')
self.data = None
self.daemon = None
+ self.classic_server = None
+ self.web_server = None
+
+ self.executor = concurrent.futures.ThreadPoolExecutor(max_workers=2)
# What kind of storage are we using?
def config_data(self):
@@ -24,7 +29,7 @@ class PyWhoisD():
mode = self.config['Storage']['mode']
if mode == 'xml':
- self.data = xml.DataXML(self.config)
+ self.data = model.DataXML(self.config)
def config_daemon(self):
"""Config common information source for all configured servers"""
@@ -40,34 +45,44 @@ class PyWhoisD():
def classic(self):
- """Returns true if web server is enabled"""
+ """Returns true if classic whois server is enabled"""
- self.config['Servers']['classic'] == 'yes'
+ return self.config['Servers']['classic'] == 'yes'
def config_servers(self):
"""Sets up server configuration from config files"""
if self.classic():
- self.classic_server = core.ClassicServer(self.config, self.daemon)
+ self.classic_server = core.ClassicServer(self.config, self.daemon)
+ else:
+ print("[+] Classic server is not enabled")
if self.web():
self.web_server = core.WebServer(self.config, self.daemon)
+ else:
+ print("[+] Web server is not enabled")
+
def start_servers(self):
- """Start configured servers"""
+ """Properly configure and start configured servers"""
self.config_servers()
- if self.classic():
- self.classic_server.start()
+ if self.classic_server:
+ print("[+] Starting classic whois server")
+ self.executor.submit(self.classic_server.serve_forever)
- if self.web():
- self.web_server.start()
+ if self.web_server:
+ self.executor.submit(self.web_server.serve_forever)
+
def main(self):
self.config_daemon()
self.start_servers()
+ # Wait for running server to finish. Probably never.
+ self.executor.shutdown()
+
if __name__ == "__main__":
pwd = PyWhoisD()
pwd.main()
nihil fit ex nihilo