Subversion Repositories Kolibri OS

Rev

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