Subversion Repositories Kolibri OS

Rev

Rev 9070 | Rev 9106 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
6419 hidnplayr 1
;    ssh.asm - SSH client for KolibriOS
2
;
9070 hidnplayr 3
;    Copyright (C) 2015-2021 Jeffrey Amelynck
6419 hidnplayr 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 .
17
 
18
format binary as ""
19
 
20
__DEBUG__       = 1
9070 hidnplayr 21
__DEBUG_LEVEL__ = 3             ; 1: Everything, including sinsitive information, 2: Debugging, 3: Errors only
6419 hidnplayr 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
6922 hidnplayr 34
        dd      mem+65536       ; required memory
35
        dd      mem+65536       ; stack pointer
6469 hidnplayr 36
        dd      params          ; parameters
6419 hidnplayr 37
        dd      0               ; path
38
 
39
include '../../macros.inc'
6469 hidnplayr 40
;include '../../struct.inc'
6419 hidnplayr 41
purge mov,add,sub
42
include '../../proc32.inc'
43
include '../../dll.inc'
44
include '../../debug-fdo.inc'
45
include '../../network.inc'
6469 hidnplayr 46
include '../../develop/libraries/libcrash/trunk/libcrash.inc'
6419 hidnplayr 47
 
48
include 'mcodes.inc'
49
include 'ssh_transport.inc'
6922 hidnplayr 50
 
6419 hidnplayr 51
include 'dh_gex.inc'
52
 
53
include 'mpint.inc'
9071 hidnplayr 54
include 'seed.inc'
6419 hidnplayr 55
include 'random.inc'
6922 hidnplayr 56
 
6419 hidnplayr 57
include 'aes256.inc'
58
include 'aes256-ctr.inc'
59
include 'aes256-cbc.inc'
6922 hidnplayr 60
 
9070 hidnplayr 61
include 'blowfish.inc'
62
include 'blowfish-ctr.inc'
63
include 'blowfish-cbc.inc'
64
 
6469 hidnplayr 65
include 'hmac_sha256.inc'
6922 hidnplayr 66
include 'hmac_sha1.inc'
67
include 'hmac_md5.inc'
6419 hidnplayr 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
 
6469 hidnplayr 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
9070 hidnplayr 91
        DEBUGF  1,'%x', eax
6469 hidnplayr 92
        loop    .next_dword
93
        DEBUGF  1,'\n'
94
 
95
        popad
9070 hidnplayr 96
end if
6469 hidnplayr 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
 
9071 hidnplayr 122
; Padding
9070 hidnplayr 123
 
9071 hidnplayr 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
 
6469 hidnplayr 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
 
7698 dunkaist 179
        temp_ctx                crash_ctx
180
        k_h_ctx                 crash_ctx
6469 hidnplayr 181
 
6922 hidnplayr 182
        mpint_tmp               dd ?
183
                                rb MAX_BITS/8
184
 
6469 hidnplayr 185
ends
186
 
6419 hidnplayr 187
start:
188
        mcall   68, 11          ; Init heap
189
 
6469 hidnplayr 190
        DEBUGF  2, "SSH: Loading libraries\n"
6419 hidnplayr 191
        stdcall dll.Load, @IMPORT
192
        test    eax, eax
193
        jnz     exit
194
 
6469 hidnplayr 195
        DEBUGF  2, "SSH: Init PRNG\n"
9071 hidnplayr 196
        call    create_seed
6419 hidnplayr 197
        call    init_random
198
 
6469 hidnplayr 199
        DEBUGF  2, "SSH: Init Console\n"
6419 hidnplayr 200
        invoke  con_start, 1
201
        invoke  con_init, 80, 25, 80, 25, title
202
 
6469 hidnplayr 203
; Check for parameters TODO
204
;        cmp     byte[params], 0
205
;        jne     resolve
6419 hidnplayr 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
6469 hidnplayr 216
        mov     esi, con.hostname
6419 hidnplayr 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:
6469 hidnplayr 225
        mov     [con.sockaddr], AF_INET4
226
        mov     [con.port], 22 shl 8
6419 hidnplayr 227
 
228
; delete terminating '\n'
6469 hidnplayr 229
        mov     esi, con.hostname
6419 hidnplayr 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
6469 hidnplayr 251
        lea     ebx, [ebx*4+ebx]
6419 hidnplayr 252
        shl     ebx, 1
253
        add     ebx, eax
