Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
9106 hidnplayr 1
;    sshlib_connection.inc - SSH connection
2
;
3
;    Copyright (C) 2016-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 .
17
 
18
proc sshlib_connect con_ptr, hostname_sz
19
 
20
locals
21
        socketnum       dd ?
22
        sockaddr        sockaddr_in
23
        ctx_ptr         dd ?
24
endl
25
 
26
        mov     edi, [con_ptr]
27
        lea     eax, [edi + sshlib_connection.part_ex_hash_ctx]
28
        mov     [ctx_ptr], eax
29
 
30
; Set default values in sockaddr struct
31
        mov     [sockaddr.sin_family], AF_INET4
32
        mov     [sockaddr.sin_port], 22 shl 8
33
 
34
; Parse hostname_sz
35
; Verify length, extract port number if given and copy base url to sshlib_connection struct
36
; Port number, if provided, will be written in sockaddr struct.
37
; Hostname ends with any character equal to 0x20 or lower
38
 
39
        mov     esi, [hostname_sz]
40
        lea     edi, [edi + sshlib_connection.hostname_sz]
41
        mov     ecx, MAX_HOSTNAME_LENGTH
42
  @@:
43
        dec     ecx
44
        jz      .err_hostname
45
        lodsb
46
        cmp     al, ':'
47
        je      .do_port
48
        stosb
49
        cmp     al, 0x20
50
        ja      @r
51
        mov     byte[edi-1], 0
52
        jmp     .hostname_ok
53
 
54
  .do_port:
55
        xor     eax, eax
56
        xor     ebx, ebx
57
        mov     byte[edi-1], 0
58
  .portloop:
59
        lodsb
60
        cmp     al, 0x20
61
        jbe     .port_done
62
        sub     al, '0'
63
        jb      .err_hostname
64
        cmp     al, 9
65
        ja      .err_hostname
66
        lea     ebx, [ebx*4+ebx]
67
        shl     ebx, 1
68
        add     ebx, eax
69
        jmp     .portloop
70
  .port_done:
71
        xchg    bl, bh
72
        mov     [sockaddr.sin_port], bx
73
 
74
  .hostname_ok:
75
; resolve name
76
        push    esp     ; reserve stack place
77
        push    esp
78
        mov     eax, [con_ptr]
79
        lea     eax, [eax+sshlib_connection.hostname_sz]
80
        invoke  getaddrinfo, eax, 0, 0
81
        pop     esi
82
; test for error
83
        test    eax, eax
84
        jnz     .err_hostname
85
 
86
; convert IP address to decimal notation
87
        mov     eax, [esi+addrinfo.ai_addr]
88
        mov     eax, [eax+sockaddr_in.sin_addr]
89
        mov     [sockaddr.sin_addr], eax
90
        invoke  inet_ntoa, eax
91
; write result
92
        stdcall sshlib_callback_connecting, [con_ptr], eax
93
; free allocated memory
94
        invoke  freeaddrinfo, esi
95
 
96
; Create socket
97
        mcall   socket, AF_INET4, SOCK_STREAM, 0
98
        cmp     eax, -1
99
        jz      .err_sock
100
        mov     [socketnum], eax
101
        mov     ebx, [con_ptr]
102
        mov     [ebx + sshlib_connection.socketnum], eax
103
 
104
; Connect
105
        DEBUGF  2, "Connecting to server\n"
106
        lea     edx, [sockaddr]
107
        mcall   connect, [socketnum], , sizeof.sockaddr_in
108
        test    eax, eax
109
        jnz     .err_sock
110
 
111
; Start calculating hash
9216 dunkaist 112
        invoke  sha2_256_init, [ctx_ptr]
9106 hidnplayr 113
; HASH: string  V_C, the client's version string (CR and NL excluded)
9216 dunkaist 114
        invoke  sha2_256_update, [ctx_ptr], ssh_ident_ha, ssh_msg_ident.length+4-2
9106 hidnplayr 115
 
116
; >> Send our identification string
117
        DEBUGF  2, "Sending ID string\n"
118
        mcall   send, [socketnum], ssh_msg_ident, ssh_msg_ident.length, 0
119
        cmp     eax, -1
120
        je      .err_sock
121
 
