Skip to content

Support W3DM game client login - #22

Open
wjlafrance wants to merge 8 commits into
BNETDocs:developfrom
wjlafrance:bnftp-v2-and-news-time
Open

wjlafrance wants to merge 8 commits into
BNETDocs:developfrom
wjlafrance:bnftp-v2-and-news-time

Conversation

@wjlafrance

Copy link
Copy Markdown
Collaborator

No description provided.

wjlafrance and others added 8 commits October 9, 2026 15:07
A version 2 client opens with a 20-byte header (platform, product, ad
banner id and extension), expects a 4-byte server token back, and then
sends the file request (start position, filetime, client token, CD key
fields, filename). Atlas parsed the short header as if it were a full
version 1 request and dropped the connection.

BNFTPState.Receive now answers the header with the server token and
serves the file named in the follow-up request. The reply uses the same
header as version 1, including the 16-bit type field; without it the
Warcraft III demo reset the connection after each download and retried.

Receive returns the number of bytes it consumed and ClientState trims
them from the receive buffer. Previously the buffer was never trimmed,
so a second request arrived behind the first one's bytes.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The timestamps were the high 32 bits of a FILETIME, which is about 31
million, so clients showed the news as dated December 1970. They are
Unix timestamps (seconds since 1970-01-01).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Like udptest.py, it runs against a live Atlas. It fetches one file over
each BNFTP version and fails if either one errors or if the two return
different content.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Warcraft III clients send this right after logging on. Atlas had no
handler, so it treated the message as unknown and disconnected the
client. The message carries the 16-bit port the client will host games
on; store it as the game data port and send no reply, as documented.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The demo (W3DM) has no password field. After SID_AUTH_INFO it sends
SID_AUTH_ACCOUNTLOGON with a random 32-byte key and a name, and treats
the reply as SID_AUTH_ACCOUNTLOGONPROOF; it never sends a proof of its
own and never creates an account.

- SID_AUTH_INFO announces logon type NLS to the demo, which drops the
  connection otherwise.
- SID_AUTH_ACCOUNTLOGON logs the demo on by name, creating the account
  on first use, and answers with SID_AUTH_ACCOUNTLOGONPROOF carrying the
  status. Name errors use the same status codes as account creation.
  Only server-to-client SID_AUTH_ACCOUNTLOGONPROOF is supported.

This is off unless battlenet.emulation.name_only_logon enables the
product (W3DM is enabled in the sample config). Name-only accounts are
marked with a new internal account key, are created without any flags
(an auto_admin name does not become an admin), and a name-only logon is
refused for any account that was not created this way, so it can never
log on to an account that has a password.

SID_AUTH_INFO's WAR3/W3XP/W3DM signature was always zeros. Warcraft III
clients check it against a public key built into the game, so with
battlenet.emulation.server_signature (modulus, private_exponent and an
optional address) set, Atlas signs the server address the way Blizzard
did (address, 0xBB padding, 0x0B). Unset, the signature stays zeros. A
client only accepts a signature from a key it has been patched to use.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The demo's Play Game button sends SID_WARCRAFTGENERAL sub-command 0 and
waits for a reply carrying the same cookie and a status. Atlas ignored
every SID_WARCRAFTGENERAL sub-command, so the client sat in "searching"
with nothing to tell it the search had started or was cancelled.

Sub-command 0 stores the cookie and answers with status 0 (search
started). Sub-command 3 answers with the stored cookie. No match is ever
reported, so a search ends with the client's own timeout.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
After SID_AUTH_CHECK the demo asks for termsofservice-enUS.txt with
SID_GETFILETIME and shows it on its logon screen. When the file is
missing it drops the connection after about 30 seconds.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
After logon the demo requests matchmaking-w3dm-enUS.dat with
SID_GETFILETIME, downloads it over BNFTP and fills the Play Game screen
from it. Without the file the game type list is empty.

make-matchmaking.sh writes the file from a table of game types, styles
and maps, using a small C# program run with dotnet. The layout is
documented in the script. The demo checks every map path against the
files it has installed, so the table lists only (4)Deadlock, the one
map it installs; other paths show as missing or corrupt and disable
Play Game.

.gitattributes keeps the script's line endings LF, like
etc/atlasd.service, so it still runs in a checkout that converts text
files to CRLF.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant