Example #1
0
	def perform_authp(self, data_parsed):
		authtoken_parsed = gs_utils.parse_authtoken(data_parsed['authtoken'], self.db)
		#print authtoken_parsed

		if "lid" in data_parsed:
			self.lid = data_parsed['lid']

		userid, profileid, gsbrcd, uniquenick = gs_utils.login_profile_via_parsed_authtoken(authtoken_parsed, self.db)

		if profileid != None:
			# Successfully logged in or created account, continue creating
			# session.
			sesskey = self.db.create_session(profileid, '')
			self.sessions[profileid] = self
			self.profileid = int(profileid)

			msg = gs_query.create_gamespy_message([('__cmd__', "pauthr"),
				('__cmd_val__', profileid),
				('lid', self.lid),])
		else:
			# login failed
			self.log(logging.WARNING, "Invalid password")
			msg = gs_query.create_gamespy_message([('__cmd__', "pauthr"),
				('__cmd_val__', -3),
				('lid', self.lid),
				('errmsg', 'Invalid Validation'),])

		self.log(logging.DEBUG, "SENDING: '%s'..." % msg)

		msg = self.crypt(msg)
		self.transport.write(bytes(msg))
    def perform_authp(self, data_parsed):
        authtoken_parsed = gs_utils.parse_authtoken(data_parsed['authtoken'], self.db)
        #print authtoken_parsed

        if "lid" in data_parsed:
            self.lid = data_parsed['lid']

        userid, profileid, gsbrcd, uniquenick = gs_utils.login_profile_via_parsed_authtoken(authtoken_parsed, self.db)

        if profileid != None:
            # Successfully logged in or created account, continue creating session.
            sesskey = self.db.create_session(profileid, '')
            self.sessions[profileid] = self
            self.profileid = int(profileid)

            msg = gs_query.create_gamespy_message([
                ('__cmd__', "pauthr"),
                ('__cmd_val__', profileid),
                ('lid', self.lid),
            ])
        else:
            # login failed
            self.log(logging.WARNING, "Invalid password")
            msg = gs_query.create_gamespy_message([
                ('__cmd__', "pauthr"),
                ('__cmd_val__', -3),
                ('lid', self.lid),
                ('errmsg', 'Invalid Validation'),
            ])

        self.log(logging.DEBUG, "SENDING: '%s'..." % msg)

        msg = self.crypt(msg)
        self.transport.write(bytes(msg))
Example #3
0
    def perform_bm(self, data_parsed):
        if data_parsed['__cmd_val__'] in ("1", "5", "102", "103"): # Message to/from clients?
            if "t" in data_parsed:
                # Send message to the profile id in "t"
                dest_profileid = int(data_parsed['t'])
                dest_profile_buddies = self.db.get_buddy_list(dest_profileid)
                dest_msg = data_parsed['msg']

                not_buddies = False

                # Check if the user is buddies with the target user before sending message.
                if not_buddies:
                    for buddy in self.buddies:
                        if buddy['userProfileId'] == dest_profileid:
                            not_buddies = True
                            break

                if not_buddies:
                    for buddy in dest_profile_buddies:
                        if buddy['userProfileId'] == self.profile:
                            not_buddies = True
                            break

                # Send error to user if they tried to send a message to someone who isn't a buddy.
                if not_buddies:
                    msg = gs_query.create_gamespy_message([
                        ('__cmd__', "error"),
                        ('__cmd_val__', ""),
                        ('err', 2305),
                        ('errmsg', "The profile the message was to be sent to is not a buddy."),
                        ('id', 1),
                    ])
                    logger.log(logging.DEBUG, "Trying to send message to someone who isn't a buddy: %s" % msg)
                    self.transport.write(msg)
                    return

                msg = gs_query.create_gamespy_message([
                    ('__cmd__', "bm"),
                    ('__cmd_val__', "1"),
                    ('f', self.profileid),
                    ('msg', dest_msg),
                ])

                if dest_profileid in self.sessions:
                    self.log(logging.DEBUG, "SENDING TO %s:%s: %s" % (self.sessions[dest_profileid].address.host, self.sessions[dest_profileid].address.port, msg))
                    self.sessions[dest_profileid].transport.write(bytes(msg))
                else:
                    if data_parsed['__cmd_val__'] == "1":
                        self.log(logging.DEBUG, "Saving message to %d: %s" % (dest_profileid, msg))
                        self.db.save_pending_message(self.profileid, dest_profileid, msg)
                    else:
                        msg = gs_query.create_gamespy_message([
                            ('__cmd__', "error"),
                            ('__cmd_val__', ""),
                            ('err', 2307),
                            ('errmsg', "The buddy to send a message to is offline."),
                            ('id', 1),
                        ])
                        logger.log(logging.DEBUG, "Trying to send message to someone who isn't online: %s" % msg)
                        self.transport.write(msg)
    def perform_bm(self, data_parsed):
        if data_parsed['__cmd_val__'] == "1" or data_parsed['__cmd_val__'] == "5" or data_parsed['__cmd_val__'] == "102" or data_parsed['__cmd_val__'] == "103": # Message to/from clients?
            if "t" in data_parsed:
                # Send message to the profile id in "t"
                dest_profileid = int(data_parsed['t'])
                dest_profile_buddies = self.db.get_buddy_list(dest_profileid)
                dest_msg = data_parsed['msg']

                not_buddies = False

                # Check if the user is buddies with the target user before sending message.
                if not_buddies:
                    for buddy in self.buddies:
                        if buddy['userProfileId'] == dest_profileid:
                            not_buddies = True
                            break

                if not_buddies:
                    for buddy in dest_profile_buddies:
                        if buddy['userProfileId'] == self.profile:
                            not_buddies = True
                            break

                # Send error to user if they tried to send a message to someone who isn't a buddy.
                if not_buddies:
                    msg_d = []
                    msg_d.append(('__cmd__', "error"))
                    msg_d.append(('__cmd_val__', ""))
                    msg_d.append(('err', 2305))
                    msg_d.append(('errmsg', "The profile the message was to be sent to is not a buddy."))
                    msg_d.append(('id', 1))
                    msg = gs_query.create_gamespy_message(msg_d)
                    logger.log(logging.DEBUG, "Trying to send message to someone who isn't a buddy: %s" % msg)
                    self.transport.write(msg)
                    return

                msg_d = []
                msg_d.append(('__cmd__', "bm"))
                msg_d.append(('__cmd_val__', "1"))
                msg_d.append(('f', self.profileid))
                msg_d.append(('msg', dest_msg))
                msg = gs_query.create_gamespy_message(msg_d)

                if dest_profileid in self.sessions:
                    self.log(logging.DEBUG, "SENDING TO %s:%s: %s" % (self.sessions[dest_profileid].address.host, self.sessions[dest_profileid].address.port, msg))
                    self.sessions[dest_profileid].transport.write(bytes(msg))
                else:
                    if data_parsed['__cmd_val__'] == "1":
                        self.log(logging.DEBUG, "Saving message to %d: %s" % (dest_profileid, msg))
                        self.db.save_pending_message(self.profileid, dest_profileid, msg)
                    else:
                        msg_d = []
                        msg_d.append(('__cmd__', "error"))
                        msg_d.append(('__cmd_val__', ""))
                        msg_d.append(('err', 2307))
                        msg_d.append(('errmsg', "The buddy to send a message to is offline."))
                        msg_d.append(('id', 1))
                        msg = gs_query.create_gamespy_message(msg_d)
                        logger.log(logging.DEBUG, "Trying to send message to someone who isn't online: %s" % msg)
                        self.transport.write(msg)
