DLS1 server added

Split NAS's DLS1 code
This commit is contained in:
Sepalani 2018-02-14 16:25:23 +01:00
parent 5b94a02706
commit d3eed4c430
9 changed files with 204 additions and 77 deletions

View File

@ -16,6 +16,7 @@ LoggerOutputFile = ON
[NasServer]
IP = 127.0.0.1
Port = 9000
SvcHost = dls1.nintendowifi.net
LoggerName = NasServer
LoggerFilename = nas_server.log
LoggerLevel = -1
@ -40,6 +41,15 @@ LoggerLevel = -1
LoggerOutputConsole = ON
LoggerOutputFile = ON
[Dls1Server]
IP = 127.0.0.1
Port = 9003
LoggerName = Dls1Server
LoggerFilename = dls1_server.log
LoggerLevel = -1
LoggerOutputConsole = ON
LoggerOutputFile = ON
[AdminPage]
IP = 127.0.0.1
Port = 9009

View File

@ -12,6 +12,7 @@ LoggerOutputFile = ON
[NasServer]
IP = 127.0.0.1
Port = 80
SvcHost = dls1.nintendowifi.net
LoggerName = NasServer
LoggerFilename = nas_server.log
LoggerLevel = -1
@ -36,6 +37,15 @@ LoggerLevel = -1
LoggerOutputConsole = ON
LoggerOutputFile = ON
[Dls1Server]
IP = 127.0.0.1
Port = 9003
LoggerName = Dls1Server
LoggerFilename = dls1_server.log
LoggerLevel = -1
LoggerOutputConsole = ON
LoggerOutputFile = ON
[AdminPage]
IP = 127.0.0.1
Port = 9009

161
dls1_server.py Normal file
View File