122
; << Check protocol version of server
123
        mov     edx, [con_ptr]
124
        lea     edx, [edx + sshlib_connection.rx_buffer + 4]
125
        mcall   recv, [socketnum], , PACKETSIZE, 0
126
        cmp     eax, -1
127
        je      .err_sock
128
 
129
        DEBUGF  2, "Received ID string\n"
130
        cmp     dword[edx], "SSH-"
131
        jne     .err_proto
132
        cmp     dword[edx+4], "2.0-"
133
        jne     .err_proto
134
 
135
; HASH: string  V_S, the server's version string (CR and NL excluded)
136
        lea     ecx, [eax+2]
137
        sub     eax, 2
138
        bswap   eax
139
        sub     edx, 4
140
        mov     dword[edx], eax
9216 dunkaist 141
        invoke  sha2_256_update, [ctx_ptr], edx, ecx
9106 hidnplayr 142
 
143
; >> Key Exchange init
144
        mov     eax, [con_ptr]
145
        mov     [eax + sshlib_connection.status], SSHLIB_CON_STAT_INIT
146
 
147
        mov     [eax + sshlib_connection.algo_kex], SSHLIB_ALGO_NONE
148
        mov     [eax + sshlib_connection.algo_hostkey], SSHLIB_ALGO_NONE
149
        mov     [eax + sshlib_connection.algo_crypt_rx], SSHLIB_ALGO_NONE
150
        mov     [eax + sshlib_connection.algo_crypt_tx], SSHLIB_ALGO_NONE
151
        mov     [eax + sshlib_connection.algo_mac_rx], SSHLIB_ALGO_NONE
152
        mov     [eax + sshlib_connection.algo_mac_tx], SSHLIB_ALGO_NONE
153
        mov     [eax + sshlib_connection.algo_compr_rx], SSHLIB_ALGO_NONE
154
        mov     [eax + sshlib_connection.algo_compr_tx], SSHLIB_ALGO_NONE
155
 
156
        mov     [eax + sshlib_connection.rx_mac_seqnr], 0
157
        mov     [eax + sshlib_connection.tx_mac_seqnr], 0
158
        mov     [eax + sshlib_connection.rx_crypt_blocksize], 4             ; minimum blocksize
159
        mov     [eax + sshlib_connection.tx_crypt_blocksize], 4
160
        mov     [eax + sshlib_connection.rx_crypt_proc], sshlib_crypt_null
161
        mov     [eax + sshlib_connection.tx_crypt_proc], sshlib_crypt_null
162
        mov     [eax + sshlib_connection.rx_mac_proc], 0
163
        mov     [eax + sshlib_connection.tx_mac_proc], 0
164
        mov     [eax + sshlib_connection.rx_mac_length], 0
165
        mov     [eax + sshlib_connection.tx_mac_length], 0
166
        mov     [eax + sshlib_connection.tx_pad_size], 8
167
        mov     [eax + sshlib_connection.tx_pad_proc], sshlib_padd_null
168
 
169
        DEBUGF  2, "Sending KEX init\n"
170
        mov     edi, ssh_msg_kex.cookie
171
        call    MBRandom
172
        stosd
173
        call    MBRandom
174
        stosd
175
        call    MBRandom
176
        stosd
177
        call    MBRandom
178
        stosd
179
        stdcall sshlib_send_packet, [con_ptr], ssh_msg_kex, ssh_msg_kex.length, 0
180
        cmp     eax, -1
181
        je      .err_sock
182
 
183
; HASH: string  I_C, the payload of the client's SSH_MSG_KEXINIT
184
        mov     esi, [con_ptr]
185
        mov     eax, [esi+sshlib_connection.tx_buffer.packet_length]
186
        bswap   eax
187
        movzx   ebx, [esi+sshlib_connection.tx_buffer.padding_length]
188
        sub     eax, ebx
189
        dec     eax
190
        lea     edx, [eax+4]
191
        bswap   eax
192
        lea     esi, [esi+sshlib_connection.tx_buffer+1]
193
        mov     dword[esi], eax
9216 dunkaist 194
        invoke  sha2_256_update, [ctx_ptr], esi, edx
9106 hidnplayr 195
 
