mirror of
https://github.com/barronwaffles/dwc_network_server_emulator.git
synced 2026-08-24 19:45:38 -05:00
Merge pull request #103 from BeanJr/master
added whitelisting to admin page
This commit is contained in:
@@ -1,13 +1,10 @@
|
||||
#Make sure you change the password to something else and don't commit it to public github!
|
||||
admin_username = "admin"
|
||||
admin_password = "opensesame"
|
||||
|
||||
from twisted.web import server, resource
|
||||
from twisted.internet import reactor
|
||||
from twisted.internet.error import ReactorAlreadyRunning
|
||||
import base64
|
||||
import codecs
|
||||
import sqlite3
|
||||
import collections
|
||||
import json
|
||||
import time
|
||||
import datetime
|
||||
@@ -23,6 +20,26 @@ logger_filename = "admin_page.log"
|
||||
logger = utils.create_logger(logger_name, logger_filename, -1, logger_output_to_console, logger_output_to_file)
|
||||
|
||||
|
||||
#Example of adminpageconf.json
|
||||
#
|
||||
# {"username":"admin","password":"opensesame"}
|
||||
#
|
||||
# NOTE: Must use double-quotes or json module will fail
|
||||
# NOTE2: Do not check the .json file into public git!
|
||||
adminpageconf = None
|
||||
try:
|
||||
adminpageconf = file('adminpageconf.json').read().strip()
|
||||
except Exception,e:
|
||||
logger.log(logging.INFO,"ERROR reading adminpageconf.json: "+str(e))
|
||||
logger.log(logging.INFO," *** WARN: adminpageconf.json could not be read. Creating one with default values")
|
||||
adminpageconf = '{"username":"admin","password":"opensesame"}'
|
||||
fd = open('adminpageconf.json','w')
|
||||
fd.write(adminpageconf)
|
||||
fd.close()
|
||||
adminpageconf = json.loads(adminpageconf)
|
||||
admin_username = str(adminpageconf['username'])
|
||||
admin_password = str(adminpageconf['password'])
|
||||
|
||||
class AdminPage(resource.Resource):
|
||||
isLeaf = True
|
||||
|
||||
@@ -39,7 +56,7 @@ class AdminPage(resource.Resource):
|
||||
actual_auth = request.getAllHeaders()['authorization'].replace("Basic ","").strip()
|
||||
if actual_auth == expected_auth:
|
||||
if actual_auth == 'YWRtaW46b3BlbnNlc2FtZQ==':
|
||||
error_message = ( 'You must change the default login info'
|
||||
error_message = ( 'You must change the default values in adminpageconf.json'
|
||||
'<a href="http://%20:%20@'+request.getHeader('host')+'">[LOG OUT]</a>' )
|
||||
response_code = 500
|
||||
else:
|
||||
@@ -54,9 +71,66 @@ class AdminPage(resource.Resource):
|
||||
request.write(error_message)
|
||||
return is_auth
|
||||
|
||||
def update_whitelist(self, request):
|
||||
address = request.getClientIP()
|
||||
dbconn = sqlite3.connect('gpcm.db')
|
||||
userid = request.args['userid'][0].strip()
|
||||
gameid = request.args['gameid'][0].upper().strip()
|
||||
macadr = request.args['macadr'][0].strip()
|
||||
actiontype = request.args['actiontype'][0]
|
||||
if not userid.isdigit() or not gameid.isalnum() or not macadr.isalnum():
|
||||
request.setResponseCode(500)
|
||||
logger.log(logging.INFO,address+" Bad data "+userid+" "+gameid+" "+macadr)
|
||||
return "Bad data"
|
||||
if actiontype == 'add':
|
||||
dbconn.cursor().execute('insert into whitelist values(?,?,?)',(userid,gameid,macadr))
|
||||
responsedata = "Added macadr=%s for gameid=%s, userid=%s" % (macadr,gameid,userid)
|
||||
else:
|
||||
dbconn.cursor().execute('delete from whitelist where userid=? and gameid=? and macadr=?',(userid,gameid,macadr))
|
||||
responsedata = "Removed macadr=%s for gameid=%s, userid=%s" % (macadr,gameid,userid)
|
||||
dbconn.commit()
|
||||
dbconn.close()
|
||||
logger.log(logging.INFO,address+" "+responsedata)
|
||||
request.setHeader("Content-Type", "text/html; charset=utf-8")
|
||||
return responsedata
|
||||
|
||||
def render_whitelist(self, request):
|
||||
address = request.getClientIP()
|
||||
dbconn = sqlite3.connect('gpcm.db')
|
||||
dbconn.cursor().execute('CREATE TABLE IF NOT EXISTS whitelist (userid TEXT, gameid TEXT, macadr TEXT)')
|
||||
logger.log(logging.INFO,address+" Viewed whitelist")
|
||||
responsedata = ("<html><meta charset='utf-8'>\r\n"
|
||||
"<title>altwfc admin page - WhiteList</title>"
|
||||
'<a href="http://%20:%20@'+request.getHeader('host')+'">[CLICK HERE TO LOG OUT]</a>'
|
||||
"<form action='updatewhitelist' method='POST'>"
|
||||
"userid:<input type='text' name='userid'>\r\n"
|
||||
"gameid:<input type='text' name='gameid'>\r\n"
|
||||
"macadr:<input type='text' name='macadr'>\r\n"
|
||||
"<input type='hidden' name='actiontype' value='add'>\r\n"
|
||||
"<input type='submit' value='Add to whitelist'></form>\r\n"
|
||||
"<table border='1'>"
|
||||
"<tr><td>userid</td><td>gameid</td><td>macadr</td></tr>\r\n")
|
||||
for row in dbconn.cursor().execute("select * from whitelist"):
|
||||
userid = str(row[0])
|
||||
gameid = str(row[1])
|
||||
macadr = str(row[2])
|
||||
responsedata += ("<tr><td>"+userid+"</td><td>"+gameid+"</td><td>"+macadr+"</td>"
|
||||
"<td><form action='updatewhitelist' method='POST'>"
|
||||
"<input type='hidden' name='userid' value='"+userid+"'>"
|
||||
"<input type='hidden' name='gameid' value='"+gameid+"'>"
|
||||
"<input type='hidden' name='macadr' value='"+macadr+"'>"
|
||||
"<input type='hidden' name='actiontype' value='remove'>\r\n"
|
||||
"<input type='submit' value='Remove from whitelist'></form></td></tr>\r\n")
|
||||
responsedata += "</table></html>"
|
||||
dbconn.close()
|
||||
request.setHeader("Content-Type", "text/html; charset=utf-8")
|
||||
return responsedata
|
||||
|
||||
def render_GET(self, request):
|
||||
if not self.is_authorized(request):
|
||||
return ""
|
||||
if request.path == "/whitelist":
|
||||
return self.render_whitelist(request)
|
||||
if request.path != "/banhammer":
|
||||
request.setResponseCode(500)
|
||||
return "wrong url path"
|
||||
@@ -74,16 +148,19 @@ class AdminPage(resource.Resource):
|
||||
'order by users.gameid '
|
||||
'')
|
||||
dbconn = sqlite3.connect('gpcm.db')
|
||||
responsedata = ("<html><meta charset='utf-8'><table border='1'>\r\n"
|
||||
responsedata = ("<html><meta charset='utf-8'>\r\n"
|
||||
"<title>altwfc admin page</title>"
|
||||
'<a href="http://%20:%20@'+request.getHeader('host')+'">[CLICK HERE TO LOG OUT]</a>'
|
||||
"<br><br>"
|
||||
'<a href="http://'+request.getHeader('host')+'/whitelist">WhiteList</a>'
|
||||
"<table border='1'>"
|
||||
"<tr><td>ingamesn or devname</td><td>gameid</td>"
|
||||
"<td>Enabled</td><td>newest dwc_pid</td>"
|
||||
"<td>gsbrcd</td><td>userid</td></tr>\r\n")
|
||||
for row in dbconn.cursor().execute(sqlstatement):
|
||||
dwc_pid = str(row[0])
|
||||
enabled = str(row[1])
|
||||
nasdata = json.loads(row[2])
|
||||
nasdata = collections.defaultdict(lambda: '', json.loads(row[2]))
|
||||
gameid = str(row[3])
|
||||
is_console = int(str(row[4]))
|
||||
userid = str(row[5])
|
||||
@@ -113,14 +190,14 @@ class AdminPage(resource.Resource):
|
||||
"<input type='hidden' name='userid' value='"+userid+"'>"
|
||||
"<input type='hidden' name='gameid' value='"+gameid+"'>"
|
||||
"<input type='hidden' name='ingamesn' value='"+ingamesn+"'>"
|
||||
"<input type='submit' value='Ban'></form></td>")
|
||||
"<input type='submit' value='Ban'></form></td></tr>")
|
||||
else:
|
||||
responsedata += ("<td><form action='enableuser' method='POST'>"
|
||||
"<input type='hidden' name='userid' value='"+userid+"'>"
|
||||
"<input type='hidden' name='gameid' value='"+gameid+"'>"
|
||||
"<input type='hidden' name='ingamesn' value='"+ingamesn+"'>"
|
||||
"<input type='submit' value='----- unban -----'></form></td>")
|
||||
responsedata += "</tr></table></html>"
|
||||
"<input type='submit' value='----- unban -----'></form></td></tr>")
|
||||
responsedata += "</table></html>"
|
||||
dbconn.close()
|
||||
request.setHeader("Content-Type", "text/html; charset=utf-8")
|
||||
return responsedata.encode('utf-8')
|
||||
@@ -128,6 +205,8 @@ class AdminPage(resource.Resource):
|
||||
def render_POST(self, request):
|
||||
if not self.is_authorized(request):
|
||||
return ""
|
||||
if request.path == "/updatewhitelist":
|
||||
return self.update_whitelist(request)
|
||||
if request.path != "/enableuser" and request.path != "/disableuser":
|
||||
request.setResponseCode(500)
|
||||
return "wrong url path"
|
||||
@@ -155,6 +234,7 @@ class AdminPage(resource.Resource):
|
||||
dbconn.commit()
|
||||
dbconn.close()
|
||||
logger.log(logging.INFO,address+" "+responsedata)
|
||||
request.setHeader("Content-Type", "text/html; charset=utf-8")
|
||||
return responsedata
|
||||
|
||||
|
||||
|
||||
@@ -94,15 +94,15 @@ class GamespyDatabase(object):
|
||||
self.conn.row_factory = sqlite3.Row
|
||||
|
||||
#self.initialize_database()
|
||||
|
||||
|
||||
def __del__(self):
|
||||
self.close()
|
||||
|
||||
def close(self):
|
||||
def close(self):
|
||||
if self.conn != None:
|
||||
self.conn.close()
|
||||
self.conn = None
|
||||
|
||||
|
||||
def initialize_database(self):
|
||||
with Transaction(self.conn) as tx:
|
||||
row = tx.queryone("SELECT COUNT(*) FROM sqlite_master WHERE name = 'users' AND type = 'table'")
|
||||
@@ -119,7 +119,7 @@ class GamespyDatabase(object):
|
||||
tx.nonquery("CREATE TABLE buddies (userProfileId INT, buddyProfileId INT, time INT, status INT, notified INT, gameid TEXT, blocked INT)")
|
||||
tx.nonquery("CREATE TABLE pending_messages (sourceid INT, targetid INT, msg TEXT)")
|
||||
tx.nonquery("CREATE TABLE gamestat_profile (profileid INT, dindex TEXT, ptype TEXT, data TEXT)")
|
||||
tx.nonquery("CREATE UNIQUE INDEX IF NOT EXISTS gamestatprofile_triple ON gamestat_profile (profileid, dindex, ptype)")
|
||||
tx.nonquery("CREATE UNIQUE INDEX gamestatprofile_triple on gamestat_profile(profileid,dindex,ptype)")
|
||||
tx.nonquery("CREATE TABLE gameinfo (profileid INT, dindex TEXT, ptype TEXT, data TEXT)")
|
||||
tx.nonquery("CREATE TABLE nas_logins (userid TEXT, authtoken TEXT, data TEXT)")
|
||||
|
||||
@@ -206,14 +206,16 @@ class GamespyDatabase(object):
|
||||
|
||||
return profileid
|
||||
|
||||
def create_user(self, userid, password, email, uniquenick, gsbrcd, console, csnum, cfc, bssid, devname, birth, gameid):
|
||||
def create_user(self, userid, password, email, uniquenick, gsbrcd, console, csnum, cfc, bssid, devname, birth, gameid, macadr):
|
||||
|
||||
#Check for console ban
|
||||
with Transaction(self.conn) as tx:
|
||||
row = tx.queryone("SELECT * FROM users WHERE userid = ? and gameid = ? and enabled = 0 limit 1", (userid, gameid))
|
||||
row = tx.queryone("SELECT * FROM users WHERE userid = ? and gameid = ? and enabled = 0 "
|
||||
"and gameid not in (select gameid from whitelist where gameid=? and macadr=?) limit 1"
|
||||
,(userid, gameid, gameid, macadr))
|
||||
r = self.get_dict(row)
|
||||
if r != None:
|
||||
logger.log(logging.INFO, "--- REJECTING BANNED CONSOLE --- userid=%s,gameid=%s", userid,gameid)
|
||||
logger.log(logging.INFO, "--- REJECTING BANNED CONSOLE --- userid=%s,gameid=%s,macadr=%s", userid,gameid,macadr)
|
||||
return None
|
||||
|
||||
if self.check_user_exists(userid, gsbrcd) == 0:
|
||||
|
||||
@@ -118,6 +118,7 @@ def login_profile_via_parsed_authtoken(authtoken_parsed, db):
|
||||
password = authtoken_parsed['gsbrcd']
|
||||
gsbrcd = authtoken_parsed['gsbrcd']
|
||||
gameid = gsbrcd[:4]
|
||||
macadr = authtoken_parsed['macadr']
|
||||
uniquenick = utils.base32_encode(int(userid)) + gsbrcd
|
||||
email = uniquenick + "@nds" # The Wii also seems to use @nds.
|
||||
|
||||
@@ -128,7 +129,7 @@ def login_profile_via_parsed_authtoken(authtoken_parsed, db):
|
||||
|
||||
valid_user = db.check_user_exists(userid, gsbrcd)
|
||||
if valid_user == False:
|
||||
profileid = db.create_user(userid, password, email, uniquenick, gsbrcd, console, csnum, cfc, bssid, devname, birth, gameid)
|
||||
profileid = db.create_user(userid, password, email, uniquenick, gsbrcd, console, csnum, cfc, bssid, devname, birth, gameid, macadr)
|
||||
else:
|
||||
profileid = db.perform_login(userid, password, gsbrcd)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user