Your SlideShare is downloading. ×
超簡単!TELNETの話
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Saving this for later?

Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime - even offline.

Text the download link to your phone

Standard text messaging rates apply

超簡単!TELNETの話

7,820
views

Published on


0 Comments
20 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
7,820
On Slideshare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
48
Comments
0
Likes
20
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. 超簡単! TELNETの話 第⼋八回  カーネル/VM探検隊 2013/4/13(Sat) @yogata
  • 2. ネットワークエンジニアの基本コマンド
  • 3. telnet
  • 4. 後輩が来た時
  • 5. 先輩! TELNETも知らないんすか wwwwww
  • 6. っていわれたらめちゃつらい
  • 7. そこで
  • 8. TELNETを復復習してみた
  • 9. きょうのおだい—  第⼀一部:TELNETを調べて分かったこと—  第⼆二部:TELNETを⾒見見る—  第三部:telnetを⾒見見る
  • 10. TELNETは暗号化出来る (↑結論論)
  • 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. WONT (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. DONT (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.
  • 15. もしかして,ネゴシエーションで暗号化機能を合意すれば使えるのでは???……でも独⾃自実装はいやだなあ
  • 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以降降  コンソールに表⽰示させるデータ
  • 23. telnet(のsra.c)書いた⼈人が認証フローはこうだよ,って⽂文章化していたので確かめてみたら,そのとおりだった……!!!
  • 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
  • 30. No.8クライアントからサーバへ,合意したオプションについて詳細なパラメータを決めていく 暗号化⽅方式の提案(SUPPORT) クライアント→サーバの⽅方向
  • 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.9RSA認証⽅方式のネゴシーエションをする 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.11REJECTされる.仕様の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  option0x0030: 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!
  • 45. 結論論TELNETは暗号化できるし公開鍵暗号で認証もできるTELNETは平⽂文でしか通信できない
  • 46. ちょっとクイズ
  • 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
  • 49. telnetの気持ちになって 考えてみる
  • 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.ctelrcv() ・未処理理の受信データが無くなるまで処理理する decrypt_̲input() ・暗号化が有効であれば復復号する ・データ処理理は現在のステータス(telrcv_̲state) switch(telrcv_̲state) に応じて変わるため場合分けする TS_̲WILL willoption() encrypt_̲send_̲support() 後回しにしたアレ
  • 74. TS_̲SEsuboption() 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()で処理される
  • 86. まとめ
  • 87. TELNETは 超簡単!
  • 88. (参考)—  TELNETがソースルーティングするところ—  コマンドとパケットキャプチャから動作を確認するcommand.ctn() ・ホスト名の解析.“/”から始まっていたらソケット,”@”  or  “!”   から始まっていたら”@”か”:”で区切切ってソースルーティング telnet.c ・サーバに接続する telnet() telnet.c Scheduler() sys_̲bsd.c process_̲ring() telnet.c telrcv() 次ページ以降降 telnet.c telsnd()
  • 89. 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!
  • 90. 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!
  • 91. しくみ 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) {
  • 92. 初期化してない*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埋める
  • 93. > 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;} 次を探す