Subversion Repositories Kolibri OS

Rev

Rev 7698 | Rev 9071 | 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'
54
include 'random.inc'
6922 hidnplayr 55
 
6419 hidnplayr 56
include 'aes256.inc'
57
include 'aes256-ctr.inc'
58
include 'aes256-cbc.inc'
6922 hidnplayr 59
 
9070 hidnplayr 60
include 'blowfish.inc'
61
include 'blowfish-ctr.inc'
62
include 'blowfish-cbc.inc'
63
 
6469 hidnplayr 64
include 'hmac_sha256.inc'
6922 hidnplayr 65
include 'hmac_sha1.inc'
66
include 'hmac_md5.inc'
6419 hidnplayr 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
 
6469 hidnplayr 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
9070 hidnplayr 90
        DEBUGF  1,'%x', eax
6469 hidnplayr 91
        loop    .next_dword
92
        DEBUGF  1,'\n'
93
 
94
        popad
9070 hidnplayr 95
end if
6469 hidnplayr 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
 
9070 hidnplayr 121
        rx_padsize              dd ?    ; = Max(8, rx_crypt_blocksize)
122
        tx_padsize              dd ?    ; = Max(8, tx_crypt_blocksize)
123
 
6469 hidnplayr 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
 
7698 dunkaist 175
        temp_ctx                crash_ctx
176
        k_h_ctx                 crash_ctx
6469 hidnplayr 177
 
6922 hidnplayr 178
        mpint_tmp               dd ?
179
                                rb MAX_BITS/8
180
 
6469 hidnplayr 181
ends
182
 
6419 hidnplayr 183
start:
184
        mcall   68, 11          ; Init heap
185
 
6469 hidnplayr 186
        DEBUGF  2, "SSH: Loading libraries\n"
6419 hidnplayr 187
        stdcall dll.Load, @IMPORT
188
        test    eax, eax
189
        jnz     exit
190
 
6469 hidnplayr 191
        DEBUGF  2, "SSH: Init PRNG\n"
6419 hidnplayr 192
        call    init_random
193
 
6469 hidnplayr 194
        DEBUGF  2, "SSH: Init Console\n"
6419 hidnplayr 195
        invoke  con_start, 1
196
        invoke  con_init, 80, 25, 80, 25, title
197
 
6469 hidnplayr 198
; Check for parameters TODO
199
;        cmp     byte[params], 0
200
;        jne     resolve
6419 hidnplayr 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
6469 hidnplayr 211
        mov     esi, con.hostname
6419 hidnplayr 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:
6469 hidnplayr 220
        mov     [con.sockaddr], AF_INET4
221
        mov     [con.port], 22 shl 8
6419 hidnplayr 222
 
223
; delete terminating '\n'
6469 hidnplayr 224
        mov     esi, con.hostname
6419 hidnplayr 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
6469 hidnplayr 246
        lea     ebx, [ebx*4+ebx]
6419 hidnplayr 247
        shl     ebx, 1
248
        add     ebx, eax
249
        jmp     .portloop
250
 
251
  .port_done:
252
        xchg    bl, bh
6469 hidnplayr 253
        mov     [con.port], bx
6419 hidnplayr 254
 
255
  .done:
256
 
257
; resolve name
258
        push    esp     ; reserve stack place
259
        push    esp
6469 hidnplayr 260
        invoke  getaddrinfo, con.hostname, 0, 0
6419 hidnplayr 261
        pop     esi
262
; test for error
263
        test    eax, eax
264
        jnz     dns_error
265
 
266
        invoke  con_write_asciiz, str3
6469 hidnplayr 267
        invoke  con_write_asciiz, con.hostname
6419 hidnplayr 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]
6469 hidnplayr 275
        mov     [con.ip], eax
6419 hidnplayr 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
6469 hidnplayr 290
        mov     [con.socketnum], eax
6419 hidnplayr 291
 
292
; Connect
6469 hidnplayr 293
        DEBUGF  2, "Connecting to server\n"