Example #5
0
    def send_status_to_friends(self, buddy_profileid=None):
        # TODO: Cache buddy list so we don't have to query the database every time
        self.buddies = self.db.get_buddy_list(self.profileid)

        if self.status == "0" and self.statstring == "Offline":
            # Going offline, don't need to send the other information.
            status_msg = "|s|%s|ss|%s" % (self.status, self.statstring)
        else:
            status_msg = "|s|%s|ss|%s|ls|%s|ip|%d|p|0|qm|0" % (
                self.status, self.statstring, self.locstring,
                self.get_ip_as_int(self.address.host))

        msg = gs_query.create_gamespy_message([
            ('__cmd__', "bm"),
            ('__cmd_val__', "100"),
            ('f', self.profileid),
            ('msg', status_msg),
        ])

        buddy_list = self.buddies
        if buddy_profileid != None:
            buddy_list = [{"buddyProfileId": buddy_profileid}]

        for buddy in buddy_list:
            if buddy['buddyProfileId'] in self.sessions:
                #self.log(logging.DEBUG, "Sending status to buddy id %s (%s:%d): %s" % (str(buddy['buddyProfileId']), self.sessions[buddy['buddyProfileId']].address.host, self.sessions[buddy['buddyProfileId']].address.port, msg))
                self.sessions[buddy['buddyProfileId']].transport.write(
                    bytes(msg))
    def send_status_to_friends(self, buddy_profileid = None):
        # TODO: Cache buddy list so we don't have to query the database every time
        self.buddies = self.db.get_buddy_list(self.profileid)

        if self.status == "0" and self.statstring == "Offline":
            # Going offline, don't need to send the other information.
            status_msg = "|s|%s|ss|%s" % (self.status, self.statstring)
        else:
            status_msg = "|s|%s|ss|%s|ls|%s|ip|%d|p|0|qm|0" % (self.status, self.statstring, self.locstring, self.get_ip_as_int(self.address.host))

        msg = gs_query.create_gamespy_message([
            ('__cmd__', "bm"),
            ('__cmd_val__', "100"),
            ('f', self.profileid),
            ('msg', status_msg),
        ])

        buddy_list = self.buddies
        if buddy_profileid != None:
            buddy_list = [{"buddyProfileId":buddy_profileid}]
            
        for buddy in buddy_list:
            if buddy['buddyProfileId'] in self.sessions:
                #self.log(logging.DEBUG, "Sending status to buddy id %s (%s:%d): %s" % (str(buddy['buddyProfileId']), self.sessions[buddy['buddyProfileId']].address.host, self.sessions[buddy['buddyProfileId']].address.port, msg))
                self.sessions[buddy['buddyProfileId']].transport.write(bytes(msg))
    def send_bm4(self, playerid):
        date = int(time.time())
        msg = gs_query.create_gamespy_message(
            [("__cmd__", "bm"), ("__cmd_val__", "4"), ("f", playerid), ("date", date), ("msg", "")]
        )

        self.transport.write(bytes(msg))
    def get_status_from_friends(self, buddy_profileid = None):
        # This will be called when the player logs in. Grab the player's buddy list and check the current sessions to
        # see if anyone is online. If they are online, make them send an update to the calling client.
        self.buddies = self.db.get_buddy_list(self.profileid)

        buddy_list = self.buddies
        if buddy_profileid != None:
            buddy_list = [{"buddyProfileId":buddy_profileid}]
        
        for buddy in self.buddies:
            if buddy['status'] != 1:
                continue

            if buddy['buddyProfileId'] in self.sessions and self.sessions[buddy['buddyProfileId']].gameid == self.gameid:
                status_msg = "|s|%s|ss|%s|ls|%s|ip|%d|p|0|qm|0" % (self.sessions[buddy['buddyProfileId']].status, self.sessions[buddy['buddyProfileId']].statstring, self.sessions[buddy['buddyProfileId']].locstring, self.get_ip_as_int(self.sessions[buddy['buddyProfileId']].address.host))
            else:
                status_msg = "|s|0|ss|Offline"

            msg = gs_query.create_gamespy_message([
                ('__cmd__', "bm"),
                ('__cmd_val__', "100"),
                ('f', buddy['buddyProfileId']),
                ('msg', status_msg),
            ])

            self.transport.write(bytes(msg))
 def send_keepalive(self):
     msg = gs_query.create_gamespy_message([
         ('__cmd__', "ka"),
         ('__cmd_val__', ""),
     ])
     self.log(logging.INFO, "%s" % "Sending keepalive...")
     self.transport.write(msg)
    def perform_setpd(self, data_parsed):
        data = self.data

        msg = gs_query.create_gamespy_message([
            ('__cmd__', "setpdr"),
            ('__cmd_val__', 1),
            ('lid', self.lid),
            ('pid', self.profileid),
            ('mod', int(time.time())),
        ])

        self.log(logging.DEBUG, "SENDING: '%s'...", msg)

        msg = self.crypt(msg)
        self.transport.write(bytes(msg))

        # TODO: Return error message.
        if int(data_parsed['pid']) != self.profileid:
            logger.log(logging.WARNING,
                       "ERROR: %d tried to update %d's profile",
                       int(data_parsed['pid']), self.profileid)
            return

        data_str = "\\data\\"
        length = int(data_parsed['length'])

        if len(data) < length:
            # The packet isn't complete yet, keep loop until we get the
            # entire packet. The length entire packet SHOULD always be
            # greater than the data field, so this check should be fine.
            return

        if data_str in data:
            idx = data.index(data_str) + len(data_str)
            data = data[idx:idx + length].rstrip("\\")
        else:
            logger.log(logging.ERROR,
                       "ERROR: Could not find \data\ in setpd command: %s",
                       data)
            data = ""

        current_data = self.db.pd_get(self.profileid, data_parsed['dindex'],
                                      data_parsed['ptype'])
        if current_data and data and 'data' in current_data:
            current_data = current_data['data'].lstrip('\\').split('\\')
            new_data = data.lstrip('\\').split('\\')

            current_data = dict(zip(current_data[0::2], current_data[1::2]))
            new_data = dict(zip(new_data[0::2], new_data[1::2]))
            for k in new_data.keys():
                current_data[k] = new_data[k]

            # TODO: use str.join()
            data = "\\"
            for k in current_data.keys():
                data += k + "\\" + current_data[k] + "\\"
            data = data.rstrip("\\")  # Don't put trailing \ into db

        self.db.pd_insert(self.profileid, data_parsed['dindex'],
                          data_parsed['ptype'], data)
    def perform_getpd(self, data_parsed):
        profile = self.db.pd_get(self.profileid, data_parsed['dindex'], data_parsed['ptype'])

        keys = data_parsed['keys'].split('\x01')

        profile_data = None

        if profile != None and 'data' in profile:
            profile_data = gs_query.parse_gamespy_message("\\prof\\" + profile['data'] + "\\final\\")

        data = ""
        if profile_data != None:
            profile_data = profile_data[0][0]

            for key in (key for key in keys if key not in ("__cmd__", "__cmd_val__", "")):
                data += "\\" + key + "\\"
                # this WILL error if profile_data isn't properly set above
                if key in profile_data:
                    data += profile_data[key]

        modified = int(time.time())

        msg = gs_query.create_gamespy_message([
            ('__cmd__', "getpdr"),
            ('__cmd_val__', 1),
            ('lid', self.lid),
            ('pid', self.profileid),
            ('mod', modified),
            ('length', len(data)),
            ('data', data),
        ])

        self.log(logging.DEBUG, "SENDING: '%s'..." % msg)
    def perform_setpd(self, data_parsed, data):
        msg_d = []
        msg_d.append(('__cmd__', "setpdr"))
        msg_d.append(('__cmd_val__', 1))
        msg_d.append(('lid', self.lid))
        msg_d.append(('pid', self.profileid))
        msg_d.append(('mod', int(time.time())))
        msg = gs_query.create_gamespy_message(msg_d)

        self.log(logging.DEBUG, "SENDING: '%s'..." % msg)

        msg = self.crypt(msg)
        self.transport.write(bytes(msg))

        # TODO: Return error message.
        if int(data_parsed['pid']) != self.profileid:
            logger.log(logging.WARNING, "ERROR: %d tried to update %d's profile" % (int(data_parsed['pid']), self.profileid))
            return

        data_str = "\\data\\"
        length = int(data_parsed['length'])

        if len(data) < length:
            # The packet isn't complete yet, keep loop until we get the entire packet.
            # The length entire packet SHOULD always be greater than the data field, so this check should be fine.
            return

        idx = data.index(data_str) + len(data_str)
        data = data[idx:idx+length]

        self.db.pd_insert(self.profileid, data_parsed['dindex'], data_parsed['ptype'], data)
    def connectionMade(self):
        try:
            self.log(logging.INFO,
                     "Received connection from %s:%d",
                     self.address.host, self.address.port)

            # Generate a random challenge string
            self.challenge = utils.generate_random_str(
                10, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
            )

            # The first command sent to the client is always a login challenge
            # containing the server challenge key.
            msg = gs_query.create_gamespy_message([
                ('__cmd__', "lc"),
                ('__cmd_val__', "1"),
                ('challenge', self.challenge),
                ('id', "1"),
            ])

            self.log(logging.DEBUG, "SENDING: '%s'...", msg)

            msg = self.crypt(msg)
            self.transport.write(bytes(msg))
        except:
            self.log(logging.ERROR,
                     "Unknown exception: %s",
                     traceback.format_exc())
    def perform_getprofile(self, data_parsed):
        #profile = self.db.get_profile_from_session_key(data_parsed['sesskey'])
        profile = self.db.get_profile_from_profileid(data_parsed['profileid'])

        # Wii example: \pi\\profileid\474888031\nick\5pde5vhn1WR9E2g1t533\userid\442778352\email\5pde5vhn1WR9E2g1t533@nds\sig\b126556e5ee62d4da9629dfad0f6b2a8\uniquenick\5pde5vhn1WR9E2g1t533\pid\11\lon\0.000000\lat\0.000000\loc\\id\2\final\
        sig = utils.generate_random_hex_str(32)

        msg_d = []
        msg_d.append(('__cmd__', "pi"))
        msg_d.append(('__cmd_val__', ""))
        msg_d.append(('profileid', profile['profileid']))
        msg_d.append(('nick', profile['uniquenick']))
        msg_d.append(('userid', profile['userid']))
        msg_d.append(('email', profile['email']))
        msg_d.append(('sig', sig))
        msg_d.append(('uniquenick', profile['uniquenick']))
        msg_d.append(('pid', profile['pid']))

        if profile['firstname'] != "":
            msg_d.append(
                ('firstname', profile['firstname']))  # Wii gets a firstname

        if profile['lastname'] != "":
            msg_d.append(('lastname', profile['lastname']))

        msg_d.append(('lon', profile['lon']))
        msg_d.append(('lat', profile['lat']))
        msg_d.append(('loc', profile['loc']))
        msg_d.append(('id', data_parsed['id']))
        msg = gs_query.create_gamespy_message(msg_d)

        self.log(logging.DEBUG, "SENDING: %s" % msg)
        self.transport.write(bytes(msg))
    def perform_otherslist(self, data_parsed):
        # Reference: http://wiki.tockdom.com/wiki/MKWii_Network_Protocol/Server/gpsp.gs.nintendowifi.net
        # Example from: filtered-mkw-log-2014-01-01-ct1310.eth
        # \otherslist\\o\146376154\uniquenick\2m0isbjmvRMCJ2i5321j\o\192817284\uniquenick\1jhggtmghRMCJ2jrsh23\o\302594991\uniquenick\7dkjp51v5RMCJ2nr3vs9\o\368031897\uniquenick\1v7p3qmkpRMCJ1o8f56p\o\447214276\uniquenick\7dkt0p6gtRMCJ2ljh72h\o\449615791\uniquenick\4puvrm1g4RMCJ00ho3v1\o\460250854\uniquenick\4rik5l1u1RMCJ0tc3fii\o\456284963\uniquenick\1unitvi86RMCJ1b10u02\o\453830866\uniquenick\7de3q52dbRMCJ2877ss2\o\450197498\uniquenick\3qtutr1ikRMCJ38gem1n\o\444241868\uniquenick\67tp53bs9RMCJ1abs7ej\o\420030955\uniquenick\5blesqia3RMCJ322bbd6\o\394609454\uniquenick\0hddp7mq2RMCJ30uv7r7\o\369478991\uniquenick\59de9c2bhRMCJ0re0fii\o\362755626\uniquenick\5tte2lif7RMCJ0cscgtg\o\350951571\uniquenick\7aeummjlaRMCJ3li4ls2\o\350740680\uniquenick\484uiqhr4RMCJ18opoj0\o\349855648\uniquenick\5blesqia3RMCJ1c245dn\o\324078642\uniquenick\62go5gpt0RMCJ0v0uhc9\o\304111337\uniquenick\4lcg6ampvRMCJ1gjre51\o\301273266\uniquenick\1dhdpjhn8RMCJ2da6f9h\o\193178453\uniquenick\3pcgu0299RMCJ3nhu50f\o\187210028\uniquenick\3tau15a9lRMCJ2ar247h\o\461622261\uniquenick\59epddrnkRMCJ1t2ge7l\oldone\\final\

        msg_d = [
            ('__cmd__', "otherslist"),
            ('__cmd_val__', ""),
        ]

        if "numopids" in data_parsed and "opids" in data_parsed:
            numopids = int(data_parsed['numopids'])
            opids = data_parsed['opids'].split('|')
            if (len(opids) != numopids) and (not int(opids[0]) == 0):
                logger.log(logging.ERROR, "Unexpected number of opids, got %d, expected %d." % (len(opids), numopids))

            # Return all uniquenicks despite any unexpected/missing opids
            for opid in opids:
                profile = self.db.get_profile_from_profileid(opid)

                msg_d.append(('o', opid))
                if profile != None:
                    msg_d.append(('uniquenick', profile['uniquenick']))
                else:
                    msg_d.append(('uniquenick', ''))

        msg_d.append(('oldone', ""))
        msg = gs_query.create_gamespy_message(msg_d)

        logger.log(logging.DEBUG, "SENDING: %s" % msg)
        self.transport.write(bytes(msg))
    def get_status_from_friends(self):
        # This will be called when the player logs in. Grab the player's buddy list and check the current sessions to
        # see if anyone is online. If they are online, make them send an update to the calling client.
        self.buddies = self.db.get_buddy_list(self.profileid)

        for buddy in self.buddies:
            if buddy['status'] != 1:
                continue

            if buddy['buddyProfileId'] in self.sessions and self.sessions[
                    buddy['buddyProfileId']].gameid == self.gameid:
                status_msg = "|s|%s|ss|%s|ls|%s|ip|%d|p|0|qm|0" % (
                    self.sessions[buddy['buddyProfileId']].status,
                    self.sessions[buddy['buddyProfileId']].statstring,
                    self.sessions[buddy['buddyProfileId']].locstring,
                    self.get_ip_as_int(
                        self.sessions[buddy['buddyProfileId']].address.host))
            else:
                status_msg = "|s|0|ss|Offline"

            msg_d = []
            msg_d.append(('__cmd__', "bm"))
            msg_d.append(('__cmd_val__', "100"))
            msg_d.append(('f', buddy['buddyProfileId']))
            msg_d.append(('msg', status_msg))
            msg = gs_query.create_gamespy_message(msg_d)

            self.transport.write(bytes(msg))
