1.簡介
此文檔具體說明了一個使用在實現Sun公司的遠程過程調用(RPC)包中的消息協議。此消息協議是由外部數據描述(XDR)語言[9]來定義的。這篇文檔假定讀者對XDR非常熟悉,它并不試圖去證實使用RPC的好處。這里推薦由BirrellandNelson[1]所寫的文章,作為了解RPC的背景。
2.術語
此文檔討論了服務器,服務,程序,過程,客戶和版本這些術語。服務器就是實現網絡服務的軟件。網絡服務是一個或多個遠程程序的集合。一個遠程程序實現了一個或多個遠程過程;這些過程的參數和結果已經存檔在特定的程序協議規范中(見附錄A中的例子)。網絡客戶是向服務發出遠程過程調用的軟件。一個服務器可能支持不止一種版本的遠程程序,這樣以便于與改變的協議兼容。
例如,一個網絡文件服務可能由兩個程序組成。一個程序處理諸如文件系統訪問控制和鎖定這樣的高層應用。另一個程序處理低層的文件I/O,擁有象“read”和“write”這樣的過程。網絡文件服務的客戶機根據自己用戶的需要將會調用服務中與這兩個程序關聯的過程。
3.RPC的模型
遠程過程調用模型與本地過程調用模型非常相似。在本地過程調用中,調用者把要傳給過程的參數放在明確定義好的位置上(例如一個結果記錄)。然后調用者將把控制轉交到被調用的過程中,最后得到返回的控制。在返回點上,被調用的過程的結果從明確定義好的位置上取出,調用者繼續執行。
遠程過程調用也是相似的,通過兩個進程邏輯地運行在一起構成一條控制主線。一個是調用者進程,另一個是服務器進程。也就是說,調用者進程發送給服務器進程一條調用消息,并等待(阻塞)直到收到響應的消息。調用消息包含被調用的過程的參數等。響應消息包含著被調用過程的結果等。一旦收到響應消息,被調用過程的結果就會被取出,調用者將恢復執行。
在服務器一側,一個進程處于休眠狀態來等待調用消息的到達。當一條調用消息到達后,服務器進程從消息中取出被調用過程的參數,計算出結果,發送響應消息,然后等待下一條調用消息。
注重:這種模式中,在任一個給定的時間上,兩個進程中只有一個是激活的。但是,這種模式只是作為一個例子。RPC協議在并發模型的實現上不作限制,也可能存在著其它的實現并發模型的方法。例如,一種實現可能選擇RPC調用是異步進行的,這樣客戶機就可以在等待服務器的響應中,做其它有用的工作。另一種可能性是使服務器創建一個新的任務來處理輸入的請求,這樣服務器就可以自由地接收其它的請求。
4.傳輸和語義
RPC協議不依靠于傳輸協議。也就是說,RPC不關心消息是怎樣從一個進程傳遞到另一個進程中去的。這個協議僅僅處理協議的規范和消息的解釋。
還有必要指出RPC并不去試圖實現任何一種可靠性,所以應用程序必須考慮在RPC下層的傳輸層協議。假如應用程序知道自己運行在象TCP/ip[6]這樣的可靠傳輸層的上層的時候,它就知道保證可靠性的大部分工作已經做好了。在另一方面,假如應用程序運行在象UDP/IP[7]這樣的不可靠傳輸層的上層,那么它必須實現自己的重傳和超時策略,而這些服務RPC層是不提供的。
因為獨立于傳輸層,RPC協議并不把非凡的語義附加到遠程過程上。可以從下面的傳輸層推斷出來(但是應該有明確的定義)。例如,考慮RPC運行在不可靠傳輸層UDP/IP的上層。假如應用程序在很短的超時后重傳RPC消息,當沒有接收到響應的時候,它能夠判定的唯一的事情就是過程沒有執行或者執行了一次以上。當收到響應的時候,它可以推斷出過程至少執行了一次。
服務器可能希望記住以前準許的從客戶端發來的請求。為了在某種程度上確保至多只執行一次的語義,服務器不再重新批準這些請求。服務器通過利用打包在RPC請求中的事務ID來實現這個功能。事務的主要用處就是客戶端的RPC層用它來匹配對請求的響應。但是,客戶應用程序當重傳一個請求的時候可以選擇再使用它以前的事務ID。服務器應用程序在知道了這個事實后,可以選擇在準許了一個請求后記住這個事務ID,為了獲得在某種程度上至多只執行一次的語義,服務器對于具有相同ID的請求不再重新批準。除了可以進行檢驗相等的操作之外,不答應服務器使用其它的方法來檢查這個ID。
另一方面,假如使用了一個象TCP/IP這樣的可靠傳輸,應用程序能夠從一條響應消息推斷出過程已經正確地執行了一次。但是,假如它沒有接收到響應消息,則不能假設遠程過程沒有執行。注重:即使使用了象TCP這樣的面向連接的協議,應用程序仍然需要超時和重新連接的功能來處理服務器崩潰的情況。
除了數據報或者面向連接的協議之外,還存在其它的傳輸層協議的可能性。例如,一種象VMTP[2]這樣的請求響應協議對RPC來說也許是最自然的傳輸層協議。
注重:在Sun中,RPC當前實現在TCP/IP以及UDP/IP的上層。
5.綁定與集合獨立性
綁定一個客戶端到一個服務上的行為并不是遠程過程調用規范的一部分。這個重要且必要的功能留給了一些上層的軟件(這個軟件可能本身就使用RPC,見附錄A)
執行者應該把RPC協議看作是網絡上的跳轉到子程序指令("JSR");裝載程序(綁定者)使JSR可用,裝載程序本身使用JSR來完成它自己的任務。同樣,網絡使RPC可用,使用RPC來完成它的任務。
6.認證
RPC協議提供了一些必要的字段使客戶能向服務標識它自己,反過來服務也要用一些字段來向客戶標識自己。安全和訪問控制機制建立在消息認證之上。一些不同的認證協議能夠得到支持。在RPC報頭中有一個字段用來指出使用哪一種認證協議。關于更具體的認證協議的信息在第九節“認證協議”中討論。
7.RPC協議的要求
RPC協議必須要能提供以下的功能:
(1)一個調用過程的唯一規范
(2)匹配響應消息和請求消息的規則
(3)服務鑒別調用者和調用者鑒別服務的規則
除了以上的要求,還需要能檢測出以下由于協議,實現,用戶和網絡治理中所產生的錯誤:
(1)RPC協議不匹配
(2)遠程程序協議版本不匹配
(3)協議錯誤(諸如錯誤指定了過程參數)
(4)遠程認證失敗的原因
(5)不能調用想要的過程的其它原因
7.1RPC程序和過程
RPC調用消息有三個無符號的字段:遠程程序號,遠程程序版本號和遠程過程號。這三個字段唯一地標識了被調用的過程。程序號由一些主要的權威來治理(就象Sun公司)。一旦執行者有了一個程序號,他就可以執行他的遠程程序;第一次執行很可能有一個版本號1。因為大多數新的協議都發展成更好,更穩定,更成熟的協議,所以調用消息中的版本字段標識了調用者使用了協議的哪一個版本。版本號使得通過相同的服務器進程運行舊協議和新協議成為可能。
過程號標識著被調用的過程。這些號碼已經歸檔在特定的程序的協議規范中。例如,文件服務協議規范可能把它的過程號5定義為“read”,過程號12定義為“write”。
就像遠程程序協議在一些版本上可能有一些變化一樣。實際的RPC消息協議也可能有所改變。因此,調用消息也有它自己的RPC版本號。對于在這里描述的RPC來說,這個版本號總是等于2。
請求消息的響應消息具有足夠的信息來區分下面的錯誤情況:
(1)RPC的遠程實現應該使用協議的第二版,RPC協議支持的最低和最高版本號
將返回。
(2)遠程程序在遠程系統中不可用。
(3)遠程程序不支持請求的版本號。遠程程序支持的最低和最高版本號將返回。
(4)請求的過程號不存在。(這總是因為調用者一方的協議或者程序出錯)
(5)傳給遠程過程的參數在服務器看來是無用的(這實際上是由客戶端和服務器之間的協議沒有達成一致造成的)。
7.2認證
服務器對調用者的認證和調用者對服務器的認證的規則是RPC協議的一部分。調用消息有兩個認證字段,證書和校驗符響應消息有一個認證字段,即響應校驗符。RPC協議規范把這三個字段都定義成不透明的類型。
enumauth_flavor{
AUTH_NULL=0,
AUTH_UNIX=1,
AUTH_SHORT=2,
AUTH_DES=3
/*更多的定義*/
};
strUCtopaque_auth{
auth_flavorflavor;
opaquebody<400>;
};
用簡單的英語表示,任何一個"opaque_auth"結構就是由一個"auth_flavor"枚舉類型后跟一些對RPC協議實現來說是不透明的字節組成的。
在認證字段中包含的數據的語義和解釋是個別指定的,獨立于認證協議規范。(第九節定義了不同的認證協議)
假如認證參數被拒絕,響應消息將包含說明為什么會被拒絕的信息。
7.3程序號分配
程序號根據下表以十六進制20000000(十進制536870912)為一組來進行分發。
0-1fffffff由Sun公司定義
20000000-3fffffff.由Sun公司定義
40000000-5fffffff暫時的
60000000-7fffffff保留
80000000-9fffffff保留
a0000000-bfffffff保留
c0000000-dfffffff保留
e0000000-ffffffff保留
第一組是屬于升陽微系統公司(Sun公司)治理的號碼范圍。在所有場所都應該是一致的。第二組號碼范圍對應用程序來說對特定場所是特有的。這個范圍主要是用來調試新程序的。當在一個場所中開發的一個應用程序要引起公眾的注重,這個應用程序就應該在第一組號碼范圍中分配一個號碼。第三組號碼范圍對應用程序來講是動態地產生程序號。最后的那些號碼范圍組是為將來使用保留的,目前還沒有使用。
7.4RPC協議的其它使用
使用RPC協議的主要目的就是為了調用遠程的過程。也就是說,每一個調用消息都與一個響應消息匹配。但是,這個協議本身是一個消息傳送協議,其它協議(非RPC協議)也可以通過這個協議來實現。Sun當前正在為下面兩種非RPC協議使用 RPC消息協議,這兩種協議是批處理(或者管道)和廣播RPC,下面將討論,但是不具體說明。
7.4.1批處理
批處理答應客戶發送一個任意大的調用消息序列給服務器;它典型地使用可靠字節流協議(象TCP/IP)來作為它的傳輸層。在批處理的時候,客戶從來不等待服務器的響應,服務器也不發送對批處理請求的響應。一個批處理調用序列總是由合法的RPC終止,這是為了刷新管道(以肯定確認)。
7.4.2廣播RPC
在基于廣播RPC的協議中,客戶向網絡中發送一個廣播數據包,然后等待響應。廣播RPC使用不可靠的數據報協議(象UDP/IP)作為它的傳輸層。支持廣播協議的服務器只有在請求被成功執行后才進行響應。在出錯的時候服務器將保持沉默。廣播RPC使用端口映射器RPC服務來獲得它的語義。(要獲得更多的信息請參見附錄A)
8.RPC消息協議
這一節用XDR數據定義語言來定義RPC消息協議。這些消息是用一種嚴謹的風格來定義的。.
enummsg_type{
CALL=0,
REPLY=1
};
/*
*調用消息的響應可以呈現出兩種形式;
*消息要么被接受要么被拒絕
*/
enumreply_stat{
MSG_ACCEPTED=0,
MSG_DENIED=1
};
/*
*假如一條調用消息被接受,下面是試圖調用遠程過程的狀態。
*/
enumaccept_stat{
SUCCESS=0,/*RPC執行成功*/
PROG_UNAVAIL=1,/*遠程沒有輸出程序*/
PROG_MISMATCH=2,/*遠程不支持版本號*/
PROC_UNAVAIL=3,/*程序不支持過程*/
GARBAGE_ARGS=4/*過程不能解釋參數*/
};
/*
*調用消息被拒絕的原因
*/
enumreject_stat{
RPC_MISMATCH=0,/*RPC版本號不等于2*/
AUTH_ERROR=1/*遠程不能認證調用者*/
};
/*
*認證失敗的原因
*/
enumauth_stat{
AUTH_BADCRED=1,/*錯誤的證書(封裝被打破)*/
AUTH_REJECTEDCRED=2,/*客戶必須開始新會話*/
AUTH_BADVERF=3,/*錯誤的校驗符(封裝被打破)*/
AUTH_REJECTEDVERF=4,/*校驗符過期或者重放*/
AUTH_TOOWEAK=5/*因為安全原因拒絕*/
};
/*
*RPC消息
*所有消息以一個事務標識符xid開始,接下來是有判別的兩個分支的聯合。
*這個聯合的判別式是msg_type等于兩類消息的一種。
*響應消息的xid總是匹配開始調用消息的xid。
*客戶端使用這個字段把收到的響應消息與調用消息配備,
*服務器端使用這個字段來檢測重傳。
*服務器端不能把這個id看作為任何一種類型的序列號。
*/
structrpc_msg{
unsignedintxid;
unionswitch(msg_typemtype){
caseCALL:
call_bodycbody;
caseREPLY:
reply_bodyrbody;
}body;
};
/*
*RPC請求調用的實體:
*在RPC協議規范的版本2中,rpcvers字段必須等于2。
*字段prog,vers,和proc確定了遠程程序,以及程序的版本號
*和在遠程程序中被調用的過程。在后面是兩個認證參數
*cred(認證證書)和verf(認證校驗符)。認證參數的下面是遠程過程的參數,
*這些參數是由具體的程序協議來指定的。
*/
structcall_body{
unsignedintrpcvers;/*必須等于2*/
unsignedintprog;
unsignedintvers;
unsignedintproc;
opaque_authcred;
opaque_authverf;
/*過程的特定參數從這里開始*/
};
/*
*RPC請求的響應實體;
*調用消息要么被接受要么被拒絕
*/
unionreply_bodyswitch(reply_statstat){
caseMSG_ACCEPTED:
accepted_replyareply;
caseMSG_DENIED:
rejected_replyrreply;
}reply;
/*
*當服務器接受RPC請求時的響應:
*即使請求被接受,也可能會有錯誤。
*第一個字段是服務器產生的認證校驗符,為了使調用者能夠識別服務器。
*接下來是一個判別式是枚舉類型accept_stat的聯合。
*聯合中SUCCESS的一個分支是特定的協議。
*聯合中ThePROG_UNAVAIL,PROC_UNAVAIL和GARBAGE_ARGS
*的分支為空。PROG_MISMATCH分支確定了服務器支持的遠程
*程序的最低和最高版本號。
*/
structaccepted_reply{
opaque_authverf;
unionswitch(accept_statstat){
caseSUCCESS:
opaqueresults[0];
/*
*具體的過程結果從這里開始
*/
casePROG_MISMATCH:
struct{
unsignedintlow;
unsignedinthigh;
}mismatch_info;
default:
/*
*空。這些情況包括PROG_UNAVAIL,
*PROC_UNAVAIL和GARBAGE_ARGS.
*/
void;
}reply_data;
};
/*
*當服務器拒絕RPC請求時的響應:
*請求可能由于兩種原因被拒絕:一種是服務器沒有運行RPC協議的
*兼容版本(RPC_MISMATCH),另一種是服務器不認證調用者(AUTH_ERROR)。
*在RPC版本不匹配的情況下,服務器返回所支持的最低和最高版本號。
*在不認證的情況下,返回失敗狀態。
*/
unionrejected_replyswitch(reject_statstat){
caseRPC_MISMATCH:
struct{
unsignedintlow;
unsignedinthigh;
}mismatch_info;
caseAUTH_ERROR:
auth_statstat;
};
9.認證協議
象前面所說的那樣,認證參數是不透明的,但是對于RPC協議的其余部分是可調整的。這一節說明了在Sun中實現(或是由Sun支持的)的認證的“特征值”。在其它的場所中可以自由得創造新的認證類型。特征值的分配的規則和程序號的分配規則是一樣的。
9.1不認證
通常過程會在調用者不知道它是誰或者服務器不關心調用者是誰的情況下調用。在這種情況下RPC消息中的證書,校驗符和響應校驗符的“特征值”(opaque_auth的聯合的判別式)為"AUTH_NULL"。opaque_auth的實體中的字節沒有定義。建議這些opaque長度為0。
9.2UNIX認證
遠程過程的調用者可能希望象在UNIX系統中那樣標識它自己。RPC調用消息中的證書判別式的值是"AUTH_UNIX"。這些證書的opaque實體編碼成下面這樣的結構:
structauth_unix{
unsignedintstamp;
stringmachinename<255>;
unsignedintuid;
unsignedintgid;
unsignedintgids<10>;
};
"stamp"是一個調用者機器產生的二進制標識符(ID)。"machinename"是調用者機器的名字(例如“krypton”)。"uid"是調用者的有效用戶標識符ID。"gid"是調用者的有效組標識符ID。"gids"是一個包含調用者作為成員的組的計數數組。伴隨著證書的校驗符應該是"AUTH_NULL"(上面定義的)
從服務器收到的響應消息中的響應校驗符的判別式的值可能是"AUTH_NULL",或者是"AUTH_SHORT"。在"AUTH_SHORT"的情況下,響應校驗符的字符串字節編碼成不透明的結構。這個新的不透明結構現在可以傳遞給服務器以代替原來的"AUTH_UNIX"特征值證書。服務器保留一個緩沖區用來把這個速記下來的不透明結構(通過一個"AUTH_SHORT"類型響應校驗符傳回)映射到調用者原來的證書上。調用者可以使用新的證書節省網絡帶寬和服務器上的cpu周期。
服務器可能在任一時間刷新這個速記下來的不透明結構。假如這種情況發生,遠程過程調用消息將由于認證錯誤被拒絕。失敗的原因將是"AUTH_REJECTEDCRED"。在這時,調用者可能希望試試原來的"AUTH_UNIX"證書類型。
9.3DES認證
UNIX認證碰到了下面兩個主要問題:
(1)命名太面向于UNIX
(2)沒有校驗符,所以證書很輕易偽造
DES認證努力來解決這兩個問題。
9.3.1命名
處理第一個問題的方法是通過使用一個簡單的字符串代替操作系統特定的整數來定位調用者。這個字符串就作為"netname"或者調用者的網絡名。除了在鑒別調用者之外,不答應服務器在任何其它的方面解釋調用者名字中的內容。因此,網絡名對于在Internet中的每一個調用者來說都應該是唯一的。
由每一個操作系統上的DES認證實現來為它的用戶產生網絡名,以確保當用戶造訪遠程服務器的時候,他的網絡名是唯一的。操作系統也知道怎樣區分本地系統中的用戶。把這種機制擴展到網絡上通常存在著一些小問題。例如,在Sun上的具有用戶ID號為515的UNIX用戶可能被分配給下面的網絡名:“unix.515@sun.com"。這個網絡名包含三項以使服務器確認它是唯一的。在Internet網上叫做“sun.com”的命名域只有一個。在這個域中用戶ID是515的UNIX用戶也僅有一個。但是,在其它的操作系統上可能有另一個用戶,例如在VMS上,也在同樣的命名域中,碰巧也有同樣的用戶ID。為了確保兩個用戶被區分,我們加入操作系統名。所以一個用戶是"unix.515@sun.com",另一個是“vms.515@sun.com”。
第一個字段實際上是一種命名方法,而不是一個操作系統名。現在僅僅是碰巧在命名方法和操作系統之間存在一對一對應。假如全世界在命名標準上取得一致,第一個字段應該是標準的名字,而不是一個操作系統名。
9.3.2DES認證校驗
不像UNIX認證,DES認證有一個校驗符,這可以使服務器驗證客戶的證書(反之客戶也可以驗證服務器的證書)。校驗符的內容主要是一個加密的時間戳。服務器可以解密這個時間戳。假如它接近真實的時間,那么客戶一定已經正確的加密了它。客戶端能加密它的唯一方法是知道這個RPC會話的“會話密鑰”。假如客戶端知道這個會話密鑰,那么它就是真正的客戶端。
會話密鑰是由一個由客戶端產生的DES密鑰[5],在第一次RPC調用時通知服務器。會話密鑰在第一次事務中由一個公鑰模式加密。使用在DES認證中的非凡的公鑰模式是Diffie-Hellman[3],它具有128比特位的密鑰長度。這種加密方法的細節以后討論。
為了完成工作,客戶端和服務器需要相同的時間概念。假如網絡時間同步不能保證,那么客戶端可以在開始會話前與服務器建立同步。也許要與Internet時間服務器協商(TIME[4])。
服務器判定一個客戶端時間戳是否有效的方法有點復雜。對于除了第一次事務之外的其它事務,服務器只檢查兩件事。
(1)這個時間戳比來自同一個客戶端的前一個時間戳大
(2)這個時間戳沒有過期。
假如服務器時間比客戶端的時間戳與客戶端的窗口值(window)相加后的總和還要晚,這個時間戳過期。“window”是客戶端在它的第一次事務中傳遞(已加密過)給服務器的一個數字。你可以把它看作是證書的生存期。
以上說明了除第一次事務的每一次事務。在第一次事務中,服務器僅檢查時間戳沒有過期。假如就是所作的全部工作的話,對于客戶端來說,發送隨機的數據代替時間戳將會非常輕易,這會有很大的成功機會。作為一個附加的檢查,客戶端在第一次事務中發送一個叫“窗口校驗符”的加密項,它必須等于窗口值減1,否則服務器將拒絕這個證書。
客戶端也必須檢查從服務器返回的校驗符,以確定服務器是合法的。服務器把它從客戶端收到的加密時間戳減一秒后再送回給客戶端。假如客戶端得到數據與此不同,它將拒絕。
9.3.3昵稱和時鐘同步
在第一次事務之后,服務器DES認證子系統在它返回給客戶端的校驗符中有一個“昵稱”整數,客戶端可以在以后的每次事務中使用這個昵稱來代替它的網絡名,加密的DES密鑰和窗口。昵稱更像一個在服務器上表的索引,在這張表中存儲著每一個客戶端的網絡名,DES密鑰譯文和窗口。
盡管客戶端和服務器的時鐘在開始時被同步,但是他們可能再次變得不同步。當這種情況發生后,客戶端RPC子系統可能在應該需要再次同步的時候得到"RPC_AUTHERROR"。
客戶端即使在與服務器同步的情況下仍然可能得到"RPC_AUTHERROR"錯誤。這個原因就是服務器的昵稱表大小有限,它可以在它需要的時候隨時刷新表中的條目。在這種情況下,客戶端應該重新發送它的原來的證書,服務器將給它一個新的昵稱。假如服務器崩潰,昵稱表中的條目得到刷新,所有的客戶端都將必須重新發送它的原來的證書。
9.3.4DES認證協議規范(用XDR語言描述)
/*
*有兩種證書:一種是客戶端使用它的全稱網絡名,另一種是客戶端使用
*由服務器發給它的昵稱(僅僅是一個無符號整數)。在第一次與服務器的事務中,
*客戶端必須使用它的全稱名。服務器將返回給客戶端它的昵稱。
*客戶端可以在以后的與服務器的事務中使用它的昵稱。并不是一定要使用昵稱,
*但是使用昵稱將是一個明智的選擇。
*/
enumauthdes_namekind{
ADN_FULLNAME=0,
ADN_NICKNAME=1
};
/*
*一個由DES加密的64比特數據塊。
*/
typedefopaquedes_block[8];
/*
*網絡用戶名的最大長度
*/
constMAXNETNAMELEN=255;
/*
*全稱包括客戶端的網絡名,一個加密的會話密鑰和窗口。窗口實際上就是
*證書的生存期。假如在校驗符中的時間戳指示的時間加上窗口后過期,
*那么服務器應該使請求過期,而且不承認它。為了確保請求不會重放,
*服務器應該保持時間戳比前一個看到的時間戳大,除非這是第一個事務。
*在第一個事務中,服務器只檢查窗口校驗符是一個小于窗口的值。
*/
structauthdes_fullname{
stringname<MAXNETNAMELEN>;/*客戶端名字*/
des_blockkey;/*公用密鑰加密過的會話密鑰*/
unsignedintwindow;/*加密過的窗口*/
};
/*
*一個證書要么是全稱要么是昵稱
*/
unionauthdes_credswitch(authdes_namekindadc_namekind){
caseADN_FULLNAME:
authdes_fullnameadc_fullname;
caseADN_NICKNAME:
unsignedintadc_nickname;
};
/*
*時間戳從1970年1月1日午夜開始給時間編碼
*/
structtimestamp{
unsignedintseconds;/*秒*/
unsignedintuseconds;/*微秒*/
};
/*
*校驗符:客戶端的種類
*窗口的校驗符僅使用在第一次事務中,在與全稱證書的關聯中,
*這些項目在加密前打包在下面的結構中。
*
*struct{
*adv_timestamp;--oneDESblock
*adc_fullname.window;--onehalfDESblock
*adv_winverf;--onehalfDESblock
*}
*這個結構以一個輸入的0向量使用CBC加密模式加密
*所有的其它時間戳加密是使用ECB加密模式加密
*/
structauthdes_verf_clnt{
timestampadv_timestamp;/*加密的時間戳*/
unsignedintadv_winverf;/*加密的窗口校驗符*/
};
/*
*校驗符:服務器種類
*服務器把這個加密的時間戳減一秒后,返回給客戶端。
*服務器也告訴客戶端它的昵稱(未加密),已備在將來的事務中使用。
*/
structauthdes_verf_svr{
timestampadv_timeverf;/*加密的校驗符*/
unsignedintadv_nickname;/*客戶端新的昵稱*/
};
9.3.5Diffie-Hellman加密方法
在這種模式中,有兩個常數"PROOT"和"MODULUS"。Sun為DES認證協議選擇了特定的值:
constPROOT=2;
constMODULUS="b520985fb31fcaf75036701e37d8b857";/*十六進制*/
這種模式工作的過程最好用一個例子來說明。假設有兩個人“A”和“B”想互相發送加密的消息。所以,A和B都隨機產生一個“秘密”密鑰,這個密鑰他們并不想讓其它人知道。把這兩個密鑰表示為SK(A)和SK(B)。他們也在一個公開的姓名地址錄中發布他們的“公用”密鑰。公用密鑰由以下方式計算出。
PK(A)=(PROOT**SK(A))modMODULUS
PK(B)=(PROOT**SK(B))modMODULUS
"**"符號在這里表示求冪。現在A和B都能得到在他們之間的“公共”密鑰,而不需要暴露他們的秘密密鑰。公共密鑰在這里描述為CK(A,B),
A電腦:
CK(A,B)=(PK(B)**SK(A))modMODULUS
B電腦:
CK(A,B)=(PK(A)**SK(B))modMODULUS
這兩個值是相等的:
(PK(B)**SK(A))modMODULUS=(PK(A)**SK(B))modMODULUS
我們去掉"modMODULUS"的取模算法部分來進行簡化。
PK(B)**SK(A)=PK(A)**SK(B)
然后,用以前B計算得到的結果來替換PK(B),對PK(A)也進行這樣的步驟
((PROOT**SK(B))**SK(A)=(PROOT**SK(A))**SK(B)
這將導致:
PROOT**(SK(A)*SK(B))=PROOT**(SK(A)*SK(B))
不使用公共密鑰CK(A,B)來加密在協議中使用的時間戳。它只用于加密會話密鑰,而使用這個會話密鑰來加密時間戳。這樣做的原因是因為應該盡可能少的使用公共密鑰,以防公共密鑰被破譯。會話密鑰即使被破譯,造成的損失也較小,因為會話的時間總是相對較短。
會話密鑰是使用56比特DES密鑰加密的。而這個公共密鑰是128比特位。為了減少比特的數量,象下面這樣從公共密鑰中選擇56比特。從公共密鑰中選擇最中間的8個字節,然后把奇偶校驗加在每一個字節的最低比特位。這樣就產生了一個帶有8比特奇偶校驗位的56比特密鑰。
10.記錄標記的標準
當RPC消息在一個字節流協議(象TCP/IP)上層傳送的時候,有必要在一個消息和另一個消息之間劃定界線,這樣是為了檢測出用戶協議的錯誤,并可能對錯誤進行恢復。這就叫做記錄標記(RM)。Sun使用RM/TCP/IP來在TCP流上傳送RPC消息。一個RPC消息適配一個RM記錄。
一個記錄是由一個或者多個記錄片斷組成。一個記錄片斷是4字節的頭,后跟0至(2**31)-1字節的片斷數據。片斷頭的字節編碼成一個無符號的二進制數;象是XDR中的整數一樣,字節的順序是從高到底的。這個數字編碼成兩個部分的值:一個部分是布爾值,指示這個片斷是否是記錄的最后一個記錄片斷(值1表明此片斷是最后一個片斷),另一部分是一個31比特的無符號二進制值,它是這個片斷數據用字節計數時的長度。布爾值是這個片斷頭的最高位比特;長度是低位的31比特。(注重這個記錄規范并不是XDR的標準形式!)
11.RPC語言
就象在一個正式的語言中需要定義XDR數據類型一樣。也需要在正式的語言中定義操作XDR數據類型的過程。為了這個目的,我們使用RPC語言。它是XDR語言的擴展。使用下面的例子來描述這種語言的精髓。
用RPC語言描述的服務的例子
這里有一個簡單ping程序的例子說明。
/*
*簡單的ping程序
*/
programPING_PROG{
/*
*最近和最好的版本
*/
versionPING_VERS_PINGBACK{
voidPINGPROC_NULL(void)=0;
/*
*Ping這個調用者,返回往返時間(用微秒來表示)。假如操作超時,
*返回-1。
*/
intPINGPROC_PINGBACK(void)=1;
}=2;
/*
*原來的版本
*/
versionPING_VERS_ORIG{
voidPINGPROC_NULL(void)=0;
}=1;
}=1;
constPING_VERS=2;/*最近的版本*/
在第一個版本中,PING_VERS_PINGBACK有兩個過程PINGPROC_NULL和PINGPROC_PINGBACK。PINGPROC_NULL不需要參數,也不返回結果,但是它對計算從客戶端到服務器再回到客戶端的往返時間很有用。在會話中,任何RPC協議的過程0都應該有同樣的語義,不需要任何種類的認證。客戶端用第二個過程來使服務器對客戶端進行一個反向的ping操作,并且它返回使用這個操作的時間值(用微秒表示)。下一個版本PING_VERS_ORIG是這個協議的原來的版本,它不包含PINGPROC_PINGBACK過程。這對兼容舊的客戶端程序很有用,隨著程序的升級,它可能從整個協議中刪去。
11.1RPC語言規范
RPC語言除了加入了"program-def"的定義,與XDR語言一樣。
program-def:
"program"identifier"{"
version-def
version-def*
"}""="constant";"
version-def:
"version"identifier"{"
procedure-def
procedure-def*
"}""="constant";"
procedure-def:
type-specifieridentifier"("type-specifier")"
"="constant";"
11.2語法的注重事項
(1)下面的要害字不能用作標識符:"program"and"version";
(2)版本名不能在一個程序定義的范圍內出現超過一次。
同樣,版本號在這個程序定義的范圍里也不能出現超過一次。
(3)過程名不能在一個版本定義的范圍內出現超過一次。
同樣,過程號在這個版本定義的范圍里也不能出現超過一次。
(4)程序的標識符有象常數標識符和類型標識符同樣的名字空間。
(5)只有無符號的常數可以分配給程序,版本和過程。
附錄A:端口映射器程序協議
端口映射器程序把RPC程序和版本號映射到特定的傳輸端口號上。這個程序可以對遠程的程序進行動態綁定。
這種方法是符合需要的,因為保留的端口號的范圍是有限的,而潛在的遠程程序是很多的。在一個保留端口號上運行端口映射器,只要查詢這個端口映射器就可以確定其它遠程成程序的端口號。
端口映射器也在廣播RPC中使用。一個給定的RPC程序在不同的機器上經常綁定到不同的端口號上,所以沒有方法直接廣播到所有的這些程序。而端口映射器有固定的端口號。要向給定的程序發送廣播,客戶端實際上把消息發送到廣播地址上的端口映射器。獲得廣播的每一個端口映射器調用由客戶端指定的本地服務。當端口映射器收到本地服務的響應,它再把這個響應發送給客戶端。
A.1端口映射器協議規范(用RPC語言)
constPMAP_PORT=111;/*端口映射器的端口號*/
/*
*(程序,版本,協議)到端口的映射
*/
structmapping{
unsignedintprog;
unsignedintvers;
unsignedintprot;
unsignedintport;
};
/*
*"prot"字段支持的值
*/
constIPPROTO_TCP=6;/*TCP/IP的協議號*/
constIPPROTO_UDP=17;/*UDP/IP的協議號*/
/*
*一個映射列表
*/
struct*pmaplist{
mappingmap;
pmaplistnext;
};
/*
*調用的參數
*/
structcall_args{
unsignedintprog;
unsignedintvers;
unsignedintproc;
opaqueargs<>;
};
/*
*調用的結果
*/
structcall_result{
unsignedintport;
opaqueres<>;
};
/*
*端口映射器的過程
*/
programPMAP_PROG{
versionPMAP_VERS{
voidPMAPPROC_NULL(void)=0;
boolPMAPPROC_SET(mapping)=1;
boolPMAPPROC_UNSET(mapping)=2;
unsignedintPMAPPROC_GETPORT(mapping)=3;
pmaplistPMAPPROC_DUMP(void)=4;
call_resultPMAPPROC_CALLIT(call_args)=5;
}=2;
}=100000;
A.2端口映射器操作
端口映射器程序當前支持兩種協議(UDP/IP和TCP/IP)。端口映射器在這兩種協議中的任一種中都分配在端口111上(SUNRPC[8])。下面是每一個端口映射器過程的描述:
PMAPPROC_NULL:
這個過程不工作。按照習慣,任何協議的0號過程不接收參數,也不返回結果。
PMAPPROC_SET:
當一個程序在一個機器上可用時,它要向同一臺機器上的端口映射器注冊它自己。
這個程序傳遞它的程序號"prog",版本號"vers",傳輸協議號"prot"和端口號
"port"。在"port"這個端口號上,程序等待服務的請求。這個過程返回一個布爾值,假如過程成功建立了映射,這個值為"TRUE"。否則,這個值為"FALSE"。
假如已經存在"(prog,vers,prot)"元組,這個過程拒絕建立映射。
PMAPPROC_UNSET:
當程序變為不可用的時候,它將在同一臺機器上的端口映射器中注銷它自己。
它的參數和結果和"PMAPPROC_SET"有同樣的含義。參數中的協議和端口
號字段將被忽略。
PMAPPROC_GETPORT:
當被給出了程序號"prog",版本號"vers"和傳輸協議號"prot",這個過程將返回
此程序等待調用請求的端口號。返回一個0的端口值意味著這個程序沒有注冊。
參數中的"port"字段將被忽略。
PMAPPROC_DUMP:
這個過程列舉了端口映射器數據庫中的所有條目。
此過程不需要參數,它返回一個程序,版本,協議,和端口值的列表。
PMAPPROC_CALLIT:
這個過程答應調用者調用在同一臺機器上的另一個遠程過程,而不需要知道這個遠程過程的端口號。通過眾所周知的端口映射器的端口號,它支持二進制遠程程序的廣播。參數"prog","vers","proc","args"分別是程序號,版本號,過程號和遠程過程的參數。
注重:
(1)假如過程成功執行,過程僅發送一個響應。否則保持沉默(不響應)。
(2)端口映射器只使用UDP/IP協議與遠程程序通信。
這個過程返回遠程程序的端口號和遠程過程執行的結果。
參考書目
[1]Birrel,A.D.,andNelson,B.J.,"ImplementingRemote
ProcedureCalls",XEROXCSL-83-7,October1983.
[2]Cheriton,D.,"VMTP:VersatileMessageTransactionProtocol",
Version0.7,RFC-1045,StanfordUniversity,February1988.
[3]Diffie&Hellman,"NetDirectionsinCryptography",IEEE
TransactionsonInformationTheoryIT-22,November1976.
[4]Postel,J.,andHarrenstien,K.,"TimeProtocol",RFC-868,
NetworkInformationCenter,SRI,May1983.
[5]NationalBureauofStandards,"DataEncryptionStandard",
FederalInformationProcessingStandardsPublication46,
January1977.
[6]Postel,J.,"TransmissionControlProtocol-DARPAInternet
ProgramProtocolSpecification",RFC-793;NetworkInformation
Center,SRI,September1981.
[7]Postel,J.,"UserDatagramProtocol",RFC-768,Network
InformationCenter,SRI,August1980.
[8]Reynolds,J.andPostel,J.;"AssignedNumbers",RFC-1010,
NetworkInformationCenter,SRI,May1987.
[9]SunMicrosystems;"XDR:ExternalDataRepresentation
Standard",RFC-1014;SunMicrosystems,June1987.
新聞熱點
疑難解答