254
        jmp     .portloop
255
 
256
  .port_done:
257
        xchg    bl, bh
6469 hidnplayr 258
        mov     [con.port], bx
6419 hidnplayr 259
 
260
  .done:
261
 
262
; resolve name
263
        push    esp     ; reserve stack place
264
        push    esp
6469 hidnplayr 265
        invoke  getaddrinfo, con.hostname, 0, 0
6419 hidnplayr 266
        pop     esi
267
; test for error
268
        test    eax, eax
269
        jnz     dns_error
270
 
271
        invoke  con_write_asciiz, str3
6469 hidnplayr 272
        invoke  con_write_asciiz, con.hostname
6419 hidnplayr 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]
6469 hidnplayr 280
        mov     [con.ip], eax
6419 hidnplayr 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
6469 hidnplayr 295
        mov     [con.socketnum], eax
6419 hidnplayr 296
 
297
; Connect
6469 hidnplayr 298
        DEBUGF  2, "Connecting to server\n"
299
        mcall   connect, [con.socketnum], con.sockaddr, 18
6419 hidnplayr 300
        test    eax, eax
301
        jnz     socket_err
302
 
6469 hidnplayr 303
; Start calculating hash
304
        invoke  sha256_init, con.temp_ctx
6419 hidnplayr 305
; HASH: string  V_C, the client's version string (CR and NL excluded)
6469 hidnplayr 306
        invoke  sha256_update, con.temp_ctx, ssh_ident_ha, ssh_ident.length+4-2
6419 hidnplayr 307
 
6469 hidnplayr 308
; >> Send our identification string
309
        DEBUGF  2, "Sending ID string\n"
310
        mcall   send, [con.socketnum], ssh_ident, ssh_ident.length, 0
6419 hidnplayr 311
        cmp     eax, -1
312
        je      socket_err
313
 
6469 hidnplayr 314
; << Check protocol version of server
315
        mcall   recv, [con.socketnum], con.rx_buffer, BUFFERSIZE, 0
6419 hidnplayr 316
        cmp     eax, -1
317
        je      socket_err
318
 
6469 hidnplayr 319
        DEBUGF  2, "Received ID string\n"
320
        cmp     dword[con.rx_buffer], "SSH-"
6419 hidnplayr 321
        jne     proto_err
6469 hidnplayr 322
        cmp     dword[con.rx_buffer+4], "2.0-"
6419 hidnplayr 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
6469 hidnplayr 329
        mov     dword[con.rx_buffer-4], eax
330
        invoke  sha256_update, con.temp_ctx, con.rx_buffer-4, edx
6419 hidnplayr 331
 
6469 hidnplayr 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
9071 hidnplayr 343
;        mov     [con.rx_padsize], 8                     ; minimum padsize
344
        mov     [con.tx_pad_size], 8
345
        mov     [con.tx_pad_proc], padding_zero
6469 hidnplayr 346
 
347
        DEBUGF  2, "Sending KEX init\n"
6419 hidnplayr 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
6469 hidnplayr 357
        stdcall ssh_send_packet, con, ssh_kex, ssh_kex.length, 0
6419 hidnplayr 358
        cmp     eax, -1
359
        je      socket_err
360
 
361
; HASH: string  I_C, the payload of the client's SSH_MSG_KEXINIT
6469 hidnplayr 362
        mov     eax, dword[con.tx_buffer+ssh_packet_header.packet_length]
6419 hidnplayr 363
        bswap   eax
6469 hidnplayr 364
        movzx   ebx, [con.tx_buffer+ssh_packet_header.padding_length]
6419 hidnplayr 365
        sub     eax, ebx
366
        dec     eax
367
        lea     edx, [eax+4]
368
        bswap   eax
6469 hidnplayr 369
        mov     dword[con.tx_buffer+1], eax
370
        invoke  sha256_update, con.temp_ctx, con.tx_buffer+1, edx
6419 hidnplayr 371
 
6469 hidnplayr 372
; << Check key exchange init of server
373
        stdcall ssh_recv_packet, con, 0
6419 hidnplayr 374
        cmp     eax, -1
375
        je      socket_err
376
 
6469 hidnplayr 377
        cmp     [con.rx_buffer.message_code], SSH_MSG_KEXINIT
6419 hidnplayr 378
        jne     proto_err
6469 hidnplayr 379
        DEBUGF  2, "Received KEX init\n"
6419 hidnplayr 380
 