Example #17
0
    def connectionMade(self):
        try:
            self.transport.setTcpKeepAlive(1)

            self.log(logging.INFO, "Received connection from %s:%d",
                     self.address.host, self.address.port)

            # Create new session id
            self.session = ""

            # Generate a random challenge string
            self.challenge = utils.generate_random_str(
                10, "ABCDEFGHIJKLMNOPQRSTUVWXYZ")

            # The first command sent to the client is always a login challenge
            # containing the server challenge key.
            msg = gs_query.create_gamespy_message([
                ('__cmd__', "lc"),
                ('__cmd_val__', "1"),
                ('challenge', self.challenge),
                ('id', "1"),
            ])

            self.log(logging.DEBUG, "SENDING: '%s'...", msg)
            self.transport.write(bytes(msg))
        except:
            self.log(logging.ERROR, "Unknown exception: %s",
                     traceback.format_exc())
Example #18
0
    def perform_getpd(self, data_parsed):
        profile = self.db.pd_get(self.profileid, data_parsed['dindex'], data_parsed['ptype'])

        data = ""
        keys = data_parsed['keys'].split('\x01')

        profile_data = None

        if profile != None and 'data' in profile:
            profile_data = gs_query.parse_gamespy_message("\\prof\\" + profile['data'] + "\\final\\")

        if profile_data != None:
            profile_data = profile_data[0][0]

        for key in keys:
            if key != "__cmd__" and key != "__cmd_val__" and key != "":
                data += "\\"
                data += key
                data += "\\"
                if key in profile_data:
                    data += profile_data[key]

        modified = int(time.time())

        msg_d = []
        msg_d.append(('__cmd__', "getpdr"))
        msg_d.append(('__cmd_val__', 1))
        msg_d.append(('lid', self.lid))
        msg_d.append(('pid', self.profileid))
        msg_d.append(('mod', modified))
        msg_d.append(('length', len(data)))
        msg_d.append(('data', data))
        msg = gs_query.create_gamespy_message(msg_d)

        self.log(logging.DEBUG, "SENDING: '%s'..." % msg)
    def perform_getprofile(self, data_parsed):
        #profile = self.db.get_profile_from_session_key(data_parsed['sesskey'])
        profile = self.db.get_profile_from_profileid(data_parsed['profileid'])

        # Wii example: \pi\\profileid\474888031\nick\5pde5vhn1WR9E2g1t533\userid\442778352\email\5pde5vhn1WR9E2g1t533@nds\sig\b126556e5ee62d4da9629dfad0f6b2a8\uniquenick\5pde5vhn1WR9E2g1t533\pid\11\lon\0.000000\lat\0.000000\loc\\id\2\final\
        sig = utils.generate_random_hex_str(32)

        msg_d = [
            ('__cmd__', "pi"),
            ('__cmd_val__', ""),
            ('profileid', profile['profileid']),
            ('nick', profile['uniquenick']),
            ('userid', profile['userid']),
            ('email', profile['email']),
            ('sig', sig),
            ('uniquenick', profile['uniquenick']),
            ('pid', profile['pid']),
        ]

        if profile['firstname'] != "":
            msg_d.append(('firstname', profile['firstname'])) # Wii gets a firstname

        if profile['lastname'] != "":
            msg_d.append(('lastname', profile['lastname']))

        msg_d.extend([
            ('lon', profile['lon']),
            ('lat', profile['lat']),
            ('loc', profile['loc']),
            ('id', data_parsed['id']),
        ])
        msg = gs_query.create_gamespy_message(msg_d)

        self.log(logging.DEBUG, "SENDING: %s" % msg)
        self.transport.write(bytes(msg))
Example #20
0
    def perform_setpd(self, data_parsed, data):
        msg_d = []
        msg_d.append(('__cmd__', "setpdr"))
        msg_d.append(('__cmd_val__', 1))
        msg_d.append(('lid', self.lid))
        msg_d.append(('pid', self.profileid))
        msg_d.append(('mod', int(time.time())))
        msg = gs_query.create_gamespy_message(msg_d)

        self.log(logging.DEBUG, "SENDING: '%s'..." % msg)

        msg = self.crypt(msg)
        self.transport.write(bytes(msg))

        # TODO: Return error message.
        if int(data_parsed['pid']) != self.profileid:
            logger.log(
                logging.WARNING, "ERROR: %d tried to update %d's profile" %
                (int(data_parsed['pid']), self.profileid))
            return

        data_str = "\\data\\"
        length = int(data_parsed['length'])
        idx = data.index(data_str) + len(data_str)
        data = data[idx:idx + length]

        self.db.pd_insert(self.profileid, data_parsed['dindex'],
                          data_parsed['ptype'], data)