294
        mcall   connect, [con.socketnum], con.sockaddr, 18
6419 hidnplayr 295
        test    eax, eax
296
        jnz     socket_err
297
 
6469 hidnplayr 298
; Start calculating hash
299
        invoke  sha256_init, con.temp_ctx
6419 hidnplayr 300
; HASH: string  V_C, the client's version string (CR and NL excluded)
6469 hidnplayr 301
        invoke  sha256_update, con.temp_ctx, ssh_ident_ha, ssh_ident.length+4-2
6419 hidnplayr 302
 
6469 hidnplayr 303
; >> Send our identification string
304
        DEBUGF  2, "Sending ID string\n"
305
        mcall   send, [con.socketnum], ssh_ident, ssh_ident.length, 0
6419 hidnplayr 306
        cmp     eax, -1
307
        je      socket_err
308
 
6469 hidnplayr 309
; << Check protocol version of server
310
        mcall   recv, [con.socketnum], con.rx_buffer, BUFFERSIZE, 0
6419 hidnplayr 311
        cmp     eax, -1
312
        je      socket_err
313
 
6469 hidnplayr 314
        DEBUGF  2, "Received ID string\n"
315
        cmp     dword[con.rx_buffer], "SSH-"
6419 hidnplayr 316
        jne     proto_err
6469 hidnplayr 317
        cmp     dword[con.rx_buffer+4], "2.0-"
6419 hidnplayr 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
6469 hidnplayr 324
        mov     dword[con.rx_buffer-4], eax
325
        invoke  sha256_update, con.temp_ctx, con.rx_buffer-4, edx
6419 hidnplayr 326
 
6469 hidnplayr 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
9070 hidnplayr 338
        mov     [con.rx_padsize], 8                     ; minimum padsize
339
        mov     [con.tx_padsize], 8
6469 hidnplayr 340
 
341
        DEBUGF  2, "Sending KEX init\n"
6419 hidnplayr 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
6469 hidnplayr 351
        stdcall ssh_send_packet, con, ssh_kex, ssh_kex.length, 0
6419 hidnplayr 352
        cmp     eax, -1
353
        je      socket_err
354
 
355
; HASH: string  I_C, the payload of the client's SSH_MSG_KEXINIT
6469 hidnplayr 356
        mov     eax, dword[con.tx_buffer+ssh_packet_header.packet_length]
6419 hidnplayr 357
        bswap   eax
6469 hidnplayr 358
        movzx   ebx, [con.tx_buffer+ssh_packet_header.padding_length]
6419 hidnplayr 359
        sub     eax, ebx
360
        dec     eax
361
        lea     edx, [eax+4]
362
        bswap   eax
6469 hidnplayr 363
        mov     dword[con.tx_buffer+1], eax
364
        invoke  sha256_update, con.temp_ctx, con.tx_buffer+1, edx
6419 hidnplayr 365
 
6469 hidnplayr 366
; << Check key exchange init of server
367
        stdcall ssh_recv_packet, con, 0
6419 hidnplayr 368
        cmp     eax, -1
369
        je      socket_err
370
 
6469 hidnplayr 371
        cmp     [con.rx_buffer.message_code], SSH_MSG_KEXINIT
6419 hidnplayr 372
        jne     proto_err
6469 hidnplayr 373
        DEBUGF  2, "Received KEX init\n"
6419 hidnplayr 374
 
6469 hidnplayr 375
        lea     esi, [con.rx_buffer+sizeof.ssh_packet_header+16]
6419 hidnplayr 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
 
9070 hidnplayr 419
; TODO: parse this structure and init procedures accordingly
6419 hidnplayr 420
 
421
; HASH: string I_S, the payload of the servers's SSH_MSG_KEXINIT
6469 hidnplayr 422
        mov     eax, dword[con.rx_buffer+ssh_packet_header.packet_length]
423
        movzx   ebx, [con.rx_buffer+ssh_packet_header.padding_length]
