Authentication steps menu

User Tag List

Results 1 to 8 of 8
  1. #1
    /dev/not/null's Avatar Member
    Reputation
    12
    Join Date
    Oct 2018
    Posts
    31
    Thanks G/R
    9/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Authentication steps

    Hello. Please, confirm my understanding of authentication steps is correct:
    1. Client connecting to World server
    2. if connection not accepted - do challenge, proof requests and then
    sending realmlist in infinite loop back to client.
    3. if connection accepted - missing step 2 and doing smsg_auth_challenge, cmsg_auth_session and smsg_auth_response
    4. after 3 waiting for client request (WHICH OPCODE SHOULD BE HERE?)

    Questions: am I need to send realmlist infinite? how to do this correctly?
    what steps was missed for end auth and start login into the world?

    Authentication steps
  2. #2
    /dev/not/null's Avatar Member
    Reputation
    12
    Join Date
    Oct 2018
    Posts
    31
    Thanks G/R
    9/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm asking because can't realize why my client stucks on 'Connected' or 'Logging in to game server'...

    World Server code:
    Code:
    class WorldServer(BaseServer):
    
        def __init__(self, host, port):
            super().__init__(host, port)
            self.connections = []
            self.writer = None
    
        async def handle_connection(self, reader: StreamReader, writer: StreamWriter):
            peername = writer.get_extra_info('peername')
            Logger.debug('[World Server]: Accept connection from {}'.format(peername))
    
            self.writer = writer
    
            if not session.is_authenticated:
                # in this loop we redirecting client requests to Login Server and sending response from Login Server back to client
                while True:
                    r, w = await asyncio.open_connection(LoginConfig.HOST.value, LoginConfig.PORT.value)
    
                    data = await reader.read(1024)
                    if not data:
                        break
                    # sending client request to Login Server
                    w.write(data)
                    response = await r.read(1024)
                    # sending Login Server response to client
                    writer.write(response)
    
            await self.accept_connection(peername)
    
            auth = AuthSessionManager(reader, writer)
            auth.prepare()
            await auth.process()
    
            while True:
                # stucks here... getting no request
                Logger.error('[World Server]: Trying to get data...')
                data = await reader.read(4096)
                if data:
                    Logger.error('data exists... {}'.format(data))
    
        async def accept_connection(self, peername):
            self.connections.append(peername)
            await queue.put(QueueMessages.WORLD_SERVER_ACCEPT_CONNECTION.value)
            session.is_connection_accepted = True
    Auth Session Manager:
    Code:
    class AuthSessionManager(object):
    
        state = AUTH_SESSION_STATES.INIT.value
    
        def __init__(self, reader: StreamReader, writer: StreamWriter):
            self.reader = reader
            self.writer = writer
            self.data = bytes()
            self.build = 0
            self.unk = 0
            self.account_name = None
            self.client_seed = 0
            self.client_hash = bytes()
            self.session_key = bytes()
            self.server_hash = bytes()
    
        def prepare(self):
            # auth seed need to generate header_crypt
            auth_seed = int.from_bytes(urandom(4), 'little')
            session.auth_seed = auth_seed
            auth_seed_bytes = pack('<I', auth_seed)
            response = WorldPacket(WorldOpCode.SMSG_AUTH_CHALLENGE.value, auth_seed_bytes).generate_packet()
            self.writer.write(response)
    
        async def process(self):
            has_timeout = False
            response = None
    
            try:
                Logger.debug('Trying to read packet')
                request = await wait_for(self.reader.read(1024), timeout=3.0)
            except TimeoutError:
                Logger.error('[Auth Session Manager]: Timeout error')
                has_timeout = True
            else:
                self._parse_data(request)
                self._load_session_key()
                self._setup_encryption()
                self._generate_server_hash()
    
                if self.server_hash != self.client_hash:
                    Logger.error('[Auth Session Manager]: Server hash is differs from client hash')
                else:
                    try:
                        response = self._get_addon_info_packet()
                        self.writer.write(response)
    
                        response = self._get_response()
                        Logger.debug('[Auth Session Manager]: responding...')
                        self.writer.write(response)
    
                    except Exception as e:
                        Logger.error('exeption = {}'.format(e))
                        traceback.print_exc(file=sys.stdout)
            finally:
                return has_timeout, response
    
        def _parse_data(self, data: bytes):
            # omit first 6 bytes, cause 01-02 = packet size, 03-04 = opcode (0x1ED), 05-06 - unknown null-bytes
            tmp_buf = BytesIO(data[6:])
            self.build = unpack('<H', tmp_buf.read(2))[0]
            # remove next 6 unknown null-bytes (\x00)
            tmp_buf.read(6)
            self.account_name = self._parse_account_name(tmp_buf)
    
            self.client_seed = tmp_buf.read(4)
            self.client_hash = tmp_buf.read(20)
    
    
        def _generate_server_hash(self):
            auth_seed = session.auth_seed
            del session.auth_seed
            to_hash = (
                self.account_name.encode('ascii') +
                bytes(4) +
                self.client_seed +
                int.to_bytes(auth_seed, 4, 'little') +
                self.session_key
            )
            self.server_hash = sha1(to_hash).digest()
    
        def _load_session_key(self):
            self.session_key = session.session_key_as_bytes
    
        def _setup_encryption(self):
            Logger.debug('Setup encryption')
            try:
                session.header_crypt = HeaderCrypt(self.session_key)
            except Exception as e:
                Logger.error('header c = {}'.format(e))
    
        def _parse_account_name(self, buffer: BytesIO):
            result = bytes()
    
            while True:
                char = buffer.read(1)
                if char and char != b'\x00':
                    result += char
                else:
                    break
    
            return result.decode('ascii')
    
        def _get_response(self):
            # updating session request
            response = pack('<BIBIB',
                            AUTH_SESSION_RESPONSE_CODES.AUTH_OK.value,
                            0x00,  # BillingTimeRemaining
                            0x00,  # BillingPlanFlags
                            0x00,  # BillingTimeRested
                            0x01   # Expansion, 0 - normal, 1 - TBC, must be set manually for each account
            )
    
            packet = WorldPacket(
                WorldOpCode.SMSG_AUTH_RESPONSE.value,
                response
            ).generate_packet(session.header_crypt)
    
            return packet
    Login server code:
    Code:
    class LoginServer(BaseServer):
    
        def __init__(self, host, port):
            super().__init__(host, port)
    
        async def handle_connection(self, reader: StreamReader, writer: StreamWriter):
            peername = writer.get_extra_info('peername')
            Logger.info('[Login Server]: Accepted connection from {}'.format(peername))
    
            if not session.is_connection_accepted:
                auth = AuthManager(reader, writer)
                has_timeout = await auth.process()
    
            writer.close()
    Auth Manager:
    Code:
    class AuthManager(object):
    
        AUTH_HANDLERS = {
            0x00: LoginChallenge,
            0x01: LoginProof,
            0x02: ReconChallenge,
            0x03: ReconProof,
            0x10: Realmlist
        }
    
        state = AUTH_STATES.INIT.value
    
        def __init__(self, reader: StreamReader, writer: StreamWriter):
            self.reader = reader
            self.writer = writer
    
        async def process(self):
            Logger.debug('[Auth Manager]: reading packet...')
    
            has_timeout = False
    
            try:
                request = await asyncio.wait_for(self.reader.read(1024), timeout=1.0)
                opcode = request[0]
                handler = AuthManager.AUTH_HANDLERS[opcode]
                # first byte of client request is opcode
                packet = request[1:]
                state, response = handler(packet).process()
    
                if response:
                    Logger.info('sending response back to client')
                    self.writer.write(response)
    
            except TimeoutError:
                Logger.error('[Auth Manager]: Timeout')
                has_timeout = True
            finally:
                return has_timeout
    Note:
    AuthSessionManager using on World Server (SMSG_AUTH_CHALLENGE, CMSG_AUTH_SESSION, SMSG_AUTH_RESPONSE)
    AuthManager using on Login Server (CHALLENGE, PROOF, REALMLIST)

    What is wrong with my code ? What I should add to fix the problem with stuck on connection ?
    Last edited by /dev/not/null; 11-08-2018 at 03:37 AM.

  3. #3
    /dev/not/null's Avatar Member
    Reputation
    12
    Join Date
    Oct 2018
    Posts
    31
    Thanks G/R
    9/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Anybody? If somebody can help I can push my current server implementation to github.

  4. #4
    /dev/not/null's Avatar Member
    Reputation
    12
    Join Date
    Oct 2018
    Posts
    31
    Thanks G/R
    9/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    well, it seems Login Server should be opened on port 3724, client will found it by itself. And realmlist should be like "set realmlist localhost" without custom ports.

  5. #5
    stoneharry's Avatar Moderator Harry

    Authenticator enabled
    Reputation
    1613
    Join Date
    Sep 2007
    Posts
    4,554
    Thanks G/R
    151/146
    Trade Feedback
    0 (0%)
    Mentioned
    3 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by /dev/not/null View Post
    well, it seems Login Server should be opened on port 3724, client will found it by itself. And realmlist should be like "set realmlist localhost" without custom ports.
    You can force other realmserver ports, e.g:

    Code:
    set realmlist 127.0.0.1:8030
    You can open WoW with the -console command and open the console with the ` key. This will give you some debug output to compare against.

    What patch version are you using? There is some information here for 3.3.5a:
    - https://www.ownedcore.com/forums/wor...n-process.html (SRP6 and WoW Authentication Process)
    - ArcEmu-Wiki has a problem (dead link at time of posting - see Server Logon Challenge - ArcEmu-Wiki / Logon Process - ArcEmu-Wiki)

    Also if you search hard enough there are a few topics discussing this in detail on these forums. I find it easier to search from google including: "sitewnedcore.com" in your search query.
    Last edited by stoneharry; 11-13-2018 at 03:09 PM.

  6. Thanks /dev/not/null (1 members gave Thanks to stoneharry for this useful post)
  7. #6
    /dev/not/null's Avatar Member
    Reputation
    12
    Join Date
    Oct 2018
    Posts
    31
    Thanks G/R
    9/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks for your answer! I'm using 2.4.3. Currently I'm trying to realize why client stucks on 'Connected' after SMSG_AUTH_RESPONSE. As I can see from wireshark, first time client do not sends anything and after some delay it starts to send packets withl length 83. What is it ?

  8. #7
    /dev/not/null's Avatar Member
    Reputation
    12
    Join Date
    Oct 2018
    Posts
    31
    Thanks G/R
    9/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Link about logon process very useful! What I should send to client on the step "World Server asks the Logon Server for the Client's session info" ? Just session key? Which opcode should I use for that?

    Currently output fron console on connecting to my server:
    GRUNT: state: LOGIN_STATE_CONNECTING result: LOGIN_OK
    GRUNT: state: LOGIN_STATE_CONNECTED result: LOGIN_OK 127.0.0.1:3724
    GRUNT: state: LOGIN_STATE_AUTHENTICATING result: LOGIN_OK
    GRUNT: state: LOGIN_STATE_CHECKSUM result: LOGIN_OK
    GRUNT: state: LOGIN_STATE_HANDSHAKING result: LOGIN_OK
    GRUNT: state: LOGIN_STATE_AUTHENTICATED result: LOGIN_OK
    ClientConnection Initiating: COP_CONNECT code=CSTATUS_CONNECTING
    ClientConnection Completed: COP_CONNECT code=REALM_LIST_REALM_NOT_FOUND result=FALSE
    ClientConnection Initiating: COP_CONNECT code=CSTATUS_CONNECTING
    After that client stucks on 'Connected' or 'Logging in to game server' (if I press ESC -> Cancel, then choose realm server again)
    Last edited by /dev/not/null; 11-14-2018 at 02:39 PM.

  9. #8
    /dev/not/null's Avatar Member
    Reputation
    12
    Join Date
    Oct 2018
    Posts
    31
    Thanks G/R
    9/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Currently client do not returns:
    ClientConnection Completed: COP_AUTHENTICATE code=AUTH_OK result=TRUE
    when connecting to my server. What does it waits for ?

    Client hangs on:
    ClientConnection Initiating: COP_AUTHENTICATE code=CSTATUS_AUTHENTICATING
    Last edited by /dev/not/null; 11-15-2018 at 11:07 AM.

Similar Threads

  1. Safest way to use CE 2.0.10 -- Step by step guide with pictures
    By [WoN][tD] in forum World of Warcraft Bots and Programs
    Replies: 13
    Last Post: 04-05-2007, 11:02 PM
  2. Step by step guide for a glitch
    By Datonking in forum World of Warcraft Exploits
    Replies: 18
    Last Post: 10-02-2006, 09:49 AM
  3. Step-By-Step Create Your Own AFK Bot! MMOwned Exclusive!
    By =sinister= in forum World of Warcraft Guides
    Replies: 6
    Last Post: 07-26-2006, 09:04 PM
  4. Authentication Key
    By Dok-121 in forum World of Warcraft General
    Replies: 4
    Last Post: 06-08-2006, 07:49 PM
All times are GMT -5. The time now is 05:12 PM. Powered by vBulletin® Version 4.2.3
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2024 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search