@ -0,0 +1,161 @@
"""DWC Network Server Emulator
Copyright (C) 2014 polaris-
Copyright (C) 2014 ToadKing
Copyright (C) 2014 AdmiralCurtiss
Copyright (C) 2014 msoucy
Copyright (C) 2015 Sepalani
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import logging
import BaseHTTPServer
import SocketServer
import os
import traceback
from other import dlc, utils
import dwc_config
logger = dwc_config.get_logger('Dls1Server')
def handle_post(handler, addr, post):
"""Handle unknown path."""
logger.log(logging.WARNING, "Unknown path request %s from %s:%d!",
handler.path, *addr)
handler.send_response(404)
return None
def handle_download_action(handler, dlc_path, post):
"""Handle unknown download action request."""
logger.log(logging.WARNING, "Unknown download action: %s", handler.path)
handler.send_response(200)
return None
def handle_download_count(handler, dlc_path, post):
"""Handle download count request."""
ret = dlc.download_count(dlc_path, post)
handler.send_response(200)
handler.send_header("Content-type", "text/plain")
handler.send_header("X-DLS-Host", "http://127.0.0.1/")
return ret
def handle_download_list(handler, dlc_path, post):
"""Handle download list request."""
ret = dlc.download_list(dlc_path, post)
handler.send_response(200)
handler.send_header("Content-type", "text/plain")
handler.send_header("X-DLS-Host", "http://127.0.0.1/")
return ret
def handle_download_contents(handler, dlc_path, post):
"""Handle download contents request."""
ret = dlc.download_contents(dlc_path, post)
if ret is None:
handler.send_response(404)
else:
handler.send_response(200)
handler.send_header("Content-type", "application/x-dsdl")
handler.send_header("Content-Disposition",
'attachment; filename="%s"' % post["contents"])
handler.send_header("X-DLS-Host", "http://127.0.0.1/")
return ret
def handle_download(handler, addr, post):
"""Handle download POST request."""
logger.log(logging.DEBUG, "Download request to %s from %s:%d",
handler.path, *addr)
logger.log(logging.DEBUG, "%s", post)
action = str(post["action"]).lower()
dlc_dir = os.path.abspath("dlc")
dlc_path = os.path.abspath(os.path.join("dlc", post["gamecd"]))
if os.path.commonprefix([dlc_dir, dlc_path]) != dlc_dir:
logging.log(logging.WARNING,
'Attempted directory traversal attack "%s",'
' cancelling.', dlc_path)
handler.send_response(403)
return
command = handler.download_actions.get(action, handle_download_action)
ret = command(handler, dlc_path, post)
logger.log(logging.DEBUG, "Download response to %s:%d", *addr)
return ret
class Dls1HTTPServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
"""Nintendo Dls1 server handler."""
post_paths = {
"/download": handle_download
}
download_actions = {
"count": handle_download_count,
"list": handle_download_list,
"contents": handle_download_contents,
}
def version_string(self):
return "Nintendo Wii (http)"
def do_POST(self):
try:
length = int(self.headers['content-length'])
post = utils.qs_to_dict(self.rfile.read(length))
client_address = (
self.headers.get('x-forwarded-for', self.client_address[0]),
self.client_address[1]
)
post['ipaddr'] = client_address[0]
command = self.post_paths.get(self.path, handle_post)
ret = command(self, client_address, post)
if ret is not None:
self.send_header("Content-Length", str(len(ret)))
self.end_headers()
self.wfile.write(ret)
except:
logger.log(logging.ERROR, "Exception occurred on POST request!")
logger.log(logging.ERROR, "%s", traceback.format_exc())
class Dls1HTTPServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):
"""Threading HTTP server."""
pass
class Dls1Server(object):
def start(self):
address = dwc_config.get_ip_port('Dls1Server')
httpd = Dls1HTTPServer(address, Dls1HTTPServerHandler)
logger.log(logging.INFO, "Now listening for connections on %s:%d...",
*address)
httpd.serve_forever()
if __name__ == "__main__":
dls1 = Dls1Server()
dls1.start()

View File

@ -75,3 +75,10 @@ def get_logger(section, filename='altwfc.cfg'):
config.getboolean(section, 'LoggerOutputConsole'),
config.getboolean(section, 'LoggerOutputFile')
)
def get_svchost(section, filename='altwfc.cfg'):
"""Return the svchost of the corresponding section."""
config = ConfigParser.RawConfigParser(allow_no_value=True)
config.read(get_config_filename(filename))
return config.get(section, 'SvcHost')

View File

@ -42,6 +42,7 @@
<Compile Include="internal_stats_server.py" />
<Compile Include="master_server.py" />
<Compile Include="nas_server.py" />
<Compile Include="dls1_server.py" />
<Compile Include="register_page.py" />
<Compile Include="storage_server.py" />
<Compile Include="gamespy\gs_database.py" />

View File

@ -28,6 +28,7 @@ from gamespy_qr_server import GameSpyQRServer
from gamespy_server_browser_server import GameSpyServerBrowserServer
from gamespy_gamestats_server import GameSpyGamestatsServer
from nas_server import NasServer
from dls1_server import Dls1Server
from internal_stats_server import InternalStatsServer
from admin_page_server import AdminPageServer
from storage_server import StorageServer
@ -59,6 +60,7 @@ if __name__ == "__main__":
# GameSpyServerBrowserServer,
GameSpyNatNegServer,
NasServer,
Dls1Server,
InternalStatsServer,
AdminPageServer,
RegPageServer,

View File

@ -22,14 +22,12 @@
import logging
import time
import urlparse
import BaseHTTPServer
import SocketServer
import os
import traceback
from gamespy import gs_database
from other import dlc, utils
from other import utils
import dwc_config
logger = dwc_config.get_logger('NasServer')
@ -134,7 +132,9 @@ def handle_ac_svcloc(handler, db, addr, post):
# DLC host = 9000
# In case the client's DNS isn't redirecting to
# dls1.nintendowifi.net
ret["svchost"] = handler.headers['host']
# NB: NAS config overrides this if set
svchost = dwc_config.get_svchost('NasServer')
ret["svchost"] = svchost if svchost else handler.headers['host']
# Brawl has 2 host headers which Apache chokes
# on, so only return the first one or else it
@ -205,77 +205,12 @@ def handle_pr(handler, addr, post):
return utils.dict_to_qs(ret)
def handle_download_action(handler, dlc_path, post):
"""Handle unknown download action request."""
logger.log(logging.WARNING, "Unknown download action: %s", handler.path)
handler.send_response(200)
return None
def handle_download_count(handler, dlc_path, post):
"""Handle download count request."""
ret = dlc.download_count(dlc_path, post)
handler.send_response(200)
handler.send_header("Content-type", "text/plain")
handler.send_header("X-DLS-Host", "http://127.0.0.1/")
return ret
def handle_download_list(handler, dlc_path, post):
"""Handle download list request."""
ret = dlc.download_list(dlc_path, post)
handler.send_response(200)
handler.send_header("Content-type", "text/plain")
handler.send_header("X-DLS-Host", "http://127.0.0.1/")
return ret
def handle_download_contents(handler, dlc_path, post):
"""Handle download contents request."""
ret = dlc.download_contents(dlc_path, post)
if ret is None:
handler.send_response(404)
else:
handler.send_response(200)
handler.send_header("Content-type", "application/x-dsdl")
handler.send_header("Content-Disposition",
'attachment; filename="%s"' % post["contents"])
handler.send_header("X-DLS-Host", "http://127.0.0.1/")
return ret
def handle_download(handler, addr, post):
"""Handle download POST request."""
logger.log(logging.DEBUG, "Download request to %s from %s:%d",
handler.path, *addr)
logger.log(logging.DEBUG, "%s", post)
action = str(post["action"]).lower()
dlc_dir = os.path.abspath("dlc")
dlc_path = os.path.abspath(os.path.join("dlc", post["gamecd"]))
if os.path.commonprefix([dlc_dir, dlc_path]) != dlc_dir:
logging.log(logging.WARNING,
'Attempted directory traversal attack "%s",'
' cancelling.', dlc_path)
handler.send_response(403)
return
command = handler.download_actions.get(action, handle_download_action)
ret = command(handler, dlc_path, post)
logger.log(logging.DEBUG, "Download response to %s:%d", *addr)
return ret
class NasHTTPServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
"""Nintendo NAS server handler."""
post_paths = {
"/ac": handle_ac,
"/pr": handle_pr,
"/download": handle_download
}
ac_actions = {
@ -284,12 +219,6 @@ class NasHTTPServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
"svcloc": handle_ac_svcloc,
}
download_actions = {
"count": handle_download_count,
"list": handle_download_list,
"contents": handle_download_contents,
}
def version_string(self):
return "Nintendo Wii (http)"

View File

@ -0,0 +1,9 @@
<VirtualHost *:80>
ServerAdmin webmaster@localhost
ServerName dls1.nintendowifi.net
ServerAlias "dls1.nintendowifi.net"
ServerAlias "dls1.nintendowifi.net, dls1.nintendowifi.net"
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:9003/
ProxyPassReverse / http://127.0.0.1:9003/
</VirtualHost>

View File

@ -4,8 +4,6 @@
ServerAlias "naswii.nintendowifi.net, naswii.nintendowifi.net"
ServerAlias "nas.nintendowifi.net"
ServerAlias "nas.nintendowifi.net, nas.nintendowifi.net"
ServerAlias "dls1.nintendowifi.net"
ServerAlias "dls1.nintendowifi.net, dls1.nintendowifi.net"
ServerAlias "conntest.nintendowifi.net"
ServerAlias "conntest.nintendowifi.net, conntest.nintendowifi.net"
ProxyPreserveHost On