當我們還在感嘆"這世界,變化快"的時候,MSN Messenger的協議已經到了第10版,簡稱MSNP10,對應于MSN Messenger 6.1。MSN Messenger 6.0則使用MSNP9?,F在Microsoft強迫MSN Messenger用戶升級到6.0或6.1版,因為服務器對MSNP8以下的版本不再支持。本文及后續文章所描述的MSN Messenger協議主要針對MSNP9/MSNP10。
1. 連 接
接線服務器(Switchboard Server, SS) - 客戶端之間聊天使用的中轉服務器。每開一個聊天窗口,客戶端和服務器就建立一個TCP會話。當客戶端之間需要進行文件傳輸或語音聊天時,發送系統消息,建立"點對點"會話通道(可能轉為使用UDP)。服務端口通常也是1863。"點對點" 通信使用的端口由客戶端自動協商決定,如文件傳輸通常使用6891端口。
2. 命 令
MSN Messenger命令使用純ASCII碼。對非ASCII碼字符使用URL編碼。命令的語法是
XXX[<SP>TrID<SP>PARAM1<SP>PARAM2…]<CRLF>
其中,<SP>是空白字符,<CRLF>是回車換行,XXX是一個3字符的命令串,TrID是一個流水號,PARAMx是參數,[ ]內是可選項。最簡單的命令沒有流水號和參數。為了方便起見,下面討論時用" "代表<SP>,"\r\n"代表<CRLF>,"\x??"代表一個值為0x??字節。紅色表示由客戶端發出,藍色表示由服務器發出。一個MSN Messenger命令的例子如下:
USR 18 TWN I example@hotmail.com\r\n
3. 錯 誤
無論是由于客戶端發出的命令無效,參數無效,還是其他什么原因,服務器可以返回一個錯誤。格式為
XXX[<SP>TrID]<CRLF>
其中,XXX是一個3位數字的串。如
ADD 21 AL non_existent@passport.com non_existent@passport.com\r\n205 21\r\n
上例中,non_existent@passport.com是一個不存在的賬號。
4. 消 息
MSN Messenger消息符合MIME 1.0標準,由消息頭與消息體組成。通常使用UTF-8編碼,消息頭中也需要URL編碼格式,消息體則直接用二進制數據。
一個MSN Messenger消息的例子如下:
MIME-Version: 1.0\r\n
Content-Type: text/plain; charset=UTF-8\r\n
X-MMS-IM-Format: FN=%E5%AE%8B%E4%BD%93; EF=; CO=0; CS=86; PF=0\r\n
\r\n
bhw98\xE4\xBD\xA0\xE5\xA5\xBD\xEF\xBC\x81
經簡單分析可知,"%E5%AE%8B%E4%BD%93"是"宋體"的UTF-8加URL編碼,而"bhw98\xE4\xBD\xA0\xE5\xA5\xBD\xEF\xBC\x81"是"bhw98你好!"的UTF-8編碼。
命令一覽
命令
| 來源
| 去向
| 說明
| 備注 |
ACK
| SS
| Client
| 確認,做出肯定回答。
| acknowledgement |
ADD
| Client
| NS
| 發出添加新聯系人到列表的請求。
| add user |
NS
| Client
| 返回添加新聯系人請求的應答。 |
ADG
| Client
| NS
| 發出添加新聯系人組請求。
| add group |
NS
| Client
| 返回添加新聯系人組請求的應答。 |
ANS
| Client
| SS
| 接受聊天連接請求。
| answer |
BLP
| Client
| NS
| 設置對尚未列入明確允許/禁止的聯系人列表的保密策略。
| block list privacy |
NS
| Client
| 返回設置保密策略請求的應答。 |
BYE
| SS
| Client
| 通知客戶端結束會話。
| bye |
CAL
| Client
| SS
| 發出建立聊天連接的請求。
| call |
SS
| Client
| 返回建立聊天連接請求的應答。 |
CHG
| Client
| NS
| 發出改變狀態的請求。
| change state |
NS
| Client
| 返回改變狀態的應答。 |
CHL
| NS
| Client
| 服務器發出驗證要求。
| challenge |
SS
| Client |
CVR
| Client
| NS
| 發出客戶端的OS、語言、MSN Messenger版本等信息。
| client version |
Client
| SS |
NS
| Client
| 返回推薦的MSN Messenger版本、升級軟件需要的下載地址等信息。 |
SS
| Client |
FLN
| NS
| Client
| 通知有聯系人列表中的用戶下線。
| off-line |
GTC
| Client
| NS
| 設置當有聯系人列表中的用戶狀態改變時給出的提示。
| greeting to changes? |
NS
| Client
| 返回設置請求的應答。 |
INF
| Client
| NS
| 詢問服務器所支持的認證方式。
| information? |
Client
| SS |
NS
| Client
| 返回服務器所支持的認證方式。 |
SS
| Client |
ILN
| NS
| Client
| 當客戶端登錄或添加聯系人到列表時,通知列表中的聯系人的狀態。
| initial online state |
IRO
| SS
| Client
| 當有新用戶加入聊天連接時,通知客戶端該連接中的用戶名單。
| initial roster information |
JIO
| SS
| Client
| 通知客戶端已經同另外的用戶建立了聊天連接。
| jion |
LSG
| Client
| NS
| 發出獲取聯系人組列表的請求。
| list groups |
NS
| Client
| 返回獲取聯系人組列表請求的應答。 |
LST
| Client
| NS
| 發出獲取聯系人列表的請求。
| list |
NS
| Client
| 返回獲取聯系人列表請求的應答。 |
MSG
| Client
| SS
| 發送消息到其他用戶(聊天對象)。
| message |
NS
| Client
| 傳遞服務器(系統) 的消息到客戶端。 |
SS
| Client
| 傳遞其他用戶(聊天對象)的消息到客戶端。 |
NAK
| SS
| Client
| 做出否定回答。
| negative acknowledgement |
NLN
| NS
| Client
| 通知客戶端聯系人上線或改變狀態。
| on-line |
OUT
| All
| All
| 結束客戶端-服務器的連接。
| out |
PNG
| Client
| NS
| 測試TCP連接狀態。
| ping |
Client
| SS |
PRP
| Client
| NS
| 發出設置個人電話號碼的請求。
| personal phone number |
NS
| Client
| 返回設置請求的應答 |
PNG
| Client
| NS
| 測試TCP連接狀態。
| ping |
Client
| SS |
QNG
| NS
| Client
| 返回測試TCP連接狀態的應答。
| quiz ping? |
SS
| Client |
QRY
| Client
| NS
| 客戶端回答服務器的驗證要求。
| quiz reply? |
Client
| SS |
REA
| Client
| NS
| 發出修改用戶昵稱的請求。
| rename nickname |
NS
| Client
| 返回修改用戶昵稱請求的應答。 |
REG
| Client
| NS
| 發出修改聯系人組的請求。
| rename group |
NS
| Client
| 返回修改聯系人組請求的應答。 |
REM
| Client
| NS
| 發出從聯系人列表中刪除用戶的請求。
| rename user |
NS
| Client
| 返回刪除用戶請求的應答。 |
RMG
| Client
| NS
| 發出刪除聯系人組的請求。
| remove group |
NS
| Client
| 返回刪除聯系人組請求的應答。 |
RNG
| NS
| Client
| 通知客戶端有人要建立聊天連接。
| ring |
SYN
| Client
| NS
| 客戶端-服務器同步。
| synchronization |
NS
| Client |
URL
| Client
| NS
| 發出獲取MSN服務URL的請求。
| URL |
NS
| Client
| 返回獲取URL請求的應答。 |
USR
| All
| All
| 聲明、傳遞、鑒別用戶身份。
| user |
VER
| Client
| DS
| 協商MSN Messenger協議版本。
| version |
Client
| NS |
DS
| Client |
NS
| Client |
XFR
| DS
| Client
| 向客戶端分配NS(通知客戶端轉向連接指定的NS)。
| transfer |
Client
| NS
| 發出分配SS的請求。 |
NS
| Client
| 返回分配SS請求的應答。 |
MSN Messenger協議--錯誤代碼一覽
代碼
| 含義
| 可能的命令
| 錯誤示例
| 備注 |
200
| 非法命令
| ?
| ABC 18\r\n 200 18\r\n
| ? |
201
| 非法參數
| ?
| CHG 19 FLN 0\r\n 201 19\r\n ADD 20 AL aaa@bbb@ccc aaa@bbb@ccc\r\n 201 20\r\n
| ? |
205
| 用戶不存在
| ADD
| ADD 21 AL none@hotmail.com none@hotmail.com\r\n 205 21\r\n
| ? |
206
| 缺少域名
| | | ? |
207
| 已經登錄
| USR
| USR 20 TWN I example@hotmail.com\r\n 207 20\r\n USR 21 TWN S 8d30fc782aa25ec9e1293fdda13cab42\r\n 207 21\r\n
| ? |
208
| 非法用戶名
| CAL
| CAL 2 @@hotmail.com\r\n 208 2\r\n
| ? |
209
| 非法用戶昵稱
| REA
| REA 18 one@hotmail.com kill%20microsoft\r\n 209 18\r\n
| ? |
210
| 用戶太多
| ADD
| ADD 23 FL one@hotmail.com one@hotmail.com 0\r\n 210 23\r\n
| 最大150 |
215
| 用戶已在列表中
| ADD
| ADD 36 FL one@hotmail.com one@hotmail.com 2\r\n ADD 36 825 FL one@hotmail.com one@hotmail.com 2\r\n ADD 37 FL one@hotmail.com one@hotmail.com 2\r\n 215 37\r\n
| |
CAL
| CAL 5 two@hotmail.com\r\n CAL 5 RINGING 213697\r\n CAL 6 two@hotmail.com\r\n 215 6\r\n |
216
| 用戶不在列表中
| REM
| REM 14 FL three@hotmail.com\r\n 216 14\r\n
| |
REA
| REA 48 three@hotmail.com three\r\n 216 48\r\n |
CAL
| CAL 2 three@hotmail.com\r\n 216 2\r\n |
217
| 用戶不在線
| CAL
| CAL 2 two@hotmail.com\r\n 217 2\r\n
| |
218
| 已在指定模式
| BLP
| BLP 17 BL\r\n BLP 17 151 BL\r\n BLP 18 BL\r\n 218 18\r\n
| |
GTC
| GTC 19 A\r\n GTC 19 152 A\r\n GTC 20 A\r\n 218 20\r\n |
219
| 用戶已經在相反的列表中
| ADD
| ADD 15 AL four@hotmail.com four@hotmail.com\r\n ADD 15 AL 56 four@hotmail.com four\r\n ADD 16 BL four@hotmail.com four@hotmail.com\r\n 219 16\r\n
| |
223
| 用戶組太多
| ADG
| ADG 28 new%20group 0\r\n 223 28\r\n
| 最大30 |
224
| 非法組號
| ADD
| RMG 24 3\r\n RMG 24 11506 3\r\n ADD 25 FL five@hotmail.com 3\r\n 224 25\r\n
| |
REM
| RMG 24 3\r\n RMG 24 11506 3\r\n REM 25 FL five@hotmail.com 3\r\n 224 25\r\n |
REG
| RMG 24 3\r\n RMG 24 11506 3\r\n REG 25 3 New%20Name 0\r\n 224 25\r\n |
RMG
| RMG 24 3\r\n RMG 24 11506 3\r\n RMG 25 3\r\n 224 25\r\n |
225
| 用戶不在組中
| REM
| REM 26 FL six@hotmail.com 3\r\n 225 26\r\n
| |
229
| 組名太長
| ADG
| ADG 27 ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 0\r\n 229 27\r\n
| 最大60 |
230
| 不能刪除組0
| RMG
| RMG 28 0\r\n 230 28\r\n
| |
300 | 缺少必要的參數 | ? | ? | ? |
302? | 尚未登錄 | ? | ? | ? |
500 | 服務器內部錯誤 | ? | ? | ? |
540 | 驗證應答錯誤 | ? | ? | ? |
600 | 服務器忙 | ? | ? | ? |
707 | 無法建立連接 | ? | ? | ? |
910 | 服務器忙 | ? | ? | ? |
911 | 身份驗證失敗 | ? | ? | ? |
?
過去的MSN Messenger版本(MSNP8以下),簡單地使用MD5等Hash算法對用戶身份進行認證。MSNP9/MSNP10使用一種TWN(Tweener)認證方式,通過SSL/TLS連接到login.passport.com和loginnet.passport.com等服務器,借助于HTTP協議輸入賬號和密碼,認證通過后,才能取得“入場券”。
真正意義上的身份認證,發生在客戶端與通知服務器(NS)之間??蛻舳说顷慛S時,首先交換版本信息。雙方均支持MSNP8以上版本時,才能進行認證過程。如果客戶端版本較低,不支持TWN,咋辦?服務器會將你一腳揣出去,信不信?
好了,廢話少說,現在拿一個成功認證的例子看看。在下面的例子中,賬號是“example@passport.com”,密碼是“password”。
VER 4 MSNP10 MSNP9 CVR0 \r\n
VER 4 MSNP9 CVR0 \r\n
CVR 5 0x0804 winnt 5.0 i386 MSNMSGR 6.1.0203 MSMSGS example@passport.com \r\n
CVR 5 6.0.0602 6.0.0602 5.0.0527 http://download.microsoft.com/download/d/4/f/d4f560d5-6dc6-4901-b149-a568415561d7/SETUPNT.EXE http://messenger.msn.com/cn \r\n
USR 6 TWN I example@passport.com \r\n
USR 6 TWN Slc=1033,id=507,tw=40,fs=1,ru=http%3A%2F%2Fmessenger%2Emsn%2Ecom,ct=1073355862,kpp=1,kv=5,ver=2.1.0173.1, tpf=ed1c2f217a21c191c61251eb8b73bb60 \r\n
(此時通過SSL進行身份認證,獲得“入場券”)
USR 7 TWN S t=4m1wWfEupDgUNb53qys5gJdw8OTJEtT82fcuDbS3U672gTymOOs6cgKeafj7WjgZNcufAQggxqHRRXko02DoflZA$$ &p=4QXNnX9rFDDgki9ZqvqPZGDGJa2Mrd5H13Zfl0NNjh4I78qPyfpzmkZPZEe0nxJTkzZSNDYtk!57cVqiYVfO86KgCRYWhi2kudS0M !7bdi82EDA1FYp3WboHD!sCQ17OZh7lPQI7fozrgsSMZwgSzRi2FNTPxf13oDNIfDCKCG!2guDvZKEpk78A$$ \r\n
USR 7 OK example@passport.com example@passport.com 1 0 \r\n
第一回合(TrID=4),雙方協商MSN版本號。客戶端說“我能支持MSNP9和MSNP10”,NS說“行,就MSNP9吧”。
第二回合(TrID=5),客戶端報告本機信息:OS = Windows 2000 (NT 5.0), 語言 = 簡體中文,MSN Messenger版本 = 6.1.0203, 賬號 = example@passport.com。NS給出了推薦的版本號,能夠使用的最老的版本號,新版本下載地址,官方網站地址等信息。
第三回合(TrID=6),客戶端要求身份認證(I = Initial),NS則給出所需要的一長串信息(S = Subsequent)。其中tpf相當于challenge,參與Hash運算,能保證每次認證返回的串是不同的。
第四回合(TrID=7),客戶端出示從認證服務器得到的“入場券”,NS放行(OK)。
第三、四回合之間,通過SSL的認證過程如下:
首先在HTTPS端口443向login.passport.com發送一個GET請求,將賬號、密碼和NS給定的一長串信息送出
GET /login2.srf HTTP/1.1 \r\n
Authorization: Passport1.4 OrgVerb=GET,OrgURL=http%3A%2F%2Fmessenger%2Emsn%2Ecom,sign-in=example%40passport.com,pwd=password, lc=1033,id=507,tw=40,fs=1,ru=http%3A%2F%2Fmessenger%2Emsn%2Ecom,ct=1073355862,kpp=1,kv=5,ver=2.1.0173.1, tpf=ed1c2f217a21c191c61251eb8b73bb60 \r\n
Host: login.passport.com \r\n \r\n
根據情況,會重定向到不同的URL。本例中,重定向到"https://loginnet.passport.com/login2.srf?lc=1033",服務器應答
HTTP/1.1 302 Found \r\n Server: Microsoft-IIS/5.0 \r\n
Date: Mon, 22 Dec 2003 21:10:05 GMT \r\n
PPServer: H: LAWPPLOG5C006 \r\n
Connection: close \r\n
Content-Type: text/html \r\n
Expires: Mon, 22 Jun 2003 21:09:05 GMT \r\n
Cache-Control: no-cache \r\n
cachecontrol: no-store \r\n Pragma: no-cache \r\n
P3P: CP="DSP CUR OTPi IND OTRi ONL FIN" \r\n
Authentication-Info: Passport1.4 da-status=redir \r\n
Location: https://loginnet.passport.com/login2.srf?lc=1033 \r\n
\r\n ... ...
然后,重新向指定的URL發出請求,得到如下響應
HTTP/1.1 200 OK \r\n
Server: Microsoft-IIS/5.0 \r\n
Date: Mon, 22 Dec 2003 21:10:07 GMT \r\n
PPServer: H: LAWPPIIS6B061 \r\n
Connection: close \r\n Content-Type: text/html \r\n
Expires: Mon, 22 Dec 2003 21:09:07 GMT \r\n
Cache-Control: no-cache \r\n
cachecontrol: no-store \r\n
Pragma: no-cache \r\n
P3P: CP="DSP CUR OTPi IND OTRi ONL FIN" \r\n
Set-Cookie: ... ... \r\n
Authentication-Info: Passport1.4 da-status=success,tname=MSPAuth,tname=MSPProf,tname=MSPSec, from-PP='t=4m1wWfEupDgUNb53qys5gJdw8OTJEtT82fcuDbS3U672gTymOOs6cgKeafj7WjgZNcufAQggxqHRRXko02DoflZA$$ &p=4QXNnX9rFDDgki9ZqvqPZGDGJa2Mrd5H13Zfl0NNjh4I78qPyfpzmkZPZEe0nxJTkzZSNDYtk!57cVqiYVfO86KgCRYWhi2kudS0M !7bdi82EDA1FYp3WboHD!sCQ17OZh7lPQI7fozrgsSMZwgSzRi2FNTPxf13oDNIfDCKCG!2guDvZKEpk78A$$', ru=http://messenger.msn.com \r\n
Content-Length: 0 \r\n
\r\n
開始時直接向loginnet.passport.com發出正確的請求,也是可以的。不難看出,在服務器認證成功的返回信息中,Authentication-Info字段的from-PP串值,就是所謂的“入場券”。
如果認證失敗,服務器返回401錯誤
HTTP/1.1 401 Unauthorized \r\n ... ...
這樣,就無法拿到“入場券”,自然不能在第四回合中輸入合法的串。
posted on 2006-05-25 14:56
surffish 閱讀(123)
評論(0) 編輯 收藏