196
; << Check key exchange init of server
197
        stdcall sshlib_recv_packet, [con_ptr], 0
198
        cmp     eax, -1
199
        je      .err_sock
200
 
201
        mov     esi, [con_ptr]
202
        cmp     [esi + sshlib_connection.rx_buffer.message_code], SSH_MSG_KEXINIT
203
        jne     .err_proto
204
        DEBUGF  2, "Received KEX init\n"
205
 
206
        lea     esi, [esi + sshlib_connection.rx_buffer + sizeof.ssh_packet_header + 16]
207
        lodsd
208
        bswap   eax
209
        DEBUGF  1, "kex_algorithms: %s\n", esi
210
        add     esi, eax
211
        lodsd
212
        bswap   eax
213
        DEBUGF  1, "server_host_key_algorithms: %s\n", esi
214
        add     esi, eax
215
        lodsd
216
        bswap   eax
217
        DEBUGF  1, "encryption_algorithms_client_to_server: %s\n", esi
218
        add     esi, eax
219
        lodsd
220
        bswap   eax
221
        DEBUGF  1, "encryption_algorithms_server_to_client: %s\n", esi
222
        add     esi, eax
223
        lodsd
224
        bswap   eax
225
        DEBUGF  1, "mac_algorithms_client_to_server: %s\n", esi
226
        add     esi, eax
227
        lodsd
228
        bswap   eax
229
        DEBUGF  1, "mac_algorithms_server_to_client: %s\n", esi
230
        add     esi, eax
231
        lodsd
232
        bswap   eax
233
        DEBUGF  1, "compression_algorithms_client_to_server: %s\n", esi
234
        add     esi, eax
235
        lodsd
236
        bswap   eax
237
        DEBUGF  1, "compression_algorithms_server_to_client: %s\n", esi
238
        add     esi, eax
239
        lodsd
240
        bswap   eax
241
        DEBUGF  1, "languages_client_to_server: %s\n", esi
242
        add     esi, eax
243
        lodsd
244
        bswap   eax
245
        DEBUGF  1, "languages_server_to_client: %s\n", esi
246
        add     esi, eax
247
        lodsb
248
        DEBUGF  1, "KEX First Packet Follows: %u\n", al
249
 
250
; TODO: parse this structure and set algorithm codes accordingly
251
; FIXME: hardcoded for now
252
        mov     esi, [con_ptr]
253
        mov     [esi+sshlib_connection.algo_kex], SSHLIB_KEX_DH_SHA256
254
        mov     [esi+sshlib_connection.algo_hostkey], SSHLIB_HOSTKEY_RSA
255
        mov     [esi+sshlib_connection.algo_crypt_rx], SSHLIB_CRYPT_AES256_CTR
256
        mov     [esi+sshlib_connection.algo_crypt_tx], SSHLIB_CRYPT_AES256_CTR
257
        mov     [esi+sshlib_connection.algo_mac_rx], SSHLIB_HMAC_SHA2_256
258
        mov     [esi+sshlib_connection.algo_mac_tx], SSHLIB_HMAC_SHA2_256
259
        mov     [esi+sshlib_connection.algo_compr_rx], SSHLIB_COMPR_NONE
260
        mov     [esi+sshlib_connection.algo_compr_tx], SSHLIB_COMPR_NONE
261
 
262
; HASH: string I_S, the payload of the servers's SSH_MSG_KEXINIT
263
        mov     esi, [con_ptr]
264
        mov     eax, [esi+sshlib_connection.rx_buffer.packet_length]
265
        movzx   ebx, [esi+sshlib_connection.rx_buffer.padding_length]
266
        sub     eax, ebx
267
        dec     eax
268
        lea     edx, [eax+4]
269
        bswap   eax
270
        lea     esi, [esi+sshlib_connection.rx_buffer+1]
271
        mov     dword[esi], eax
9216 dunkaist 272
        invoke  sha2_256_update, [ctx_ptr], esi, edx
9106 hidnplayr 273
 
274
; Exchange keys with the server
275
 
276
        stdcall sshlib_dh_gex, [con_ptr]
277
        test    eax, eax
278
        jnz     .err
279
 
280
; Re-seed RNG for padding bytes
281
 
282
        call    create_seed