Example #21
0
    def perform_otherslist(self, data_parsed):
        # Reference: http://wiki.tockdom.com/wiki/MKWii_Network_Protocol/Server/gpsp.gs.nintendowifi.net
        # Example from: filtered-mkw-log-2014-01-01-ct1310.eth
        # \otherslist\\o\146376154\uniquenick\2m0isbjmvRMCJ2i5321j\o\192817284\uniquenick\1jhggtmghRMCJ2jrsh23\o\302594991\uniquenick\7dkjp51v5RMCJ2nr3vs9\o\368031897\uniquenick\1v7p3qmkpRMCJ1o8f56p\o\447214276\uniquenick\7dkt0p6gtRMCJ2ljh72h\o\449615791\uniquenick\4puvrm1g4RMCJ00ho3v1\o\460250854\uniquenick\4rik5l1u1RMCJ0tc3fii\o\456284963\uniquenick\1unitvi86RMCJ1b10u02\o\453830866\uniquenick\7de3q52dbRMCJ2877ss2\o\450197498\uniquenick\3qtutr1ikRMCJ38gem1n\o\444241868\uniquenick\67tp53bs9RMCJ1abs7ej\o\420030955\uniquenick\5blesqia3RMCJ322bbd6\o\394609454\uniquenick\0hddp7mq2RMCJ30uv7r7\o\369478991\uniquenick\59de9c2bhRMCJ0re0fii\o\362755626\uniquenick\5tte2lif7RMCJ0cscgtg\o\350951571\uniquenick\7aeummjlaRMCJ3li4ls2\o\350740680\uniquenick\484uiqhr4RMCJ18opoj0\o\349855648\uniquenick\5blesqia3RMCJ1c245dn\o\324078642\uniquenick\62go5gpt0RMCJ0v0uhc9\o\304111337\uniquenick\4lcg6ampvRMCJ1gjre51\o\301273266\uniquenick\1dhdpjhn8RMCJ2da6f9h\o\193178453\uniquenick\3pcgu0299RMCJ3nhu50f\o\187210028\uniquenick\3tau15a9lRMCJ2ar247h\o\461622261\uniquenick\59epddrnkRMCJ1t2ge7l\oldone\\final\

        msg_d = []
        msg_d.append(('__cmd__', "otherslist"))
        msg_d.append(('__cmd_val__', ""))

        if "numopids" in data_parsed and "opids" in data_parsed:
            numopids = int(data_parsed['numopids'])
            opids = data_parsed['opids'].split('|')
            if (len(opids) != numopids) and (not int(opids[0]) == 0):
                logger.log(
                    logging.ERROR,
                    "Unexpected number of opids, got %d, expected %d." %
                    (len(opids), numopids))

            # Return all uniquenicks despite any unexpected/missing opids
            for opid in opids:
                profile = self.db.get_profile_from_profileid(opid)

                msg_d.append(('o', opid))
                if profile != None:
                    msg_d.append(('uniquenick', profile['uniquenick']))

                else:
                    msg_d.append(('uniquenick', ''))

        msg_d.append(('oldone', ""))
        msg = gs_query.create_gamespy_message(msg_d)

        self.transport.write(bytes(msg))
    def perform_setpd(self, data_parsed, data):
        msg_d = []
        msg_d.append(('__cmd__', "setpdr"))
        msg_d.append(('__cmd_val__', 1))
        msg_d.append(('lid', self.lid))
        msg_d.append(('pid', self.profileid))
        msg_d.append(('mod', int(time.time())))
        msg = gs_query.create_gamespy_message(msg_d)

        self.log(logging.DEBUG, "SENDING: '%s'..." % msg)

        msg = self.crypt(msg)
        self.transport.write(bytes(msg))

        # TODO: Return error message.
        if int(data_parsed['pid']) != self.profileid:
            logger.log(logging.WARNING, "ERROR: %d tried to update %d's profile" % (int(data_parsed['pid']), self.profileid))
            return

        data_str = "\\data\\"
        length = int(data_parsed['length'])
        idx = data.index(data_str) + len(data_str)
        data = data[idx:idx+length]

        self.db.pd_insert(self.profileid, data_parsed['dindex'], data_parsed['ptype'], data)
    def perform_setpd(self, data_parsed, data):
        msg_d = []
        msg_d.append(('__cmd__', "setpdr"))
        msg_d.append(('__cmd_val__', 1))
        msg_d.append(('lid', self.lid))
        msg_d.append(('pid', self.profileid))
        msg_d.append(('mod', int(time.time())))
        msg = gs_query.create_gamespy_message(msg_d)

        self.log(logging.DEBUG, "SENDING: '%s'..." % msg)

        msg = self.crypt(msg)
        self.transport.write(bytes(msg))

        # TODO: Return error message.
        if int(data_parsed['pid']) != self.profileid:
            logger.log(
                logging.WARNING, "ERROR: %d tried to update %d's profile" %
                (int(data_parsed['pid']), self.profileid))
            return

        data_str = "\\data\\"
        length = int(data_parsed['length'])

        if len(data) < length:
            # The packet isn't complete yet, keep loop until we get the entire packet.
            # The length entire packet SHOULD always be greater than the data field, so this check should be fine.
            return

        idx = data.index(data_str) + len(data_str)
        data = data[idx:idx + length]

        self.db.pd_insert(self.profileid, data_parsed['dindex'],
                          data_parsed['ptype'], data)
    def perform_ka(self, data_parsed):
        self.keepalive = int(time.time())

        msg = gs_query.create_gamespy_message([
            ('__cmd__', "ka"),
            ('__cmd_val__', ""),
        ])
        self.transport.write(msg)
Example #25
0
    def perform_ka(self, data_parsed):
        self.keepalive = int(time.time())

        msg = gs_query.create_gamespy_message([
            ('__cmd__', "ka"),
            ('__cmd_val__', ""),
        ])
        self.transport.write(msg)
Example #26
0
	def perform_ka(self, data_parsed):
		msg = gs_query.create_gamespy_message([('__cmd__', "ka"),
			('__cmd_val__', ""),])

		self.log(logging.DEBUG, "SENDING: '%s'..." % msg)

		msg = self.crypt(msg)
		self.transport.write(bytes(msg))
		return
 def send_bm4(self, playerid):        
     date = int(time.time())
     msg = gs_query.create_gamespy_message([
         ('__cmd__', "bm"),
         ('__cmd_val__', "4"),
         ('f', playerid),
         ('date', date),
         ('msg', ""),
     ])
     
     self.transport.write(bytes(msg))
Example #28
0
    def send_bm4(self, playerid):
        date = int(time.time())
        msg = gs_query.create_gamespy_message([
            ('__cmd__', "bm"),
            ('__cmd_val__', "4"),
            ('f', playerid),
            ('date', date),
            ('msg', ""),
        ])

        self.transport.write(bytes(msg))
    def perform_ka(self, data_parsed):
        msg = gs_query.create_gamespy_message([
            ('__cmd__', "ka"),
            ('__cmd_val__', ""),
        ])

        self.log(logging.DEBUG, "SENDING: '%s'...", msg)

        msg = self.crypt(msg)
        self.transport.write(bytes(msg))
        return
    def perform_setpd(self, data_parsed):
        data = self.data

        msg = gs_query.create_gamespy_message([
            ('__cmd__', "setpdr"),
            ('__cmd_val__', 1),
            ('lid', self.lid),
            ('pid', self.profileid),
            ('mod', int(time.time())),
        ])

        self.log(logging.DEBUG, "SENDING: '%s'..." % msg)

        msg = self.crypt(msg)
        self.transport.write(bytes(msg))

        # TODO: Return error message.
        if int(data_parsed['pid']) != self.profileid:
            logger.log(logging.WARNING, "ERROR: %d tried to update %d's profile" % (int(data_parsed['pid']), self.profileid))
            return

        data_str = "\\data\\"
        length = int(data_parsed['length'])

        if len(data) < length:
            # The packet isn't complete yet, keep loop until we get the entire packet.
            # The length entire packet SHOULD always be greater than the data field, so this check should be fine.
            return

        if data_str in data:
            idx = data.index(data_str) + len(data_str)
            data = data[idx:idx+length].rstrip("\\")
        else:
            logger.log(logging.ERROR, "ERROR: Could not find \data\ in setpd command: %s", data)
            data = ""

        current_data = self.db.pd_get(self.profileid, data_parsed['dindex'], data_parsed['ptype'])
        if current_data and data and 'data' in current_data:
          current_data = current_data['data'].lstrip('\\').split('\\')
          new_data = data.lstrip('\\').split('\\')

          current_data = dict(zip(current_data[0::2],current_data[1::2]))
          new_data = dict(zip(new_data[0::2],new_data[1::2]))
          for k in new_data.keys():
            current_data[k] = new_data[k]

          data = "\\"
          for k in current_data.keys():
            data += k+"\\"+current_data[k]+"\\" 
          data = data.rstrip("\\")#Don't put trailing \ into db

        self.db.pd_insert(self.profileid, data_parsed['dindex'], data_parsed['ptype'], data)
Example #31
0
    def get_buddy_authorized(self):
        buddies = self.db.buddy_need_auth_message(self.profileid)

        for buddy in buddies:
            msg = gs_query.create_gamespy_message([
                ('__cmd__', "bm"),
                ('__cmd_val__', "1"),
                ('f', buddy['userProfileId']),
                ('msg', "I have authorized your request to add me to your list"),
            ])

            self.transport.write(bytes(msg))
            self.db.buddy_sent_auth_message(buddy['userProfileId'], buddy['buddyProfileId'])
    def send_buddy_request(self, session, profileid, senttime=None):
        sig = utils.generate_random_hex_str(32)
        msg = "\r\n\r\n"
        msg += "|signed|" + sig

        if senttime is None:
            senttime = int(time.time())

        msg = gs_query.create_gamespy_message(
            [("__cmd__", "bm"), ("__cmd_val__", "2"), ("f", profileid), ("date", senttime), ("msg", msg)]
        )

        session.transport.write(bytes(msg))
    def get_buddy_authorized(self):
        buddies = self.db.buddy_need_auth_message(self.profileid)

        for buddy in buddies:
            msg = gs_query.create_gamespy_message([
                ('__cmd__', "bm"),
                ('__cmd_val__', "1"),
                ('f', buddy['userProfileId']),
                ('msg', "I have authorized your request to add me to your list"),
            ])

            self.transport.write(bytes(msg))
            self.db.buddy_sent_auth_message(buddy['userProfileId'], buddy['buddyProfileId'])
    def perform_getpd(self, data_parsed):
        pid = int(data_parsed['pid'])
        profile = self.db.pd_get(pid, data_parsed['dindex'], data_parsed['ptype'])

        if profile == None:
            self.log(logging.WARNING, "Could not find profile for %d %s %s" % (pid, data_parsed['dindex'], data_parsed['ptype']))

        keys = data_parsed['keys'].split('\x01')

        profile_data = None
        data = ""

        # Someone figure out if this is actually a good way to handle this when no profile is found
        if profile != None and 'data' in profile:
            profile_data = profile['data']
            if profile_data.endswith("\\"):
                profile_data = profile_data[:-1]
            profile_data = gs_query.parse_gamespy_message("\\prof\\" + profile_data + "\\final\\")

            if profile_data != None:
                profile_data = profile_data[0][0]
            else:
                self.log(logging.WARNING, "Could not get data section from profile for %d" % pid)

            if len(keys) > 0 and keys[0] != "":
                for key in (key for key in keys if key not in ("__cmd__", "__cmd_val__", "")):
                    data += "\\" + key + "\\"

                    if profile_data != None and key in profile_data:
                        data += profile_data[key]
            else:
                self.log(logging.WARNING, "No keys requested, defaulting to all keys: %s" % (profile['data']))
                data = profile['data']

        modified = int(time.time())

        msg = gs_query.create_gamespy_message([
            ('__cmd__', "getpdr"),
            ('__cmd_val__', 1),
            ('lid', self.lid),
            ('pid', pid),
            ('mod', modified),
            ('length', len(data)),
            ('data', data),
        ])

        self.log(logging.DEBUG, "SENDING: '%s'..." % msg)
        msg = self.crypt(msg)
        self.transport.write(bytes(msg))
    def perform_getpd(self, data_parsed):
        logger.log(logging.DEBUG, "FIXME: Implement getpd: %s" % data_parsed)

        # Return all of the data regardless of whatever the parameters passed to the function are.
        # I'll properly implement this once I get a real example of it in action.
        data = self.db.pd_get(self.profileid, data_parsed['dindex'], data_parsed['ptype'])

        msg_d = []
        msg_d.append(('__cmd__', "getpdr"))
        msg_d.append(('__cmd_val__', 1))
        msg_d.append(('lid', self.lid))
        msg_d.append(('pid', self.profileid))
        msg_d.append(('length', len(data)))
        msg_d.append(('data', data))
        msg = gs_query.create_gamespy_message(msg_d)
    def get_buddy_authorized(self):
        buddies = self.db.buddy_need_auth_message(self.profileid)

        for buddy in buddies:
            msg = gs_query.create_gamespy_message(
                [
                    ("__cmd__", "bm"),
                    ("__cmd_val__", "1"),
                    ("f", buddy["userProfileId"]),
                    ("msg", "I have authorized your request to add me to" " your list"),
                ]
            )

            self.transport.write(bytes(msg))
            self.db.buddy_sent_auth_message(buddy["userProfileId"], buddy["buddyProfileId"])
Example #37
0
    def perform_getpd(self, data_parsed):
        logger.log(logging.DEBUG, "FIXME: Implement getpd: %s" % data_parsed)

        # Return all of the data regardless of whatever the parameters passed to the function are.
        # I'll properly implement this once I get a real example of it in action.
        data = self.db.pd_get(self.profileid, data_parsed['dindex'],
                              data_parsed['ptype'])

        msg_d = []
        msg_d.append(('__cmd__', "getpdr"))
        msg_d.append(('__cmd_val__', 1))
        msg_d.append(('lid', self.lid))
        msg_d.append(('pid', self.profileid))
        msg_d.append(('length', len(data)))
        msg_d.append(('data', data))
        msg = gs_query.create_gamespy_message(msg_d)
    def perform_bm(self, data_parsed):
        if data_parsed['__cmd_val__'] == "1": # Message to/from clients?
            if "t" in data_parsed:
                # Send message to the profile id in "t"
                dest_profileid = int(data_parsed['t'])
                dest_msg = data_parsed['msg']

                msg_d = []
                msg_d.append(('__cmd__', "bm"))
                msg_d.append(('__cmd_val__', "1"))
                msg_d.append(('f', self.profileid))
                msg_d.append(('msg', dest_msg))
                msg = gs_query.create_gamespy_message(msg_d)

                self.log(logging.DEBUG, "SENDING TO %s:%s: %s" % (self.sessions[dest_profileid].address.host, self.sessions[dest_profileid].address.port, msg))
                self.sessions[dest_profileid].transport.write(bytes(msg))
    def send_status_to_friends(self):
        # TODO: Cache buddy list so we don't have to query the database every time
        buddies = self.db.get_buddy_list(self.profileid)

        status_msg = "|s|%s|ss|%s|ls|%s|ip|%d|p|0|qm|0" % (self.status, self.statstring, self.locstring, self.get_ip_as_int(self.address.host))

        msg_d = []
        msg_d.append(('__cmd__', "bm"))
        msg_d.append(('__cmd_val__', "100"))
        msg_d.append(('f', self.profileid))
        msg_d.append(('msg', status_msg))
        msg = gs_query.create_gamespy_message(msg_d)

        for buddy in buddies:
            if buddy['buddyProfileId'] in self.sessions:
                self.sessions[buddy['buddyProfileId']].transport.write(bytes(msg))
    def send_buddy_request(self, session, profileid, senttime=None):
        sig = utils.generate_random_hex_str(32)
        msg = "\r\n\r\n"
        msg += "|signed|" + sig

        if senttime == None:
            senttime = int(time.time())

        msg_d = []
        msg_d.append(('__cmd__', "bm"))
        msg_d.append(('__cmd_val__', "2"))
        msg_d.append(('f', profileid))
        msg_d.append(('date', senttime))
        msg_d.append(('msg', msg))
        msg = gs_query.create_gamespy_message(msg_d)

        session.transport.write(bytes(msg))
    def send_buddy_request(self, session, profileid, senttime = None):
        sig = utils.generate_random_hex_str(32)
        msg = "\r\n\r\n"
        msg += "|signed|" + sig

        if senttime == None:
            senttime = int(time.time())

        msg_d = []
        msg_d.append(('__cmd__', "bm"))
        msg_d.append(('__cmd_val__', "2"))
        msg_d.append(('f', profileid))
        msg_d.append(('date', senttime))
        msg_d.append(('msg', msg))
        msg = gs_query.create_gamespy_message(msg_d)

        session.transport.write(bytes(msg))
Example #42
0
    def connectionMade(self):
        self.log(logging.INFO, "Received connection from %s:%d" % (self.address.host, self.address.port))

        # Generate a random challenge string
        self.challenge = utils.generate_random_str(10, "ABCDEFGHIJKLMNOPQRSTUVWXYZ")

        # The first command sent to the client is always a login challenge containing the server challenge key.
        msg_d = []
        msg_d.append(('__cmd__', "lc"))
        msg_d.append(('__cmd_val__', "1"))
        msg_d.append(('challenge', self.challenge))
        msg_d.append(('id', "1"))
        msg = gs_query.create_gamespy_message(msg_d)

        self.log(logging.DEBUG, "SENDING: '%s'..." % msg)

        msg = self.crypt(msg)
        self.transport.write(bytes(msg))