6469 hidnplayr 381
        lea     esi, [con.rx_buffer+sizeof.ssh_packet_header+16]
6419 hidnplayr 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
 
9070 hidnplayr 425
; TODO: parse this structure and init procedures accordingly
6419 hidnplayr 426
 
427
; HASH: string I_S, the payload of the servers's SSH_MSG_KEXINIT
6469 hidnplayr 428
        mov     eax, dword[con.rx_buffer+ssh_packet_header.packet_length]
429
        movzx   ebx, [con.rx_buffer+ssh_packet_header.padding_length]
6419 hidnplayr 430
        sub     eax, ebx
431
        dec     eax
432
        lea     edx, [eax+4]
433
        bswap   eax
6469 hidnplayr 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
6419 hidnplayr 436
 
437
; Exchange keys with the server
6469 hidnplayr 438
 
9070 hidnplayr 439
; TODO: host verification
440
 
6419 hidnplayr 441
        stdcall dh_gex
442
        test    eax, eax
443
        jnz     exit
444
 
9071 hidnplayr 445
; Set keys and initialize transport subroutines
6419 hidnplayr 446
 
6469 hidnplayr 447
        DEBUGF  2, "SSH: Setting encryption keys\n"
6419 hidnplayr 448
 
9070 hidnplayr 449
        stdcall aes256_ctr_init, con.rx_iv
6469 hidnplayr 450
        mov     [con.rx_crypt_ctx_ptr], eax
451
 
9070 hidnplayr 452
        stdcall aes256_set_encrypt_key, eax, con.rx_enc_key
453
        mov     [con.rx_crypt_proc], aes256_ctr_crypt
6469 hidnplayr 454
        mov     [con.rx_crypt_blocksize], AES256_BLOCKSIZE
9071 hidnplayr 455
;        mov     [con.rx_pad_size], AES256_BLOCKSIZE
6469 hidnplayr 456
 
9070 hidnplayr 457
        stdcall aes256_ctr_init, con.tx_iv
6469 hidnplayr 458
        mov     [con.tx_crypt_ctx_ptr], eax
459
 
460
        stdcall aes256_set_encrypt_key, eax, con.tx_enc_key
9070 hidnplayr 461
        mov     [con.tx_crypt_proc], aes256_ctr_crypt
6469 hidnplayr 462
        mov     [con.tx_crypt_blocksize], AES256_BLOCKSIZE
463
 
9071 hidnplayr 464
        mov     [con.tx_pad_size], AES256_BLOCKSIZE
465
        mov     [con.tx_pad_proc], MBRandom
466
 
6469 hidnplayr 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
 
9071 hidnplayr 475
; Re-seed RNG for padding bytes
476
        call    create_seed
477
        call    init_random
478
 
6469 hidnplayr 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
 
9070 hidnplayr 491
        stdcall ssh_msg_handler, con, 0
6469 hidnplayr 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
 
9070 hidnplayr 500
        DEBUGF  2, "SSH: User authentication\n"
6469 hidnplayr 501
 
9070 hidnplayr 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
6469 hidnplayr 509
 
9070 hidnplayr 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
6469 hidnplayr 516
 
9070 hidnplayr 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
 
6469 hidnplayr 579
        cmp     eax, -1
580
        je      socket_err
581
 
9070 hidnplayr 582
        invoke  con_write_asciiz, str14
583
 
6469 hidnplayr 584
; << Check for userauth acceptance
585
 
9070 hidnplayr 586
        stdcall ssh_msg_handler, con, 0
6469 hidnplayr 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
 
9070 hidnplayr 603
        stdcall ssh_msg_handler, con, 0
6469 hidnplayr 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
 
9070 hidnplayr 620
        stdcall ssh_msg_handler, con, 0
6469 hidnplayr 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
 
9070 hidnplayr 637
; TODO
638
;
639
;        stdcall ssh_msg_handler, con, 0
6469 hidnplayr 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
 
6419 hidnplayr 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
 
9070 hidnplayr 658
        stdcall ssh_msg_handler, con, 0
6469 hidnplayr 659
        cmp     eax, 0
660
        jbe     closed
6419 hidnplayr 661
 
6469 hidnplayr 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
6419 hidnplayr 667
        DEBUGF  1, 'SSH: got %u bytes of data !\n', eax
668
 
6469 hidnplayr 669
        lea     esi, [con.rx_buffer.message_code+5+4]