283
        call    init_random
284
 
285
        xor     eax, eax
286
        ret
287
 
288
  .err_hostname:
289
        mov     eax, SSHLIB_ERR_HOSTNAME
290
        ret
291
 
292
  .err_sock:
293
        mov     eax, SSHLIB_ERR_SOCKET
294
        ret
295
 
296
  .err_proto:
297
        mov     eax, SSHLIB_ERR_PROTOCOL
298
        ret
299
 
300
  .err:
301
        ret
302
 
303
endp
304
 
305
 
306
 
307
 
308
; Handle common messages and return to caller for specific ones
309
proc sshlib_msg_handler, con_ptr, flags
310
 
311
  .recv:
312
; Send a window update if advertised window drops below half
313
        cmp     [ssh_chan.rcv_wnd], BUFFERSIZE/2
314
        ja      .no_wnd
315
        mov     eax, BUFFERSIZE
316
        bswap   eax
317
        mov     [ssh_msg_channel_window_adjust.wnd], eax
318
        stdcall sshlib_send_packet, [con_ptr], ssh_msg_channel_window_adjust, ssh_msg_channel_window_adjust.length, 0
319
        mov     [ssh_chan.rcv_wnd], BUFFERSIZE
320
  .no_wnd:
321
 
322
; Receive 1 SSH packet
323
        stdcall sshlib_recv_packet, [con_ptr], [flags]
324
        cmp     eax, 0
325
        jle     .ret
326
 
327
        mov     esi, [con_ptr]
328
        lea     esi, [esi + sshlib_connection.rx_buffer]
329
        mov     al, [esi + ssh_packet_header.message_code]
330
        inc     esi
331
 
332
        cmp     al, SSH_MSG_DISCONNECT
333
        je      .disc
334
        cmp     al, SSH_MSG_IGNORE
335
        je      .ign
336
        cmp     al, SSH_MSG_DEBUG
337
        je      .dbg
338
        cmp     al, SSH_MSG_GLOBAL_REQUEST
339
        je      .glob_req
340
        cmp     al, SSH_MSG_CHANNEL_WINDOW_ADJUST
341
        je      .chan_win_adj
342
;        cmp     al, SSH_MSG_CHANNEL_REQUEST
343
;        je      .chan_req
344
        cmp     al, SSH_MSG_CHANNEL_EOF
345
        je      .chan_eof
346
        cmp     al, SSH_MSG_CHANNEL_CLOSE
347
        je      .chan_close
348
 
349
  .ret:
350
        ret
351
 
352
  .disc:
353
        DEBUGF  3, "SSH: Disconnect message received\n"
354
        mov     eax, SSHLIB_ERR_DISCONNECTING
355
        ret
356
 
357
  .ign:
358
        DEBUGF  3, "SSH: Ignore MSG received\n"
359
        jmp     .recv
360
 
361
  .dbg:
362
        DEBUGF  3, "SSH: Debug MSG received\n"
363
        ;TODO
364
        jmp     .recv
365
 
366
  .glob_req:
367
        DEBUGF  3, "SSH: Global MSG received\n"
368
        ;TODO
369
        jmp     .recv
370
 
371
  .chan_win_adj:
372
        mov     eax, dword[esi]
373
        bswap   eax
374
        mov     [ssh_chan.snd_wnd], eax
375
        ; TODO: validate channel number, act accordingly
376
        DEBUGF  3, "SSH: Channel %u window update received\n", eax
377
        jmp     .recv
378
 
379
  .chan_eof:
380
        mov     eax, dword[esi]
381
        bswap   eax
382
        ; TODO: validate channel number, act accordingly
383
        DEBUGF  3, "SSH: Channel %u EOF received\n", eax
384
        jmp     .recv
385
 
386
  .chan_close:
387
        mov     eax, dword[esi]
388
        bswap   eax
389
        ; TODO: validate channel number
390
        DEBUGF  3, "SSH: Channel %u close received\n", eax
391
        ; Reply with close message
392
        stdcall sshlib_send_packet, [con_ptr], ssh_msg_channel_close, ssh_msg_channel_close.length, 0
393
        xor     eax, eax
394
        ret
395
 
9216 dunkaist 396
endp