MSNP8 is a new protocol that was introduced with MSN Messenger 5. The following description of the protocol has been somewhat peer-reviewed and tested, but may still contain omissions or errors. Please contact us if you find anything wrong with this page.
In order to implement MSNP8, you need to use the "bitwise AND" function in a couple of places. Unlike the "logical AND" used in conditional statements, "bitwise AND" manipulates numbers on a binary level - it's almost impossible to guess what's going on just by looking at the decimal output. To work out what a binary AND does, break the numbers you're ANDing into a sum of powers of 2. The output of a bitwise AND is the sum of the powers of 2 which appear in both input numbers. For example, 11 is 8+2+1, and 7 is 4+2+1, so a bitwise AND on 11 and 7 will return 3 (2+1).
Different programming languages use different symbols to represent "bitwise AND" - consult your documentation to find out what it is in your language. This site will use "AND", so "3 AND 2" means "do a bitwise AND on the numbers 3 and 2".
Clients that support MSNP8 must also support the CVR0
protocol. The CVR
command must be sent immediately after the VER
command to a notification server. The format of the CVR command has also changed slightly in MSNP8 - you must now send a string as the eighth argument to the CVR command. The official client sends your passport, but the server is just as happy if you send something else, like "null". The format of the CVR
reply has not changed.
The INF
command, which was optional in MSNP7, no longer exists in MSNP8. If you attempt to send it while logging in, you will be immediately disconnected.
The format of the USR
command is almost unchanged in MSNP8, but MD5 authentication has been abandoned in favour of TWN ("Tweener") authentication, which is based on Passport authentication, discussed below. If you try to use MD5 authentication, you will be immediately disconnected by the server. The final USR
reply from the server now includes an extra numerical argument at the end, which may be related to the extra numerical arguments discussed in status messages, below.
When a client authenticates with MS Passport, it is given a "ticket". This ticket is passed back to the notification server in the final USR
reply.
Putting an example of an MSNP8 login on this page would cause horizontal scrolling, so please see the authentication example page.
Passport Authentication is Microsoft's attempt to provide a "single sign-on" system for all Internet services, from Messenger to online banking. Some background information about it is available on MSDN, but this page assumes no knowledge of passport.
Authentication with MS Passport involves sending HTTPS requests to Microsoft's Passport servers in order to retrieve a passport "ticket", which is then sent to the server you really want to connect to. HTTPS is HyperText Transfer Protocol encrypted using "Secure Sockets Layer". It is recommended that you find a library for your chosen programming language that supports HTTPS - even if you choose to write your own HTTP parser, you should not try to implement SSL (it's far too complex and security-sensitive to implement as part of a larger project).
Passport servers allow you to either send your login details as an HTML file in the body of the request or as headers of the HTTPS request itself. The "HTML" method is only intended for use by web browsers, but will work fine for MSN Messenger clients. The "header" method is recommended for Messenger clients, and is the only method explained on this site. The passport authentication process involves the following steps:
USR
reply.Connecting to the Nexus involves sending an HTTPS GET request for the URL "https://nexus.passport.com/rdr/pprdr.asp". The Nexus allows you to use HTTPS version 1.0. The server should always reply with a 200 OK
message with an empty body. The important information is contained in the "PassportURLs" header, which contains a comma-separated list. The "DALogin" field of this header contains the address of the login server. This value isn't technically a valid URL, so your HTTPS library might require you to add "https://" to the start of it.
The client should then send an HTTPS GET request for the URL given to it by the Nexus. Login servers require you to use HTTPS version 1.1. The request should include an "Authorization" header, which is made up of a preamble ("Passport1.4 OrgVerb=GET,OrgURL=http%3A%2F%2Fmessenger%2Emsn%2Ecom"), your URL-encoded passport, password, and the challenge string given to you by the Notification Server.
The server's response should be either a 200 OK
message (for success), 302 Found
(for redirection) or 401 Unauthorized
(for failure). The message will contain either an "Authentication-Info" or a "WWW-Authenticate" header. It's not known why two different header names are used, although at present "WWW-Authenticate" is only used with failed logins. It's safest to assume that the two header names are interchangeable. The header will contain a "da-status" field of "success", "failed" or "redir" (redirect). If the response is a redirection, there will also be a "Location" header, which includes the URL the client is being redirected to.
If the response is a failure, the header will include a "cbtxt" field, which contains a URL-encoded error message, and a "cburl" header that contains the URL of a picture you might want to display along with it.
If the response is a redirection, the "Location" field will contain the URL of another Login Server. At the time of writing, the client will be redirected if it has a passport that ends in "@hotmail.com" or "@msn.com". The client must begin the login step again.
If the response is a success, the "Authentication-Info" header will include a "from-PP" field, which contains the ticket to return to the Notification Server. This field has a slightly unusual format, in that the value is inside apostrophes and includes several equals signs (but no commas).
Because passport authentication involves very long strings, it causes horizontal scrolling when displayed on this site, so please see the authentication example page.
The initial text/x-msmsgsprofile
message sent by the server has gained two fields and lost one. The "LoginTime" field no longer exists - you should record your system's idea of UNIX time instead. Also, the "ClientIP" and "ClientPort" fields have been added to the end of the message. These tell the client about the IP address and source port the server believes the client is connecting from. The source port for a connection is the port on the client computer, whereas the destination port (usually 1863 in MSN Messenger sessions) is the port the server listens on. Unfortunately, a bug in the MSN Messenger server mangles the "ClientPort" value, and you need to do some work to get the actual port number.
The technical term is that the value has been "byte-swapped", and an explanation of what exactly has happened is beyond the scope of this page. There are several ways to get the correct number back, but the recommended method is to calculate ((ClientPort AND 255) * 256) + ((ClientPort AND 65280) / 256) - there are neater ways to write that function, but they would take a much deeper understanding of binary arithmetic to explain. An alternative is to use a function called ntohc
, but this function doesn't exist in all programming languages, and doesn't work on all hardware architectures (for example, it won't work on Apple computers).
The client port and IP address can be used to guess whether the connection to the server is going through some kind of network address translation ("NAT") or proxy server. In MSNP8, this information is only used to decide the value of the "Connectivity" field during file transfer, but more advanced handling of this information - this is covered on the MSNP9 page.
Here is an example message, where the client's actual source port is 1025:
MSG Hotmail Hotmail 432
\r\n
MIME-Version: 1.0\r\n
Content-Type: text/x-msmsgsprofile; charset=UTF-8\r\n
EmailEnabled: 1\r\n
MemberIdHigh: 84352\r\n
MemberIdLow: 1317109683\r\n
lang_preference: 1033\r\n
preferredEmail: \r\n
country: UK\r\n
PostalCode: \r\n
Gender: \r\n
Kid: 0\r\n
Age: \r\n
BDayPre: \r\n
Birthday: \r\n
Wallet: \r\n
Flags: 1031\r\n
sid: 507\r\n
kv: 5\r\n
MSPAuth: 4sCuECZ4UsAaBIy0AIsk!c9bWcuATTmuQ$$\r\n
ClientIP: 81.99.77.64\r\n
ClientPort: 260\r\n
\r\n
The CHG
, ILN
and NLN
, but not FLN
commands now have a an extra numerical argument at the end. This argument represents some kind of client ID structuce, which is discussed more in the client ID page.
Clients set their version number with the CHG
command, which will then be passed to other clients along with ILN
and NLN
notifications. If you leaving the extra parameter out of a CHG
, the server will set your version number to 0.
Here is an example CHG
with no extra parameter:
>>> CHG 12 NLN
\r\n
<<< CHG 12 NLN 0
\r\n
Here is an example CHG
with a version number of 500:
>>> CHG 12 NLN 500
\r\n
<<< CHG 12 NLN 500
\r\n
And an example ILN
:
<<< ILN 12 AWY example@passport.com Mike 268435492
\r\n
Microsoft were presumably pressured to reduce the time it took to log into MSN Messenger, as the SYN
command has been overhauled to minimise bandwidth. When the cached version of the contact list is the same as the version on the server, the response is just the same as it was in MSNP7, but when the cached version is out-of-date, the response is very different. Note that the change of format for many responses only applies to the SYN
command - responses to other commands (e.g. ADD
) are the same as in MSNP7.
The initial SYN response will contain a TrID and one or three parameters.
LST
responses to expect.LSG
responses to expect.Next, GTC
and BLP
responses will be received. Neither has a TrID or list version number.
If you have any personal phone numbers, PRP
s will be sent next. Blank phone numbers will not be sent, neither will "MOB" or "MBE" if their value is "N". They include just two parameters:
Then the group list is sent by the server. These no longer have a TrID, list version number, incrementing number or total number.
Next, the user list and phone numbers are sent by the server. The format of this has changed totally from MSNP7.
The new LST
response lists each user once in total (instead of once for every list they appear in), and includes three or four parameters (and no TrID):
Each list has a numerical value, and a user's list number represents the sum of the lists the user is in. The FL's value is 1, the AL is 2, the BL is 4 and the RL is 8. So, someone on your FL and AL but not your BL or RL would have a list number of 3.
Programming note: it's easiest to separate out the lists a user belongs to with the "bitwise AND" function. Doing a bitwise AND between a user's list number and a list value will return the list value if the user is on that list, or zero otherwise. For example, if someone's list number is 11, you can check whether they are on your AL by doing "11 AND 2", which will return 2. Similarly, checking whether they are on your BL with "11 AND 4" will return 0.
BPR
responses are sent immediately after the user they apply to, and are formatted identically to PRP
s.
Here is an example SYN response:
>>> SYN 1 0
\r\n
<<< SYN 1 139 5 4
\r\n
<<< GTC A\r\n
<<< BLP AL\r\n
<<< PRP PHH 01%20234\r\n
<<< PRP PHM 56%20789\r\n
<<< LSG 0 Other%20Contacts 0\r\n
<<< LSG 1 Coworkers 0\r\n
<<< LSG 2 Friends 0\r\n
<<< LSG 3 Family 0\r\n
<<< LST user1@passport.com user1 4\r\n
<<< LST user2@passport.com user2 10\r\n
<<< LST user3@passport.com user3 11 0,1,2,3\r\n
<<< LST user4@passport.com user4 11 0\r\n
<<< BPR PHH 01%20234\r\n
<<< BPR MOB Y\r\n
<<< LST user5@passport.com user5 12\r\n
CHL
s needn't change from MSNP7, but more information about CHL strings has been found during the analysis of clients that support MSNP8. The client's QRY
includes a string that was previously thought to always be "msmsgs@msnmsgr.com". In fact, it turns out that different Microsoft-registered clients send different strings here, and have appropriately different hashes. An alternative is to use "PROD0038W!61ZTF9" instead of "msmsgs@msnmsgr.com" and "VT6PX?UQTM4WM%YR" instead of "Q1P7W2E4J9R8U3S5".
The SDC
command has been changed in MSNP8. It can now be sent at any time, not just ofter a FND
(which no longer works for any protocol version). It takes a TrID and eight parameters:
For example, if I wanted to contact someone with the address "example@passport.com", I might send the following:
>>> SDC 3 example@passport.com 0x0409 MSMSGS WindowsMessenger X X Andrew%20Sayers 8
\r\n
Hi Mike! (no newline)
If the message was successfully sent, the server will return an SDC
response with a TrID and a single parameter of "OK":
<<< SDC 21 OK
\r\n