6419 hidnplayr 670
        mov     ecx, eax
6469 hidnplayr 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
6419 hidnplayr 679
        pusha
680
@@:
681
        lodsb
682
        DEBUGF  1, "%x ", eax:2
683
        dec     ecx
684
        jnz     @r
685
        popa
6469 hidnplayr 686
        DEBUGF  1, "\n"
6419 hidnplayr 687
        jmp     mainloop
688
 
6469 hidnplayr 689
 
6419 hidnplayr 690
proto_err:
9070 hidnplayr 691
        mov     eax, con.rx_buffer
692
        int3
693
 
6469 hidnplayr 694
        DEBUGF  3, "SSH: protocol error\n"
6419 hidnplayr 695
        invoke  con_write_asciiz, str7
696
        jmp     prompt
697
 
698
socket_err:
6469 hidnplayr 699
        DEBUGF  3, "SSH: socket error %d\n", ebx
6419 hidnplayr 700
        invoke  con_write_asciiz, str6
701
        jmp     prompt
702
 
703
dns_error:
6469 hidnplayr 704
        DEBUGF  3, "SSH: DNS error %d\n", eax
6419 hidnplayr 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:
6469 hidnplayr 719
        DEBUGF  3, "SSH: Exiting\n"
720
        mcall   close, [con.socketnum]
6419 hidnplayr 721
        mcall   -1
722
 
723
 
724
thread:
725
        mcall   40, 0
726
  .loop:
727
        invoke  con_getch2
6469 hidnplayr 728
        mov     [ssh_channel_data+9], al
9070 hidnplayr 729
        stdcall ssh_send_packet, con, ssh_channel_data, ssh_channel_data.length, MSG_DONTWAIT
6419 hidnplayr 730
 
731
        invoke  con_get_flags
732
        test    eax, 0x200                      ; con window closed?
733
        jz      .loop
734
        mcall   -1
735
 
9070 hidnplayr 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
 
6419 hidnplayr 772
; data
773
title   db      'Secure Shell',0
774
str1    db      'SSH client for KolibriOS',10,10,\
9070 hidnplayr 775
                'Please enter URL of SSH server (hostname:port)',10,10,0
6419 hidnplayr 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
9070 hidnplayr 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
6419 hidnplayr 789
 
790
ssh_ident_ha:
791
        dd_n (ssh_ident.length-2)
792
ssh_ident:
9071 hidnplayr 793
        db "SSH-2.0-KolibriOS_SSH_0.04",13,10
6419 hidnplayr 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
9070 hidnplayr 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"
6419 hidnplayr 809
  .encryption_algorithms_server_to_client:
810
        dd_n .mac_algorithms_client_to_server - .encryption_algorithms_server_to_client - 4
9070 hidnplayr 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"
6419 hidnplayr 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
9070 hidnplayr 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
6419 hidnplayr 842
  .length = $ - ssh_gex_req
843
 
844
 
845
ssh_new_keys:
846
        db SSH_MSG_NEWKEYS
847
  .length = $ - ssh_new_keys
848
 
849
 
6469 hidnplayr 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
9070 hidnplayr 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
6469 hidnplayr 863
        dd_n 8
9070 hidnplayr 864
        db "password"                   ; method name in US-ASCII: none, publickey, password, hostbased
865
        db 0                            ; bool: false
6469 hidnplayr 866
        dd_n 14
9070 hidnplayr 867
        db "pass123"
6469 hidnplayr 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
 
6419 hidnplayr 912
include_debug_strings
913
 
914
align 4
915
@IMPORT:
916
 
917
library network, 'network.obj', \
6469 hidnplayr 918
        console, 'console.obj', \
919
        libcrash, 'libcrash.obj'
6419 hidnplayr 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', \
9070 hidnplayr 936
        con_get_flags,  'con_get_flags', \
937
        con_set_flags,  'con_set_flags'
6419 hidnplayr 938
 
6469 hidnplayr 939
import  libcrash, \
940
        sha256_init, 'sha256_init', \
941
        sha256_update, 'sha256_update', \
6922 hidnplayr 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'
6419 hidnplayr 949
 
950
IncludeIGlobals
951
 
952
i_end:
953
 
954
IncludeUGlobals
955
 
6469 hidnplayr 956
params          rb 1024
6419 hidnplayr 957
 
6469 hidnplayr 958
con             ssh_connection
6419 hidnplayr 959
 
960
mem: