Subversion Repositories Kolibri OS

Rev

Rev 7698 | Rev 9071 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;    ssh.asm - SSH client for KolibriOS
  2. ;
  3. ;    Copyright (C) 2015-2021 Jeffrey Amelynck
  4. ;
  5. ;    This program is free software: you can redistribute it and/or modify
  6. ;    it under the terms of the GNU General Public License as published by
  7. ;    the Free Software Foundation, either version 3 of the License, or
  8. ;    (at your option) any later version.
  9. ;
  10. ;    This program is distributed in the hope that it will be useful,
  11. ;    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. ;    GNU General Public License for more details.
  14. ;
  15. ;    You should have received a copy of the GNU General Public License
  16. ;    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  17.  
  18. format binary as ""
  19.  
  20. __DEBUG__       = 1
  21. __DEBUG_LEVEL__ = 3             ; 1: Everything, including sinsitive information, 2: Debugging, 3: Errors only
  22.  
  23. BUFFERSIZE      = 4096
  24. MAX_BITS        = 8192
  25.  
  26. DH_PRIVATE_KEY_SIZE     = 256
  27.  
  28. use32
  29.  
  30.         db      'MENUET01'      ; signature
  31.         dd      1               ; header version
  32.         dd      start           ; entry point
  33.         dd      i_end           ; initialized size
  34.         dd      mem+65536       ; required memory
  35.         dd      mem+65536       ; stack pointer
  36.         dd      params          ; parameters
  37.         dd      0               ; path
  38.  
  39. include '../../macros.inc'
  40. ;include '../../struct.inc'
  41. purge mov,add,sub
  42. include '../../proc32.inc'
  43. include '../../dll.inc'
  44. include '../../debug-fdo.inc'
  45. include '../../network.inc'
  46. include '../../develop/libraries/libcrash/trunk/libcrash.inc'
  47.  
  48. include 'mcodes.inc'
  49. include 'ssh_transport.inc'
  50.  
  51. include 'dh_gex.inc'
  52.  
  53. include 'mpint.inc'
  54. include 'random.inc'
  55.  
  56. include 'aes256.inc'
  57. include 'aes256-ctr.inc'
  58. include 'aes256-cbc.inc'
  59.  
  60. include 'blowfish.inc'
  61. include 'blowfish-ctr.inc'
  62. include 'blowfish-cbc.inc'
  63.  
  64. include 'hmac_sha256.inc'
  65. include 'hmac_sha1.inc'
  66. include 'hmac_md5.inc'
  67.  
  68. ; macros for network byte order
  69. macro dd_n op {
  70.    dd 0 or (((op) and 0FF000000h) shr 24) or \
  71.            (((op) and 000FF0000h) shr  8) or \
  72.            (((op) and 00000FF00h) shl  8) or \
  73.            (((op) and 0000000FFh) shl 24)
  74. }
  75.  
  76. macro dw_n op {
  77.    dw 0 or (((op) and 0FF00h) shr 8) or \
  78.            (((op) and 000FFh) shl 8)
  79. }
  80.  
  81. proc dump_hex _ptr, _length
  82. if __DEBUG_LEVEL__ <= 1
  83.         pushad
  84.  
  85.         mov     esi, [_ptr]
  86.         mov     ecx, [_length]
  87.   .next_dword:
  88.         lodsd
  89.         bswap   eax
  90.         DEBUGF  1,'%x', eax
  91.         loop    .next_dword
  92.         DEBUGF  1,'\n'
  93.  
  94.         popad
  95. end if
  96.         ret
  97. endp
  98.  
  99. struct  ssh_connection
  100.  
  101. ; Connection
  102.  
  103.         hostname                rb 1024
  104.  
  105.         socketnum               dd ?
  106.  
  107.         sockaddr                dw ?            ; Address family
  108.         port                    dw ?
  109.         ip                      dd ?
  110.                                 rb 10
  111.  
  112. ; Encryption/Decryption
  113.  
  114.         rx_crypt_proc           dd ?
  115.         tx_crypt_proc           dd ?
  116.         rx_crypt_ctx_ptr        dd ?
  117.         tx_crypt_ctx_ptr        dd ?
  118.         rx_crypt_blocksize      dd ?
  119.         tx_crypt_blocksize      dd ?
  120.  
  121.         rx_padsize              dd ?    ; = Max(8, rx_crypt_blocksize)
  122.         tx_padsize              dd ?    ; = Max(8, tx_crypt_blocksize)
  123.  
  124. ; Message authentication
  125.  
  126.         rx_mac_proc             dd ?
  127.         tx_mac_proc             dd ?
  128.         rx_mac_ctx              hmac_sha256_context
  129.         tx_mac_ctx              hmac_sha256_context
  130.         rx_mac_length           dd ?
  131.         tx_mac_length           dd ?
  132.  
  133. ; Buffers
  134.  
  135.         rx_seq                  dd ?            ; Packet sequence number for MAC
  136.         rx_buffer               ssh_packet_header
  137.                                 rb BUFFERSIZE-sizeof.ssh_packet_header
  138.  
  139.         tx_seq                  dd ?            ; Packet sequence number for MAC
  140.         tx_buffer               ssh_packet_header
  141.                                 rb BUFFERSIZE-sizeof.ssh_packet_header
  142.  
  143.         send_data               dw ?
  144.  
  145. ; Output from key exchange
  146.         dh_K                    dd ?            ; Shared Secret (Big endian)
  147.                                 rb MAX_BITS/8
  148.         dh_K_length             dd ?            ; Length in little endian
  149.  
  150.         dh_H                    rb 32           ; Exchange Hash
  151.         session_id_prefix       db ?
  152.         session_id              rb 32
  153.         rx_iv                   rb 32           ; Rx initialisation vector
  154.         tx_iv                   rb 32           ; Tx initialisation vector
  155.         rx_enc_key              rb 32           ; Rx encryption key
  156.         tx_enc_key              rb 32           ; Tx encryption key
  157.         rx_int_key              rb 32           ; Rx integrity key
  158.         tx_int_key              rb 32           ; Tx integrity key
  159.  
  160. ; Diffie Hellman
  161.         dh_p                    dd ?
  162.                                 rb MAX_BITS/8
  163.         dh_g                    dd ?
  164.                                 rb MAX_BITS/8
  165.         dh_x                    dd ?
  166.                                 rb MAX_BITS/8
  167.         dh_e                    dd ?
  168.                                 rb MAX_BITS/8
  169.         dh_f                    dd ?
  170.                                 rb MAX_BITS/8
  171.  
  172.         dh_signature            dd ?
  173.                                 rb MAX_BITS/8
  174.  
  175.         temp_ctx                crash_ctx
  176.         k_h_ctx                 crash_ctx
  177.  
  178.         mpint_tmp               dd ?
  179.                                 rb MAX_BITS/8
  180.  
  181. ends
  182.  
  183. start:
  184.         mcall   68, 11          ; Init heap
  185.  
  186.         DEBUGF  2, "SSH: Loading libraries\n"
  187.         stdcall dll.Load, @IMPORT
  188.         test    eax, eax
  189.         jnz     exit
  190.  
  191.         DEBUGF  2, "SSH: Init PRNG\n"
  192.         call    init_random
  193.  
  194.         DEBUGF  2, "SSH: Init Console\n"
  195.         invoke  con_start, 1
  196.         invoke  con_init, 80, 25, 80, 25, title
  197.  
  198. ; Check for parameters TODO
  199. ;        cmp     byte[params], 0
  200. ;        jne     resolve
  201.  
  202. main:
  203.         invoke  con_cls
  204. ; Welcome user
  205.         invoke  con_write_asciiz, str1
  206.  
  207. prompt:
  208. ; write prompt
  209.         invoke  con_write_asciiz, str2
  210. ; read string
  211.         mov     esi, con.hostname
  212.         invoke  con_gets, esi, 256
  213. ; check for exit
  214.         test    eax, eax
  215.         jz      done
  216.         cmp     byte[esi], 10
  217.         jz      done
  218.  
  219. resolve:
  220.         mov     [con.sockaddr], AF_INET4
  221.         mov     [con.port], 22 shl 8
  222.  
  223. ; delete terminating '\n'
  224.         mov     esi, con.hostname
  225.   @@:
  226.         lodsb
  227.         cmp     al, ':'
  228.         je      .do_port
  229.         cmp     al, 0x20
  230.         ja      @r
  231.         mov     byte[esi-1], 0
  232.         jmp     .done
  233.  
  234.   .do_port:
  235.         xor     eax, eax
  236.         xor     ebx, ebx
  237.         mov     byte[esi-1], 0
  238.   .portloop:
  239.         lodsb
  240.         cmp     al, 0x20
  241.         jbe     .port_done
  242.         sub     al, '0'
  243.         jb      hostname_error
  244.         cmp     al, 9
  245.         ja      hostname_error
  246.         lea     ebx, [ebx*4+ebx]
  247.         shl     ebx, 1
  248.         add     ebx, eax
  249.         jmp     .portloop
  250.  
  251.   .port_done:
  252.         xchg    bl, bh
  253.         mov     [con.port], bx
  254.  
  255.   .done:
  256.  
  257. ; resolve name
  258.         push    esp     ; reserve stack place
  259.         push    esp
  260.         invoke  getaddrinfo, con.hostname, 0, 0
  261.         pop     esi
  262. ; test for error
  263.         test    eax, eax
  264.         jnz     dns_error
  265.  
  266.         invoke  con_write_asciiz, str3
  267.         invoke  con_write_asciiz, con.hostname
  268.  
  269. ; write results
  270.         invoke  con_write_asciiz, str8
  271.  
  272. ; convert IP address to decimal notation
  273.         mov     eax, [esi+addrinfo.ai_addr]
  274.         mov     eax, [eax+sockaddr_in.sin_addr]
  275.         mov     [con.ip], eax
  276.         invoke  inet_ntoa, eax
  277. ; write result
  278.         invoke  con_write_asciiz, eax
  279. ; free allocated memory
  280.         invoke  freeaddrinfo, esi
  281.  
  282.         invoke  con_write_asciiz, str9
  283.  
  284.         mcall   40, EVM_STACK + EVM_KEY
  285.  
  286. ; Create socket
  287.         mcall   socket, AF_INET4, SOCK_STREAM, 0
  288.         cmp     eax, -1
  289.         jz      socket_err
  290.         mov     [con.socketnum], eax
  291.  
  292. ; Connect
  293.         DEBUGF  2, "Connecting to server\n"
  294.         mcall   connect, [con.socketnum], con.sockaddr, 18
  295.         test    eax, eax
  296.         jnz     socket_err
  297.  
  298. ; Start calculating hash
  299.         invoke  sha256_init, con.temp_ctx
  300. ; HASH: string  V_C, the client's version string (CR and NL excluded)
  301.         invoke  sha256_update, con.temp_ctx, ssh_ident_ha, ssh_ident.length+4-2
  302.  
  303. ; >> Send our identification string
  304.         DEBUGF  2, "Sending ID string\n"
  305.         mcall   send, [con.socketnum], ssh_ident, ssh_ident.length, 0
  306.         cmp     eax, -1
  307.         je      socket_err
  308.  
  309. ; << Check protocol version of server
  310.         mcall   recv, [con.socketnum], con.rx_buffer, BUFFERSIZE, 0
  311.         cmp     eax, -1
  312.         je      socket_err
  313.  
  314.         DEBUGF  2, "Received ID string\n"
  315.         cmp     dword[con.rx_buffer], "SSH-"
  316.         jne     proto_err
  317.         cmp     dword[con.rx_buffer+4], "2.0-"
  318.         jne     proto_err
  319.  
  320. ; HASH: string  V_S, the server's version string (CR and NL excluded)
  321.         lea     edx, [eax+2]
  322.         sub     eax, 2
  323.         bswap   eax
  324.         mov     dword[con.rx_buffer-4], eax
  325.         invoke  sha256_update, con.temp_ctx, con.rx_buffer-4, edx
  326.  
  327. ; >> Key Exchange init
  328.         mov     [con.rx_seq], 0
  329.         mov     [con.tx_seq], 0
  330.         mov     [con.rx_crypt_blocksize], 4             ; minimum blocksize
  331.         mov     [con.tx_crypt_blocksize], 4
  332.         mov     [con.rx_crypt_proc], 0
  333.         mov     [con.tx_crypt_proc], 0
  334.         mov     [con.rx_mac_proc], 0
  335.         mov     [con.tx_mac_proc], 0
  336.         mov     [con.rx_mac_length], 0
  337.         mov     [con.tx_mac_length], 0
  338.         mov     [con.rx_padsize], 8                     ; minimum padsize
  339.         mov     [con.tx_padsize], 8
  340.  
  341.         DEBUGF  2, "Sending KEX init\n"
  342.         mov     edi, ssh_kex.cookie
  343.         call    MBRandom
  344.         stosd
  345.         call    MBRandom
  346.         stosd
  347.         call    MBRandom
  348.         stosd
  349.         call    MBRandom
  350.         stosd
  351.         stdcall ssh_send_packet, con, ssh_kex, ssh_kex.length, 0
  352.         cmp     eax, -1
  353.         je      socket_err
  354.  
  355. ; HASH: string  I_C, the payload of the client's SSH_MSG_KEXINIT
  356.         mov     eax, dword[con.tx_buffer+ssh_packet_header.packet_length]
  357.         bswap   eax
  358.         movzx   ebx, [con.tx_buffer+ssh_packet_header.padding_length]
  359.         sub     eax, ebx
  360.         dec     eax
  361.         lea     edx, [eax+4]
  362.         bswap   eax
  363.         mov     dword[con.tx_buffer+1], eax
  364.         invoke  sha256_update, con.temp_ctx, con.tx_buffer+1, edx
  365.  
  366. ; << Check key exchange init of server
  367.         stdcall ssh_recv_packet, con, 0
  368.         cmp     eax, -1
  369.         je      socket_err
  370.  
  371.         cmp     [con.rx_buffer.message_code], SSH_MSG_KEXINIT
  372.         jne     proto_err
  373.         DEBUGF  2, "Received KEX init\n"
  374.  
  375.         lea     esi, [con.rx_buffer+sizeof.ssh_packet_header+16]
  376.         lodsd
  377.         bswap   eax
  378.         DEBUGF  1, "kex_algorithms: %s\n", esi
  379.         add     esi, eax
  380.         lodsd
  381.         bswap   eax
  382.         DEBUGF  1, "server_host_key_algorithms: %s\n", esi
  383.         add     esi, eax
  384.         lodsd
  385.         bswap   eax
  386.         DEBUGF  1, "encryption_algorithms_client_to_server: %s\n", esi
  387.         add     esi, eax
  388.         lodsd
  389.         bswap   eax
  390.         DEBUGF  1, "encryption_algorithms_server_to_client: %s\n", esi
  391.         add     esi, eax
  392.         lodsd
  393.         bswap   eax
  394.         DEBUGF  1, "mac_algorithms_client_to_server: %s\n", esi
  395.         add     esi, eax
  396.         lodsd
  397.         bswap   eax
  398.         DEBUGF  1, "mac_algorithms_server_to_client: %s\n", esi
  399.         add     esi, eax
  400.         lodsd
  401.         bswap   eax
  402.         DEBUGF  1, "compression_algorithms_client_to_server: %s\n", esi
  403.         add     esi, eax
  404.         lodsd
  405.         bswap   eax
  406.         DEBUGF  1, "compression_algorithms_server_to_client: %s\n", esi
  407.         add     esi, eax
  408.         lodsd
  409.         bswap   eax
  410.         DEBUGF  1, "languages_client_to_server: %s\n", esi
  411.         add     esi, eax
  412.         lodsd
  413.         bswap   eax
  414.         DEBUGF  1, "languages_server_to_client: %s\n", esi
  415.         add     esi, eax
  416.         lodsb
  417.         DEBUGF  1, "KEX First Packet Follows: %u\n", al
  418.  
  419. ; TODO: parse this structure and init procedures accordingly
  420.  
  421. ; HASH: string I_S, the payload of the servers's SSH_MSG_KEXINIT
  422.         mov     eax, dword[con.rx_buffer+ssh_packet_header.packet_length]
  423.         movzx   ebx, [con.rx_buffer+ssh_packet_header.padding_length]
  424.         sub     eax, ebx
  425.         dec     eax
  426.         lea     edx, [eax+4]
  427.         bswap   eax
  428.         mov     dword[con.rx_buffer+sizeof.ssh_packet_header-5], eax
  429.         invoke  sha256_update, con.temp_ctx, con.rx_buffer+sizeof.ssh_packet_header-5, edx
  430.  
  431. ; Exchange keys with the server
  432.  
  433. ; TODO: host verification
  434.  
  435.         stdcall dh_gex
  436.         test    eax, eax
  437.         jnz     exit
  438.  
  439. ; Set keys
  440.  
  441.         DEBUGF  2, "SSH: Setting encryption keys\n"
  442.  
  443.         stdcall aes256_ctr_init, con.rx_iv
  444.         mov     [con.rx_crypt_ctx_ptr], eax
  445.  
  446.         stdcall aes256_set_encrypt_key, eax, con.rx_enc_key
  447.         mov     [con.rx_crypt_proc], aes256_ctr_crypt
  448.         mov     [con.rx_crypt_blocksize], AES256_BLOCKSIZE
  449.         mov     [con.rx_padsize], AES256_BLOCKSIZE
  450.  
  451.         stdcall aes256_ctr_init, con.tx_iv
  452.         mov     [con.tx_crypt_ctx_ptr], eax
  453.  
  454.         stdcall aes256_set_encrypt_key, eax, con.tx_enc_key
  455.         mov     [con.tx_crypt_proc], aes256_ctr_crypt
  456.         mov     [con.tx_crypt_blocksize], AES256_BLOCKSIZE
  457.         mov     [con.tx_padsize], AES256_BLOCKSIZE
  458.  
  459.         stdcall hmac_sha256_setkey, con.rx_mac_ctx, con.rx_int_key, SHA256_HASH_SIZE
  460.         mov     [con.rx_mac_proc], hmac_sha256
  461.         mov     [con.rx_mac_length], SHA256_HASH_SIZE
  462.  
  463.         stdcall hmac_sha256_setkey, con.tx_mac_ctx, con.tx_int_key, SHA256_HASH_SIZE
  464.         mov     [con.tx_mac_proc], hmac_sha256
  465.         mov     [con.tx_mac_length], SHA256_HASH_SIZE
  466.  
  467. ; TODO: erase all keys from memory and free the memory
  468.  
  469. ; >> Request service (user-auth)
  470.  
  471.         DEBUGF  2, "SSH: Requesting service\n"
  472.  
  473.         stdcall ssh_send_packet, con, ssh_request_service, ssh_request_service.length, 0
  474.         cmp     eax, -1
  475.         je      socket_err
  476.  
  477. ; << Check for service acceptance
  478.  
  479.         stdcall ssh_msg_handler, con, 0
  480.         cmp     eax, -1
  481.         je      socket_err
  482.  
  483.         cmp     [con.rx_buffer.message_code], SSH_MSG_SERVICE_ACCEPT
  484.         jne     proto_err
  485.  
  486. ; >> Request user authentication
  487.  
  488.         DEBUGF  2, "SSH: User authentication\n"
  489.  
  490.         mcall   68, 12, 1024    ; FIXME
  491.         test    eax, eax
  492.         jz      done            ; FIXME
  493.         mov     edi, eax
  494.         mov     ebx, eax
  495.         mov     byte[edi], SSH_MSG_USERAUTH_REQUEST
  496.         inc     edi
  497.  
  498.         ; Get username
  499.         add     edi, 4
  500.         invoke  con_write_asciiz, str12
  501.         invoke  con_gets, edi, 256      ; FIXME
  502.         test    eax, eax
  503.         jz      done            ; FIXME
  504.  
  505.         mov     edx, eax
  506.         mov     ecx, 256
  507.         xor     al, al
  508.         repne   scasb
  509.  
  510.         dec     edi             ; \0
  511.         dec     edi             ; \n
  512.         push    edi
  513.         sub     edi, edx
  514.         bswap   edi
  515.         mov     [edx-4], edi
  516.         pop     edi
  517.  
  518.         mov     dword[edi], 0x0e000000  ; 14 Bswapped
  519.         mov     dword[edi+4], "ssh-"
  520.         mov     dword[edi+8], "conn"
  521.         mov     dword[edi+12], "ecti"
  522.         mov     word[edi+16], "on"
  523.         add     edi, 18
  524.  
  525.         mov     dword[edi], 0x08000000  ; 8 Bswapped
  526.         mov     dword[edi+4], "pass"
  527.         mov     dword[edi+8], "word"
  528.  
  529.         mov     byte[edi+12], 0         ; bool
  530.         add     edi, 13
  531.  
  532.         ; Get password
  533.         add     edi, 4
  534.         invoke  con_write_asciiz, str13
  535.         push    eax
  536.         invoke  con_gets, edi, 256      ; FIXME
  537.         test    eax, eax
  538.         jz      done            ; FIXME
  539.  
  540.         mov     edx, eax
  541.         mov     ecx, 256
  542.         xor     al, al
  543.         repne scasb
  544.  
  545.         dec     edi             ; \0
  546.         dec     edi             ; \n
  547.         push    edi
  548.         sub     edi, edx
  549.         bswap   edi
  550.         mov     [edx-4], edi
  551.         pop     edi
  552.         sub     edi, ebx
  553.  
  554.         push    ebx
  555.         stdcall ssh_send_packet, con, ebx, edi, 0
  556.  
  557.         ; Clear used buffer and free
  558.         pop     edx
  559.         mov     edi, edx
  560.         push    eax
  561.         mov     ecx, 1024/4     ; FIXME
  562.         xor     eax, eax
  563.         rep stosd
  564.         mcall   68, 13, edx
  565.         pop     eax
  566.  
  567.         cmp     eax, -1
  568.         je      socket_err
  569.  
  570.         invoke  con_write_asciiz, str14
  571.  
  572. ; << Check for userauth acceptance
  573.  
  574.         stdcall ssh_msg_handler, con, 0
  575.         cmp     eax, -1
  576.         je      socket_err
  577.  
  578.         cmp     [con.rx_buffer.message_code], SSH_MSG_USERAUTH_SUCCESS
  579.         jne     proto_err
  580.  
  581. ; >> Open channel
  582.  
  583.         DEBUGF  2, "SSH: Open channel\n"
  584.  
  585.         stdcall ssh_send_packet, con, ssh_channel_open, ssh_channel_open.length, 0
  586.         cmp     eax, -1
  587.         je      socket_err
  588.  
  589. ; << Check for channel open confirmation
  590.  
  591.         stdcall ssh_msg_handler, con, 0
  592.         cmp     eax, -1
  593.         je      socket_err
  594.  
  595.         cmp     [con.rx_buffer.message_code], SSH_MSG_CHANNEL_OPEN_CONFIRMATION
  596.         jne     proto_err
  597.  
  598. ; >> Channel request: pty
  599.  
  600.         DEBUGF  2, "SSH: Request pty\n"
  601.  
  602.         stdcall ssh_send_packet, con, ssh_channel_request, ssh_channel_request.length, 0
  603.         cmp     eax, -1
  604.         je      socket_err
  605.  
  606. ; << Check for channel request confirmation
  607.  
  608.         stdcall ssh_msg_handler, con, 0
  609.         cmp     eax, -1
  610.         je      socket_err
  611.  
  612.         cmp     [con.rx_buffer.message_code], SSH_MSG_CHANNEL_SUCCESS
  613.         jne     proto_err
  614.  
  615. ; >> Channel request: shell
  616.  
  617.         DEBUGF  2, "SSH: Request shell\n"
  618.  
  619.         stdcall ssh_send_packet, con, ssh_shell_request, ssh_shell_request.length, 0
  620.         cmp     eax, -1
  621.         je      socket_err
  622.  
  623. ; << Check for channel request confirmation (FIXME: this may not be first packet!)
  624.  
  625. ; TODO
  626. ;
  627. ;        stdcall ssh_msg_handler, con, 0
  628. ;        cmp     eax, -1
  629. ;        je      socket_err
  630.  
  631. ;        cmp     [con.rx_buffer.message_code], SSH_MSG_CHANNEL_SUCCESS
  632. ;        jne     proto_err
  633.  
  634. ; Launch network thread
  635.         mcall   18, 7
  636.         push    eax
  637.         mcall   51, 1, thread, mem - 2048
  638.         pop     ecx
  639.         mcall   18, 3
  640.  
  641. mainloop:
  642.         call    [con_get_flags]
  643.         test    eax, 0x200                      ; con window closed?
  644.         jnz     exit
  645.  
  646.         stdcall ssh_msg_handler, con, 0
  647.         cmp     eax, 0
  648.         jbe     closed
  649.  
  650.         cmp     [con.rx_buffer.message_code], SSH_MSG_CHANNEL_DATA
  651.         jne     .dump
  652.  
  653.         mov     eax, dword[con.rx_buffer.message_code+5]
  654.         bswap   eax
  655.         DEBUGF  1, 'SSH: got %u bytes of data !\n', eax
  656.  
  657.         lea     esi, [con.rx_buffer.message_code+5+4]
  658.         mov     ecx, eax
  659.         lea     edi, [esi + eax]
  660.         mov     byte [edi], 0
  661.         invoke  con_write_asciiz, esi
  662.         jmp     mainloop
  663.  
  664.   .dump:
  665.         lea     esi, [con.rx_buffer]
  666.         mov     ecx, eax
  667.         pusha
  668. @@:
  669.         lodsb
  670.         DEBUGF  1, "%x ", eax:2
  671.         dec     ecx
  672.         jnz     @r
  673.         popa
  674.         DEBUGF  1, "\n"
  675.         jmp     mainloop
  676.  
  677.  
  678. proto_err:
  679.         mov     eax, con.rx_buffer
  680.         int3
  681.  
  682.         DEBUGF  3, "SSH: protocol error\n"
  683.         invoke  con_write_asciiz, str7
  684.         jmp     prompt
  685.  
  686. socket_err:
  687.         DEBUGF  3, "SSH: socket error %d\n", ebx
  688.         invoke  con_write_asciiz, str6
  689.         jmp     prompt
  690.  
  691. dns_error:
  692.         DEBUGF  3, "SSH: DNS error %d\n", eax
  693.         invoke  con_write_asciiz, str5
  694.         jmp     prompt
  695.  
  696. hostname_error:
  697.         invoke  con_write_asciiz, str10
  698.         jmp     prompt
  699.  
  700. closed:
  701.         invoke  con_write_asciiz, str11
  702.         jmp     prompt
  703.  
  704. done:
  705.         invoke  con_exit, 1
  706. exit:
  707.         DEBUGF  3, "SSH: Exiting\n"
  708.         mcall   close, [con.socketnum]
  709.         mcall   -1
  710.  
  711.  
  712. thread:
  713.         mcall   40, 0
  714.   .loop:
  715.         invoke  con_getch2
  716.         mov     [ssh_channel_data+9], al
  717.         stdcall ssh_send_packet, con, ssh_channel_data, ssh_channel_data.length, MSG_DONTWAIT
  718.  
  719.         invoke  con_get_flags
  720.         test    eax, 0x200                      ; con window closed?
  721.         jz      .loop
  722.         mcall   -1
  723.  
  724.  
  725. ; Handle common messages and return from specific ones
  726. proc ssh_msg_handler, con, flags
  727.  
  728.   .recv:
  729.         stdcall ssh_recv_packet, [con], [flags]
  730.         cmp     eax, -1
  731.         je      .ret
  732.  
  733.         cmp     [con.rx_buffer.message_code], SSH_MSG_DISCONNECT
  734.         je      .disc
  735.         cmp     [con.rx_buffer.message_code], SSH_MSG_IGNORE
  736.         je      .ign
  737.         cmp     [con.rx_buffer.message_code], SSH_MSG_DEBUG
  738.         je      .dbg
  739.         cmp     [con.rx_buffer.message_code], SSH_MSG_GLOBAL_REQUEST
  740.         je      .glob
  741.  
  742.   .ret:
  743.         ret
  744.  
  745.   .disc:
  746.         mov     eax, -1
  747.         ret
  748.  
  749.   .ign:
  750.         jmp     .recv
  751.  
  752.   .dbg:
  753.   .glob:
  754.         ; TODO
  755.  
  756.         jmp     .recv
  757.  
  758. endp
  759.  
  760. ; data
  761. title   db      'Secure Shell',0
  762. str1    db      'SSH client for KolibriOS',10,10,\
  763.                 'Please enter URL of SSH server (hostname:port)',10,10,0
  764. str2    db      '> ',0
  765. str3    db      'Connecting to ',0
  766. str4    db      10,0
  767. str5    db      'Name resolution failed.',10,10,0
  768. str6    db      'A socket error occured.',10,10,0
  769. str7    db      'A protocol error occured.',10,10,0
  770. str8    db      ' (',0
  771. str9    db      ')',10,0
  772. str10   db      'Invalid hostname.',10,10,0
  773. str11   db      10,'Remote host closed the connection.',10,10,0
  774. str12   db      'Login as: ',0
  775. str13   db      'Password: ', 27, '[?25l', 27, '[30;40m', 0
  776. str14   db      10, 27, '[?25h', 27, '[0m', 0
  777.  
  778. ssh_ident_ha:
  779.         dd_n (ssh_ident.length-2)
  780. ssh_ident:
  781.         db "SSH-2.0-KolibriOS_SSH_0.03",13,10
  782.   .length = $ - ssh_ident
  783.  
  784. ssh_kex:
  785.         db SSH_MSG_KEXINIT
  786.   .cookie:
  787.         rd 4
  788.   .kex_algorithms:
  789.         dd_n .server_host_key_algorithms - .kex_algorithms - 4
  790.         db "diffie-hellman-group-exchange-sha256" ; diffie-hellman-group-exchange-sha1
  791.   .server_host_key_algorithms:
  792.         dd_n .encryption_algorithms_client_to_server - .server_host_key_algorithms - 4
  793.         db "ssh-rsa"                    ;,ssh-dss
  794.   .encryption_algorithms_client_to_server:
  795.         dd_n .encryption_algorithms_server_to_client - .encryption_algorithms_client_to_server - 4
  796.         db "aes256-ctr"                 ;,aes256-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se,aes192-ctr,aes192-cbc,aes128-ctr,aes128-cbc,blowfish-ctr,blowfish-cbc,3des-ctr,3des-cbc,arcfour256,arcfour128"
  797.   .encryption_algorithms_server_to_client:
  798.         dd_n .mac_algorithms_client_to_server - .encryption_algorithms_server_to_client - 4
  799.         db "aes256-ctr"                 ;,aes256-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se,aes192-ctr,aes192-cbc,aes128-ctr,aes128-cbc,blowfish-ctr,blowfish-cbc,3des-ctr,3des-cbc,arcfour256,arcfour128"
  800.   .mac_algorithms_client_to_server:
  801.         dd_n .mac_algorithms_server_to_client - .mac_algorithms_client_to_server - 4
  802.         db "hmac-sha2-256"              ;,hmac-sha1,hmac-sha1-96,hmac-md5"
  803.   .mac_algorithms_server_to_client:
  804.         dd_n .compression_algorithms_client_to_server - .mac_algorithms_server_to_client - 4
  805.         db "hmac-sha2-256"              ;,hmac-sha1,hmac-sha1-96,hmac-md5"
  806.   .compression_algorithms_client_to_server:
  807.         dd_n .compression_algorithms_server_to_client - .compression_algorithms_client_to_server - 4
  808.         db "none"                       ;,zlib"
  809.   .compression_algorithms_server_to_client:
  810.         dd_n .languages_client_to_server - .compression_algorithms_server_to_client - 4
  811.         db "none"                       ;,zlib"
  812.   .languages_client_to_server:
  813.         dd_n .languages_server_to_client - .languages_client_to_server - 4
  814.         db ""
  815.   .languages_server_to_client:
  816.         dd_n .first_kex_packet_follows - .languages_server_to_client - 4
  817.         db ""
  818.   .first_kex_packet_follows:
  819.         db 0
  820.   .reserved:
  821.         dd_n 0
  822.   .length = $ - ssh_kex
  823.  
  824.  
  825. ssh_gex_req:
  826.         db SSH_MSG_KEX_DH_GEX_REQUEST
  827.         dd_n 4096/4                      ; DH GEX min
  828.         dd_n 4096/2                      ; DH GEX number of bits
  829.         dd_n 4096                        ; DH GEX Max
  830.   .length = $ - ssh_gex_req
  831.  
  832.  
  833. ssh_new_keys:
  834.         db SSH_MSG_NEWKEYS
  835.   .length = $ - ssh_new_keys
  836.  
  837.  
  838. ssh_request_service:
  839.         db SSH_MSG_SERVICE_REQUEST
  840.         dd_n 12                         ; String length
  841.         db "ssh-userauth"               ; Service name
  842.   .length = $ - ssh_request_service
  843.  
  844.  
  845. ssh_request_userauth:
  846.         db SSH_MSG_USERAUTH_REQUEST
  847.         dd_n 9
  848.         db "user123"                    ; user name in ISO-10646 UTF-8 encoding [RFC3629]
  849.         dd_n 14
  850.         db "ssh-connection"             ; service name in US-ASCII
  851.         dd_n 8
  852.         db "password"                   ; method name in US-ASCII: none, publickey, password, hostbased
  853.         db 0                            ; bool: false
  854.         dd_n 14
  855.         db "pass123"
  856.   .length = $ - ssh_request_userauth
  857.  
  858.  
  859. ssh_channel_open:
  860.         db SSH_MSG_CHANNEL_OPEN
  861.         dd_n 7
  862.         db "session"
  863.         dd_n 0                          ; Sender channel
  864.         dd_n 1024                       ; Initial window size
  865.         dd_n 1024                       ; maximum packet size
  866.   .length = $ - ssh_channel_open
  867.  
  868. ssh_channel_request:
  869.         db SSH_MSG_CHANNEL_REQUEST
  870.         dd_n 0                          ; Recipient channel
  871.         dd_n 7
  872.         db "pty-req"
  873.         db 1                            ; Bool: want reply
  874.         dd_n 5
  875.         db "xterm"
  876.         dd_n 80                         ; terminal width (rows)
  877.         dd_n 25                         ; terminal height (rows)
  878.         dd_n 0                          ; terminal width (pixels)
  879.         dd_n 0                          ; terminal height (pixels)
  880.  
  881.         dd_n 0                          ; list of supported opcodes
  882.   .length = $ - ssh_channel_request
  883.  
  884. ssh_shell_request:
  885.         db SSH_MSG_CHANNEL_REQUEST
  886.         dd_n 0                          ; Recipient channel
  887.         dd_n 5
  888.         db "shell"
  889.         db 1                            ; Bool: want reply
  890.   .length = $ - ssh_shell_request
  891.  
  892. ssh_channel_data:
  893.         db SSH_MSG_CHANNEL_DATA
  894.         dd_n 0                          ; Sender channel
  895.         dd_n 1
  896.         db ?
  897.   .length = $ - ssh_channel_data
  898.  
  899.  
  900. include_debug_strings
  901.  
  902. align 4
  903. @IMPORT:
  904.  
  905. library network, 'network.obj', \
  906.         console, 'console.obj', \
  907.         libcrash, 'libcrash.obj'
  908.  
  909. import  network, \
  910.         getaddrinfo, 'getaddrinfo', \
  911.         freeaddrinfo, 'freeaddrinfo', \
  912.         inet_ntoa, 'inet_ntoa'
  913.  
  914. import  console, \
  915.         con_start, 'START', \
  916.         con_init, 'con_init', \
  917.         con_write_asciiz, 'con_write_asciiz', \
  918.         con_exit, 'con_exit', \
  919.         con_gets, 'con_gets', \
  920.         con_cls, 'con_cls', \
  921.         con_getch2, 'con_getch2', \
  922.         con_set_cursor_pos, 'con_set_cursor_pos', \
  923.         con_write_string, 'con_write_string', \
  924.         con_get_flags,  'con_get_flags', \
  925.         con_set_flags,  'con_set_flags'
  926.  
  927. import  libcrash, \
  928.         sha256_init, 'sha256_init', \
  929.         sha256_update, 'sha256_update', \
  930.         sha256_final, 'sha256_final',\
  931.         sha1_init, 'sha1_init', \
  932.         sha1_update, 'sha1_update', \
  933.         sha1_final, 'sha1_final', \
  934.         md5_init, 'md5_init', \
  935.         md5_update, 'md5_update', \
  936.         md5_final, 'md5_final'
  937.  
  938. IncludeIGlobals
  939.  
  940. i_end:
  941.  
  942. IncludeUGlobals
  943.  
  944. params          rb 1024
  945.  
  946. con             ssh_connection
  947.  
  948. mem:
  949.