Example #43
0
	def perform_auth(self, data_parsed):
		self.log(logging.DEBUG, "Parsing 'auth'...")

		if "gamename" in data_parsed:
			self.gameid = data_parsed['gamename']

		self.session = utils.generate_random_number_str(10)

		msg = gs_query.create_gamespy_message([('__cmd__', "lc"),
			('__cmd_val__', "2"),
			('sesskey', self.session),
			('proof', 0),
			('id', "1"),])

		self.log(logging.DEBUG, "SENDING: '%s'..." % msg)

		msg = self.crypt(msg)
		self.transport.write(bytes(msg))
    def connectionMade(self):
        self.log(logging.INFO, "Received connection from %s:%d" % (self.address.host, self.address.port))

        # Generate a random challenge string
        self.challenge = utils.generate_random_str(10, "ABCDEFGHIJKLMNOPQRSTUVWXYZ")

        # The first command sent to the client is always a login challenge containing the server challenge key.
        msg_d = []
        msg_d.append(('__cmd__', "lc"))
        msg_d.append(('__cmd_val__', "1"))
        msg_d.append(('challenge', self.challenge))
        msg_d.append(('id', "1"))
        msg = gs_query.create_gamespy_message(msg_d)

        self.log(logging.DEBUG, "SENDING: '%s'..." % msg)

        msg = self.crypt(msg)
        self.transport.write(bytes(msg))
    def get_buddy_requests(self):
        # Get list people who have added the user but haven't been accepted yet.
        buddies = self.db.get_pending_buddy_requests(self.profileid)

        profile = self.db.get_profile_from_profileid(self.profileid)
        sig = utils.generate_random_hex_str(32)
        msg = "\r\n\r\n"
        msg += "|signed|" + sig

        for buddy in buddies:
            msg_d = []
            msg_d.append(('__cmd__', "bm"))
            msg_d.append(('__cmd_val__', "2"))
            msg_d.append(('f', buddy['userProfileId']))
            msg_d.append(('date', buddy['time']))
            msg_d.append(('msg', msg))
            msg = gs_query.create_gamespy_message(msg_d)

            self.transport.write(bytes(msg))
    def send_status_to_friends(self):
        # TODO: Cache buddy list so we don't have to query the database every time
        self.buddies = self.db.get_buddy_list(self.profileid)

        if self.status == "0" and self.statstring == "Offline":
            # Going offline, don't need to send the other information.
            status_msg = "|s|%s|ss|%s" % (self.status, self.statstring)
        else:
            status_msg = "|s|%s|ss|%s|ls|%s|ip|%d|p|0|qm|0" % (self.status, self.statstring, self.locstring, self.get_ip_as_int(self.address.host))

        msg = gs_query.create_gamespy_message([
            ('__cmd__', "bm"),
            ('__cmd_val__', "100"),
            ('f', self.profileid),
            ('msg', status_msg),
        ])

        for buddy in self.buddies:
            if buddy['buddyProfileId'] in self.sessions:
                self.sessions[buddy['buddyProfileId']].transport.write(bytes(msg))
    def perform_auth(self, data_parsed):
        self.log(logging.DEBUG, "%s", "Parsing 'auth'...")

        if "gamename" in data_parsed:
            self.gameid = data_parsed['gamename']

        self.session = utils.generate_random_number_str(10)

        msg = gs_query.create_gamespy_message([
            ('__cmd__', "lc"),
            ('__cmd_val__', "2"),
            ('sesskey', self.session),
            ('proof', 0),
            ('id', "1"),
        ])

        self.log(logging.DEBUG, "SENDING: '%s'...", msg)

        msg = self.crypt(msg)
        self.transport.write(bytes(msg))
    def perform_getprofile(self, data_parsed):
        # profile = self.db.get_profile_from_session_key(
        #     data_parsed['sesskey']
        # )
        profile = self.db.get_profile_from_profileid(data_parsed["profileid"])

        # Wii example:
        # \pi\\profileid\474888031\nick\5pde5vhn1WR9E2g1t533\userid\442778352
        # \email\5pde5vhn1WR9E2g1t533@nds\sig\b126556e5ee62d4da9629dfad0f6b2a8
        # \uniquenick\5pde5vhn1WR9E2g1t533\pid\11\lon\0.000000\lat\0.000000
        # \loc\\id\2\final\
        sig = utils.generate_random_hex_str(32)

        msg_d = [
            ("__cmd__", "pi"),
            ("__cmd_val__", ""),
            ("profileid", profile["profileid"]),
            ("nick", profile["uniquenick"]),
            ("userid", profile["userid"]),
            ("email", profile["email"]),
            ("sig", sig),
            ("uniquenick", profile["uniquenick"]),
            ("pid", profile["pid"]),
        ]

        if profile["firstname"]:
            # Wii gets a firstname
            msg_d.append(("firstname", profile["firstname"]))

        if profile["lastname"]:
            msg_d.append(("lastname", profile["lastname"]))

        msg_d.extend(
            [("lon", profile["lon"]), ("lat", profile["lat"]), ("loc", profile["loc"]), ("id", data_parsed["id"])]
        )
        msg = gs_query.create_gamespy_message(msg_d)

        self.log(logging.DEBUG, "SENDING: %s", msg)
        self.transport.write(bytes(msg))
    def send_status_to_friends(self):
        # TODO: Cache buddy list so we don't have to query the database every time
        self.buddies = self.db.get_buddy_list(self.profileid)

        if self.status == "0" and self.statstring == "Offline":
            # Going offline, don't need to send the other information.
            status_msg = "|s|%s|ss|%s" % (self.status, self.statstring)
        else:
            status_msg = "|s|%s|ss|%s|ls|%s|ip|%d|p|0|qm|0" % (
                self.status, self.statstring, self.locstring,
                self.get_ip_as_int(self.address.host))

        msg_d = []
        msg_d.append(('__cmd__', "bm"))
        msg_d.append(('__cmd_val__', "100"))
        msg_d.append(('f', self.profileid))
        msg_d.append(('msg', status_msg))
        msg = gs_query.create_gamespy_message(msg_d)

        for buddy in self.buddies:
            if buddy['buddyProfileId'] in self.sessions:
                self.sessions[buddy['buddyProfileId']].transport.write(
                    bytes(msg))
Example #50
0
	def perform_getpd(self, data_parsed):
		pid = int(data_parsed['pid'])
		profile = self.db.pd_get(pid, data_parsed['dindex'], data_parsed['ptype'])

		if profile == None:
			self.log(logging.WARNING, "Could not find profile for %d %s %s" % (pid, data_parsed['dindex'], data_parsed['ptype']))

		keys = data_parsed['keys'].split('\x01')

		profile_data = None
		data = ""

		# Someone figure out if this is actually a good way to handle this when
		# no profile is found
		if profile != None and 'data' in profile:
			profile_data = profile['data']
			if profile_data.endswith("\\"):
				profile_data = profile_data[:-1]
			profile_data = gs_query.parse_gamespy_message("\\prof\\" + profile_data + "\\final\\")

			if profile_data != None:
				profile_data = profile_data[0][0]
			else:
				self.log(logging.WARNING, "Could not get data section from profile for %d" % pid)

			if len(keys):
				for key in (key for key in keys if key not in ("__cmd__", "__cmd_val__", "")):
					data += "\\" + key + "\\"

					if profile_data != None and key in profile_data:
						data += profile_data[key]
			else:
				self.log(logging.WARNING, "No keys requested, defaulting to all keys: %s" % (profile['data']))
				data = profile['data']

		modified = int(time.time())

		msg = gs_query.create_gamespy_message([('__cmd__', "getpdr"),
			('__cmd_val__', 1),
			('lid', self.lid),
			('pid', pid),
			('mod', modified),
			('length', len(data)),
			('data', data),])

		msg = msg.replace("\\data\\","\\data\\\\") # data needs to be preceded by an extra slash

		datastring = ""
		try:
			datastring = re.findall('.*data\\\\(.*)',msg)[0].replace("\\final\\","")
		except:
			pass

		# This works because the data string is a key-value pair, splitting the
		# string by \ should yield a list with an even number of elements.
		# But,
		# because of the extra \ prepended to the datastring, it'll be odd.
		# So ultimately I expect the list to have an odd number of elements.
		# If it's even, len(list)%2 will be zero...  and that means the last
		# field in the datastring is empty and doesn't have a closing \.
		if datastring and not len(datastring.split('\\')) % 2:
			msg = msg.replace("\\final\\","\\\\final\\") # An empty field must be terminated by \ before \final\

		self.log(logging.DEBUG, "SENDING: '%s'..." % msg)
		msg = self.crypt(msg)
		self.transport.write(bytes(msg))
    def perform_login(self, data_parsed):
        authtoken_parsed = gs_utils.parse_authtoken(data_parsed['authtoken'], self.db)
        
        if authtoken_parsed == None:
            self.log(logging.WARNING, "Invalid Authtoken.")
            msg = gs_query.create_gamespy_message([
                ('__cmd__', "error"),
                ('__cmd_val__', ""),
                ('err', '266'),
                ('fatal', ''),
                ('errmsg', 'There was an error validating the pre-authentication.'),
                ('id', data_parsed['id']),
            ])
            self.transport.write(bytes(msg))
            return

        if 'sdkrevision' in data_parsed:
            self.sdkrevision = data_parsed['sdkrevision']

        # Verify the client's response
        valid_response = gs_utils.generate_response(self.challenge, authtoken_parsed['challenge'], data_parsed['challenge'], data_parsed['authtoken'])
        if data_parsed['response'] != valid_response:
            self.log(logging.ERROR, "ERROR: Got invalid response. Got %s, expected %s" % (data_parsed['response'], valid_response))

        proof = gs_utils.generate_proof(self.challenge, authtoken_parsed['challenge'], data_parsed['challenge'], data_parsed['authtoken'])

        userid, profileid, gsbrcd, uniquenick = gs_utils.login_profile_via_parsed_authtoken(authtoken_parsed, self.db)

        if profileid != None:
            # Successfully logged in or created account, continue creating session.
            loginticket = gs_utils.base64_encode(utils.generate_random_str(16))
            self.sesskey = self.db.create_session(profileid, loginticket)

            self.sessions[profileid] = self

            self.buddies = self.db.get_buddy_list(self.profileid)
            self.blocked = self.db.get_blocked_list(self.profileid)

            if self.sdkrevision == "11": # Used in Tatsunoko vs Capcom
                def make_list(data):
                    list = []
                    for d in data:
                        if d['status'] == 1:
                            list.append(str(d['buddyProfileId']))
                    return list

                block_list = make_list(self.blocked)
                msg = gs_query.create_gamespy_message([
                    ('__cmd__', "blk"),
                    ('__cmd_val__', str(len(block_list))),
                    ('list', ','.join(block_list)),
                ])

                self.log(logging.DEBUG, "SENDING: %s" % msg)
                self.transport.write(bytes(msg))

                buddy_list = make_list(self.buddies)
                msg = gs_query.create_gamespy_message([
                    ('__cmd__', "bdy"),
                    ('__cmd_val__', str(len(buddy_list))),
                    ('list', ','.join(buddy_list)),
                ])

                self.log(logging.DEBUG, "SENDING: %s" % msg)
                self.transport.write(bytes(msg))


            msg = gs_query.create_gamespy_message([
                ('__cmd__', "lc"),
                ('__cmd_val__', "2"),
                ('sesskey', self.sesskey),
                ('proof', proof),
                ('userid', userid),
                ('profileid', profileid),
                ('uniquenick', uniquenick),
                # Some kind of token... don't know it gets used or generated, but it doesn't seem to have any negative effects if it's not properly generated.
                ('lt', loginticket),
                ('id', data_parsed['id']),
            ])

            # Take the first 4 letters of gsbrcd instead of gamecd because they should be consistent across game
            # regions. For example, the US version of Metroid Prime Hunters has the gamecd "AMHE" and the first 4 letters
            # of gsbrcd are "AMHE". However, the Japanese version of Metroid Prime Hunters has the gamecd "AMHJ" with
            # the first 4 letters of bsbrcd as "AMHE". Tetris DS is the other way, with the first 4 letters as the
            # Japanese version (ATRJ) while the gamecd is region specific (ATRE for US and ATRJ for JP).
            # gameid is used to send all people on the player's friends list a status updates, so don't make it region
            # specific.
            self.gameid = gsbrcd[:4]
            self.profileid = int(profileid)

            self.log(logging.DEBUG, "SENDING: %s" % msg)
            self.transport.write(bytes(msg))

            # Get pending messages.
            self.get_pending_messages()

            # Send any friend statuses when the user logs in.
            # This will allow the user to see if their friends are hosting a game as soon as they log in.
            self.get_status_from_friends()
            self.send_status_to_friends()

            # profile = self.db.get_profile_from_profileid(profileid)
            # if profile != None:
            #     self.statstring = profile['stat']
            #     self.locstring = profile['loc']
        else:
            self.log(logging.INFO, "Invalid password or banned user")
            msg = gs_query.create_gamespy_message([
                ('__cmd__', "error"),
                ('__cmd_val__', ""),
                ('err', '256'),
                ('fatal', ''),
                ('errmsg', 'Login failed.'),
                ('id', data_parsed['id']),
            ])
            self.log(logging.DEBUG, "SENDING: %s" % msg)
            self.transport.write(bytes(msg))
    def perform_login(self, data_parsed):
        authtoken_parsed = gs_utils.parse_authtoken(data_parsed['authtoken'],
                                                    self.db)
        #print authtoken_parsed

        # Track what console is connecting and save it in the database during user creation just in case we can use
        # the information in the future.
        console = 0  # 0 = NDS, 1 = Wii

        # get correct information
        userid = authtoken_parsed['userid']

        # The Wii does not use passwd, so take another uniquely generated string as the password.
        if "passwd" in authtoken_parsed:
            password = authtoken_parsed['passwd']
        else:
            password = authtoken_parsed['gsbrcd']
            console = 1

        gsbrcd = authtoken_parsed['gsbrcd']
        gameid = gsbrcd[:4]
        uniquenick = utils.base32_encode(int(userid)) + gsbrcd
        email = uniquenick + "@nds"  # The Wii also seems to use @nds.

        # Wii: Serial number
        if "csnum" in authtoken_parsed:
            csnum = authtoken_parsed['csnum']
            console = 1
        else:
            csnum = ""

        # Wii: Friend code
        if "cfc" in authtoken_parsed:
            cfc = authtoken_parsed['cfc']
            console = 1
        else:
            cfc = ""

        # NDS: Wifi network's BSSID
        if "bssid" in authtoken_parsed:
            bssid = authtoken_parsed['bssid']
        else:
            bssid = ""

        # NDS: Device name
        if "devname" in authtoken_parsed:
            devname = authtoken_parsed['devname']
        else:
            devname = ""

        # NDS: User's birthday
        if "birth" in authtoken_parsed:
            birth = authtoken_parsed['birth']
        else:
            birth = ""

        # Verify the client's response
        valid_response = gs_utils.generate_response(
            self.challenge, authtoken_parsed['challenge'],
            data_parsed['challenge'], data_parsed['authtoken'])
        if data_parsed['response'] != valid_response:
            self.log(
                logging.ERROR,
                "ERROR: Got invalid response. Got %s, expected %s" %
                (data_parsed['response'], valid_response))

        proof = gs_utils.generate_proof(self.challenge,
                                        authtoken_parsed['challenge'],
                                        data_parsed['challenge'],
                                        data_parsed['authtoken'])

        valid_user = self.db.check_user_exists(userid, gsbrcd)
        if valid_user == False:
            profileid = self.db.create_user(userid, password, email,
                                            uniquenick, gsbrcd, console, csnum,
                                            cfc, bssid, devname, birth, gameid)
        else:
            profileid = self.db.perform_login(userid, password, gsbrcd)

            if profileid == None:
                # Handle case where the user is invalid
                self.log(logging.ERROR, "Invalid password")

        if profileid != None:
            # Successfully logged in or created account, continue creating session.
            sesskey = self.db.create_session(profileid)

            self.sessions[profileid] = self

            msg_d = []
            msg_d.append(('__cmd__', "lc"))
            msg_d.append(('__cmd_val__', "2"))
            msg_d.append(('sesskey', sesskey))
            msg_d.append(('proof', proof))
            msg_d.append(('userid', userid))
            msg_d.append(('profileid', profileid))
            msg_d.append(('uniquenick', uniquenick))
            msg_d.append(
                ('lt', gs_utils.base64_encode(utils.generate_random_str(16)))
            )  # Some kind of token... don't know it gets used or generated, but it doesn't seem to have any negative effects if it's not properly generated.
            msg_d.append(('id', data_parsed['id']))
            msg = gs_query.create_gamespy_message(msg_d)

            # Take the first 4 letters of gsbrcd instead of gamecd because they should be consistent across game
            # regions. For example, the US version of Metroid Prime Hunters has the gamecd "AMHE" and the first 4 letters
            # of gsbrcd are "AMHE". However, the Japanese version of Metroid Prime Hunters has the gamecd "AMHJ" with
            # the first 4 letters of bsbrcd as "AMHE". Tetris DS is the other way, with the first 4 letters as the
            # Japanese version (ATRJ) while the gamecd is region specific (ATRE for US and ATRJ for JP).
            # gameid is used to send all people on the player's friends list a status updates, so don't make it region
            # specific.
            self.gameid = gsbrcd[0:4]
            self.profileid = int(profileid)

            self.log(logging.DEBUG, "SENDING: %s" % msg)
            self.transport.write(bytes(msg))

            self.buddies = self.db.get_buddy_list(self.profileid)
            self.blocked = self.db.get_blocked_list(self.profileid)

            # Get pending messages.
            self.get_pending_messages()

            # Send any friend statuses when the user logs in.
            # This will allow the user to see if their friends are hosting a game as soon as they log in.
            self.get_status_from_friends()
            self.send_status_to_friends()
Example #53
0
    def perform_login(self, data_parsed):
        authtoken_parsed = gs_utils.parse_authtoken(data_parsed['authtoken'],
                                                    self.db)

        if authtoken_parsed is None:
            self.log(logging.WARNING, "%s", "Invalid Authtoken.")
            msg = gs_query.create_gamespy_message([
                ('__cmd__', "error"),
                ('__cmd_val__', ""),
                ('err', '266'),
                ('fatal', ''),
                ('errmsg', 'There was an error validating the'
                 ' pre-authentication.'),
                ('id', data_parsed['id']),
            ])
            self.transport.write(bytes(msg))
            return

        if 'sdkrevision' in data_parsed:
            self.sdkrevision = data_parsed['sdkrevision']

        # Verify the client's response
        valid_response = gs_utils.generate_response(
            self.challenge, authtoken_parsed['challenge'],
            data_parsed['challenge'], data_parsed['authtoken'])
        if data_parsed['response'] != valid_response:
            self.log(logging.ERROR, "ERROR: Got invalid response."
                     " Got %s, expected %s", data_parsed['response'],
                     valid_response)

        proof = gs_utils.generate_proof(self.challenge,
                                        authtoken_parsed['challenge'],
                                        data_parsed['challenge'],
                                        data_parsed['authtoken'])

        userid, profileid, gsbrcd, uniquenick = \
            gs_utils.login_profile_via_parsed_authtoken(authtoken_parsed,
                                                        self.db)

        if profileid is not None:
            # Successfully logged in or created account, continue
            # creating session.
            loginticket = gs_utils.base64_encode(utils.generate_random_str(16))
            self.sesskey = self.db.create_session(profileid, loginticket)

            self.sessions[profileid] = self

            self.buddies = self.db.get_buddy_list(self.profileid)
            self.blocked = self.db.get_blocked_list(self.profileid)

            if self.sdkrevision == "11":  # Used in Tatsunoko vs Capcom

                def make_list(data):
                    return [
                        str(d['buddyProfileId']) for d in data
                        if d['status'] == 1
                    ]

                block_list = make_list(self.blocked)
                msg = gs_query.create_gamespy_message([
                    ('__cmd__', "blk"),
                    ('__cmd_val__', str(len(block_list))),
                    ('list', ','.join(block_list)),
                ])

                self.log(logging.DEBUG, "SENDING: %s", msg)
                self.transport.write(bytes(msg))

                buddy_list = make_list(self.buddies)
                msg = gs_query.create_gamespy_message([
                    ('__cmd__', "bdy"),
                    ('__cmd_val__', str(len(buddy_list))),
                    ('list', ','.join(buddy_list)),
                ])

                self.log(logging.DEBUG, "SENDING: %s", msg)
                self.transport.write(bytes(msg))

            msg = gs_query.create_gamespy_message([
                ('__cmd__', "lc"),
                ('__cmd_val__', "2"),
                ('sesskey', self.sesskey),
                ('proof', proof),
                ('userid', userid),
                ('profileid', profileid),
                ('uniquenick', uniquenick),
                # Some kind of token... don't know it gets used or generated,
                # but it doesn't seem to have any negative effects if it's
                # not properly generated.
                ('lt', loginticket),
                ('id', data_parsed['id']),
            ])

            # Take the first 4 letters of gsbrcd instead of gamecd because
            # they should be consistent across game regions. For example, the
            # US version of Metroid Prime Hunters has the gamecd "AMHE" and
            # the first 4 letters of gsbrcd are "AMHE". However, the Japanese
            # version of Metroid Prime Hunters has the gamecd "AMHJ" with the
            # first 4 letters of bsbrcd as "AMHE". Tetris DS is the other way,
            # with the first 4 letters as the Japanese version (ATRJ) while
            # the gamecd is region specific (ATRE for US and ATRJ for JP).
            # gameid is used to send all people on the player's friends list a
            # status updates, so don't make it region specific.
            self.gameid = gsbrcd[:4]
            self.profileid = int(profileid)

            self.log(logging.DEBUG, "SENDING: %s", msg)
            self.transport.write(bytes(msg))

            # Get pending messages.
            self.get_pending_messages()

            # Send any friend statuses when the user logs in.
            # This will allow the user to see if their friends are hosting a
            # game as soon as they log in.
            self.get_status_from_friends()
            self.send_status_to_friends()

            # profile = self.db.get_profile_from_profileid(profileid)
            # if profile is not None:
            #     self.statstring = profile['stat']
            #     self.locstring = profile['loc']
        else:
            self.log(logging.INFO, "%s", "Invalid password or banned user")
            msg = gs_query.create_gamespy_message([
                ('__cmd__', "error"),
                ('__cmd_val__', ""),
                ('err', '256'),
                ('fatal', ''),
                ('errmsg', 'Login failed.'),
                ('id', data_parsed['id']),
            ])
            self.log(logging.DEBUG, "SENDING: %s", msg)
            self.transport.write(bytes(msg))
    def perform_getpd(self, data_parsed):
        pid = int(data_parsed['pid'])
        profile = self.db.pd_get(pid, data_parsed['dindex'],
                                 data_parsed['ptype'])

        if profile is None:
            self.log(logging.WARNING, "Could not find profile for %d %s %s",
                     pid, data_parsed['dindex'], data_parsed['ptype'])

        keys = data_parsed['keys'].split('\x01')

        profile_data = None
        data = ""

        # Someone figure out if this is actually a good way to handle this
        # when no profile is found
        if profile is not None and 'data' in profile:
            profile_data = profile['data']
            if profile_data.endswith("\\"):
                profile_data = profile_data[:-1]
            profile_data = \
                gs_query.parse_gamespy_message("\\prof\\" + profile_data +
                                               "\\final\\")

            if profile_data is not None:
                profile_data = profile_data[0][0]
            else:
                self.log(logging.WARNING,
                         "Could not get data section from profile for %d", pid)

            if len(keys):
                # TODO: more clean/pythonic way to do (join?)
                for key in keys:
                    if key in ("__cmd__", "__cmd_val__", ""):
                        continue
                    data += "\\" + key + "\\"

                    if profile_data is not None and key in profile_data:
                        data += profile_data[key]
            else:
                self.log(logging.WARNING,
                         "No keys requested, defaulting to all keys: %s",
                         profile['data'])
                data = profile['data']

        modified = int(time.time())

        # Check if there is a nul byte and data after it
        data_blocks = data.split('\x00')
        if len(data_blocks) > 1 and any(block for block in data_blocks[1:]):
            self.log(logging.WARNING, "Data after nul byte: %s", data)

        data = data_blocks[0]
        msg = gs_query.create_gamespy_message([('__cmd__', "getpdr"),
                                               ('__cmd_val__', 1),
                                               ('lid', self.lid), ('pid', pid),
                                               ('mod', modified),
                                               ('length', len(data)),
                                               ('data', ''), (data, )])

        if msg.count('\\') % 2:
            # An empty field must be terminated by \ before \final\
            msg = msg.replace("\\final\\", "\\\\final\\")

        self.log(logging.DEBUG, "SENDING: '%s'...", msg)
        msg = self.crypt(msg)
        self.transport.write(bytes(msg))
Example #55
0
    def perform_authp(self, data_parsed):
        authtoken_parsed = gs_utils.parse_authtoken(data_parsed['authtoken'],
                                                    self.db)
        #print authtoken_parsed

        if "lid" in data_parsed:
            self.lid = data_parsed['lid']

        # Track what console is connecting and save it in the database during user creation just in case we can use
        # the information in the future.
        console = 0  # 0 = NDS, 1 = Wii

        # get correct information
        userid = authtoken_parsed['userid']

        # The Wii does not use passwd, so take another uniquely generated string as the password.
        if "passwd" in authtoken_parsed:
            password = authtoken_parsed['passwd']
        else:
            password = authtoken_parsed['gsbrcd']
            console = 1

        gsbrcd = authtoken_parsed['gsbrcd']
        gameid = gsbrcd[:4]
        uniquenick = utils.base32_encode(int(userid)) + gsbrcd
        email = uniquenick + "@nds"  # The Wii also seems to use @nds.

        # Wii: Serial number
        if "csnum" in authtoken_parsed:
            csnum = authtoken_parsed['csnum']
            console = 1
        else:
            csnum = ""

        # Wii: Friend code
        if "cfc" in authtoken_parsed:
            cfc = authtoken_parsed['cfc']
            console = 1
        else:
            cfc = ""

        # NDS: Wifi network's BSSID
        if "bssid" in authtoken_parsed:
            bssid = authtoken_parsed['bssid']
        else:
            bssid = ""

        # NDS: Device name
        if "devname" in authtoken_parsed:
            devname = authtoken_parsed['devname']
        else:
            devname = ""

        # NDS: User's birthday
        if "birth" in authtoken_parsed:
            birth = authtoken_parsed['birth']
        else:
            birth = ""

        valid_user = self.db.check_user_exists(userid, gsbrcd)
        profileid = None
        if valid_user:
            profileid = self.db.perform_login(userid, password, gsbrcd)

            if profileid == None:
                # Handle case where the user is invalid
                self.log(logging.ERROR, "Invalid password")

        if profileid != None:
            # Successfully logged in or created account, continue creating session.
            sesskey = self.db.create_session(profileid)

            self.sessions[profileid] = self

            msg_d = []
            msg_d.append(('__cmd__', "pauthr"))
            msg_d.append(('__cmd_val__', profileid))
            msg_d.append(('lid', self.lid))
            msg = gs_query.create_gamespy_message(msg_d)

            self.profileid = int(profileid)

            self.log(logging.DEBUG, "SENDING: '%s'..." % msg)

            msg = self.crypt(msg)
            self.transport.write(bytes(msg))
        else:
            # Return error
            pass