6419 hidnplayr 424
        sub     eax, ebx
425
        dec     eax
426
        lea     edx, [eax+4]
427
        bswap   eax
6469 hidnplayr 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
6419 hidnplayr 430
 
431
; Exchange keys with the server
6469 hidnplayr 432
 
9070 hidnplayr 433
; TODO: host verification
434
 
6419 hidnplayr 435
        stdcall dh_gex
436
        test    eax, eax
437
        jnz     exit
438
 
439
; Set keys
440
 
6469 hidnplayr 441
        DEBUGF  2, "SSH: Setting encryption keys\n"
6419 hidnplayr 442
 
9070 hidnplayr 443
        stdcall aes256_ctr_init, con.rx_iv
6469 hidnplayr 444
        mov     [con.rx_crypt_ctx_ptr], eax
445
 
9070 hidnplayr 446
        stdcall aes256_set_encrypt_key, eax, con.rx_enc_key
447
        mov     [con.rx_crypt_proc], aes256_ctr_crypt
6469 hidnplayr 448
        mov     [con.rx_crypt_blocksize], AES256_BLOCKSIZE
9070 hidnplayr 449
        mov     [con.rx_padsize], AES256_BLOCKSIZE
6469 hidnplayr 450
 
9070 hidnplayr 451
        stdcall aes256_ctr_init, con.tx_iv
6469 hidnplayr 452
        mov     [con.tx_crypt_ctx_ptr], eax
453
 
454
        stdcall aes256_set_encrypt_key, eax, con.tx_enc_key
9070 hidnplayr 455
        mov     [con.tx_crypt_proc], aes256_ctr_crypt
6469 hidnplayr 456
        mov     [con.tx_crypt_blocksize], AES256_BLOCKSIZE
9070 hidnplayr 457
        mov     [con.tx_padsize], AES256_BLOCKSIZE
6469 hidnplayr 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
 
9070 hidnplayr 479
        stdcall ssh_msg_handler, con, 0
6469 hidnplayr 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
 
9070 hidnplayr 488
        DEBUGF  2, "SSH: User authentication\n"
6469 hidnplayr 489
 
9070 hidnplayr 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
6469 hidnplayr 497
 
9070 hidnplayr 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
6469 hidnplayr 504
 
9070 hidnplayr 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
 
6469 hidnplayr 567
        cmp     eax, -1
568
        je      socket_err
569
 
9070 hidnplayr 570
        invoke  con_write_asciiz, str14
571
 
6469 hidnplayr 572
; << Check for userauth acceptance
573
 
9070 hidnplayr 574
        stdcall ssh_msg_handler, con, 0
6469 hidnplayr 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
 
9070 hidnplayr 591
        stdcall ssh_msg_handler, con, 0
6469 hidnplayr 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
 
9070 hidnplayr 608
        stdcall ssh_msg_handler, con, 0
6469 hidnplayr 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
 
9070 hidnplayr 625
; TODO
626
;
627
;        stdcall ssh_msg_handler, con, 0
6469 hidnplayr 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
 
6419 hidnplayr 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
 
9070 hidnplayr 646
        stdcall ssh_msg_handler, con, 0
6469 hidnplayr 647
        cmp     eax, 0
648
        jbe     closed
6419 hidnplayr 649
 
6469 hidnplayr 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
6419 hidnplayr 655
        DEBUGF  1, 'SSH: got %u bytes of data !\n', eax
656
 
6469 hidnplayr 657
        lea     esi, [con.rx_buffer.message_code+5+4]
6419 hidnplayr 658
        mov     ecx, eax
6469 hidnplayr 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
6419 hidnplayr 667
        pusha
668
@@:
669
        lodsb
670
        DEBUGF  1, "%x ", eax:2
671
        dec     ecx
672
        jnz     @r
673
        popa
6469 hidnplayr 674
        DEBUGF  1, "\n"
6419 hidnplayr 675
        jmp     mainloop
676
 
6469 hidnplayr 677
 
