SlideShare a Scribd company logo
超簡単!


   TELNETの話
   第⼋八回  カーネル/VM探検隊
       2013/4/13(Sat)
          @yogata
ネットワーク
エンジニアの
基本コマンド
telnet
後輩が来た時
先輩!
 TELNETも
知らないんすか
 wwwwww
って
いわれたら
めちゃつらい
そこで
TELNETを
復復習してみた
きょうのおだい
—  第⼀一部:TELNETを調べて分かったこと


—  第⼆二部:TELNETを⾒見見る


—  第三部:telnetを⾒見見る
TELNETは
暗号化出来る
  (↑結論論)
TELNETとは
—  みんな⼤大好きRFC
—  RFC  854  -‐‑‒    TELNET  PROTOCOL  SPECIFICATION
  —  http://tools.ietf.org/html/rfc854

—  RFC  855  -‐‑‒    TELNET  OPTION  SPECIFICATIONS
  —  http://tools.ietf.org/html/rfc855
TELNETとは
—  TELNETの3つの役割  (RFC854)
 1.  “Network  Virtual  Terminal”をつくること
   —  クライアント・サーバはNVTへ⼊入出⼒力力する
   —  コードセット(7bit  USASCII),  標準制御機能(割込,出
       ⼒力力停⽌止,⽂文字削除等)の定義などなど
 2.  セッション確⽴立立時にオプション交換をすること
   —  ネゴシエーションフェーズを経て,ターミナルとプロ
       セスは使う機能を決めることができる
 3.  ターミナルとプロセスで表⽰示内容を同期させること
   —  ターミナルの情報をプロセスに随時通知する
   —  例例えばtelnet上でエディタを開くときに,ターミナル
       はプロセスにターミナルサイズを伝えたいはず(viの論論
       理理⾏行行を決めるにはターミナルサイズが必須)
TELNETとは
—  TELNETの3つの役割  (RFC854)
 1.  “Network  Virtual  Terminal”をつくること
   —  クライアント・サーバはNVTへ⼊入出⼒力力する
   —  コードセット(7bit  USASCII),  標準制御機能(割込,出
       ⼒力力停⽌止,⽂文字削除等)の定義などなど
 2.  セッション確⽴立立時にオプション交換をすること
   —  ネゴシエーションフェーズを経て,ターミナルとプロ
       セスは使う機能を決めることができる
 3.  ターミナルとプロセスで表⽰示内容を同期させること
              これなに?
   —  ターミナルの情報をプロセスに随時通知する
   —  例例えばtelnet上でエディタを開くときに,ターミナル
       はプロセスにターミナルサイズを伝えたいはず(viの論論
       理理⾏行行を決めるにはターミナルサイズが必須)
TELNETネゴシエーション
  —  サーバとクライアントで使⽤用する機能を決める
NAME	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 CODE	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 MEANING	
 
SE	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 240	
 	
 	
 	
 End	
 of	
 subnegotiation	
 parameters.	
 
SB	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 250	
 	
 	
 	
 Indicates	
 that	
 what	
 follows	
 is	
 
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 subnegotiation	
 of	
 the	
 indicated	
 option.	
 
WILL	
 (option	
 code)	
 	
 251	
 	
 	
 	
 Indicates	
 the	
 desire	
 to	
 begin	
                                              使うオプションの宣⾔言
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 performing,	
 or	
 confirmation	
 that	
 
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 you	
 are	
 now	
 performing,	
 the	
          or  DOに対する合意
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 indicated	
 option.	
 
WON'T	
 (option	
 code)	
 252	
 	
 	
 	
 Indicates	
 the	
 refusal	
 to	
 perform,	
 
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 or	
 continue	
 performing,	
 the	
 
                                                                                                                                使わないオプションの宣⾔言
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 indicated	
 option.	
                          or  DONʼ’Tに対する合意
DO	
 (option	
 code)	
 	
 	
 	
 253	
 	
 	
 	
 Indicates	
 the	
 request	
 that	
 the	
 
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 other	
 party	
 perform,	
 or	
 
                                                                                                                                相⼿手に使って欲しい
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 confirmation	
 that	
 you	
 are	
 expecting	
  オプションの宣⾔言
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 the	
 other	
 party	
 to	
 perform,	
 the	
    or  WILLに対する合意
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 indicated	
 option.	
 
DON'T	
 (option	
 code)	
 254	
 	
 	
 	
 Indicates	
 the	
 demand	
 that	
 the	
 
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 other	
 party	
 stop	
 performing,	
 
                                                                                                                                相⼿手に使ってほしくない
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 or	
 confirmation	
 that	
 you	
 are	
 no	
    オプションの宣⾔言
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 longer	
 expecting	
 the	
 other	
 party	
     or  WONʼ’Tに対する合意
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 to	
 perform,	
 the	
 indicated	
 option.	
 
IAC	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 255	
 	
 	
 	
 Data	
 Byte	
 255.
もしかして,
ネゴシエーションで
暗号化機能を合意すれば
使えるのでは???

……でも
独⾃自実装はいやだなあ
TELNETの暗号化
—  TELNETの暗号化はRFC化されている  
 (RFC2946〜~)
 —  RFC2946  -‐‑‒    Telnet  Data  Encryption  Option
     —  暗号化オプションネゴシエーションのコマンドコード,
         暗号化アルゴリズムをネゴシエーションするコード
         の定義
     —  TELNETコマンドコード:38  (0x26)
 —  RFC2947以降降は各暗号化アルゴリズムに関する定義
     —  暗号化アルゴリズムのネゴシエーションは
         SuBnegotiation(0xfa)の中で⾏行行う
パケットヘッダでは
パケット上では  [IAC]  [Command]  [OpCode]の組みが複数連続

                            ・コマンドコード
                            WILL:   251(0xfb)
                            WONʼ’T: 252(0xfc)
                            DO:     253(0xfd)
                            DONʼ’T: 254(0xfe)
                            IAC:    255(0xff)

                            ・オプションコード
                            Authentication:        37(0x25)
                            Encryption:            38(0x26)
                            Suppress  Go  Ahead:   3(0x09)
                            Terminal  Type:        24(0x18)
                                など
パケットヘッダでは
サブネゴシエーションの場合は
[IAC]  [SB]  [OpCode]  [OpType(オプションコード依存)]  [IAC]  [SE]
の順番になる
                                         ・コマンドコード
                                         SE(Subnegotiation  End):
                                                 240(0xf0)
                                         SB(SuBnegotiation):
                                                 250(0xfa)
                                         IAC:    255(0xff)

                                         ・オプションコード
                                         Authentication: 37(0x25)
きょうのおだい
—  第⼀一部:TELNETを調べて分かったこと
 —  TELNETは暗号化出来る


—  第⼆二部:TELNETを⾒見見る


—  第三部:telnetを⾒見見る
TELNETのキャプチャを⾒見見る
—  環境
 —  サーバ:FreeBSDのデフォルトのtelnetd
 —  クライアント:FreeBSDのデフォルトのtelnet
   %  telnet  localhost
シーケンス概要(1)
サーバ                                              クライアント

 No.4  オプションネゴシエーション  [IAC]  [Will/Do]  が
 たくさん                                                   最初のネゴシーエション
 No.5  Do  Authentication  Optionだけ回答
                                                        Suppress  Go  Aheadとか
                                                        単発でネゴシエーションが
 No.7  残りのオプションすべてに回答
       [IAC]  [SB]  [Auth]  [Send]  [RSA],
                                                        終わるのはここで完了了
       [IAC]  [SB]  [Enc]  [Support]  [types…],  …


 No.8  [IAC]  [SB]  [Auth]  [IS]  [RSA]  [Auth],
        [IAC]  [SB]  [Enc]  [Beginstart]
                                                        認証⽅方式のネゴシエーション
        [IAC]  [SB]  [Enc]  [Support]  [types…],…


 No.9  [IAC]  [SB]  [Auth]  [Reply]  [RSA]  [Auth]



 No.11  [IAC]  [SB]  [Auth]  [IS]  [RSA]  [Reject]



 No.12  [IAC]  [SB]  [Auth]  [Reply]  [RSA]  [Accept]
シーケンス概要(2)
サーバ                                               クライアント

 No.14  [IAC]  [SB]  [Auth]  [IS]  [RSA]  [Response]      引き続き
 No.15  [IAC]  [SB]  [Auth]  [Reply]  [RSA]  [Forward],
                                                          認証⽅方式と暗号化⽅方式の
      [IAC]  [SB]  [Enc]  [IS]  [DES_̲CFB64]
                                                          ネゴシエーション
 No.16  [IAC]  [SB]  [Enc]  [IS]  [DES_̲CFB64],
      [IAC]  [WONʼ’T]  [Envoption]
                                                          暗号化⽅方式の
 No.17  [IAC]  [SB]  [Enc]  [Reply]  [DES_̲CFB64],        ネゴシエーション
      [IAC]  [SB]  [Enc]  [ENC_̲KEYID]


 No.18  [IAC]  [SB]  [Enc]  [ENC_̲KEYID]
      [IAC]  [SB]  [Enc]  [DEC_̲KEYID]


 No.19    [IAC]  [SB]  [Enc]  [DEC_̲KEYID],
      [IAC]  [SB]  [Encrypt-‐‑‒Start]


 No.20    [IAC]  [SB]  [Enc]  [Start]


 No.21以降降  コンソールに表⽰示させるデータ
telnet(のsra.c)書いた⼈人が認証フローはこうだよ,
って⽂文章化していたので確かめてみたら,そのとおりだった……!!!
暗号化のシーケンス  (DEC_̲CFB64の場合)  参考:RFC2952/2946
暗号化は⽅方向があるので,双⽅方向でシーケンスが発⽣生する(→⾒見見た⽬目2倍)

Host1                                                                 Host2

                             IAC  DO  ENCRYPT

                            IAC  WILL  ENCRYPT

             IAC  SB  ENCRYPT  SUPPORT  DES_̲CFB64  IAC  SE

         IAC  SB  ENCRYPT  IS  DES_̲CFB64  CFB64_̲IV  <IV>  IAC  SE


        IAC  SB  ENCRYPT  REPLY  DES_̲CFB64  CFB64_̲IV_̲OK  IAC  SE


                     IAC  SB  ENCRYPT  START  IAC  SE
No.4
 クライアントからサーバへ,オプションのネゴシ
 エーションを⾏行行う.

                                 認証
                                暗号化
                                全⼆二重通信
                                端末タイプの指定




Do:  相⼿手(今回はサーバ)に使って
     欲しいオプション
Will:  ⾃自分(今回はクライアント)が
     使いたいオプション
No.5
サーバは認証にだけ  Do  で答える(なぜか)




                           Host1                               Host2
                                        IAC  DO  AUTH
                                       IAC  WILL  AUTH

                              IAC  SB  AUTH  SEND  SRA  IAC  SE
                                     IAC  SB  AUTH  IS  SRA
                                      KEY  <PKA>  IAC  SE
                                   IAC  SB  AUTH  REPLY  SRA
                                     KEY  <PKB>  IAC  SE
                                     IAC  SB  AUTH  IS  SRA
                                    USER<PKA(U)>  IAC  SE
                                   IAC  SB  AUTH  REPLY  SRA
                                      CONTINUE  IAC  SE
                                     IAC  SB  AUTH  IS  SRA
                                    PASS  <PKA(P)>  IAC  SE

                                   IAC  SB  AUTH  REPLY  SRA
                                   [ACCEPT|REJECT]  IAC  SE
No.7
サーバからクライアントへ,最初のネゴシエー
ションに返答する.(すべてDo/Willで返す)




1{                                                     
                                                                             (参考)No.4


                                                                             1{                              
2                                                           
                                                                             2                               
3                                                 
                                                                             3                          
4                                                                       _̲
                                                                             4                                           _̲
5                                                           
                                                                             5                               
6                                                           
7                                                                            6                               
                                                                             7                     
8                                                                
                                                                             8                                    
9                                       
                                                                             9                     
10                                                          
                                                                             10                              
No.7
認証のネゴシエーション.
SRAでの認証を提案.

                          認証⽅方式の提案(SEND)

                      Host1                               Host2
                                   IAC  DO  AUTH
                                  IAC  WILL  AUTH

                         IAC  SB  AUTH  SEND  SRA  IAC  SE
                                IAC  SB  AUTH  IS  SRA
                                 KEY  <PKA>  IAC  SE
                              IAC  SB  AUTH  REPLY  SRA
                                KEY  <PKB>  IAC  SE
                                IAC  SB  AUTH  IS  SRA
                               USER<PKA(U)>  IAC  SE
                              IAC  SB  AUTH  REPLY  SRA
                                 CONTINUE  IAC  SE
                                IAC  SB  AUTH  IS  SRA
                               PASS  <PKA(P)>  IAC  SE

                              IAC  SB  AUTH  REPLY  SRA
                              [ACCEPT|REJECT]  IAC  SE
No.7
暗号化のネゴシエーション.
利利⽤用可能な暗号化⽅方式のリストを通知する.




                          Host1                                      Host2
                                         IAC  DO  ENCRYPT
                                        IAC  WILL  ENCRYPT
                                    IAC  SB  ENCRYPT  SUPPORT
                                        DES_̲CFB64  IAC  SE
                                  IAC  SB  ENCRYPT  IS  DES_̲CFB64
                                       CFB64_̲IV  <IV>  IAC  SE
     暗号化⽅方式の提案(SUPPORT)      IAC  SB  ENCRYPT  REPLY  DES_̲CFB64
     サーバ→クライアントの⽅方向                  CFB64_̲IV_̲OK  IAC  SE
                                     IAC  SB  ENCRYPT  ENC_̲KEYID
                                              keyid  IAC  SE
                                     IAC  SB  ENCRYPT  DEC_̲KEYID
                                              keyid  IAC  SE

                                  IAC  SB  ENCRYPT  START  IAC  SE
No.8
クライアントからサーバへ,合意したオプション
について詳細なパラメータを決めていく




       暗号化⽅方式の提案(SUPPORT)
       クライアント→サーバの⽅方向
No.8の認証のところ
公開鍵を送る.




             Host1                               Host2
                          IAC  DO  AUTH
                         IAC  WILL  AUTH

                IAC  SB  AUTH  SEND  SRA  IAC  SE
                       IAC  SB  AUTH  IS  SRA
                        KEY  <PKA>  IAC  SE
                     IAC  SB  AUTH  REPLY  SRA
                       KEY  <PKB>  IAC  SE
                       IAC  SB  AUTH  IS  SRA
                      USER<PKA(U)>  IAC  SE
                     IAC  SB  AUTH  REPLY  SRA
                        CONTINUE  IAC  SE
                       IAC  SB  AUTH  IS  SRA
                      PASS  <PKA(P)>  IAC  SE

                     IAC  SB  AUTH  REPLY  SRA
                     [ACCEPT|REJECT]  IAC  SE
No.8の暗号化のところ
サポートしている暗号化⽅方式を送る




                    Host1                                      Host2
                                   IAC  DO  ENCRYPT
                                  IAC  WILL  ENCRYPT
                              IAC  SB  ENCRYPT  SUPPORT
                                  DES_̲CFB64  IAC  SE
                            IAC  SB  ENCRYPT  IS  DES_̲CFB64
                                 CFB64_̲IV  <IV>  IAC  SE
                       IAC  SB  ENCRYPT  REPLY  DES_̲CFB64
                               CFB64_̲IV_̲OK  IAC  SE
                               IAC  SB  ENCRYPT  ENC_̲KEYID
                                        keyid  IAC  SE
                               IAC  SB  ENCRYPT  DEC_̲KEYID
                                        keyid  IAC  SE

                            IAC  SB  ENCRYPT  START  IAC  SE
No.9
RSA認証⽅方式のネゴシーエションをする




                       Host1                               Host2
                                    IAC  DO  AUTH
                                   IAC  WILL  AUTH

                          IAC  SB  AUTH  SEND  SRA  IAC  SE
                                 IAC  SB  AUTH  IS  SRA
                                  KEY  <PKA>  IAC  SE
                               IAC  SB  AUTH  REPLY  SRA
                                 KEY  <PKB>  IAC  SE
                                 IAC  SB  AUTH  IS  SRA
                                USER<PKA(U)>  IAC  SE
                               IAC  SB  AUTH  REPLY  SRA
                                  CONTINUE  IAC  SE
                                 IAC  SB  AUTH  IS  SRA
                                PASS  <PKA(P)>  IAC  SE

                               IAC  SB  AUTH  REPLY  SRA
                               [ACCEPT|REJECT]  IAC  SE
No.11
REJECTされる.仕様のUSER(1)が,wiresharkで
REJCT(1)と解釈したためだと考えられる




                               Host1                               Host2
                                            IAC  DO  AUTH
                                           IAC  WILL  AUTH

                                   IAC  SB  AUTH  SEND  SRA  IAC  SE
                                         IAC  SB  AUTH  IS  SRA
                                          KEY  <PKA>  IAC  SE
                                       IAC  SB  AUTH  REPLY  SRA
                                         KEY  <PKB>  IAC  SE
                                         IAC  SB  AUTH  IS  SRA
                                        USER<PKA(U)>  IAC  SE
                                       IAC  SB  AUTH  REPLY  SRA
                                          CONTINUE  IAC  SE
                                         IAC  SB  AUTH  IS  SRA
                                        PASS  <PKA(P)>  IAC  SE

                                       IAC  SB  AUTH  REPLY  SRA
                                       [ACCEPT|REJECT]  IAC  SE
No.12
認証⽅方式のネゴシエーション




                         Host1                               Host2
                                      IAC  DO  AUTH
                                     IAC  WILL  AUTH

                            IAC  SB  AUTH  SEND  SRA  IAC  SE
                                   IAC  SB  AUTH  IS  SRA
                                    KEY  <PKA>  IAC  SE
                                 IAC  SB  AUTH  REPLY  SRA
                                   KEY  <PKB>  IAC  SE
                                   IAC  SB  AUTH  IS  SRA
                                  USER<PKA(U)>  IAC  SE
                                 IAC  SB  AUTH  REPLY  SRA
                                    CONTINUE  IAC  SE
                                   IAC  SB  AUTH  IS  SRA
                                  PASS  <PKA(P)>  IAC  SE

                                 IAC  SB  AUTH  REPLY  SRA
                                 [ACCEPT|REJECT]  IAC  SE
No.14
認証⽅方式の決定




                   Host1                               Host2
                                IAC  DO  AUTH
                               IAC  WILL  AUTH

                      IAC  SB  AUTH  SEND  SRA  IAC  SE
                             IAC  SB  AUTH  IS  SRA
                              KEY  <PKA>  IAC  SE
                           IAC  SB  AUTH  REPLY  SRA
                             KEY  <PKB>  IAC  SE
                             IAC  SB  AUTH  IS  SRA
                            USER<PKA(U)>  IAC  SE
                           IAC  SB  AUTH  REPLY  SRA
                              CONTINUE  IAC  SE
                             IAC  SB  AUTH  IS  SRA
                            PASS  <PKA(P)>  IAC  SE

                           IAC  SB  AUTH  REPLY  SRA
                           [ACCEPT|REJECT]  IAC  SE
No.15
認証⽅方式の決定と暗号化⽅方式の決定
(まずは認証⽅方式)




                      Host1                               Host2
                                   IAC  DO  AUTH
                                  IAC  WILL  AUTH

                         IAC  SB  AUTH  SEND  SRA  IAC  SE
                                IAC  SB  AUTH  IS  SRA
                                 KEY  <PKA>  IAC  SE
                              IAC  SB  AUTH  REPLY  SRA
                                KEY  <PKB>  IAC  SE
                                IAC  SB  AUTH  IS  SRA
                               USER<PKA(U)>  IAC  SE
                              IAC  SB  AUTH  REPLY  SRA
                                 CONTINUE  IAC  SE
                                IAC  SB  AUTH  IS  SRA
                               PASS  <PKA(P)>  IAC  SE

                              IAC  SB  AUTH  REPLY  SRA
                              [ACCEPT|REJECT]  IAC  SE
No.15
認証⽅方式の決定と暗号化⽅方式の決定
(次に暗号化⽅方式)




                                          Host1                                      Host2
                                                         IAC  DO  ENCRYPT
                                                        IAC  WILL  ENCRYPT
                                                    IAC  SB  ENCRYPT  SUPPORT
                                                        DES_̲CFB64  IAC  SE
                                                  IAC  SB  ENCRYPT  IS  DES_̲CFB64
                                                       CFB64_̲IV  <IV>  IAC  SE
                                             IAC  SB  ENCRYPT  REPLY  DES_̲CFB64
                                                     CFB64_̲IV_̲OK  IAC  SE

         1.    Command Names and Codes!              IAC  SB  ENCRYPT  ENC_̲KEYID
              Encryption Type!                                keyid  IAC  SE
                 DES_CFB64        1!                 IAC  SB  ENCRYPT  DEC_̲KEYID
              Suboption Commands!                             keyid  IAC  SE
                 CFB64_IV         1!
                 CFB64_IV_OK      2!              IAC  SB  ENCRYPT  START  IAC  SE
                 CFB64_IV_BAD     3!
No.16
暗号化アルゴリズムの決定




                                          Host1                                      Host2
                                                         IAC  DO  ENCRYPT
                                                        IAC  WILL  ENCRYPT
                                                    IAC  SB  ENCRYPT  SUPPORT
                                                        DES_̲CFB64  IAC  SE
                                                  IAC  SB  ENCRYPT  IS  DES_̲CFB64
                                                       CFB64_̲IV  <IV>  IAC  SE
                                             IAC  SB  ENCRYPT  REPLY  DES_̲CFB64
                                                     CFB64_̲IV_̲OK  IAC  SE
 1.    Command Names and Codes!
      Encryption Type!                               IAC  SB  ENCRYPT  ENC_̲KEYID
         DES_CFB64        1!                                  keyid  IAC  SE
      Suboption Commands!                            IAC  SB  ENCRYPT  DEC_̲KEYID
         CFB64_IV         1!                                  keyid  IAC  SE
         CFB64_IV_OK      2!
         CFB64_IV_BAD     3!                      IAC  SB  ENCRYPT  START  IAC  SE
No.17
暗号化アルゴリズムの決定と鍵交換




                     Host1                                      Host2
                                    IAC  DO  ENCRYPT
                                   IAC  WILL  ENCRYPT
                               IAC  SB  ENCRYPT  SUPPORT
                                   DES_̲CFB64  IAC  SE
                             IAC  SB  ENCRYPT  IS  DES_̲CFB64
                                  CFB64_̲IV  <IV>  IAC  SE
                        IAC  SB  ENCRYPT  REPLY  DES_̲CFB64
                                CFB64_̲IV_̲OK  IAC  SE
                                IAC  SB  ENCRYPT  ENC_̲KEYID
                                         keyid  IAC  SE
                                IAC  SB  ENCRYPT  DEC_̲KEYID
                                         keyid  IAC  SE

                             IAC  SB  ENCRYPT  START  IAC  SE
No.18
鍵交換




              Host1                                      Host2
                             IAC  DO  ENCRYPT
                            IAC  WILL  ENCRYPT
                        IAC  SB  ENCRYPT  SUPPORT
                            DES_̲CFB64  IAC  SE
                      IAC  SB  ENCRYPT  IS  DES_̲CFB64
                           CFB64_̲IV  <IV>  IAC  SE
                 IAC  SB  ENCRYPT  REPLY  DES_̲CFB64
                         CFB64_̲IV_̲OK  IAC  SE
                         IAC  SB  ENCRYPT  ENC_̲KEYID
                                  keyid  IAC  SE
                         IAC  SB  ENCRYPT  DEC_̲KEYID
                                  keyid  IAC  SE

                      IAC  SB  ENCRYPT  START  IAC  SE
No.19
鍵交換と暗号化開始(⽚片⽅方向)




                           Host1                                      Host2
                                          IAC  DO  ENCRYPT
                                         IAC  WILL  ENCRYPT
                                     IAC  SB  ENCRYPT  SUPPORT
                                         DES_̲CFB64  IAC  SE
                                   IAC  SB  ENCRYPT  IS  DES_̲CFB64
                                        CFB64_̲IV  <IV>  IAC  SE
                              IAC  SB  ENCRYPT  REPLY  DES_̲CFB64
                                      CFB64_̲IV_̲OK  IAC  SE
                                      IAC  SB  ENCRYPT  ENC_̲KEYID
                                               keyid  IAC  SE
                                      IAC  SB  ENCRYPT  DEC_̲KEYID
                                               keyid  IAC  SE

                                   IAC  SB  ENCRYPT  START  IAC  SE
No.20
暗号化して通信開始(これで双⽅方向)




                       Host1                                      Host2
                                      IAC  DO  ENCRYPT
                                     IAC  WILL  ENCRYPT
                                 IAC  SB  ENCRYPT  REQUEST
                                        START  IAC  SE
                                 IAC  SB  ENCRYPT  SUPPORT
                                     DES_̲CFB64  IAC  SE
                               IAC  SB  ENCRYPT  IS  DES_̲CFB64
                                    CFB64_̲IV  <IV>  IAC  SE
                          IAC  SB  ENCRYPT  REPLY  DES_̲CFB64
                                  CFB64_̲IV_̲OK  IAC  SE
                                  IAC  SB  ENCRYPT  ENC_̲KEYID
                                           keyid  IAC  SE
                                  IAC  SB  ENCRYPT  DEC_̲KEYID
                                           keyid  IAC  SE

                               IAC  SB  ENCRYPT  START  IAC  SE
with  ENCRYPTION  option      without  ENCRYPTION  option
0x0030:   8..t.L.^....Free!   0x0030:   !....K.Hsr/<..d.!
0x0040:   BSD/amd64.(sage.!   0x0040:   ..C:............!
0x0050:   osaka.remu).(pts!   0x0050:   ...j.r..........!
0x0060:   /3)........Last.!   0x0060:   .M`......4.u...e!
0x0070:   login:.Mon.Apr..!   0x0070:   ....u..u..r.....!
0x0080:   8.23:44:55.from.!   0x0080:   .....aAcU...=...!
0x0090:   localhost..FreeB!   0x0090:   m..n...4.....Q..!
0x00a0:   SD.9.0-RELEASE.(!   0x00a0:   ....A(1...m....b!
0x00b0:   GENERIC).#0:.Tue!   0x00b0:   Yg[.......~HT"..!
0x00c0:   .Jan..3.07:46:30!   0x00c0:   .....5t.x....&.O!
0x00d0:   .UTC.2012..You.h!   0x00d0:   ........T...M...!
0x00e0:   ave.mail.....!..!   0x00e0:   E.0.1.-.#C^n...6!
結論論

TELNETは暗号化できるし
公開鍵暗号で認証もできる

TELNETは平⽂文でしか
通信できない
ちょっと
クイズ
Q.  “ff  fa  26  01  02  ff  f0”はなんでしょう  ?


A.      
   1.  IAC  SB  ENCRYPT  SUPPORT
           DES_̲CFB64  IAC  SE

  2.  IAC  SB  AUTH  SEND  SRA  IAC  SE

  3.  IAC  SB  AUTH  REPLY  SRA  CONTINUE
          IAC  SE
Q.  “ff  fa  26  01  02  ff  f0”はなんでしょう  ?


A.      
   1.  IAC  SB  ENCRYPT  SUPPORT
           DES_̲CFB64  IAC  SE

          よくわからない
  2.  IAC  SB  AUTH  SEND  SRA  IAC  SE

  3.  IAC  SB  AUTH  REPLY  SRA  CONTINUE
          IAC  SE
telnetの
気持ちになって
 考えてみる
きょうのおだい
—  第⼀一部:TELNETを調べて分かったこと
 —  TELNETは暗号化出来る


—  第⼆二部:TELNETを⾒見見る
    —  鍵認証できるし,暗号化も出来る
    —  でも,認証化⽅方式ネゴの途中でREJECTされる
   (なぜか)

—  第三部:telnetを⾒見見る
main.c
                                  main()
 main()                         ・init_̲termnal()→ttyiring/ttyoringの初期化
                                ・init_̲network()→netiring/netoringの初期化
       main.c                   ・init_̲telnet()→シェル環境変数を取得(env_̲init()),
                                 エスケープ⽂文字等の設定など
             tninit()           ・init_̲sys()→標準⼊入出⼒力力を⼊入出⼒力力に設定
                                 (tin=stdin;  tout=stdout;)
sys_̲bsd.c
                                *ringについて
  TerminalSaveState()           ・ring.hで定義される構造体Ringの変数.リングバッ
                                ファと管理理変数
                                ・ネットワークからrecv()したデータや,ネットワー
                                クへsend()するデータ等を保持
         getopt()               ・バッファ,バッファサイズ,リングバッファなので
                                次の受信位置,今処理理している位置のポインタ等
                  command.c
                                  引数が有る場合はこちらを実⾏行行.tn()内で無限
command.c                tn()     ループするので,tn()からcommand()には結果的
                                  に⾏行行かない  (詳細は次ページ)
      command()
                                  引数がない場合はこちらを実⾏行行  
command.c
                                         tn()
 tn()              ・ホスト名の解析.“/”から始まっていたらソケット,”@”か“!”  
                    から始まっていたら”@”か”:”で区切切ってソースルーティング
                   ・サーバに接続する

   telnet.c
                              ・認証・暗号化の初期化
                              ・TELNETオプションの初期ネゴシエーション設定
        telnet()               (send_̲do(option,  1)  /  send_̲will(option,  1))
                               →  netoringに  “IAC  DO/WILL  [option]”  を追加する  
                               (まだ送信しない)  
        telnet.c                   ・netoringの未送信データ,netiringの未処理理データ,
              Scheduler()           ttyoringの未表⽰示データ,netiringの未処理理⼊入⼒力力
                                    データがあるか確認する
                                    (ring_̲full_̲count()  /  ring_̲empty_̲count())
                      sys_̲bsd.c

                        process_̲ring()
                   telnet.c   telrcv()
                                             次ページ以降降
                   telnet.c   telsnd()
main.c
                     telnetクライアント
main()
                                                           →⾒見見てきた所
                   main.c

             tninit()                                      →これから⾒見見る所

sys_̲bsd.c

  TerminalSaveState()

          getopt()            command.c
                                                     telnet.c
 command.c                  tn()          telnet()
         command()                                       telnet.c

                                               Scheduler()              sys_̲bsd.c

                                                                process_̲ring()

                                                                    telrcv()   telnet.c


                                                                    telsnd()   telnet.c
main.c
                     telnetクライアント
main()
                                                           →⾒見見てきた所
                   main.c

             tninit()                                      →これから⾒見見る所



                                                 次はココ
sys_̲bsd.c

  TerminalSaveState()

          getopt()            command.c
                                                     telnet.c
 command.c                  tn()          telnet()
         command()                                       telnet.c

                                               Scheduler()              sys_̲bsd.c

                                                                process_̲ring()

                                                                    telrcv()   telnet.c


                                                                    telsnd()   telnet.c
sys_̲bsd.c
                          process_̲ring()
process_̲ring()

                              [ネットワークからの受信]
                    recv()    ・recv()で受信したデータをnetiringに読み込む
                              ・netdata設定が有効ならダンプ表⽰示する

             sys_̲bsd.c       [ターミナルからの⼊入⼒力力]
             TerminalRead()   ・tin(=stdin)をttyiringに読み込む
                              ・termdata設定が有効ならダンプ表⽰示する

             network.c        [ネットワークへの送信]
                 netflush()    ・暗号化が有効であれば暗号化する
                              ・送信バッファの内容をサーバへ送信する(send())
             termina.c
                 ttyflush()    [ターミナルへの出⼒力力]
                              ・tout(=stdout)に出⼒力力(write())する

戻り値の処理理                       ・netflush()/ttyflush()したバイト数を戻り値に設
                               定する
                              tin/toutは最初の⽅方のinit_̲sys()で
                              tin=stdin;  tout=stdout;  してある
telnetクライアント
main()        main.c
                                                              →⾒見見てきた所

             tninit()   main.c                                →これから⾒見見る所

sys_̲bsd.c

  TerminalSaveState()

         getopt()                command.c
                                                        telnet.c
 command.c                  tn()             telnet()
       command()                                            telnet.c

                                                  Scheduler()              sys_̲bsd.c

                                                                   process_̲ring()


                  次はココ                                                 telrcv()

                                                                       telsnd()
                                                                                  telnet.c

                                                                                  telnet.c
telnet.c
                                    telrcv()
telrcv()             ・未処理理の受信データが無くなるまで処理理する


           decrypt_̲input()         ・暗号化が有効であれば復復号する

                                    ・データ処理理は現在のステータス(telrcv_̲state)
      switch(telrcv_̲state)
                                     に応じて変わるため場合分けする

                      TS_̲CR           ・改⾏行行処理理

                                       ・IACを受け取ればTS_̲IACへ遷移.それ以
                      TS_̲DATA
                                        外は受信データをttyoringへ追加する

                      TS_̲IAC          ・IAC状態なら,受信データに応じて状態を
                                        遷移する

                               WILL/WONT/DO/DONT   ・TS_̲XXXに遷移する

                                       ・サブオプションバッファを初期化して(IAC  
                               SB
                                        SBは⼊入れない),TS_̲SBに遷移する
telnet.cのtelrcv()のところ
                           telrcv()
switch(telrcv_̲state)

                TS_̲WILL   willoption()

                                     encrypt_̲send_̲support()
                                                  暗号化は後回し


               TS_̲WONT    wontoption()
                                              DO  FLOW  CONTROLの
               TS_̲DO      dooption()
                                              ときは端末の再設定を⾏行行う
               TS_̲DONT    dontoption()




                                            この4つはいずれの場合も
                                            最後にTS_̲DATAに遷移する
telnet.cのtelrcv()のところ
                                   telrcv()
switch(telrcv_̲state)

                             ・IACならTS_̲SEにしてIAC  IACかIAC  SEを判断する
              TS_̲SB         ・IAC以外ならサブオプションバッファに追加する


              TS_̲SE

                        IAC  IAC      ・サブオプションバッファにIACを追加して
                                       TS_̲SBに戻す

                                      ・IAC  SEをサブオプションバッファに追加して,
                        IAC  SE
                                       サブオプション処理理をして,TS_̲DATAに戻す.
                  suboption()         次々のページ

                    IAC  IACでも           ・サブオプション処理理をして
                    IAC  SEでもない           TS_̲IACに戻す

                        suboption()    次々のページ
telrcv()
telnet.cのtelrcv()のところ
  switch(telrcv_̲state)


netiringに未処理理のデータ
があれば最初に戻る


                          ・netiringの受信データを処理理したので,リングバッ
   ring_̲consumed()
                           ファの処理理・受信位置のポインタを更更新する
   &戻り値の処理理
                          ・処理理したバイト数を返す
telnet.c
                            telrcv()
suboption()         ・サブオプションバッファはIAC  SBの後のオプションコードか
                     ら⼊入っているので,オプションコードに応じた処理理を⾏行行う
                    ・使いたくないオプションには同意しない
                    ・必要に応じて返答を作成しnetoringに追加する

           TELOPT_̲TTYPE      ・IAC  SB  TTYPE  IS  [termname]  IA  SE
                               をnetoringに追加する

                              ・IAC  SB  TSPEED  IS  [ospeed]  [ispeed]  IA  SE
           TELOPT_̲TSPEED
                               をnetoringに追加する

           TELOPT_̲LFLOW      ・ターミナルを再設定

           TELOPT_̲LINEMODE    ・IAC  SB  LINEMODE  MODE  ACK  IAC  SE
              MODE              をnetoringに追加する

              FORWARDMASK          ・必要に応じて  IAC  SB  LINEMODE  DONʼ’T  
              SLC                   FORWARDMASKをnetoringに追加する

     続きは次のページ                      ・なんか⾊色々
telnet.c
                              telrcv()
suboption()

           TELOPT_̲NEW_̲ENVIRON

              env_̲opt()        ・env_̲opt_̲start()して,環境変数の区切切り毎に
                                 env_̲opt_̲add()する

                 env_̲opt_̲start()     ・ENVIRON⽤用バッファを確保して
                                        IAC  SB  ENV  IS  を⼊入れる

                 env_̲opt_̲add()       ・ENVオプション⽤用バッファ(opt_̲reply)
                                        追加する

                                     ・DISPLAY変数がNULLだったり,異異常に⻑⾧長
                                      かったりしたらWONTにする
           TELOPT_̲XDISPLOC           (下のメッセージが作れないから)
                                     ・使える場合は応答をnetoringに追加する
                                      IAC  SB  XDISPLOC  IS  $DISPLAY  IAC  SE

     続きは次のページ
telnet.c
                                 telrcv()
suboption()

           TELOPT_̲AUTHENTICATION
                      auth.c
              IS               auth_̲is()       (*Authenticator)-‐‑‒>is()
              SEND             auth_̲send()     (*Authenticator)-‐‑‒>send()
              REPLY            auth_̲reply()    (*Authenticator)-‐‑‒>reply()
              NAME             auth_̲name()    ・ユーザ名を取得


続きは後のページ
認証について
telnetがサポートする認証⽅方式はXauthP構造体(Authenticator型)をリス
ト化したauthenticators変数に設定している.
ü  XauthPの詳細  (auth.h)                             初期化・SEND/IS/REPLY時の応答,
  typedef  struct  XauthP  {                        ステータス確認,デバッグ表⽰示が
       int type;            int way;                関数ポインタになっている
       int (*init)(struct  XauthP  *,  int);
       int (*send)(struct  XauthP  *);
       void (*is)(struct  XauthP  *,  unsigned  char  *,  int);
       void (*reply)(struct  XauthP  *,  unsigned  char  *,  int);
       int (*status)(struct  XauthP  *,  char  *,  int);
       void (*printsub)(unsigned  char  *,  int,  unsigned  char  *,  int);
  }  Authenticator;

ü  authenticatorsにSRAを設定しているようす  (auth.c)
  Authenticator  authenticators[]  =  {                                  sra_̲is,
  …                                                                      sra_̲reply,
  #ifdef  SRA                                                            sra_̲status,
    {  AUTHTYPE_̲SRA,                                                    sra_̲printsub  },
          AUTH_̲WHO_̲CLIENT|AUTH_̲HOW_̲ONE_̲WAY,                 #endif
          sra_̲init,
          sra_̲send,
SRAの場合
    キャプチャからSRAであることがわかるので,これに着⽬目して確認する
    telnet.c
    suboption()                                                           Server -> Client は
                                                                          SEND / REPLY だけなので,
                           TELOPT_̲AUTHENTICATION                         IS は省略
Client                               Server         auth.c
               IAC  DO  AUTH                   IS            auth_̲is()
               IAC  WILL  AUTH

    IAC  SB  AUTH  SEND  SRA  IAC  SE
                                                    (*Authenticator)-‐‑‒>is()      sra_̲is()
           IAC  SB  AUTH  IS  SRA
            KEY  <PKA>  IAC  SE
         IAC  SB  AUTH  REPLY  SRA
           KEY  <PKB>  IAC  SE
                                               SEND          auth_̲send()
           IAC  SB  AUTH  IS  SRA
          USER<PKA(U)>  IAC  SE                     (*Authenticator)-‐‑‒>send()    sra_̲send()
         IAC  SB  AUTH  REPLY  SRA
            CONTINUE  IAC  SE
           IAC  SB  AUTH  IS  SRA              REPLY         auth_̲reply()
          PASS  <PKA(P)>  IAC  SE

         IAC  SB  AUTH  REPLY  SRA
         [ACCEPT|REJECT]  IAC  SE
                                                    (*Authenticator)-‐‑‒>reply()   sra_̲reply()
SRAの場合
そういえばtelnet()で認証・暗号化の初期化をしていた.

telnet()
                               サポートしているすべての認証⽅方式で
       auth_̲encrypt_̲init()
                               (*Authenticator)-‐‑‒>init()
                               →  sra_̲init()
                                   sra_̲init()
               auth_̲init()

                                       応答のひな形を
                                       “IAC  SB  AUTH  IS  SRA”
                                       で初期化
                                        pk.c

                                        鍵認証のペアを作成
                                        genkey()


             encrypt_̲init()
sra.c
                             SRAの場合
sra_̲send()             ・サブオプション解析でIAC  SB  AUTH  SENDを受信して
                         いた時に実⾏行行する


              公開鍵を送る
              “IAC    SB    AUTH    IS    SRA    KEY  <PKA>    IAC    SE”
                                                             Client                               Server
                                                                            IAC  DO  AUTH
                                                                          IAC  WILL  AUTH

                                                                 IAC  SB  AUTH  SEND  SRA  IAC  SE
                                                                        IAC  SB  AUTH  IS  SRA
                                                                         KEY  <PKA>  IAC  SE
                                                                      IAC  SB  AUTH  REPLY  SRA
                                                                        KEY  <PKB>  IAC  SE
                                                                        IAC  SB  AUTH  IS  SRA
                                                                       USER<PKA(U)>  IAC  SE
                                                                      IAC  SB  AUTH  REPLY  SRA
                                                                         CONTINUE  IAC  SE
                                                                        IAC  SB  AUTH  IS  SRA
                                                                       PASS  <PKA(P)>  IAC  SE

                                                                      IAC  SB  AUTH  REPLY  SRA
                                                                      [ACCEPT|REJECT]  IAC  SE
sra.c
                         SRAの場合
sra_̲reply()   受信データの解析


         SRA_̲KEY         “IAC  SB  AUTH  REPLY  SRA  KEY  <PKB>  IAC  SE”

                    鍵暗号化された共通鍵
                    <PKB>を抽出                        Client                               Server
                                                                  IAC  DO  AUTH
                                                                 IAC  WILL  AUTH
                <PKB>と秘密鍵(PKA)から
                                                        IAC  SB  AUTH  SEND  SRA  IAC  SE
                共通鍵を取得する
                                                               IAC  SB  AUTH  IS  SRA
                                                                KEY  <PKA>  IAC  SE
                                                             IAC  SB  AUTH  REPLY  SRA
                                                               KEY  <PKB>  IAC  SE
               ユーザ名を共通鍵で暗号化する                                  IAC  SB  AUTH  IS  SRA
               <PKA(U)>                                       USER<PKA(U)>  IAC  SE
                                                             IAC  SB  AUTH  REPLY  SRA
                                                                CONTINUE  IAC  SE
               IAC  SB  AUTH  IS  SRA  USER                    IAC  SB  AUTH  IS  SRA
               <PKA(U)>  IAC  SE                              PASS  <PKA(P)>  IAC  SE

                                                             IAC  SB  AUTH  REPLY  SRA
                                                             [ACCEPT|REJECT]  IAC  SE
続きは次のページ
SRAの場合
                            “IAC  SB  AUTH  REPLY  SRA  CONTINUE
    SRA_̲CONTINUE                IAC  SE”


                                               Client                               Server
                                                             IAC  DO  AUTH
        パスワードを共通鍵で暗号化する
        <PKA(P)>                                            IAC  WILL  AUTH

                                                   IAC  SB  AUTH  SEND  SRA  IAC  SE
                                                          IAC  SB  AUTH  IS  SRA
                                                           KEY  <PKA>  IAC  SE
    “IAC  SB  AUTH  IS  SRA  USER  <PKA(P)>”
                                                        IAC  SB  AUTH  REPLY  SRA
                                                          KEY  <PKB>  IAC  SE
                                                          IAC  SB  AUTH  IS  SRA
                                                         USER<PKA(U)>  IAC  SE
                                                        IAC  SB  AUTH  REPLY  SRA
                                                           CONTINUE  IAC  SE
                                                          IAC  SB  AUTH  IS  SRA
                                                         PASS  <PKA(P)>  IAC  SE

                                                        IAC  SB  AUTH  REPLY  SRA
                                                        [ACCEPT|REJECT]  IAC  SE
続きは次のページ
telnet.c
                             telrcv()
suboption()                                  戻ってtelnet.cのsuboption()の続き

           TELOPT_̲ENCRYPT
                                  encrypt.c
              START       encrypt_̲start()     ・復復号⽤用の関数ポインタを設定
              END         encrypt_̲end()       ・復復号⽤用の関数ポインタを削除

              SUPPORT     encrypt_̲support()       (*Encryptions)-‐‑‒>start()
                               ・IAC  SB  ENCRYPT  SUPPORT  <encrypt-‐‑‒list>
                                のうち最初にサポートしている⽅方式を採⽤用


              REQSTART     encrypt_̲request_̲start()    encrypt_̲start_̲output()
               ・IAC  SB  ENCRYPT  START  [key]  IAC  SEをnetoringに書き込
                み,暗号化⽤用の関数ポインタを設定
              REQEND       encrypt_̲request_̲end()      encrypt_̲send_̲end()
   続きは
              ・IAC  SB  ENCRYPT  END  IAC  SEをnetoringに書き込み,暗号
  次ページ
               化⽤用の関数ポインタを削除(0にする)
telnet.c
                             telrcv()
suboption()

           TELOPT_̲ENCRYPT

              IS           encrypt_̲is()        (*Encryptions)-‐‑‒>is()
              REPLY        encrypt_̲reply()     (*Encryptions)-‐‑‒>reply()
                             encrypt.c
              ENC_̲KEYID     encrypt_̲enc_̲keyid()
              DEC_̲KEYID     encrypt_̲dec_̲keyid()

                                                     encrypt_keyid()

                                              encrypt_̲start_̲output()
                                                       ・REQSTARTの時と同じ

     ・IAC  SB  ENCRYPT  START  [key]  IAC  SEをnetoringに
      書き込み,暗号化⽤用の関数ポインタを設定
暗号化について
telnetがサポートする暗号化⽅方式はEncryptions構造体(Encryptions型)を
リスト化したencryptions変数に設定している.
ü  Encryptionsの詳細  (encrypt.h)
  typedef  struct  {
       const  char  *name;      int type;
       void (*output)(unsigned  char  *,  int);
                                                       認証のAuthenticatorsと同様に,
       int (*input)(int);                              関数ポインタになっている
       void (*init)(int);
       int (*start)(int,  int);
       int (*is)(unsigned  char  *,  int);
       int (*reply)(unsigned  char  *,  int);
       void (*session)(Session_̲Key  *,  int);
       int (*keyid)(int,  unsigned  char  *,  int  *);
       void (*printsub)(unsigned  char  *,  int,  unsigned  char  *,  int);
  }  Encryptions;
ü  encryptionsに設定しているようす  (auth.c)
  static  Encryptions  encryptions[]  =  {                 cfb64_̲is,
          {  "DES_̲CFB64", ENCTYPE_̲DES_̲CFB64,            cfb64_̲reply,
          cfb64_̲encrypt,                                  cfb64_̲session,
          cfb64_̲decrypt,                                  cfb64_̲keyid,
          cfb64_̲init,                                     cfb64_̲printsub  },
          cfb64_̲start,
DES_̲CFB64の場合
キャプチャからDEC_̲CFB64であることがわかるので,これに着⽬目して確
認する

telnet.c
telrcv()             ・未処理理の受信データが無くなるまで処理理する

           decrypt_̲input()    ・暗号化が有効であれば復復号する

                               ・データ処理理は現在のステータス(telrcv_̲state)
      switch(telrcv_̲state)
                                に応じて変わるため場合分けする

                        TS_̲WILL   willoption()

                                             encrypt_̲send_̲support()
                                                      後回しにしたアレ
TS_̲SE

suboption()
                                                                cfb64_̲start()
           TELOPT_̲ENCRYPT

              SUPPORT      encrypt_̲support()        (*Encryptions)-‐‑‒>start()

                                                                 cfb64_̲is()

              IS            encrypt_̲is()         (*Encryptions)-‐‑‒>is()
              REPLY         encrypt_̲reply()      (*Encryptions)-‐‑‒>reply()
                             encrypt.c
              ENC_̲KEYID     encrypt_̲enc_̲keyid()                cfb64_̲reply()
              DEC_̲KEYID     encrypt_̲dec_̲keyid()


                                                   encrypt_keyid()

                                               encrypt_̲start_̲output()
DES_̲CFB64の場合
そういえばtelnet()で認証・暗号化の初期化をしていた.

telnet()

       auth_̲encrypt_̲init()

               auth_̲init()

              encrypt_̲init()
                         SUPPORTメッセージを作成:
                         IAC  SB  ENCRYPT  SUPPORT  <encrypt-‐‑‒list>  IAC  SE

                          サポートしているすべての暗号化⽅方式で
                          (*Encryptions)-‐‑‒>init()  → cfb64_̲init()
                                    厳密にはENCRYPT_̲DES_̲CFB64
                  応答のひな形を設定:  [X]  [X]  [X]  [X]  DES_̲CFB64
                                                     enc_̲des.c
   応答のひな形を設定:
                                                     fb64_̲init()
   IAC    SB    ENCRYPT    IS    DES_̲CFB64
telnet.c
                           DES_̲CFB64の場合
   telrcv()

                decrypt_̲input()

            switch(telrcv_̲state)

                                   TS_̲WILL          willoption()
Host1                                      Host2               encrypt.c
               IAC  DO  ENCRYPT
                                                               encrypt_̲send_̲support()
              IAC  WILL  ENCRYPT
          IAC  SB  ENCRYPT  SUPPORT
              DES_̲CFB64  IAC  SE
        IAC  SB  ENCRYPT  IS  DES_̲CFB64
             CFB64_̲IV  <IV>  IAC  SE              さっき作ったSUPPORTメッセージを
   IAC  SB  ENCRYPT  REPLY  DES_̲CFB64             netoringに書き込む
           CFB64_̲IV_̲OK  IAC  SE                  IAC  SB  ENCRYPT  SUPPORT  <encrypt-‐‑‒list>  IAC  SE
           IAC  SB  ENCRYPT  ENC_̲KEYID
                    keyid  IAC  SE
           IAC  SB  ENCRYPT  DEC_̲KEYID
                    keyid  IAC  SE

        IAC  SB  ENCRYPT  START  IAC  SE
enc_̲des.c
                 DES_̲CFB64の場合
cfb64_̲start()

        fb64_̲start()

                 DIR_̲DECRYPT

             stateがFAILEDなら
             IN_̲PROGRESSにする                     Host1                                      Host2
                                                                IAC  DO  ENCRYPT

                 DIR_̲ENCRYPT                                  IAC  WILL  ENCRYPT
                                                           IAC  SB  ENCRYPT  SUPPORT
                                                               DES_̲CFB64  IAC  SE
                 DESのIVを作る                               IAC  SB  ENCRYPT  IS  DES_̲CFB64
                                                              CFB64_̲IV  <IV>  IAC  SE

  送信データの作成:                                         IAC  SB  ENCRYPT  REPLY  DES_̲CFB64
                                                            CFB64_̲IV_̲OK  IAC  SE
  IAC    SB    ENCRYPT    IS    DES_̲CFB64                  IAC  SB  ENCRYPT  ENC_̲KEYID
  CFB64_̲IV    <IV>    IAC    SE                                     keyid  IAC  SE
                                                            IAC  SB  ENCRYPT  DEC_̲KEYID
                                                                     keyid  IAC  SE
              netoringに書き込む                              IAC  SB  ENCRYPT  START  IAC  SE
enc_̲des.c
                    DES_̲CFB64の場合
cfb64_̲is()

       fb64_̲is()

               FB64_̲IS
                          fb64_̲stream_̲iv()
                                                        Host1                                      Host2
              送信データの作成:                                                IAC  DO  ENCRYPT
              IAC    SB    ENCRYPT    REPLY    
                                                                      IAC  WILL  ENCRYPT
              DES_̲CFB64    FB64_̲IV_̲OK    IAC    SE
                                                                  IAC  SB  ENCRYPT  SUPPORT
                                                                      DES_̲CFB64  IAC  SE
                                                                IAC  SB  ENCRYPT  IS  DES_̲CFB64
                         netoringに書き込む                               CFB64_̲IV  <IV>  IAC  SE
                                                           IAC  SB  ENCRYPT  REPLY  DES_̲CFB64
                                                                   CFB64_̲IV_̲OK  IAC  SE
                                                                   IAC  SB  ENCRYPT  ENC_̲KEYID
                                                                            keyid  IAC  SE
               それ以外
                                                                   IAC  SB  ENCRYPT  DEC_̲KEYID
                                                                            keyid  IAC  SE
                          エラー表⽰示
                                                                IAC  SB  ENCRYPT  START  IAC  SE
enc_̲des.c
                 DES_̲CFB64の場合
cfb64_̲reply()
                                            送信データの作成:
       fb64_̲reply()                        IAC    SB    ENCRYPT    
                                            ENCRYPT_̲ENC_̲KEYID    0    IAC    SE
             FB64_̲IV_̲OK

                       fb64_̲stream_̲iv()          netoringに書き込む
                                               Host1                                      Host2
                 encrypt_̲send_̲keyid()                       IAC  DO  ENCRYPT
                                                             IAC  WILL  ENCRYPT
                                                         IAC  SB  ENCRYPT  SUPPORT
                                                             DES_̲CFB64  IAC  SE
                                                       IAC  SB  ENCRYPT  IS  DES_̲CFB64
             FB64_̲IV_̲BAD                                  CFB64_̲IV  <IV>  IAC  SE
                                                   IAC  SB  ENCRYPT  REPLY  DES_̲CFB64
                   fb64_̲stream_̲iv                        CFB64_̲IV_̲OK  IAC  SE
                                                          IAC  SB  ENCRYPT  ENC_̲KEYID
                                                                   keyid  IAC  SE
             それ以外                                         IAC  SB  ENCRYPT  DEC_̲KEYID
                                                                   keyid  IAC  SE
                   エラー表⽰示
                                                       IAC  SB  ENCRYPT  START  IAC  SE
telnetクライアント
main()        main.c
                                                               →⾒見見てきた所

             tninit()   main.c                                 →これから⾒見見る所



                                             ⻑⾧長かった
sys_̲bsd.c

  TerminalSaveState()

         getopt()                command.c
                                                         telnet.c
 command.c                  tn()              telnet()
       command()                                             telnet.c

                                                   Scheduler()              sys_̲bsd.c

                                                                    process_̲ring()


                  次はココ                                                  telrcv()

                                                                        telsnd()
                                                                                   telnet.c

                                                                                   telnet.c
telnet.c
                           telsnd()
                   ・ttyiringの中⾝身をnetoringに処理理&コピーする
 telsnd()
                    (※send()しない)
                                   無い
             netoringの空きある?
                 ある
               未処理理ttyiring した          もう⼀一回確認しても未処理理無し?
               全部処理理した?                  (ring_̲full_̲consecutive())   なかった
                      まだ                       あった


            ttyiringから1バイト取得
                           y
                 制御⽂文字?             command()
                    n
                               n
              BINARYモード?            改⾏行行をエスケープ
                    y

・IAC(0xff)なら,IAC  IACをnetoringに追加                              処理理したバイト数を
 (0xffは0xff  0xffにエスケープが必要)                                      戻り値にして終了了
・それ以外なら,そのままnetoringに追加
telnetクライアント
main()        main.c
                                                              →⾒見見てきた所

             tninit()   main.c                                →これから⾒見見る所

sys_̲bsd.c

  TerminalSaveState()

         getopt()                command.c
                                                        telnet.c
 command.c                  tn()             telnet()
       command()                                            telnet.c

                                                  Scheduler()              sys_̲bsd.c

                                                                   process_̲ring()


                  次はココ                                                 telrcv()

                                                                       telsnd()
                                                                                  telnet.c

                                                                                  telnet.c
command.c
                           command()
command(int  top,  const  char  *tbuf,  int  cnt)

                           y
       tbuf  ==  NULL  ?       標準⼊入⼒力力から1⾏行行読み込む
                n
                                                    引数無しでtelnetを実⾏行行した
                                                    ときはこっちに来る
      作業領領域にコピー



     ⼊入⼒力力コマンドを探す
          getcmd()
                                      完全⼀一致  or             部分⼀一致・完全⼀一致が
                                      部分⼀一致が1つ              1つもない
     部分⼀一致が
      2つ以上
  “?Ambiguous  command”          (*Command)-‐‑‒>handler()   “?Invalid  command”
telnetクライアントコマンド
telnetクライアント上のコマンドはCommand構造体でリスト化して保持
している(cmdtab変数)
ü  Command構造体の詳細  (command.c)
  typedef struct {
                                                            各コマンドで⾏行行される内容は関
      const char *name; /* command name */           数ポインタになっている
      const char *help; /* help string (NULL for no help) */
      int (*handler)(int, char **); /* routine which executes command */
      int needconnect; /* Do we need to be connected to execute? */
  } Command;

ü  encryptionsに設定しているようす  (auth.c)
  static  Command  cmdtab[]  =  {
          {  "close",     closehelp,     bye,                                 1  },
          {  "logout",    logouthelp,    (int  (*)(int,  char  **))logout,    1  },
          {  "display",   displayhelp,   display,                             0  },
          {  "mode",      modestring,    modecmd,                             0  },
          {  "telnet",    openhelp,      tn,                                  0  },
          {  "open",      openhelp,      tn,                                  0  },
          {  "quit",      quithelp,      (int  (*)(int,  char  **))quit,      0  },
          {  "send",      sendhelp,      sendcmd,                             0  },
          …
                                         (*Command)-‐‑‒>handler()
telnetクライアントコマンド
static  Command  cmdtab[]  =  {
        {  "close",     closehelp,     bye,                                 1  },
        {  "logout",    logouthelp,    (int  (*)(int,  char  **))logout,    1  },
        {  "display",   displayhelp,   display,                             0  },
        {  "mode",      modestring,    modecmd,                             0  },
        {  "telnet",    openhelp,      tn,                                  0  },
        {  "open",      openhelp,      tn,                                  0  },
        {  "quit",      quithelp,      (int  (*)(int,  char  **))quit,      0  },
        {  "send",      sendhelp,      sendcmd,                             0  },
        …
                                       (*Command)-‐‑‒>handler()




% telnet!                                                        % telnet 192.168.1.1!
                                                    同じ
telnet> open 192.168.1.1!

引数無しなのでcommand()にいって,                                           引数ありなのでtn()で処理される
openコマンドのハンドラtn()で処理される
まとめ
TELNETは
 超簡単!
超簡単!TELNETの話
(参考)
—  TELNETがソースルーティングするところ
—  コマンドとパケットキャプチャから動作を確認する
command.c

tn()               ・ホスト名の解析.“/”から始まっていたらソケット,”@”  or  “!”  
                    から始まっていたら”@”か”:”で区切切ってソースルーティング
   telnet.c        ・サーバに接続する
     telnet()

       telnet.c

           Scheduler()
                     sys_̲bsd.c

                       process_̲ring()
                  telnet.c   telrcv()
                                         次ページ以降降
                  telnet.c   telsnd()
Loose  Source  Routing
—  ホスト名をʼ’@ʼ’から初めて,ʼ’@ʼ’区切切りにすると,
 Loose  Source  RoutingのIPオプション付きパケットを
 送信する

 > telnet @10.3.3.1@10.4.4.4@10.5.5.5@10.6.6.6@10.7.7.7!
Strict  Source  Routing
—  ホスト名をʼ’!ʼ’から初めて,ʼ’@ʼ’区切切りにすると,
 Loose  Source  RoutingのIPオプション付きパケットを
 送信する

 > telnet !@10.3.3.1@10.1.1.1@10.2.2.2@10.3.3.3@10.4.4.4!
しくみ
                           if (hostp[0] == '/') {
                             (ソケットだった時の処理)
          tn()
                           } else if (hostp[0] == '@' || hostp[0] == '!') {
                                 if ((hostname = strrchr(hostp, ':')) == NULL)
                                     hostname = strrchr(hostp, '@');
                                 if (hostname == NULL) {
                                     hostname = hostp;
 引数からソケット(ʻ‘/ʼ’)か                } else {
ソースルート(ʻ‘!ʼ’  か  ʻ‘@ʼ’)か             hostname++;
  ホスト名かを判断する                         srcroute = 1;
                                 }
                               } else
                                   hostname = hostp;
                                                        hostpからソースルートの
                            if (srcroute != 0) {          IPオプションヘッダを
    ソースルートなら                                               作って,srpに⼊入れる
                           ….
   sourceroute()する
                                 result = sourceroute(res, hostp,
                                       &srp, &srlen, &proto, &opt);
作ったソースルートのIPオ              if (srp && setsockopt(net, proto, opt,
プションヘッダを設定する               (char *)srp, srlen) < 0) {
初期化してない*lenp  (tn()では&srlen)
sourceroute()                    に対して  if(*lenp  <  7)  return  -‐‑‒1;
                                 してる気がする……
                    引数をチェック
                (⻑⾧長さが不不正に短くない
                      こととか)               if (*cp == '!') {
                                               cp++;
                                               *lsrp++ = IPOPT_SSRR;
     ソースルーティングのIP  Option作成               } else
     ・ʼ’!ʼ’  から始まっていたら  SSRRを設定                *lsrp++ = IPOPT_LSRR;
     ・ʼ’@ʼ’から始まっていたらLSRRを設定
     ・それ以外だったら終了了する                       if (*cp != '@')
                                               return -1;


     ・pointer(=4)を埋める
     ・ホスト名をʼ’@ʼ’とʼ’:ʼ’で区切切って埋める            詳細は次ページ
     ・ソースルーティングのIP  Option⻑⾧長を決
      めて,length埋める
> telnet !@10.3.3.1@10.1.1.1@10.2.2.2@10.3.3.3@10.4.4.4!
                                  @区切りのホスト名から
     cpの初期位置は                     ソースルーティングのIPオプション付きパケットを作る
     ホスト名の先頭’1’
     (‘@’の次)

for (c = 0;;) {
      for (cp2 = cp; (c = *cp2); cp2++) {
            if (c == ',') {
                  *cp2++ = '0';
                  if (*cp2 == '@')
                        cp2++;
            } else if (c == '@') {
                  *cp2++ = '0’
            } else if (c == ':') {
                  *cp2++ = '0';
            } else                                 ‘@’と’:’の区切り位置を探して
                  continue;                        区切り位置を’0にする
            break;                                 →次にgetaddrinfo()に渡すため
      }
      error = getaddrinfo(cp, NULL, &hints, &res);
      _sin = (struct sockaddr_in *)res->ai_addr;         IP Optionに埋める
      memcpy(lsrp, (char *)&_sin->sin_addr, 4);
      lsrp += 4;
      cp = cp2;
}                                              次を探す

More Related Content

超簡単!TELNETの話

  • 1. 超簡単! TELNETの話 第⼋八回  カーネル/VM探検隊 2013/4/13(Sat) @yogata
  • 11. TELNETとは —  みんな⼤大好きRFC —  RFC  854  -‐‑‒    TELNET  PROTOCOL  SPECIFICATION —  http://tools.ietf.org/html/rfc854 —  RFC  855  -‐‑‒    TELNET  OPTION  SPECIFICATIONS —  http://tools.ietf.org/html/rfc855
  • 12. TELNETとは —  TELNETの3つの役割  (RFC854) 1.  “Network  Virtual  Terminal”をつくること —  クライアント・サーバはNVTへ⼊入出⼒力力する —  コードセット(7bit  USASCII),  標準制御機能(割込,出 ⼒力力停⽌止,⽂文字削除等)の定義などなど 2.  セッション確⽴立立時にオプション交換をすること —  ネゴシエーションフェーズを経て,ターミナルとプロ セスは使う機能を決めることができる 3.  ターミナルとプロセスで表⽰示内容を同期させること —  ターミナルの情報をプロセスに随時通知する —  例例えばtelnet上でエディタを開くときに,ターミナル はプロセスにターミナルサイズを伝えたいはず(viの論論 理理⾏行行を決めるにはターミナルサイズが必須)
  • 13. TELNETとは —  TELNETの3つの役割  (RFC854) 1.  “Network  Virtual  Terminal”をつくること —  クライアント・サーバはNVTへ⼊入出⼒力力する —  コードセット(7bit  USASCII),  標準制御機能(割込,出 ⼒力力停⽌止,⽂文字削除等)の定義などなど 2.  セッション確⽴立立時にオプション交換をすること —  ネゴシエーションフェーズを経て,ターミナルとプロ セスは使う機能を決めることができる 3.  ターミナルとプロセスで表⽰示内容を同期させること これなに? —  ターミナルの情報をプロセスに随時通知する —  例例えばtelnet上でエディタを開くときに,ターミナル はプロセスにターミナルサイズを伝えたいはず(viの論論 理理⾏行行を決めるにはターミナルサイズが必須)
  • 14. TELNETネゴシエーション —  サーバとクライアントで使⽤用する機能を決める NAME CODE MEANING SE 240 End of subnegotiation parameters. SB 250 Indicates that what follows is subnegotiation of the indicated option. WILL (option code) 251 Indicates the desire to begin 使うオプションの宣⾔言 performing, or confirmation that you are now performing, the or  DOに対する合意 indicated option. WON'T (option code) 252 Indicates the refusal to perform, or continue performing, the 使わないオプションの宣⾔言 indicated option. or  DONʼ’Tに対する合意 DO (option code) 253 Indicates the request that the other party perform, or 相⼿手に使って欲しい confirmation that you are expecting オプションの宣⾔言 the other party to perform, the or  WILLに対する合意 indicated option. DON'T (option code) 254 Indicates the demand that the other party stop performing, 相⼿手に使ってほしくない or confirmation that you are no オプションの宣⾔言 longer expecting the other party or  WONʼ’Tに対する合意 to perform, the indicated option. IAC 255 Data Byte 255.
  • 16. TELNETの暗号化 —  TELNETの暗号化はRFC化されている   (RFC2946〜~) —  RFC2946  -‐‑‒    Telnet  Data  Encryption  Option —  暗号化オプションネゴシエーションのコマンドコード, 暗号化アルゴリズムをネゴシエーションするコード の定義 —  TELNETコマンドコード:38  (0x26) —  RFC2947以降降は各暗号化アルゴリズムに関する定義 —  暗号化アルゴリズムのネゴシエーションは SuBnegotiation(0xfa)の中で⾏行行う
  • 17. パケットヘッダでは パケット上では  [IAC]  [Command]  [OpCode]の組みが複数連続 ・コマンドコード WILL: 251(0xfb) WONʼ’T: 252(0xfc) DO:   253(0xfd) DONʼ’T: 254(0xfe) IAC:   255(0xff) ・オプションコード Authentication:   37(0x25) Encryption:     38(0x26) Suppress  Go  Ahead: 3(0x09) Terminal  Type:   24(0x18) など
  • 18. パケットヘッダでは サブネゴシエーションの場合は [IAC]  [SB]  [OpCode]  [OpType(オプションコード依存)]  [IAC]  [SE] の順番になる ・コマンドコード SE(Subnegotiation  End):   240(0xf0) SB(SuBnegotiation):   250(0xfa) IAC:   255(0xff) ・オプションコード Authentication: 37(0x25)
  • 19. きょうのおだい —  第⼀一部:TELNETを調べて分かったこと —  TELNETは暗号化出来る —  第⼆二部:TELNETを⾒見見る —  第三部:telnetを⾒見見る
  • 20. TELNETのキャプチャを⾒見見る —  環境 —  サーバ:FreeBSDのデフォルトのtelnetd —  クライアント:FreeBSDのデフォルトのtelnet %  telnet  localhost
  • 21. シーケンス概要(1) サーバ クライアント No.4  オプションネゴシエーション  [IAC]  [Will/Do]  が たくさん 最初のネゴシーエション No.5  Do  Authentication  Optionだけ回答 Suppress  Go  Aheadとか 単発でネゴシエーションが No.7  残りのオプションすべてに回答 [IAC]  [SB]  [Auth]  [Send]  [RSA], 終わるのはここで完了了 [IAC]  [SB]  [Enc]  [Support]  [types…],  … No.8  [IAC]  [SB]  [Auth]  [IS]  [RSA]  [Auth], [IAC]  [SB]  [Enc]  [Beginstart] 認証⽅方式のネゴシエーション [IAC]  [SB]  [Enc]  [Support]  [types…],… No.9  [IAC]  [SB]  [Auth]  [Reply]  [RSA]  [Auth] No.11  [IAC]  [SB]  [Auth]  [IS]  [RSA]  [Reject] No.12  [IAC]  [SB]  [Auth]  [Reply]  [RSA]  [Accept]
  • 22. シーケンス概要(2) サーバ クライアント No.14  [IAC]  [SB]  [Auth]  [IS]  [RSA]  [Response] 引き続き No.15  [IAC]  [SB]  [Auth]  [Reply]  [RSA]  [Forward], 認証⽅方式と暗号化⽅方式の [IAC]  [SB]  [Enc]  [IS]  [DES_̲CFB64] ネゴシエーション No.16  [IAC]  [SB]  [Enc]  [IS]  [DES_̲CFB64], [IAC]  [WONʼ’T]  [Envoption] 暗号化⽅方式の No.17  [IAC]  [SB]  [Enc]  [Reply]  [DES_̲CFB64], ネゴシエーション [IAC]  [SB]  [Enc]  [ENC_̲KEYID] No.18  [IAC]  [SB]  [Enc]  [ENC_̲KEYID] [IAC]  [SB]  [Enc]  [DEC_̲KEYID] No.19    [IAC]  [SB]  [Enc]  [DEC_̲KEYID], [IAC]  [SB]  [Encrypt-‐‑‒Start] No.20    [IAC]  [SB]  [Enc]  [Start] No.21以降降  コンソールに表⽰示させるデータ
  • 24. 暗号化のシーケンス  (DEC_̲CFB64の場合)  参考:RFC2952/2946 暗号化は⽅方向があるので,双⽅方向でシーケンスが発⽣生する(→⾒見見た⽬目2倍) Host1 Host2 IAC  DO  ENCRYPT IAC  WILL  ENCRYPT IAC  SB  ENCRYPT  SUPPORT  DES_̲CFB64  IAC  SE IAC  SB  ENCRYPT  IS  DES_̲CFB64  CFB64_̲IV  <IV>  IAC  SE IAC  SB  ENCRYPT  REPLY  DES_̲CFB64  CFB64_̲IV_̲OK  IAC  SE IAC  SB  ENCRYPT  START  IAC  SE
  • 25. No.4 クライアントからサーバへ,オプションのネゴシ エーションを⾏行行う. 認証 暗号化 全⼆二重通信 端末タイプの指定 Do:  相⼿手(今回はサーバ)に使って 欲しいオプション Will:  ⾃自分(今回はクライアント)が 使いたいオプション
  • 26. No.5 サーバは認証にだけ  Do  で答える(なぜか) Host1 Host2 IAC  DO  AUTH IAC  WILL  AUTH IAC  SB  AUTH  SEND  SRA  IAC  SE IAC  SB  AUTH  IS  SRA KEY  <PKA>  IAC  SE IAC  SB  AUTH  REPLY  SRA KEY  <PKB>  IAC  SE IAC  SB  AUTH  IS  SRA USER<PKA(U)>  IAC  SE IAC  SB  AUTH  REPLY  SRA CONTINUE  IAC  SE IAC  SB  AUTH  IS  SRA PASS  <PKA(P)>  IAC  SE IAC  SB  AUTH  REPLY  SRA [ACCEPT|REJECT]  IAC  SE
  • 27. No.7 サーバからクライアントへ,最初のネゴシエー ションに返答する.(すべてDo/Willで返す) 1{             (参考)No.4 1{             2             2             3           3           4                  _̲ 4                  _̲ 5             5             6             7         6             7         8               8               9         9         10             10            
  • 28. No.7 認証のネゴシエーション. SRAでの認証を提案. 認証⽅方式の提案(SEND) Host1 Host2 IAC  DO  AUTH IAC  WILL  AUTH IAC  SB  AUTH  SEND  SRA  IAC  SE IAC  SB  AUTH  IS  SRA KEY  <PKA>  IAC  SE IAC  SB  AUTH  REPLY  SRA KEY  <PKB>  IAC  SE IAC  SB  AUTH  IS  SRA USER<PKA(U)>  IAC  SE IAC  SB  AUTH  REPLY  SRA CONTINUE  IAC  SE IAC  SB  AUTH  IS  SRA PASS  <PKA(P)>  IAC  SE IAC  SB  AUTH  REPLY  SRA [ACCEPT|REJECT]  IAC  SE
  • 29. No.7 暗号化のネゴシエーション. 利利⽤用可能な暗号化⽅方式のリストを通知する. Host1 Host2 IAC  DO  ENCRYPT IAC  WILL  ENCRYPT IAC  SB  ENCRYPT  SUPPORT DES_̲CFB64  IAC  SE IAC  SB  ENCRYPT  IS  DES_̲CFB64 CFB64_̲IV  <IV>  IAC  SE 暗号化⽅方式の提案(SUPPORT) IAC  SB  ENCRYPT  REPLY  DES_̲CFB64 サーバ→クライアントの⽅方向 CFB64_̲IV_̲OK  IAC  SE  IAC  SB  ENCRYPT  ENC_̲KEYID keyid  IAC  SE  IAC  SB  ENCRYPT  DEC_̲KEYID keyid  IAC  SE IAC  SB  ENCRYPT  START  IAC  SE
  • 31. No.8の認証のところ 公開鍵を送る. Host1 Host2 IAC  DO  AUTH IAC  WILL  AUTH IAC  SB  AUTH  SEND  SRA  IAC  SE IAC  SB  AUTH  IS  SRA KEY  <PKA>  IAC  SE IAC  SB  AUTH  REPLY  SRA KEY  <PKB>  IAC  SE IAC  SB  AUTH  IS  SRA USER<PKA(U)>  IAC  SE IAC  SB  AUTH  REPLY  SRA CONTINUE  IAC  SE IAC  SB  AUTH  IS  SRA PASS  <PKA(P)>  IAC  SE IAC  SB  AUTH  REPLY  SRA [ACCEPT|REJECT]  IAC  SE
  • 32. No.8の暗号化のところ サポートしている暗号化⽅方式を送る Host1 Host2 IAC  DO  ENCRYPT IAC  WILL  ENCRYPT IAC  SB  ENCRYPT  SUPPORT DES_̲CFB64  IAC  SE IAC  SB  ENCRYPT  IS  DES_̲CFB64 CFB64_̲IV  <IV>  IAC  SE IAC  SB  ENCRYPT  REPLY  DES_̲CFB64 CFB64_̲IV_̲OK  IAC  SE  IAC  SB  ENCRYPT  ENC_̲KEYID keyid  IAC  SE  IAC  SB  ENCRYPT  DEC_̲KEYID keyid  IAC  SE IAC  SB  ENCRYPT  START  IAC  SE
  • 33. No.9 RSA認証⽅方式のネゴシーエションをする Host1 Host2 IAC  DO  AUTH IAC  WILL  AUTH IAC  SB  AUTH  SEND  SRA  IAC  SE IAC  SB  AUTH  IS  SRA KEY  <PKA>  IAC  SE IAC  SB  AUTH  REPLY  SRA KEY  <PKB>  IAC  SE IAC  SB  AUTH  IS  SRA USER<PKA(U)>  IAC  SE IAC  SB  AUTH  REPLY  SRA CONTINUE  IAC  SE IAC  SB  AUTH  IS  SRA PASS  <PKA(P)>  IAC  SE IAC  SB  AUTH  REPLY  SRA [ACCEPT|REJECT]  IAC  SE
  • 34. No.11 REJECTされる.仕様のUSER(1)が,wiresharkで REJCT(1)と解釈したためだと考えられる Host1 Host2 IAC  DO  AUTH IAC  WILL  AUTH IAC  SB  AUTH  SEND  SRA  IAC  SE IAC  SB  AUTH  IS  SRA KEY  <PKA>  IAC  SE IAC  SB  AUTH  REPLY  SRA KEY  <PKB>  IAC  SE IAC  SB  AUTH  IS  SRA USER<PKA(U)>  IAC  SE IAC  SB  AUTH  REPLY  SRA CONTINUE  IAC  SE IAC  SB  AUTH  IS  SRA PASS  <PKA(P)>  IAC  SE IAC  SB  AUTH  REPLY  SRA [ACCEPT|REJECT]  IAC  SE
  • 35. No.12 認証⽅方式のネゴシエーション Host1 Host2 IAC  DO  AUTH IAC  WILL  AUTH IAC  SB  AUTH  SEND  SRA  IAC  SE IAC  SB  AUTH  IS  SRA KEY  <PKA>  IAC  SE IAC  SB  AUTH  REPLY  SRA KEY  <PKB>  IAC  SE IAC  SB  AUTH  IS  SRA USER<PKA(U)>  IAC  SE IAC  SB  AUTH  REPLY  SRA CONTINUE  IAC  SE IAC  SB  AUTH  IS  SRA PASS  <PKA(P)>  IAC  SE IAC  SB  AUTH  REPLY  SRA [ACCEPT|REJECT]  IAC  SE
  • 36. No.14 認証⽅方式の決定 Host1 Host2 IAC  DO  AUTH IAC  WILL  AUTH IAC  SB  AUTH  SEND  SRA  IAC  SE IAC  SB  AUTH  IS  SRA KEY  <PKA>  IAC  SE IAC  SB  AUTH  REPLY  SRA KEY  <PKB>  IAC  SE IAC  SB  AUTH  IS  SRA USER<PKA(U)>  IAC  SE IAC  SB  AUTH  REPLY  SRA CONTINUE  IAC  SE IAC  SB  AUTH  IS  SRA PASS  <PKA(P)>  IAC  SE IAC  SB  AUTH  REPLY  SRA [ACCEPT|REJECT]  IAC  SE
  • 37. No.15 認証⽅方式の決定と暗号化⽅方式の決定 (まずは認証⽅方式) Host1 Host2 IAC  DO  AUTH IAC  WILL  AUTH IAC  SB  AUTH  SEND  SRA  IAC  SE IAC  SB  AUTH  IS  SRA KEY  <PKA>  IAC  SE IAC  SB  AUTH  REPLY  SRA KEY  <PKB>  IAC  SE IAC  SB  AUTH  IS  SRA USER<PKA(U)>  IAC  SE IAC  SB  AUTH  REPLY  SRA CONTINUE  IAC  SE IAC  SB  AUTH  IS  SRA PASS  <PKA(P)>  IAC  SE IAC  SB  AUTH  REPLY  SRA [ACCEPT|REJECT]  IAC  SE
  • 38. No.15 認証⽅方式の決定と暗号化⽅方式の決定 (次に暗号化⽅方式) Host1 Host2 IAC  DO  ENCRYPT IAC  WILL  ENCRYPT IAC  SB  ENCRYPT  SUPPORT DES_̲CFB64  IAC  SE IAC  SB  ENCRYPT  IS  DES_̲CFB64 CFB64_̲IV  <IV>  IAC  SE IAC  SB  ENCRYPT  REPLY  DES_̲CFB64 CFB64_̲IV_̲OK  IAC  SE 1. Command Names and Codes!  IAC  SB  ENCRYPT  ENC_̲KEYID Encryption Type! keyid  IAC  SE DES_CFB64 1!  IAC  SB  ENCRYPT  DEC_̲KEYID Suboption Commands! keyid  IAC  SE CFB64_IV 1! CFB64_IV_OK 2! IAC  SB  ENCRYPT  START  IAC  SE CFB64_IV_BAD 3!
  • 39. No.16 暗号化アルゴリズムの決定 Host1 Host2 IAC  DO  ENCRYPT IAC  WILL  ENCRYPT IAC  SB  ENCRYPT  SUPPORT DES_̲CFB64  IAC  SE IAC  SB  ENCRYPT  IS  DES_̲CFB64 CFB64_̲IV  <IV>  IAC  SE IAC  SB  ENCRYPT  REPLY  DES_̲CFB64 CFB64_̲IV_̲OK  IAC  SE 1. Command Names and Codes! Encryption Type!  IAC  SB  ENCRYPT  ENC_̲KEYID DES_CFB64 1! keyid  IAC  SE Suboption Commands!  IAC  SB  ENCRYPT  DEC_̲KEYID CFB64_IV 1! keyid  IAC  SE CFB64_IV_OK 2! CFB64_IV_BAD 3! IAC  SB  ENCRYPT  START  IAC  SE
  • 40. No.17 暗号化アルゴリズムの決定と鍵交換 Host1 Host2 IAC  DO  ENCRYPT IAC  WILL  ENCRYPT IAC  SB  ENCRYPT  SUPPORT DES_̲CFB64  IAC  SE IAC  SB  ENCRYPT  IS  DES_̲CFB64 CFB64_̲IV  <IV>  IAC  SE IAC  SB  ENCRYPT  REPLY  DES_̲CFB64 CFB64_̲IV_̲OK  IAC  SE  IAC  SB  ENCRYPT  ENC_̲KEYID keyid  IAC  SE  IAC  SB  ENCRYPT  DEC_̲KEYID keyid  IAC  SE IAC  SB  ENCRYPT  START  IAC  SE
  • 41. No.18 鍵交換 Host1 Host2 IAC  DO  ENCRYPT IAC  WILL  ENCRYPT IAC  SB  ENCRYPT  SUPPORT DES_̲CFB64  IAC  SE IAC  SB  ENCRYPT  IS  DES_̲CFB64 CFB64_̲IV  <IV>  IAC  SE IAC  SB  ENCRYPT  REPLY  DES_̲CFB64 CFB64_̲IV_̲OK  IAC  SE  IAC  SB  ENCRYPT  ENC_̲KEYID keyid  IAC  SE  IAC  SB  ENCRYPT  DEC_̲KEYID keyid  IAC  SE IAC  SB  ENCRYPT  START  IAC  SE
  • 42. No.19 鍵交換と暗号化開始(⽚片⽅方向) Host1 Host2 IAC  DO  ENCRYPT IAC  WILL  ENCRYPT IAC  SB  ENCRYPT  SUPPORT DES_̲CFB64  IAC  SE IAC  SB  ENCRYPT  IS  DES_̲CFB64 CFB64_̲IV  <IV>  IAC  SE IAC  SB  ENCRYPT  REPLY  DES_̲CFB64 CFB64_̲IV_̲OK  IAC  SE  IAC  SB  ENCRYPT  ENC_̲KEYID keyid  IAC  SE  IAC  SB  ENCRYPT  DEC_̲KEYID keyid  IAC  SE IAC  SB  ENCRYPT  START  IAC  SE
  • 43. No.20 暗号化して通信開始(これで双⽅方向) Host1 Host2 IAC  DO  ENCRYPT IAC  WILL  ENCRYPT IAC  SB  ENCRYPT  REQUEST START  IAC  SE IAC  SB  ENCRYPT  SUPPORT DES_̲CFB64  IAC  SE IAC  SB  ENCRYPT  IS  DES_̲CFB64 CFB64_̲IV  <IV>  IAC  SE IAC  SB  ENCRYPT  REPLY  DES_̲CFB64 CFB64_̲IV_̲OK  IAC  SE  IAC  SB  ENCRYPT  ENC_̲KEYID keyid  IAC  SE  IAC  SB  ENCRYPT  DEC_̲KEYID keyid  IAC  SE IAC  SB  ENCRYPT  START  IAC  SE
  • 44. with  ENCRYPTION  option without  ENCRYPTION  option 0x0030: 8..t.L.^....Free! 0x0030: !....K.Hsr/<..d.! 0x0040: BSD/amd64.(sage.! 0x0040: ..C:............! 0x0050: osaka.remu).(pts! 0x0050: ...j.r..........! 0x0060: /3)........Last.! 0x0060: .M`......4.u...e! 0x0070: login:.Mon.Apr..! 0x0070: ....u..u..r.....! 0x0080: 8.23:44:55.from.! 0x0080: .....aAcU...=...! 0x0090: localhost..FreeB! 0x0090: m..n...4.....Q..! 0x00a0: SD.9.0-RELEASE.(! 0x00a0: ....A(1...m....b! 0x00b0: GENERIC).#0:.Tue! 0x00b0: Yg[.......~HT"..! 0x00c0: .Jan..3.07:46:30! 0x00c0: .....5t.x....&.O! 0x00d0: .UTC.2012..You.h! 0x00d0: ........T...M...! 0x00e0: ave.mail.....!..! 0x00e0: E.0.1.-.#C^n...6!
  • 47. Q.  “ff  fa  26  01  02  ff  f0”はなんでしょう  ? A.      1.  IAC  SB  ENCRYPT  SUPPORT        DES_̲CFB64  IAC  SE 2.  IAC  SB  AUTH  SEND  SRA  IAC  SE 3.  IAC  SB  AUTH  REPLY  SRA  CONTINUE        IAC  SE
  • 48. Q.  “ff  fa  26  01  02  ff  f0”はなんでしょう  ? A.      1.  IAC  SB  ENCRYPT  SUPPORT        DES_̲CFB64  IAC  SE よくわからない 2.  IAC  SB  AUTH  SEND  SRA  IAC  SE 3.  IAC  SB  AUTH  REPLY  SRA  CONTINUE        IAC  SE
  • 50. きょうのおだい —  第⼀一部:TELNETを調べて分かったこと —  TELNETは暗号化出来る —  第⼆二部:TELNETを⾒見見る —  鍵認証できるし,暗号化も出来る —  でも,認証化⽅方式ネゴの途中でREJECTされる (なぜか) —  第三部:telnetを⾒見見る
  • 51. main.c main() main() ・init_̲termnal()→ttyiring/ttyoringの初期化 ・init_̲network()→netiring/netoringの初期化 main.c ・init_̲telnet()→シェル環境変数を取得(env_̲init()), エスケープ⽂文字等の設定など tninit() ・init_̲sys()→標準⼊入出⼒力力を⼊入出⼒力力に設定 (tin=stdin;  tout=stdout;) sys_̲bsd.c *ringについて  TerminalSaveState() ・ring.hで定義される構造体Ringの変数.リングバッ ファと管理理変数 ・ネットワークからrecv()したデータや,ネットワー クへsend()するデータ等を保持 getopt() ・バッファ,バッファサイズ,リングバッファなので 次の受信位置,今処理理している位置のポインタ等 command.c 引数が有る場合はこちらを実⾏行行.tn()内で無限 command.c tn() ループするので,tn()からcommand()には結果的 に⾏行行かない  (詳細は次ページ) command() 引数がない場合はこちらを実⾏行行  
  • 52. command.c tn() tn() ・ホスト名の解析.“/”から始まっていたらソケット,”@”か“!”   から始まっていたら”@”か”:”で区切切ってソースルーティング ・サーバに接続する telnet.c ・認証・暗号化の初期化 ・TELNETオプションの初期ネゴシエーション設定 telnet() (send_̲do(option,  1)  /  send_̲will(option,  1)) →  netoringに  “IAC  DO/WILL  [option]”  を追加する   (まだ送信しない)   telnet.c ・netoringの未送信データ,netiringの未処理理データ, Scheduler() ttyoringの未表⽰示データ,netiringの未処理理⼊入⼒力力 データがあるか確認する (ring_̲full_̲count()  /  ring_̲empty_̲count()) sys_̲bsd.c process_̲ring() telnet.c telrcv() 次ページ以降降 telnet.c telsnd()
  • 53. main.c telnetクライアント main() →⾒見見てきた所 main.c tninit() →これから⾒見見る所 sys_̲bsd.c  TerminalSaveState() getopt() command.c telnet.c command.c tn() telnet() command() telnet.c Scheduler() sys_̲bsd.c process_̲ring() telrcv() telnet.c telsnd() telnet.c
  • 54. main.c telnetクライアント main() →⾒見見てきた所 main.c tninit() →これから⾒見見る所 次はココ sys_̲bsd.c  TerminalSaveState() getopt() command.c telnet.c command.c tn() telnet() command() telnet.c Scheduler() sys_̲bsd.c process_̲ring() telrcv() telnet.c telsnd() telnet.c
  • 55. sys_̲bsd.c process_̲ring() process_̲ring() [ネットワークからの受信] recv() ・recv()で受信したデータをnetiringに読み込む ・netdata設定が有効ならダンプ表⽰示する sys_̲bsd.c [ターミナルからの⼊入⼒力力] TerminalRead() ・tin(=stdin)をttyiringに読み込む ・termdata設定が有効ならダンプ表⽰示する network.c [ネットワークへの送信] netflush() ・暗号化が有効であれば暗号化する ・送信バッファの内容をサーバへ送信する(send()) termina.c ttyflush() [ターミナルへの出⼒力力] ・tout(=stdout)に出⼒力力(write())する 戻り値の処理理 ・netflush()/ttyflush()したバイト数を戻り値に設 定する tin/toutは最初の⽅方のinit_̲sys()で tin=stdin;  tout=stdout;  してある
  • 56. telnetクライアント main() main.c →⾒見見てきた所 tninit() main.c →これから⾒見見る所 sys_̲bsd.c  TerminalSaveState() getopt() command.c telnet.c command.c tn() telnet() command() telnet.c Scheduler() sys_̲bsd.c process_̲ring() 次はココ telrcv() telsnd() telnet.c telnet.c
  • 57. telnet.c telrcv() telrcv() ・未処理理の受信データが無くなるまで処理理する decrypt_̲input() ・暗号化が有効であれば復復号する ・データ処理理は現在のステータス(telrcv_̲state) switch(telrcv_̲state) に応じて変わるため場合分けする TS_̲CR ・改⾏行行処理理 ・IACを受け取ればTS_̲IACへ遷移.それ以 TS_̲DATA 外は受信データをttyoringへ追加する TS_̲IAC ・IAC状態なら,受信データに応じて状態を 遷移する WILL/WONT/DO/DONT ・TS_̲XXXに遷移する ・サブオプションバッファを初期化して(IAC   SB SBは⼊入れない),TS_̲SBに遷移する
  • 58. telnet.cのtelrcv()のところ telrcv() switch(telrcv_̲state) TS_̲WILL willoption() encrypt_̲send_̲support() 暗号化は後回し TS_̲WONT wontoption() DO  FLOW  CONTROLの TS_̲DO dooption() ときは端末の再設定を⾏行行う TS_̲DONT dontoption() この4つはいずれの場合も 最後にTS_̲DATAに遷移する
  • 59. telnet.cのtelrcv()のところ telrcv() switch(telrcv_̲state) ・IACならTS_̲SEにしてIAC  IACかIAC  SEを判断する TS_̲SB ・IAC以外ならサブオプションバッファに追加する TS_̲SE IAC  IAC ・サブオプションバッファにIACを追加して TS_̲SBに戻す ・IAC  SEをサブオプションバッファに追加して, IAC  SE サブオプション処理理をして,TS_̲DATAに戻す. suboption() 次々のページ IAC  IACでも ・サブオプション処理理をして IAC  SEでもない TS_̲IACに戻す suboption() 次々のページ
  • 60. telrcv() telnet.cのtelrcv()のところ switch(telrcv_̲state) netiringに未処理理のデータ があれば最初に戻る ・netiringの受信データを処理理したので,リングバッ ring_̲consumed() ファの処理理・受信位置のポインタを更更新する &戻り値の処理理 ・処理理したバイト数を返す
  • 61. telnet.c telrcv() suboption() ・サブオプションバッファはIAC  SBの後のオプションコードか ら⼊入っているので,オプションコードに応じた処理理を⾏行行う ・使いたくないオプションには同意しない ・必要に応じて返答を作成しnetoringに追加する TELOPT_̲TTYPE ・IAC  SB  TTYPE  IS  [termname]  IA  SE をnetoringに追加する ・IAC  SB  TSPEED  IS  [ospeed]  [ispeed]  IA  SE TELOPT_̲TSPEED をnetoringに追加する TELOPT_̲LFLOW ・ターミナルを再設定 TELOPT_̲LINEMODE ・IAC  SB  LINEMODE  MODE  ACK  IAC  SE MODE をnetoringに追加する FORWARDMASK ・必要に応じて  IAC  SB  LINEMODE  DONʼ’T   SLC FORWARDMASKをnetoringに追加する 続きは次のページ ・なんか⾊色々
  • 62. telnet.c telrcv() suboption() TELOPT_̲NEW_̲ENVIRON env_̲opt() ・env_̲opt_̲start()して,環境変数の区切切り毎に env_̲opt_̲add()する env_̲opt_̲start() ・ENVIRON⽤用バッファを確保して IAC  SB  ENV  IS  を⼊入れる env_̲opt_̲add() ・ENVオプション⽤用バッファ(opt_̲reply) 追加する ・DISPLAY変数がNULLだったり,異異常に⻑⾧長 かったりしたらWONTにする TELOPT_̲XDISPLOC (下のメッセージが作れないから) ・使える場合は応答をnetoringに追加する IAC  SB  XDISPLOC  IS  $DISPLAY  IAC  SE 続きは次のページ
  • 63. telnet.c telrcv() suboption() TELOPT_̲AUTHENTICATION auth.c IS auth_̲is() (*Authenticator)-‐‑‒>is() SEND auth_̲send() (*Authenticator)-‐‑‒>send() REPLY auth_̲reply() (*Authenticator)-‐‑‒>reply() NAME auth_̲name() ・ユーザ名を取得 続きは後のページ
  • 64. 認証について telnetがサポートする認証⽅方式はXauthP構造体(Authenticator型)をリス ト化したauthenticators変数に設定している. ü  XauthPの詳細  (auth.h) 初期化・SEND/IS/REPLY時の応答, typedef  struct  XauthP  { ステータス確認,デバッグ表⽰示が int type;     int way; 関数ポインタになっている int (*init)(struct  XauthP  *,  int); int (*send)(struct  XauthP  *); void (*is)(struct  XauthP  *,  unsigned  char  *,  int); void (*reply)(struct  XauthP  *,  unsigned  char  *,  int); int (*status)(struct  XauthP  *,  char  *,  int); void (*printsub)(unsigned  char  *,  int,  unsigned  char  *,  int); }  Authenticator; ü  authenticatorsにSRAを設定しているようす  (auth.c) Authenticator  authenticators[]  =  {        sra_̲is, …        sra_̲reply, #ifdef  SRA        sra_̲status,  {  AUTHTYPE_̲SRA,          sra_̲printsub  },        AUTH_̲WHO_̲CLIENT|AUTH_̲HOW_̲ONE_̲WAY, #endif        sra_̲init,        sra_̲send,
  • 65. SRAの場合 キャプチャからSRAであることがわかるので,これに着⽬目して確認する telnet.c suboption() Server -> Client は SEND / REPLY だけなので, TELOPT_̲AUTHENTICATION IS は省略 Client Server auth.c IAC  DO  AUTH IS auth_̲is() IAC  WILL  AUTH IAC  SB  AUTH  SEND  SRA  IAC  SE (*Authenticator)-‐‑‒>is()   sra_̲is() IAC  SB  AUTH  IS  SRA KEY  <PKA>  IAC  SE IAC  SB  AUTH  REPLY  SRA KEY  <PKB>  IAC  SE SEND auth_̲send() IAC  SB  AUTH  IS  SRA USER<PKA(U)>  IAC  SE (*Authenticator)-‐‑‒>send() sra_̲send() IAC  SB  AUTH  REPLY  SRA CONTINUE  IAC  SE IAC  SB  AUTH  IS  SRA REPLY auth_̲reply() PASS  <PKA(P)>  IAC  SE IAC  SB  AUTH  REPLY  SRA [ACCEPT|REJECT]  IAC  SE (*Authenticator)-‐‑‒>reply() sra_̲reply()
  • 66. SRAの場合 そういえばtelnet()で認証・暗号化の初期化をしていた. telnet() サポートしているすべての認証⽅方式で auth_̲encrypt_̲init() (*Authenticator)-‐‑‒>init() →  sra_̲init() sra_̲init() auth_̲init() 応答のひな形を “IAC  SB  AUTH  IS  SRA” で初期化 pk.c 鍵認証のペアを作成 genkey() encrypt_̲init()
  • 67. sra.c SRAの場合 sra_̲send() ・サブオプション解析でIAC  SB  AUTH  SENDを受信して いた時に実⾏行行する 公開鍵を送る “IAC    SB    AUTH    IS    SRA    KEY  <PKA>    IAC    SE” Client Server IAC  DO  AUTH IAC  WILL  AUTH IAC  SB  AUTH  SEND  SRA  IAC  SE IAC  SB  AUTH  IS  SRA KEY  <PKA>  IAC  SE IAC  SB  AUTH  REPLY  SRA KEY  <PKB>  IAC  SE IAC  SB  AUTH  IS  SRA USER<PKA(U)>  IAC  SE IAC  SB  AUTH  REPLY  SRA CONTINUE  IAC  SE IAC  SB  AUTH  IS  SRA PASS  <PKA(P)>  IAC  SE IAC  SB  AUTH  REPLY  SRA [ACCEPT|REJECT]  IAC  SE
  • 68. sra.c SRAの場合 sra_̲reply() 受信データの解析 SRA_̲KEY  “IAC  SB  AUTH  REPLY  SRA  KEY  <PKB>  IAC  SE” 鍵暗号化された共通鍵 <PKB>を抽出 Client Server IAC  DO  AUTH IAC  WILL  AUTH <PKB>と秘密鍵(PKA)から IAC  SB  AUTH  SEND  SRA  IAC  SE 共通鍵を取得する IAC  SB  AUTH  IS  SRA KEY  <PKA>  IAC  SE IAC  SB  AUTH  REPLY  SRA KEY  <PKB>  IAC  SE ユーザ名を共通鍵で暗号化する IAC  SB  AUTH  IS  SRA <PKA(U)> USER<PKA(U)>  IAC  SE IAC  SB  AUTH  REPLY  SRA CONTINUE  IAC  SE IAC  SB  AUTH  IS  SRA  USER IAC  SB  AUTH  IS  SRA <PKA(U)>  IAC  SE PASS  <PKA(P)>  IAC  SE IAC  SB  AUTH  REPLY  SRA [ACCEPT|REJECT]  IAC  SE 続きは次のページ
  • 69. SRAの場合  “IAC  SB  AUTH  REPLY  SRA  CONTINUE SRA_̲CONTINUE    IAC  SE” Client Server IAC  DO  AUTH パスワードを共通鍵で暗号化する <PKA(P)> IAC  WILL  AUTH IAC  SB  AUTH  SEND  SRA  IAC  SE IAC  SB  AUTH  IS  SRA KEY  <PKA>  IAC  SE “IAC  SB  AUTH  IS  SRA  USER  <PKA(P)>” IAC  SB  AUTH  REPLY  SRA KEY  <PKB>  IAC  SE IAC  SB  AUTH  IS  SRA USER<PKA(U)>  IAC  SE IAC  SB  AUTH  REPLY  SRA CONTINUE  IAC  SE IAC  SB  AUTH  IS  SRA PASS  <PKA(P)>  IAC  SE IAC  SB  AUTH  REPLY  SRA [ACCEPT|REJECT]  IAC  SE 続きは次のページ
  • 70. telnet.c telrcv() suboption() 戻ってtelnet.cのsuboption()の続き TELOPT_̲ENCRYPT encrypt.c START encrypt_̲start() ・復復号⽤用の関数ポインタを設定 END encrypt_̲end() ・復復号⽤用の関数ポインタを削除 SUPPORT encrypt_̲support() (*Encryptions)-‐‑‒>start() ・IAC  SB  ENCRYPT  SUPPORT  <encrypt-‐‑‒list> のうち最初にサポートしている⽅方式を採⽤用 REQSTART encrypt_̲request_̲start() encrypt_̲start_̲output() ・IAC  SB  ENCRYPT  START  [key]  IAC  SEをnetoringに書き込 み,暗号化⽤用の関数ポインタを設定 REQEND encrypt_̲request_̲end() encrypt_̲send_̲end() 続きは ・IAC  SB  ENCRYPT  END  IAC  SEをnetoringに書き込み,暗号 次ページ 化⽤用の関数ポインタを削除(0にする)
  • 71. telnet.c telrcv() suboption() TELOPT_̲ENCRYPT IS encrypt_̲is() (*Encryptions)-‐‑‒>is() REPLY encrypt_̲reply() (*Encryptions)-‐‑‒>reply() encrypt.c ENC_̲KEYID encrypt_̲enc_̲keyid() DEC_̲KEYID encrypt_̲dec_̲keyid() encrypt_keyid() encrypt_̲start_̲output() ・REQSTARTの時と同じ ・IAC  SB  ENCRYPT  START  [key]  IAC  SEをnetoringに 書き込み,暗号化⽤用の関数ポインタを設定
  • 72. 暗号化について telnetがサポートする暗号化⽅方式はEncryptions構造体(Encryptions型)を リスト化したencryptions変数に設定している. ü  Encryptionsの詳細  (encrypt.h) typedef  struct  { const  char  *name;   int type; void (*output)(unsigned  char  *,  int); 認証のAuthenticatorsと同様に, int (*input)(int); 関数ポインタになっている void (*init)(int); int (*start)(int,  int); int (*is)(unsigned  char  *,  int); int (*reply)(unsigned  char  *,  int); void (*session)(Session_̲Key  *,  int); int (*keyid)(int,  unsigned  char  *,  int  *); void (*printsub)(unsigned  char  *,  int,  unsigned  char  *,  int); }  Encryptions; ü  encryptionsに設定しているようす  (auth.c) static  Encryptions  encryptions[]  =  {        cfb64_̲is,        {  "DES_̲CFB64", ENCTYPE_̲DES_̲CFB64,        cfb64_̲reply,        cfb64_̲encrypt,        cfb64_̲session,        cfb64_̲decrypt,        cfb64_̲keyid,        cfb64_̲init,        cfb64_̲printsub  },        cfb64_̲start,
  • 73. DES_̲CFB64の場合 キャプチャからDEC_̲CFB64であることがわかるので,これに着⽬目して確 認する telnet.c telrcv() ・未処理理の受信データが無くなるまで処理理する decrypt_̲input() ・暗号化が有効であれば復復号する ・データ処理理は現在のステータス(telrcv_̲state) switch(telrcv_̲state) に応じて変わるため場合分けする TS_̲WILL willoption() encrypt_̲send_̲support() 後回しにしたアレ
  • 74. TS_̲SE suboption() cfb64_̲start() TELOPT_̲ENCRYPT SUPPORT encrypt_̲support() (*Encryptions)-‐‑‒>start() cfb64_̲is() IS encrypt_̲is() (*Encryptions)-‐‑‒>is() REPLY encrypt_̲reply() (*Encryptions)-‐‑‒>reply() encrypt.c ENC_̲KEYID encrypt_̲enc_̲keyid() cfb64_̲reply() DEC_̲KEYID encrypt_̲dec_̲keyid() encrypt_keyid() encrypt_̲start_̲output()
  • 75. DES_̲CFB64の場合 そういえばtelnet()で認証・暗号化の初期化をしていた. telnet() auth_̲encrypt_̲init() auth_̲init() encrypt_̲init() SUPPORTメッセージを作成: IAC  SB  ENCRYPT  SUPPORT  <encrypt-‐‑‒list>  IAC  SE サポートしているすべての暗号化⽅方式で (*Encryptions)-‐‑‒>init()  → cfb64_̲init() 厳密にはENCRYPT_̲DES_̲CFB64 応答のひな形を設定:  [X]  [X]  [X]  [X]  DES_̲CFB64 enc_̲des.c 応答のひな形を設定: fb64_̲init() IAC    SB    ENCRYPT    IS    DES_̲CFB64
  • 76. telnet.c DES_̲CFB64の場合 telrcv() decrypt_̲input() switch(telrcv_̲state) TS_̲WILL willoption() Host1 Host2 encrypt.c IAC  DO  ENCRYPT encrypt_̲send_̲support() IAC  WILL  ENCRYPT IAC  SB  ENCRYPT  SUPPORT DES_̲CFB64  IAC  SE IAC  SB  ENCRYPT  IS  DES_̲CFB64 CFB64_̲IV  <IV>  IAC  SE さっき作ったSUPPORTメッセージを IAC  SB  ENCRYPT  REPLY  DES_̲CFB64 netoringに書き込む CFB64_̲IV_̲OK  IAC  SE IAC  SB  ENCRYPT  SUPPORT  <encrypt-‐‑‒list>  IAC  SE  IAC  SB  ENCRYPT  ENC_̲KEYID keyid  IAC  SE  IAC  SB  ENCRYPT  DEC_̲KEYID keyid  IAC  SE IAC  SB  ENCRYPT  START  IAC  SE
  • 77. enc_̲des.c DES_̲CFB64の場合 cfb64_̲start() fb64_̲start() DIR_̲DECRYPT stateがFAILEDなら IN_̲PROGRESSにする Host1 Host2 IAC  DO  ENCRYPT DIR_̲ENCRYPT IAC  WILL  ENCRYPT IAC  SB  ENCRYPT  SUPPORT DES_̲CFB64  IAC  SE DESのIVを作る IAC  SB  ENCRYPT  IS  DES_̲CFB64 CFB64_̲IV  <IV>  IAC  SE 送信データの作成: IAC  SB  ENCRYPT  REPLY  DES_̲CFB64 CFB64_̲IV_̲OK  IAC  SE IAC    SB    ENCRYPT    IS    DES_̲CFB64      IAC  SB  ENCRYPT  ENC_̲KEYID CFB64_̲IV    <IV>    IAC    SE keyid  IAC  SE  IAC  SB  ENCRYPT  DEC_̲KEYID keyid  IAC  SE netoringに書き込む IAC  SB  ENCRYPT  START  IAC  SE
  • 78. enc_̲des.c DES_̲CFB64の場合 cfb64_̲is() fb64_̲is() FB64_̲IS fb64_̲stream_̲iv() Host1 Host2 送信データの作成: IAC  DO  ENCRYPT IAC    SB    ENCRYPT    REPLY     IAC  WILL  ENCRYPT DES_̲CFB64    FB64_̲IV_̲OK    IAC    SE IAC  SB  ENCRYPT  SUPPORT DES_̲CFB64  IAC  SE IAC  SB  ENCRYPT  IS  DES_̲CFB64 netoringに書き込む CFB64_̲IV  <IV>  IAC  SE IAC  SB  ENCRYPT  REPLY  DES_̲CFB64 CFB64_̲IV_̲OK  IAC  SE  IAC  SB  ENCRYPT  ENC_̲KEYID keyid  IAC  SE それ以外  IAC  SB  ENCRYPT  DEC_̲KEYID keyid  IAC  SE エラー表⽰示 IAC  SB  ENCRYPT  START  IAC  SE
  • 79. enc_̲des.c DES_̲CFB64の場合 cfb64_̲reply() 送信データの作成: fb64_̲reply() IAC    SB    ENCRYPT     ENCRYPT_̲ENC_̲KEYID    0    IAC    SE FB64_̲IV_̲OK fb64_̲stream_̲iv() netoringに書き込む Host1 Host2 encrypt_̲send_̲keyid() IAC  DO  ENCRYPT IAC  WILL  ENCRYPT IAC  SB  ENCRYPT  SUPPORT DES_̲CFB64  IAC  SE IAC  SB  ENCRYPT  IS  DES_̲CFB64 FB64_̲IV_̲BAD CFB64_̲IV  <IV>  IAC  SE IAC  SB  ENCRYPT  REPLY  DES_̲CFB64 fb64_̲stream_̲iv CFB64_̲IV_̲OK  IAC  SE  IAC  SB  ENCRYPT  ENC_̲KEYID keyid  IAC  SE それ以外  IAC  SB  ENCRYPT  DEC_̲KEYID keyid  IAC  SE エラー表⽰示 IAC  SB  ENCRYPT  START  IAC  SE
  • 80. telnetクライアント main() main.c →⾒見見てきた所 tninit() main.c →これから⾒見見る所 ⻑⾧長かった sys_̲bsd.c  TerminalSaveState() getopt() command.c telnet.c command.c tn() telnet() command() telnet.c Scheduler() sys_̲bsd.c process_̲ring() 次はココ telrcv() telsnd() telnet.c telnet.c
  • 81. telnet.c telsnd() ・ttyiringの中⾝身をnetoringに処理理&コピーする telsnd() (※send()しない) 無い netoringの空きある? ある 未処理理ttyiring した もう⼀一回確認しても未処理理無し? 全部処理理した? (ring_̲full_̲consecutive()) なかった まだ あった ttyiringから1バイト取得 y 制御⽂文字? command() n n BINARYモード? 改⾏行行をエスケープ y ・IAC(0xff)なら,IAC  IACをnetoringに追加 処理理したバイト数を (0xffは0xff  0xffにエスケープが必要) 戻り値にして終了了 ・それ以外なら,そのままnetoringに追加
  • 82. telnetクライアント main() main.c →⾒見見てきた所 tninit() main.c →これから⾒見見る所 sys_̲bsd.c  TerminalSaveState() getopt() command.c telnet.c command.c tn() telnet() command() telnet.c Scheduler() sys_̲bsd.c process_̲ring() 次はココ telrcv() telsnd() telnet.c telnet.c
  • 83. command.c command() command(int  top,  const  char  *tbuf,  int  cnt) y tbuf  ==  NULL  ? 標準⼊入⼒力力から1⾏行行読み込む n 引数無しでtelnetを実⾏行行した ときはこっちに来る 作業領領域にコピー ⼊入⼒力力コマンドを探す getcmd() 完全⼀一致  or 部分⼀一致・完全⼀一致が 部分⼀一致が1つ 1つもない 部分⼀一致が 2つ以上 “?Ambiguous  command” (*Command)-‐‑‒>handler() “?Invalid  command”
  • 84. telnetクライアントコマンド telnetクライアント上のコマンドはCommand構造体でリスト化して保持 している(cmdtab変数) ü  Command構造体の詳細  (command.c) typedef struct { 各コマンドで⾏行行される内容は関 const char *name; /* command name */ 数ポインタになっている const char *help; /* help string (NULL for no help) */ int (*handler)(int, char **); /* routine which executes command */ int needconnect; /* Do we need to be connected to execute? */ } Command; ü  encryptionsに設定しているようす  (auth.c) static  Command  cmdtab[]  =  {        {  "close",   closehelp, bye,             1  },        {  "logout",   logouthelp, (int  (*)(int,  char  **))logout, 1  },        {  "display", displayhelp, display,           0  },        {  "mode",   modestring, modecmd,         0  },        {  "telnet",   openhelp, tn,             0  },        {  "open",   openhelp, tn,             0  },        {  "quit",   quithelp,   (int  (*)(int,  char  **))quit,   0  },        {  "send",   sendhelp, sendcmd,         0  },        … (*Command)-‐‑‒>handler()
  • 85. telnetクライアントコマンド static  Command  cmdtab[]  =  {        {  "close",   closehelp, bye,             1  },        {  "logout",   logouthelp, (int  (*)(int,  char  **))logout, 1  },        {  "display", displayhelp, display,           0  },        {  "mode",   modestring, modecmd,         0  },        {  "telnet",   openhelp, tn,             0  },        {  "open",   openhelp, tn,             0  },        {  "quit",   quithelp,   (int  (*)(int,  char  **))quit,   0  },        {  "send",   sendhelp, sendcmd,         0  },        … (*Command)-‐‑‒>handler() % telnet! % telnet 192.168.1.1! 同じ telnet> open 192.168.1.1! 引数無しなのでcommand()にいって, 引数ありなのでtn()で処理される openコマンドのハンドラtn()で処理される
  • 89. (参考) —  TELNETがソースルーティングするところ —  コマンドとパケットキャプチャから動作を確認する command.c tn() ・ホスト名の解析.“/”から始まっていたらソケット,”@”  or  “!”   から始まっていたら”@”か”:”で区切切ってソースルーティング telnet.c ・サーバに接続する telnet() telnet.c Scheduler() sys_̲bsd.c process_̲ring() telnet.c telrcv() 次ページ以降降 telnet.c telsnd()
  • 90. Loose  Source  Routing —  ホスト名をʼ’@ʼ’から初めて,ʼ’@ʼ’区切切りにすると, Loose  Source  RoutingのIPオプション付きパケットを 送信する > telnet @[email protected]@[email protected]@10.7.7.7!
  • 91. Strict  Source  Routing —  ホスト名をʼ’!ʼ’から初めて,ʼ’@ʼ’区切切りにすると, Loose  Source  RoutingのIPオプション付きパケットを 送信する > telnet [email protected]@[email protected]@[email protected]!
  • 92. しくみ if (hostp[0] == '/') { (ソケットだった時の処理) tn() } else if (hostp[0] == '@' || hostp[0] == '!') { if ((hostname = strrchr(hostp, ':')) == NULL) hostname = strrchr(hostp, '@'); if (hostname == NULL) { hostname = hostp; 引数からソケット(ʻ‘/ʼ’)か } else { ソースルート(ʻ‘!ʼ’  か  ʻ‘@ʼ’)か hostname++; ホスト名かを判断する srcroute = 1; } } else hostname = hostp; hostpからソースルートの if (srcroute != 0) { IPオプションヘッダを ソースルートなら 作って,srpに⼊入れる …. sourceroute()する result = sourceroute(res, hostp, &srp, &srlen, &proto, &opt); 作ったソースルートのIPオ if (srp && setsockopt(net, proto, opt, プションヘッダを設定する (char *)srp, srlen) < 0) {
  • 93. 初期化してない*lenp  (tn()では&srlen) sourceroute() に対して  if(*lenp  <  7)  return  -‐‑‒1; してる気がする…… 引数をチェック (⻑⾧長さが不不正に短くない こととか) if (*cp == '!') { cp++; *lsrp++ = IPOPT_SSRR; ソースルーティングのIP  Option作成 } else ・ʼ’!ʼ’  から始まっていたら  SSRRを設定 *lsrp++ = IPOPT_LSRR; ・ʼ’@ʼ’から始まっていたらLSRRを設定 ・それ以外だったら終了了する if (*cp != '@') return -1; ・pointer(=4)を埋める ・ホスト名をʼ’@ʼ’とʼ’:ʼ’で区切切って埋める 詳細は次ページ ・ソースルーティングのIP  Option⻑⾧長を決 めて,length埋める
  • 94. > telnet [email protected]@[email protected]@[email protected]! @区切りのホスト名から cpの初期位置は ソースルーティングのIPオプション付きパケットを作る ホスト名の先頭’1’ (‘@’の次) for (c = 0;;) { for (cp2 = cp; (c = *cp2); cp2++) { if (c == ',') { *cp2++ = '0'; if (*cp2 == '@') cp2++; } else if (c == '@') { *cp2++ = '0’ } else if (c == ':') { *cp2++ = '0'; } else ‘@’と’:’の区切り位置を探して continue; 区切り位置を’0にする break; →次にgetaddrinfo()に渡すため } error = getaddrinfo(cp, NULL, &hints, &res); _sin = (struct sockaddr_in *)res->ai_addr; IP Optionに埋める memcpy(lsrp, (char *)&_sin->sin_addr, 4); lsrp += 4; cp = cp2; } 次を探す