Subversion Repositories Kolibri OS

Rev

Rev 9112 | Rev 9114 | 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__         = 2             ; 1: Everything, including sensitive information, 2: Debugging, 3: Errors only
  22.  
  23. BUFFERSIZE              = 64*1024       ; Must be at least 32K according rfc4253#section-6.1
  24. PACKETSIZE              = 32*1024       ; Must be at least 32K according rfc4253#section-6.1
  25. MAX_BITS                = 8192
  26.  
  27. DH_PRIVATE_KEY_SIZE     = 256
  28. MAX_INPUT_LENGTH        = 255 ;;; WHAT WAS THIS AGAIN ?!
  29. MAX_USERNAME_LENGTH     = 256
  30. MAX_PASSWORD_LENGTH     = 256
  31. MAX_HOSTNAME_LENGTH     = 4096
  32. MAX_PUBLIC_KEY_SIZE     = 4096
  33.  
  34. use32
  35.  
  36.         db      'MENUET01'      ; signature
  37.         dd      1               ; header version
  38.         dd      start           ; entry point
  39.         dd      i_end           ; initialized size
  40.         dd      mem+65536       ; required memory
  41.         dd      mem+65536       ; stack pointer
  42.         dd      params          ; parameters
  43.         dd      0               ; path
  44.  
  45. include '../../macros.inc'
  46. ;include '../../struct.inc'
  47. purge mov,add,sub
  48. include '../../proc32.inc'
  49. include '../../dll.inc'
  50. include '../../debug-fdo.inc'
  51. include '../../network.inc'
  52. include '../../develop/libraries/libcrash/trunk/libcrash.inc'
  53.  
  54. ; macros for network byte order
  55. macro dd_n op {
  56.    dd 0 or (((op) and 0FF000000h) shr 24) or \
  57.            (((op) and 000FF0000h) shr  8) or \
  58.            (((op) and 00000FF00h) shl  8) or \
  59.            (((op) and 0000000FFh) shl 24)
  60. }
  61.  
  62. macro dw_n op {
  63.    dw 0 or (((op) and 0FF00h) shr 8) or \
  64.            (((op) and 000FFh) shl 8)
  65. }
  66.  
  67. macro str string {
  68.     local .start, .stop
  69.  
  70.     dd_n (.stop-.start)
  71.  
  72.     .start db string
  73.     .stop:
  74. }
  75.  
  76. proc dump_hex _ptr, _length
  77. if __DEBUG_LEVEL__ <= 1
  78.         pushad
  79.  
  80.         mov     esi, [_ptr]
  81.         mov     ecx, [_length]
  82.   .next_dword:
  83.         lodsd
  84.         bswap   eax
  85.         DEBUGF  1,'%x', eax
  86.         loop    .next_dword
  87.         DEBUGF  1,'\n'
  88.  
  89.         popad
  90. end if
  91.         ret
  92. endp
  93.  
  94. macro DEBUGM l, s, m {
  95. if __DEBUG__
  96.         DEBUGF  l, s
  97.   if l >=__DEBUG_LEVEL__
  98.         stdcall mpint_print, m
  99.   end if
  100. end if
  101. }
  102.  
  103. include 'mpint.inc'
  104. include 'seed.inc'
  105. include 'random.inc'
  106.  
  107. include 'aes256.inc'
  108. include 'aes256-ctr.inc'
  109. include 'aes256-cbc.inc'
  110.  
  111. include 'blowfish.inc'
  112. include 'blowfish-ctr.inc'
  113. include 'blowfish-cbc.inc'
  114.  
  115. include 'hmac_sha256.inc'
  116. include 'hmac_sha1.inc'
  117. include 'hmac_md5.inc'
  118.  
  119. include 'sshlib.inc'
  120.  
  121. include 'sshlib_mcodes.inc'
  122. include 'sshlib_transport.inc'
  123. include 'sshlib_connection.inc'
  124. include 'sshlib_dh_gex.inc'
  125. include 'sshlib_host.inc'
  126. include 'sshlib_channel.inc'
  127. include 'sshlib_userauth.inc'
  128.  
  129. include 'encodings.inc'         ; Unfortunately, we dont have UTF-8 capable console yet :(
  130.  
  131. start:
  132.         mcall   68, 11          ; Init heap
  133.  
  134.         DEBUGF  2, "SSH: Loading libraries\n"
  135.         stdcall dll.Load, @IMPORT
  136.         test    eax, eax
  137.         jnz     main.fail
  138.  
  139.         DEBUGF  2, "SSH: Init PRNG\n"
  140.         call    create_seed
  141.         call    init_random
  142.  
  143.         DEBUGF  2, "SSH: Init Console\n"
  144.         invoke  con_start, 1
  145.         invoke  con_init, 80, 25, 80, 250, title
  146.  
  147.         cmp     byte[params], 0
  148.         jne     main.connect
  149.  
  150. main:
  151.         invoke  con_cls
  152. ; Welcome user
  153.         invoke  con_write_asciiz, str1a
  154.   .prompt:
  155.         invoke  con_write_asciiz, str1b
  156. ; Reset window title
  157.         invoke  con_set_title, title
  158. ; Write prompt
  159.         invoke  con_write_asciiz, str2
  160. ; read string
  161.         mov     esi, params
  162.         invoke  con_gets, esi, MAX_HOSTNAME_LENGTH
  163. ; check for exit
  164.         test    eax, eax
  165.         jz      .done
  166.         cmp     byte[esi], 10
  167.         jz      .done
  168.  
  169.   .connect:
  170.         stdcall sshlib_connect, ssh_con, params
  171.         cmp     eax, 0
  172.         jg      .prompt
  173.         jl      .error
  174.  
  175.   .login:
  176.         mcall   68, 12, (MAX_USERNAME_LENGTH + MAX_PASSWORD_LENGTH)
  177.         test    eax, eax
  178.         jz      .done   ; ERR_NOMEM
  179.         mov     esi, eax
  180.         lea     edi, [eax + MAX_USERNAME_LENGTH]
  181.  
  182. ; Get username
  183.         invoke  con_write_asciiz, str12
  184.         invoke  con_gets, esi, MAX_USERNAME_LENGTH
  185.         test    eax, eax
  186. ;;        jz      .con_closed_must_clear
  187.  
  188. ; Get password
  189.         invoke  con_write_asciiz, str13a
  190.         invoke  con_gets, edi, MAX_PASSWORD_LENGTH
  191.         test    eax, eax
  192. ;;        jz      .con_closed_must_clear
  193.         invoke  con_write_asciiz, str13b
  194.  
  195. ; Authenticate
  196.         stdcall sshlib_userauth_password, ssh_con, esi, edi
  197. ; Clear and free username and password
  198.   .clear:
  199.         push    eax
  200.         mov     edx, edi
  201.         xor     eax, eax
  202.         mov     ecx, (MAX_USERNAME_LENGTH + MAX_PASSWORD_LENGTH)/4
  203.         rep     stosd
  204.         mcall   68, 13, edx
  205.         pop     eax
  206.  
  207.         cmp     eax, 0
  208.         jg      .login          ; Authentication failed
  209.         jl      .error          ; An error occured
  210.  
  211. ; Open a channel
  212.         stdcall sshlib_chan_open, ssh_con
  213.         cmp     eax, 0
  214.         jg      .prompt         ; Authentication failed
  215.         jl      .error          ; An error occured
  216.  
  217. ; Start console input handler thread without deactivating the current window
  218. ; Get active window ID
  219.         mcall   18, 7
  220.         push    eax
  221. ; Create thread
  222.         mcall   51, 1, con_in_thread, mem - 2048
  223. ; Activate window with given ID
  224.         pop     ecx
  225.         mcall   18, 3
  226.  
  227.   .loop:
  228.         invoke  con_get_flags
  229.         test    eax, 0x200                      ; console window closed?
  230.         jnz     .con_closed
  231.  
  232.         stdcall sshlib_msg_handler, ssh_con, 0
  233.         cmp     eax, 0
  234.         jle     .check_err
  235.  
  236.         cmp     [ssh_con.rx_buffer.message_code], SSH_MSG_CHANNEL_DATA
  237.         jne     .dump
  238.  
  239.         mov     eax, dword[ssh_con.rx_buffer.message_code+5]
  240.         bswap   eax
  241.         DEBUGF  1, 'SSH: got %u bytes of data !\n', eax
  242.  
  243.         lea     esi, [ssh_con.rx_buffer.message_code+5+4]
  244.         lea     edx, [esi+eax]
  245.         lea     edi, [ssh_con.rx_buffer]
  246.   @@:
  247.         call    get_byte_utf8
  248.         stosb
  249.         cmp     esi, edx
  250.         jb      @r
  251.         xor     al, al
  252.         stosb
  253.  
  254.         lea     esi, [ssh_con.rx_buffer]
  255.         DEBUGF  3, 'SSH msg: %s\n', esi
  256.  
  257.         invoke  con_write_asciiz, esi
  258.         jmp     .loop
  259.  
  260.   .dump:
  261.         DEBUGF  3, "SSH: Unsupported message: "
  262.         lea     esi, [ssh_con.rx_buffer.message_code]
  263.         mov     ecx, eax
  264.         pusha
  265.   @@:
  266.         lodsb
  267.         DEBUGF  3, "%x ", eax:2
  268.         dec     ecx
  269.         jnz     @r
  270.         popa
  271.         DEBUGF  3, "\n"
  272.         jmp     .loop
  273.  
  274.   .check_err:
  275.         jz      .err_conn_closed
  276.         cmp     ebx, EWOULDBLOCK
  277.         je      .loop
  278.         jmp     .err_sock
  279.  
  280.   .con_closed:
  281.         ; Send close message on the active channel
  282.         stdcall sshlib_send_packet, ssh_con, ssh_msg_channel_close, ssh_msg_channel_close.length, 0
  283.         jmp     .done
  284.  
  285.   .error:
  286.  
  287. ; TODO: proper cleanup after error
  288.  
  289.         cmp     eax, SSHLIB_ERR_NOMEM
  290.         je      .done
  291.         cmp     eax, SSHLIB_ERR_SOCKET
  292.         je      .err_sock
  293.         cmp     eax, SSHLIB_ERR_PROTOCOL
  294.         je      .err_proto
  295.         cmp     eax, SSHLIB_ERR_HOSTNAME
  296.         je      .err_hostname
  297.         cmp     eax, SSHLIB_ERR_HKEY_VERIFY_FAIL
  298.         je      .err_hostkey_fail
  299.         cmp     eax, SSHLIB_ERR_HKEY_SIGNATURE
  300.         je      .err_hostkey_signature
  301.         cmp     eax, SSHLIB_ERR_HKEY_PUBLIC_KEY
  302.         je      .err_hostkey
  303.  
  304.         jmp     .done
  305.  
  306.  
  307.   .err_proto:
  308. ;        lea     eax, [ssh_con.rx_buffer]
  309. ;        int3
  310.         invoke  con_write_asciiz, str7
  311.         jmp     .prompt
  312.  
  313.   .err_sock:
  314.         invoke  con_write_asciiz, str6
  315.  
  316.         mov     eax, str14
  317.         cmp     ebx, ETIMEDOUT
  318.         je      .err_sock_detail
  319.         mov     eax, str15
  320.         cmp     ebx, ECONNREFUSED
  321.         je      .err_sock_detail
  322.         mov     eax, str16
  323.         cmp     ebx, ECONNRESET
  324.         je      .err_sock_detail
  325.         mov     eax, str17
  326.   .err_sock_detail:
  327.         invoke  con_write_asciiz, eax
  328.         jmp     .prompt
  329.  
  330.   .err_hostname:
  331.         invoke  con_write_asciiz, str10
  332.         jmp     .prompt
  333.  
  334.   .err_conn_closed:
  335.         invoke  con_write_asciiz, str11
  336.         jmp     .prompt
  337.  
  338.   .err_hostkey:
  339.         invoke  con_write_asciiz, str19
  340.         jmp     .prompt
  341.  
  342.   .err_hostkey_signature:
  343.         invoke  con_write_asciiz, str20
  344.         jmp     .prompt
  345.  
  346.   .err_hostkey_fail:
  347.         invoke  con_write_asciiz, str21
  348.         jmp     .prompt
  349.  
  350.   .done:
  351.         invoke  con_exit, 1
  352.   .exit:
  353.         DEBUGF  3, "SSH: Exiting\n"
  354.         mcall   close, [ssh_con.socketnum]
  355.   .fail:
  356.         mcall   -1
  357.  
  358.  
  359. proc sshlib_callback_connecting, con_ptr, connstring_sz
  360.  
  361.         invoke  con_write_asciiz, str3
  362.         mov     eax, [con_ptr]
  363.         lea     eax, [eax+sshlib_connection.hostname_sz]
  364.         invoke  con_write_asciiz, eax
  365.         invoke  con_write_asciiz, str8
  366.         invoke  con_write_asciiz, [connstring_sz]
  367.         invoke  con_write_asciiz, str9
  368.  
  369.         ret
  370. endp
  371.  
  372.  
  373. proc sshlib_callback_hostkey_problem, con_ptr, problem_type, hostkey_sz
  374.  
  375.         cmp     [problem_type], SSHLIB_HOSTKEY_PROBLEM_UNKNOWN
  376.         je      .unknown
  377.         cmp     [problem_type], SSHLIB_HOSTKEY_PROBLEM_MISMATCH
  378.         je      .mismatch
  379.  
  380.         mov     eax, -1
  381.         ret
  382.  
  383.   .unknown:
  384.         invoke  con_write_asciiz, str22
  385.         jmp     .ask
  386.  
  387.   .mismatch:
  388.         invoke  con_write_asciiz, str23
  389. ;        jmp     .ask
  390.   .ask:
  391.         invoke  con_write_asciiz, str24a
  392.         invoke  con_write_asciiz, [hostkey_sz]
  393.         invoke  con_write_asciiz, str24b
  394.   .getansw:
  395.         invoke  con_getch2
  396.         or      al, 0x20        ; convert to lowercase
  397.         cmp     al, 'a'
  398.         je      .accept
  399.         cmp     al, 'c'
  400.         je      .once
  401.         cmp     al, 'x'
  402.         je      .refuse
  403.         jmp     .getansw
  404.  
  405.   .accept:
  406.         mov     eax, SSHLIB_HOSTKEY_ACCEPT
  407.         ret
  408.   .once:
  409.         mov     eax, SSHLIB_HOSTKEY_ONCE
  410.         ret
  411.   .refuse:
  412.         mov     eax, SSHLIB_HOSTKEY_REFUSE
  413.         ret
  414.  
  415. endp
  416.  
  417.  
  418.  
  419. align 16
  420. con_in_thread:
  421.  
  422.   .loop:
  423. ; TODO: check if channel is still open somehow
  424.  
  425.         invoke  con_get_input, ssh_msg_channel_data.data, MAX_INPUT_LENGTH
  426.         test    eax, eax
  427.         jz      .no_input
  428.  
  429.         lea     ecx, [eax + ssh_msg_channel_data.data - ssh_msg_channel_data]
  430.         bswap   eax
  431.         mov     [ssh_msg_channel_data.len], eax
  432.         stdcall sshlib_send_packet, ssh_con, ssh_msg_channel_data, ecx, 0
  433.         cmp     eax, 0
  434.         jle     .exit
  435.  
  436.   .no_input:
  437.         invoke  con_get_flags
  438.         test    eax, 0x200                      ; con window closed?
  439.         jz      .loop
  440.  
  441.   .exit:
  442.         mcall   -1
  443.  
  444.  
  445. ; data
  446. title   db 'Secure Shell',0
  447. str1a   db 'SSHv2 client for KolibriOS',10,0
  448. str1b   db 10,'Please enter URL of SSH server (hostname:port)',10,0
  449. str2    db '> ',0
  450. str3    db 'Connecting to ',0
  451. str4    db 10,0
  452. str6    db 10, 27, '[2J',27,'[mA network error has occured.',10,0
  453. str7    db 10, 27, '[2J',27,'[mAn SSH protocol error has occured.',10,0
  454. str8    db ' (',0
  455. str9    db ')',10,0
  456. str10   db 'Host does not exist.',10,10,0
  457. str11   db 10, 27, '[2J',27,'[mThe remote host closed the connection.',10,0
  458. str12   db 'Login as: ',0
  459. str13a  db 'Password: ', 27, '[?25l', 27, '[30;40m', 0
  460. str13b  db 10, 27, '[?25h', 27, '[0m', 27, '[2J', 0
  461. str14   db 'The connection timed out',10,0
  462. str15   db 'The connection was refused',10,0
  463. str16   db 'The connection was reset',10,0
  464. str17   db 'No details available',10,0
  465. ;str18   db 'User authentication failed',10,0;;;;
  466. str19   db "The remote host's public key is invalid.", 10, 0
  467. str20   db "The remote host's signature is invalid.", 10, 0
  468. str21   db "The remote host failed to verify it's own public key.", 10, 0
  469. str22   db "The host key for the server was not found in the cache.", 10
  470.         db "There is no guarantee to the servers identity !",10, 0
  471.  
  472. str23   db "The host key provided by the host does not match the cached one.", 10
  473.         db "This may indicate that the remote server has been compromised!", 10, 0
  474.  
  475. str24a  db 10, "The remote host key is: ", 10, 0
  476. str24b  db 10, 10, "If you trust this host, press A to accept and store the (new) key.", 10
  477.         db "Press C to connect to the host but don't store the (new) key.", 10
  478.         db "Press X to abort.", 10, 0
  479.  
  480.  
  481. ssh_ident_ha:
  482.         dd_n (ssh_msg_ident.length-2)
  483. ssh_msg_ident:
  484.         db "SSH-2.0-KolibriOS_SSH_0.07",13,10
  485.   .length = $ - ssh_msg_ident
  486.  
  487.  
  488. ssh_msg_kex:
  489.         db SSH_MSG_KEXINIT
  490.   .cookie:
  491.         rd 4
  492.   .kex_algorithms:
  493.         str "diffie-hellman-group-exchange-sha256" ; diffie-hellman-group-exchange-sha1
  494.   .server_host_key_algorithms:
  495.         str "rsa-sha2-256,ssh-rsa"       ;,ssh-dss
  496.   .encryption_algorithms_client_to_server:
  497.         str "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"
  498.   .encryption_algorithms_server_to_client:
  499.         str "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"
  500.   .mac_algorithms_client_to_server:
  501.         str "hmac-sha2-256"              ;,hmac-sha1,hmac-sha1-96,hmac-md5"
  502.   .mac_algorithms_server_to_client:
  503.         str "hmac-sha2-256"              ;,hmac-sha1,hmac-sha1-96,hmac-md5"
  504.   .compression_algorithms_client_to_server:
  505.         str "none"                       ;,zlib"
  506.   .compression_algorithms_server_to_client:
  507.         str "none"                       ;,zlib"
  508.   .languages_client_to_server:
  509.         str ""
  510.   .languages_server_to_client:
  511.         str ""
  512.   .first_kex_packet_follows:
  513.         db 0
  514.   .reserved:
  515.         dd_n 0
  516.   .length = $ - ssh_msg_kex
  517.  
  518.  
  519. ssh_msg_gex_req:
  520.         db SSH_MSG_KEX_DH_GEX_REQUEST
  521.         dd_n 4096/4                      ; DH GEX min
  522.         dd_n 4096/2                      ; DH GEX number of bits
  523.         dd_n 4096                        ; DH GEX Max
  524.   .length = $ - ssh_msg_gex_req
  525.  
  526.  
  527. ssh_msg_new_keys:
  528.         db SSH_MSG_NEWKEYS
  529.   .length = $ - ssh_msg_new_keys
  530.  
  531.  
  532. ssh_msg_request_service:
  533.         db SSH_MSG_SERVICE_REQUEST
  534.         str "ssh-userauth"              ; Service name
  535.   .length = $ - ssh_msg_request_service
  536.  
  537.  
  538. ssh_msg_channel_open:
  539.         db SSH_MSG_CHANNEL_OPEN
  540.         str "session"
  541.         dd_n 0                          ; Sender channel
  542.         dd_n BUFFERSIZE                 ; Initial window size
  543.         dd_n PACKETSIZE                 ; maximum packet size
  544.   .length = $ - ssh_msg_channel_open
  545.  
  546.  
  547. ssh_msg_channel_close:
  548.         db SSH_MSG_CHANNEL_CLOSE
  549.         dd_n 0                          ; Sender channel
  550.   .length = $ - ssh_msg_channel_close
  551.  
  552.  
  553. ssh_msg_channel_request:
  554.         db SSH_MSG_CHANNEL_REQUEST
  555.         dd_n 0                          ; Recipient channel
  556.         str "pty-req"
  557.         db 1                            ; Bool: want reply
  558.         str "xterm"
  559.         dd_n 80                         ; terminal width (rows)
  560.         dd_n 25                         ; terminal height (rows)
  561.         dd_n 80*8                       ; terminal width (pixels)
  562.         dd_n 25*16                      ; terminal height (pixels)
  563.  
  564.         dd_n 0                          ; list of supported opcodes
  565.   .length = $ - ssh_msg_channel_request
  566.  
  567.  
  568. ssh_msg_shell_request:
  569.         db SSH_MSG_CHANNEL_REQUEST
  570.         dd_n 0                          ; Recipient channel
  571.         str "shell"
  572.         db 1                            ; Bool: want reply
  573.   .length = $ - ssh_msg_shell_request
  574.  
  575.  
  576. ssh_msg_channel_data:
  577.         db SSH_MSG_CHANNEL_DATA
  578.         dd_n 0                          ; Sender channel
  579.   .len  dd ?
  580.   .data rb MAX_INPUT_LENGTH + 1
  581.  
  582.  
  583. ssh_msg_channel_window_adjust:
  584.         db SSH_MSG_CHANNEL_WINDOW_ADJUST
  585.         dd_n 0                          ; Sender channel
  586.   .wnd  dd ?
  587.   .length = $ - ssh_msg_channel_window_adjust
  588.  
  589.  
  590. include_debug_strings
  591.  
  592. align 4
  593. @IMPORT:
  594.  
  595. library network, 'network.obj', \
  596.         console, 'console.obj', \
  597.         libcrash, 'libcrash.obj', \
  598.         libini, 'libini.obj'
  599.  
  600. import  network, \
  601.         getaddrinfo, 'getaddrinfo', \
  602.         freeaddrinfo, 'freeaddrinfo', \
  603.         inet_ntoa, 'inet_ntoa'
  604.  
  605. import  console, \
  606.         con_start, 'START', \
  607.         con_init, 'con_init', \
  608.         con_write_asciiz, 'con_write_asciiz', \
  609.         con_exit, 'con_exit', \
  610.         con_gets, 'con_gets', \
  611.         con_cls, 'con_cls', \
  612.         con_getch2, 'con_getch2', \
  613.         con_get_flags, 'con_get_flags', \
  614.         con_set_title, 'con_set_title', \
  615.         con_get_input, 'con_get_input'
  616.  
  617. import  libcrash, \
  618.         sha256_init, 'sha256_init', \
  619.         sha256_update, 'sha256_update', \
  620.         sha256_final, 'sha256_final',\
  621.         sha1_init, 'sha1_init', \
  622.         sha1_update, 'sha1_update', \
  623.         sha1_final, 'sha1_final', \
  624.         md5_init, 'md5_init', \
  625.         md5_update, 'md5_update', \
  626.         md5_final, 'md5_final'
  627.  
  628. import  libini, \
  629.         ini_get_str, 'ini_get_str', \
  630.         ini_set_str, 'ini_set_str'
  631.  
  632. IncludeIGlobals
  633.  
  634. i_end:
  635.  
  636. IncludeUGlobals
  637.  
  638. params          rb MAX_HOSTNAME_LENGTH
  639.  
  640. ssh_con         sshlib_connection
  641. ssh_chan        sshlib_channel
  642.  
  643. mem:
  644.