6419 hidnplayr 678
proto_err:
9070 hidnplayr 679
        mov     eax, con.rx_buffer
680
        int3
681
 
6469 hidnplayr 682
        DEBUGF  3, "SSH: protocol error\n"
6419 hidnplayr 683
        invoke  con_write_asciiz, str7
684
        jmp     prompt
685
 
686
socket_err:
6469 hidnplayr 687
        DEBUGF  3, "SSH: socket error %d\n", ebx
6419 hidnplayr 688
        invoke  con_write_asciiz, str6
689
        jmp     prompt
690
 
691
dns_error:
6469 hidnplayr 692
        DEBUGF  3, "SSH: DNS error %d\n", eax
6419 hidnplayr 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:
6469 hidnplayr 707
        DEBUGF  3, "SSH: Exiting\n"
708
        mcall   close, [con.socketnum]
6419 hidnplayr 709
        mcall   -1
710
 
711
 
712
thread:
713
        mcall   40, 0
714
  .loop:
715
        invoke  con_getch2
6469 hidnplayr 716
        mov     [ssh_channel_data+9], al
9070 hidnplayr 717
        stdcall ssh_send_packet, con, ssh_channel_data, ssh_channel_data.length, MSG_DONTWAIT
6419 hidnplayr 718
 
719
        invoke  con_get_flags
720
        test    eax, 0x200                      ; con window closed?
721
        jz      .loop
722
        mcall   -1
723
 
9070 hidnplayr 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
 
6419 hidnplayr 760
; data
761
title   db      'Secure Shell',0
762
str1    db      'SSH client for KolibriOS',10,10,\
9070 hidnplayr 763
                'Please enter URL of SSH server (hostname:port)',10,10,0
6419 hidnplayr 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
9070 hidnplayr 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
6419 hidnplayr 777
 
778
ssh_ident_ha:
779
        dd_n (ssh_ident.length-2)
780
ssh_ident:
9070 hidnplayr 781
        db "SSH-2.0-KolibriOS_SSH_0.03",13,10
6419 hidnplayr 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
9070 hidnplayr 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"
6419 hidnplayr 797
  .encryption_algorithms_server_to_client:
798
        dd_n .mac_algorithms_client_to_server - .encryption_algorithms_server_to_client - 4
9070 hidnplayr 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"
6419 hidnplayr 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
9070 hidnplayr 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
6419 hidnplayr 830
  .length = $ - ssh_gex_req
831
 
832
 
833
ssh_new_keys:
834
        db SSH_MSG_NEWKEYS
835
  .length = $ - ssh_new_keys
836
 
837
 
6469 hidnplayr 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
9070 hidnplayr 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
6469 hidnplayr 851
        dd_n 8
9070 hidnplayr 852
        db "password"                   ; method name in US-ASCII: none, publickey, password, hostbased
853
        db 0                            ; bool: false
6469 hidnplayr 854
        dd_n 14
9070 hidnplayr 855
        db "pass123"
6469 hidnplayr 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
 
6419 hidnplayr 900
include_debug_strings
901
 
902
align 4
903
@IMPORT:
904
 
905
library network, 'network.obj', \
6469 hidnplayr 906
        console, 'console.obj', \
907
        libcrash, 'libcrash.obj'
6419 hidnplayr 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', \
9070 hidnplayr 924
        con_get_flags,  'con_get_flags', \
925
        con_set_flags,  'con_set_flags'
6419 hidnplayr 926
 
6469 hidnplayr 927
import  libcrash, \
928
        sha256_init, 'sha256_init', \
929
        sha256_update, 'sha256_update', \
6922 hidnplayr 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'
6419 hidnplayr 937
 
938
IncludeIGlobals
939
 
940
i_end:
941
 
942
IncludeUGlobals
943
 
6469 hidnplayr 944
params          rb 1024
6419 hidnplayr 945
 
6469 hidnplayr 946
con             ssh_connection
6419 hidnplayr 947
 
948
mem: