This repository has been archived by the owner on Mar 19, 2021. It is now read-only.
forked from barneygale/quarry
-
Notifications
You must be signed in to change notification settings - Fork 0
/
auth_server.py
109 lines (96 loc) · 3.77 KB
/
auth_server.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
from quarry.net.server import ServerFactory, ServerProtocol
from random import randrange
from os import environ
from base64 import b64encode
from json import loads as jsondecode
import urllib2
###
### AUTH SERVER
### ask mojang to authenticate the user
###
def generate_token(length):
"""
generates a pronouncable token
"""
cons = 'bcdfghjklmnprstvwyz'
vows = 'aeiou'
token = ''
start = randrange(2) # begin with con or vow?
for i in range(0, length):
token += cons[randrange(19)] if i % 2 == start else vows[randrange(5)]
return token[:6] + "-" + token[6:]
class AuthProtocol(ServerProtocol):
def store_token(self, uuid):
"""
gets a new token using `generate_token`
and sends it to the website
returns the token or None if the request failed
"""
token = generate_token(10)
req = urllib2.Request(
# URL
environ.get("WEBSITE_URI"),
# data
"uuid=%s&token=%s" % (uuid, token),
# headers
{
"User-Agent": "Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0", # fuck you too, CloudFlare
"X-Auth-Server-Key": environ.get("WEBSITE_AUTH_KEY")
}
)
try:
response = urllib2.urlopen(req).read()
if jsondecode(response) == {"success": True, "errors": {}}:
self.logger.info("%s registered token %s" % (uuid, token))
return token
else:
raise urllib2.URLError(response)
except urllib2.URLError, e:
self.logger.error(e)
return None
def player_joined(self):
# This method gets called when a player successfully joins the server.
# If we're in online mode (the default), this means auth with the
# session server was successful and the user definitely owns the
# username they claim to.
# Call super. This switches us to "play" mode, marks the player as
# in-game, and does some logging.
ServerProtocol.player_joined(self)
# Define your own logic here. It could be an HTTP request to an API,
# or perhaps an update to a database table.
username = self.username
ip_addr = self.recv_addr.host
uuid = str(self.uuid).replace('-', '')
self.logger.info("[%s (%s) authed with IP %s]" % (username, uuid, ip_addr))
color_sign = u"\u00A7" # section sign, used for color codes in MC
token = self.store_token(uuid)
# Kick the player
if token:
self.close(("Thanks &a" + username + "&r, your token is &6" + token).replace("&", color_sign))
else:
self.close("&4Error! Please try again later, sorry.".replace("&", color_sign))
class AuthFactory(ServerFactory):
protocol = AuthProtocol
def main(args):
# Parse options
import optparse
parser = optparse.OptionParser(
usage="usage: %prog server_auth "
"[options]")
parser.add_option("-a", "--host",
dest="host", default="0.0.0.0",
help="address to listen on")
parser.add_option("-p", "--port",
dest="port", default="25565", type="int",
help="port to listen on")
(options, args) = parser.parse_args(args)
# Create factory
factory = AuthFactory()
factory.motd = "Authentication Server"
with open("server_icon.png", "rb") as image_file:
factory.favicon = "data:image/png;base64,%s" % (b64encode(image_file.read()))
# Listen
port = int(environ.get('RUPPELLS_SOCKETS_LOCAL_PORT') or options.port)
factory.listen(options.host, port)
print("Auth server listening on %s:%s" % (options.host, port))
factory.run()