Subversion Repositories Kolibri OS

Rev

Rev 3819 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3819 Rev 3824
1
struct  thread_data
1
struct  thread_data
2
                        rb 1024
2
                        rb 1024
3
        stack           rb 0
3
        stack           rb 0
4
 
4
 
5
        home_dir        rb 1024         ; home directory in wich the user is locked, asciiz
5
        home_dir        rb 1024         ; home directory in wich the user is locked, asciiz
6
        work_dir        rb 1024         ; working directory, must at all times begin and end with a '/', asciiz
6
        work_dir        rb 1024         ; working directory, must at all times begin and end with a '/', asciiz
7
        fpath           rb 1024*3       ; file path, combination of home_dir, work_dir and filename
7
        fpath           rb 1024*3       ; file path, combination of home_dir, work_dir and filename
8
                                        ; Will also be used to temporarily store username
8
                                        ; Will also be used to temporarily store username
9
 
9
 
10
        type            db ?    ; ASCII/EBDIC/IMAGE/..
10
        type            db ?    ; ASCII/EBDIC/IMAGE/..
11
        mode            db ?    ; active/passive
11
        mode            db ?    ; active/passive
12
        socketnum       dd ?    ; Commands socket
12
        socketnum       dd ?    ; Commands socket
13
        state           dd ?    ; disconnected/logging in/logged in/..
13
        state           dd ?    ; disconnected/logging in/logged in/..
14
        passivesocknum  dd ?    ; when in passive mode, this is the listening socket
14
        passivesocknum  dd ?    ; when in passive mode, this is the listening socket
15
        datasocketnum   dd ?    ; socket used for data transfers
15
        datasocketnum   dd ?    ; socket used for data transfers
16
        permissions     dd ?    ; read/write/execute/....
16
        permissions     dd ?    ; read/write/execute/....
17
        buffer_ptr      dd ?
17
        buffer_ptr      dd ?
18
        pid             dd ?    ; Process id of the current thread
18
        pid             dd ?    ; Process id of the current thread
19
 
19
 
20
        datasock        sockaddr_in
20
        datasock        sockaddr_in
21
 
21
 
22
        buffer          rb BUFFERSIZE
22
        buffer          rb BUFFERSIZE
23
ends
23
ends
24
 
24
 
25
;------------------------------------------------
25
;------------------------------------------------
26
; parse_cmd
26
; parse_cmd
27
;
27
;
28
; Internal function wich uses the 'commands'
28
; Internal function wich uses the 'commands'
29
;  table to call an appropriate cmd_xx function.
29
;  table to call an appropriate cmd_xx function.
30
;
30
;
31
; input: esi = ptr to ascii commands
31
; input: esi = ptr to ascii commands
32
;        ecx = number of bytes input
32
;        ecx = number of bytes input
33
;        ebp = pointer to thread_data structure
33
;        ebp = pointer to thread_data structure
34
;
34
;
35
; output: none
35
; output: none
36
;
36
;
37
;------------------------------------------------
37
;------------------------------------------------
38
align 4
38
align 4
39
parse_cmd:                              ; esi must point to command
39
parse_cmd:                              ; esi must point to command
40
 
40
 
41
        cmp     byte [esi], 0x20        ; skip all leading characters
41
        cmp     byte [esi], 0x20        ; skip all leading characters
42
        ja      .ok
42
        ja      .ok
43
        inc     esi
43
        inc     esi
44
        dec     ecx
44
        dec     ecx
45
        cmp     ecx, 3
45
        cmp     ecx, 3
46
        jb      .error
46
        jb      .error
47
        jmp     parse_cmd
47
        jmp     parse_cmd
48
  .ok:
48
  .ok:
49
        cmp     byte [esi+3], 0x20
49
        cmp     byte [esi+3], 0x20
50
        ja      @f
50
        ja      @f
51
        mov     byte [esi+3], 0
51
        mov     byte [esi+3], 0
52
       @@:
52
       @@:
53
 
53
 
54
        mov     eax, [esi]
54
        mov     eax, [esi]
55
        and     eax, not 0x20202020     ; convert to upper case
55
        and     eax, not 0x20202020     ; convert to upper case
56
        mov     edi, commands           ; list of commands to scan
56
        mov     edi, commands           ; list of commands to scan
57
  .scanloop:
57
  .scanloop:
58
        cmp     eax, [edi]
58
        cmp     eax, [edi]
59
        je      .got_it
59
        je      .got_it
60
 
60
 
61
        add     edi, 5*4
61
        add     edi, 5*4
62
        cmp     byte [edi], 0
62
        cmp     byte [edi], 0
63
        jne     .scanloop
63
        jne     .scanloop
64
 
64
 
65
  .error:
65
  .error:
66
        cmp     [ebp + thread_data.state], STATE_ACTIVE
66
        cmp     [ebp + thread_data.state], STATE_ACTIVE
67
        jb      login_first
67
        jb      login_first
68
        sendFTP "500 Unsupported command"
68
        sendFTP "500 Unsupported command"
69
        ret
69
        ret
70
 
70
 
71
  .got_it:
71
  .got_it:
72
        mov     eax, [ebp + thread_data.state]
72
        mov     eax, [ebp + thread_data.state]
73
        jmp     dword [edi + 4 + eax]
73
        jmp     dword [edi + 4 + eax]
74
 
74
 
75
 
75
 
76
align 4
76
align 4
77
iglobal
77
iglobal
78
commands:               ; all commands must be in uppercase
78
commands:               ; all commands must be in uppercase
79
 
79
 
80
        dd 'ABOR', login_first, login_first, login_first, cmdABOR
80
        dd 'ABOR', login_first, login_first, login_first, cmdABOR
81
;        dd 'ACCT', login_first, login_first, login_first, cmd_ACCT
81
;        dd 'ACCT', login_first, login_first, login_first, cmd_ACCT
82
;        dd 'APPE', login_first, login_first, login_first, cmd_APPE
82
;        dd 'APPE', login_first, login_first, login_first, cmd_APPE
83
        dd 'CDUP', login_first, login_first, login_first, cmdCDUP
83
        dd 'CDUP', login_first, login_first, login_first, cmdCDUP
84
        dd 'CWD',  login_first, login_first, login_first, cmdCWD
84
        dd 'CWD',  login_first, login_first, login_first, cmdCWD
85
        dd 'DELE', login_first, login_first, login_first, cmdDELE
85
        dd 'DELE', login_first, login_first, login_first, cmdDELE
86
;        dd 'HELP', login_first, login_first, login_first, cmd_HELP
86
;        dd 'HELP', login_first, login_first, login_first, cmd_HELP
87
        dd 'LIST', login_first, login_first, login_first, cmdLIST
87
        dd 'LIST', login_first, login_first, login_first, cmdLIST
88
;        dd 'MDTM', login_first, login_first, login_first, cmd_MDTM
88
;        dd 'MDTM', login_first, login_first, login_first, cmd_MDTM
89
;        dd 'MKD',  login_first, login_first, login_first, cmd_MKD
89
;        dd 'MKD',  login_first, login_first, login_first, cmd_MKD
90
;        dd 'MODE', login_first, login_first, login_first, cmd_MODE
90
;        dd 'MODE', login_first, login_first, login_first, cmd_MODE
91
        dd 'NLST', login_first, login_first, login_first, cmdNLST
91
;        dd 'NLST', login_first, login_first, login_first, cmdNLST
92
        dd 'NOOP', login_first, login_first, login_first, cmdNOOP
92
        dd 'NOOP', login_first, login_first, login_first, cmdNOOP
93
        dd 'PASS', cmdPASS.0,   cmdPASS    , cmdPASS.2,   cmdPASS.3
93
        dd 'PASS', cmdPASS.0,   cmdPASS    , cmdPASS.2,   cmdPASS.3
94
        dd 'PASV', login_first, login_first, login_first, cmdPASV
94
        dd 'PASV', login_first, login_first, login_first, cmdPASV
95
        dd 'PORT', login_first, login_first, login_first, cmdPORT
95
        dd 'PORT', login_first, login_first, login_first, cmdPORT
96
        dd 'PWD',  login_first, login_first, login_first, cmdPWD
96
        dd 'PWD',  login_first, login_first, login_first, cmdPWD
97
        dd 'QUIT', cmdQUIT,     cmdQUIT,     cmdQUIT,     cmdQUIT
97
        dd 'QUIT', cmdQUIT,     cmdQUIT,     cmdQUIT,     cmdQUIT
98
;        dd 'REIN', login_first, login_first, login_first, cmd_REIN
98
;        dd 'REIN', login_first, login_first, login_first, cmd_REIN
99
;        dd 'REST', login_first, login_first, login_first, cmd_REST
99
;        dd 'REST', login_first, login_first, login_first, cmd_REST
100
        dd 'RETR', login_first, login_first, login_first, cmdRETR
100
        dd 'RETR', login_first, login_first, login_first, cmdRETR
101
;        dd 'RMD', login_first, login_first, login_first, cmd_RMD
101
;        dd 'RMD', login_first, login_first, login_first, cmd_RMD
102
;        dd 'RNFR', login_first, login_first, login_first, cmd_RNFR
102
;        dd 'RNFR', login_first, login_first, login_first, cmd_RNFR
103
;        dd 'RNTO', login_first, login_first, login_first, cmd_RNTO
103
;        dd 'RNTO', login_first, login_first, login_first, cmd_RNTO
104
;        dd 'SITE', login_first, login_first, login_first, cmd_SITE
104
;        dd 'SITE', login_first, login_first, login_first, cmd_SITE
105
;        dd 'SIZE', login_first, login_first, login_first, cmd_SIZE
105
;        dd 'SIZE', login_first, login_first, login_first, cmd_SIZE
106
;        dd 'STAT', login_first, login_first, login_first, cmd_STAT
106
;        dd 'STAT', login_first, login_first, login_first, cmd_STAT
107
        dd 'STOR', login_first, login_first, login_first, cmdSTOR
107
        dd 'STOR', login_first, login_first, login_first, cmdSTOR
108
;        dd 'STOU', login_first, login_first, login_first, cmd_STOU
108
;        dd 'STOU', login_first, login_first, login_first, cmd_STOU
109
;        dd 'STRU', login_first, login_first, login_first, cmd_STRU
109
;        dd 'STRU', login_first, login_first, login_first, cmd_STRU
110
        dd 'SYST', login_first, login_first, login_first, cmdSYST
110
        dd 'SYST', login_first, login_first, login_first, cmdSYST
111
        dd 'TYPE', login_first, login_first, login_first, cmdTYPE
111
        dd 'TYPE', login_first, login_first, login_first, cmdTYPE
112
        dd 'USER', cmdUSER,     cmdUSER,     cmdUSER,     cmdUSER.2
112
        dd 'USER', cmdUSER,     cmdUSER,     cmdUSER,     cmdUSER.2
113
        db 0    ; end marker
113
        db 0    ; end marker
114
endg
114
endg
115
 
115
 
116
align 4
116
align 4
117
login_first:
117
login_first:
118
        sendFTP "530 Please login with USER and PASS"
118
        sendFTP "530 Please login with USER and PASS"
119
        ret
119
        ret
120
 
120
 
121
align 4
121
align 4
122
permission_denied:
122
permission_denied:
123
        sendFTP "550 Permission denied"
123
        sendFTP "550 Permission denied"
124
        ret
124
        ret
125
 
125
 
126
align 4
126
align 4
127
socketerror:
127
socketerror:
128
        invoke  con_set_flags, 0x0c
128
        invoke  con_set_flags, 0x0c
129
        invoke  con_write_asciiz, str_sockerr
129
        invoke  con_write_asciiz, str_sockerr
130
        invoke  con_set_flags, 0x07
130
        invoke  con_set_flags, 0x07
131
 
131
 
132
        sendFTP "425 Can't open data connection"
132
        sendFTP "425 Can't open data connection"
133
        ret
133
        ret
134
 
134
 
135
align 4
135
align 4
136
abort_transfer:
136
abort_transfer:
137
        and     [ebp + thread_data.permissions], not ABORT
137
        and     [ebp + thread_data.permissions], not ABORT
138
        mov     [ebp + thread_data.mode], MODE_NOTREADY
138
        mov     [ebp + thread_data.mode], MODE_NOTREADY
139
        invoke  file.close, ebx
139
        invoke  file.close, ebx
140
        mcall   close, [ebp + thread_data.datasocketnum]
140
        mcall   close, [ebp + thread_data.datasocketnum]
141
 
141
 
142
        sendFTP "530 Transfer aborted"
142
        sendFTP "530 Transfer aborted"
143
        ret
143
        ret
144
 
144
 
145
align 4
145
align 4
146
ip_to_dword:    ; esi = ptr to str, cl = separator ('.', ',')
146
ip_to_dword:    ; esi = ptr to str, cl = separator ('.', ',')
147
 
147
 
148
        call    ascii_to_byte
148
        call    ascii_to_byte
149
        mov     bl, al
149
        mov     bl, al
150
        cmp     byte [esi], cl
150
        cmp     byte [esi], cl
151
        jne     .err
151
        jne     .err
152
        inc     esi
152
        inc     esi
153
 
153
 
154
        call    ascii_to_byte
154
        call    ascii_to_byte
155
        mov     bh, al
155
        mov     bh, al
156
        cmp     byte [esi], cl
156
        cmp     byte [esi], cl
157
        jne     .err
157
        jne     .err
158
        inc     esi
158
        inc     esi
159
 
159
 
160
        shl     ebx, 16
160
        shl     ebx, 16
161
 
161
 
162
        call    ascii_to_byte
162
        call    ascii_to_byte
163
        mov     bl, al
163
        mov     bl, al
164
        cmp     byte [esi], cl
164
        cmp     byte [esi], cl
165
        jne     .err
165
        jne     .err
166
        inc     esi
166
        inc     esi
167
 
167
 
168
        call    ascii_to_byte
168
        call    ascii_to_byte
169
        mov     bh, al
169
        mov     bh, al
170
 
170
 
171
        ror     ebx, 16
171
        ror     ebx, 16
172
        ret
172
        ret
173
 
173
 
174
  .err:
174
  .err:
175
        xor     ebx, ebx
175
        xor     ebx, ebx
176
        ret
176
        ret
177
 
177
 
178
align 4         ; esi = ptr to str, output in eax
178
align 4         ; esi = ptr to str, output in eax
179
ascii_to_byte:
179
ascii_to_byte:
180
 
180
 
181
        xor     eax, eax
181
        xor     eax, eax
182
        push    ebx
182
        push    ebx
183
 
183
 
184
  .loop:
184
  .loop:
185
        movzx   ebx, byte[esi]
185
        movzx   ebx, byte[esi]
186
        sub     bl, '0'
186
        sub     bl, '0'
187
        jb      .done
187
        jb      .done
188
        cmp     bl, 9
188
        cmp     bl, 9
189
        ja      .done
189
        ja      .done
190
        lea     eax, [eax*4 + eax]      ;
190
        lea     eax, [eax*4 + eax]      ;
191
        shl     eax, 1                  ; eax = eax * 10
191
        shl     eax, 1                  ; eax = eax * 10
192
        add     eax, ebx
192
        add     eax, ebx
193
        inc     esi
193
        inc     esi
194
 
194
 
195
        jmp     .loop
195
        jmp     .loop
196
 
196
 
197
  .done:
197
  .done:
198
        pop     ebx
198
        pop     ebx
199
        ret
199
        ret
200
 
200
 
201
align 4
201
align 4
202
dword_to_ascii: ; edi = ptr where to write, eax is number
202
dword_to_ascii: ; edi = ptr where to write, eax is number
203
 
203
 
204
        push    edx ebx ecx
204
        push    edx ebx ecx
205
        mov     ebx, 10
205
        mov     ebx, 10
206
        xor     ecx, ecx
206
        xor     ecx, ecx
207
 
207
 
208
       @@:
208
       @@:
209
        xor     edx, edx
209
        xor     edx, edx
210
        div     ebx
210
        div     ebx
211
        add     edx, '0'
211
        add     edx, '0'
212
        pushw   dx
212
        pushw   dx
213
        inc     ecx
213
        inc     ecx
214
        test    eax, eax
214
        test    eax, eax
215
        jnz     @r
215
        jnz     @r
216
 
216
 
217
       @@:
217
       @@:
218
        popw    ax
218
        popw    ax
219
        stosb
219
        stosb
220
        dec     ecx
220
        dec     ecx
221
        jnz     @r
221
        jnz     @r
222
 
222
 
223
        pop     ecx ebx edx
223
        pop     ecx ebx edx
224
        ret
224
        ret
225
 
225
 
226
align 4
226
align 4
227
create_path:            ; combine home_dir and work_dir strings into fpath
227
create_path:            ; combine home_dir and work_dir strings into fpath
228
 
228
 
229
        lea     edi, [ebp + thread_data.fpath]
229
        lea     edi, [ebp + thread_data.fpath]
230
        lea     esi, [ebp + thread_data.home_dir]
230
        lea     esi, [ebp + thread_data.home_dir]
231
        mov     ecx, 1024
231
        mov     ecx, 1024
232
  .loop1:
232
  .loop1:
233
        lodsb
233
        lodsb
234
        cmp     al, 0x20
234
        cmp     al, 0x20
235
        jb      .next
235
        jb      .next
236
        stosb
236
        stosb
237
        loop    .loop1
237
        loop    .loop1
238
  .next:
238
  .next:
239
 
239
 
240
        cmp     byte[edi-1], '/'
240
        cmp     byte[edi-1], '/'
241
        jne     @f
241
        jne     @f
242
        dec     edi
242
        dec     edi
243
       @@:
243
       @@:
244
 
244
 
245
        lea     esi, [ebp + thread_data.work_dir]
245
        lea     esi, [ebp + thread_data.work_dir]
246
        mov     ecx, 1024
246
        mov     ecx, 1024
247
  .loop2:
247
  .loop2:
248
        lodsb
248
        lodsb
249
        cmp     al, 0x20
249
        cmp     al, 0x20
250
        jb      .done
250
        jb      .done
251
        stosb
251
        stosb
252
        loop    .loop2
252
        loop    .loop2
253
 
253
 
254
  .done:
254
  .done:
255
        xor     al, al
255
        xor     al, al
256
        stosb
256
        stosb
257
        ret
257
        ret
258
 
258
 
259
 
259
 
260
align 4
260
align 4
261
nextpasvport:
261
nextpasvport:
262
 
262
 
263
        inc     [pasv_port]
263
        inc     [pasv_port]
264
 
264
 
265
        mov     ax, [pasv_port]
265
        mov     ax, [pasv_port]
266
        cmp     ax, [pasv_start]
266
        cmp     ax, [pasv_start]
267
        jb      .restart
267
        jb      .restart
268
        cmp     ax, [pasv_end]
268
        cmp     ax, [pasv_end]
269
        ja      .restart
269
        ja      .restart
270
 
270
 
271
        ret
271
        ret
272
 
272
 
273
  .restart:
273
  .restart:
274
        pushw   [pasv_start]
274
        pushw   [pasv_start]
275
        popw    [pasv_port]
275
        popw    [pasv_port]
276
 
276
 
277
        ret
277
        ret
278
 
278
 
279
 
279
 
280
align 4
280
align 4
281
open_datasock:
281
open_datasock:
282
 
282
 
283
        cmp     [ebp + thread_data.mode], MODE_PASSIVE_OK
283
        cmp     [ebp + thread_data.mode], MODE_PASSIVE_OK
284
        je      .start
284
        je      .already_open
285
 
285
 
286
; If we are in active mode, it's time to open a data socket..
286
; If we are in active mode, it's time to open the data socket..
287
        cmp     [ebp + thread_data.mode], MODE_ACTIVE
287
        cmp     [ebp + thread_data.mode], MODE_ACTIVE
288
        jne     .not_active
288
        jne     .not_active
289
        mov     ecx, [ebp + thread_data.datasocketnum]
289
        mov     ecx, [ebp + thread_data.datasocketnum]
290
        lea     edx, [ebp + thread_data.datasock]
290
        lea     edx, [ebp + thread_data.datasock]
291
        mov     esi, sizeof.thread_data.datasock
291
        mov     esi, sizeof.thread_data.datasock
292
        mcall   connect
292
        mcall   connect
293
        cmp     eax, -1
293
        cmp     eax, -1
294
        jne     .start
294
        je      .socketerror
295
 
295
        invoke  con_write_asciiz, str_datasock2
296
  .socketerror:
296
        ret
-
 
297
 
-
 
298
  .already_open:
-
 
299
        invoke  con_write_asciiz, str_alopen
-
 
300
        ret
-
 
301
 
-
 
302
  .socketerror:
297
        add     esp, 4
303
        add     esp, 4
298
        jmp     socketerror
304
        jmp     socketerror
299
 
305
 
300
; If we are still in passive_wait, it's time we accept an incomming call..
306
; If we are still in passive_wait, it's time we accept an incomming call..
301
  .not_active:
307
  .not_active:
302
        cmp     [ebp + thread_data.mode], MODE_PASSIVE_WAIT
308
        cmp     [ebp + thread_data.mode], MODE_PASSIVE_WAIT
303
        jne     .socketerror
309
        jne     .socketerror
304
 
310
 
305
  .try_now:
311
  .try_now:
306
        mov     ecx, [ebp + thread_data.passivesocknum]
312
        mov     ecx, [ebp + thread_data.passivesocknum]
307
        lea     edx, [ebp + thread_data.datasock]
313
        lea     edx, [ebp + thread_data.datasock]
308
        mov     esi, sizeof.thread_data.datasock
314
        mov     esi, sizeof.thread_data.datasock
309
        mcall   accept
315
        mcall   accept
310
        cmp     eax, -1
316
        cmp     eax, -1
311
        jne     .pasv_ok
317
        jne     .pasv_ok
312
        mov     [ebp + thread_data.mode], MODE_PASSIVE_FAILED                   ; assume that we will fail
318
        mov     [ebp + thread_data.mode], MODE_PASSIVE_FAILED                   ; assume that we will fail
313
        mcall   23, 200
319
        mcall   23, 200
314
        mcall   accept
320
        mcall   accept
315
        cmp     eax, -1
321
        cmp     eax, -1
316
        je      .socketerror
322
        je      .socketerror
317
  .pasv_ok:
323
  .pasv_ok:
318
        mov     [ebp + thread_data.datasocketnum], eax
324
        mov     [ebp + thread_data.datasocketnum], eax
319
        mov     [ebp + thread_data.mode], MODE_PASSIVE_OK
325
        mov     [ebp + thread_data.mode], MODE_PASSIVE_OK
320
        mcall   close   ; [ebp + thread_data.passivesocknum]
326
        mcall   close   ; [ebp + thread_data.passivesocknum]
321
        mov     [ebp + thread_data.passivesocknum], -1
327
        mov     [ebp + thread_data.passivesocknum], -1
322
        invoke  con_write_asciiz, str_datasock
328
        invoke  con_write_asciiz, str_datasock
323
 
329
 
324
  .start:
330
        ret
325
        ret
-
 
326
 
331
 
327
 
332
 
328
;------------------------------------------------
333
;------------------------------------------------
329
; "ABOR"
334
; "ABOR"
330
;
335
;
331
; This command aborts the current filetransfer.
336
; This command aborts the current filetransfer.
332
;
337
;
333
;------------------------------------------------
338
;------------------------------------------------
334
align 4
339
align 4
335
cmdABOR:
340
cmdABOR:
336
 
341
 
337
        or      [ebp + thread_data.permissions], ABORT
342
        or      [ebp + thread_data.permissions], ABORT
338
        sendFTP "250 Command succesul"
343
        sendFTP "250 Command succesul"
339
        ret
344
        ret
340
 
345
 
341
;------------------------------------------------
346
;------------------------------------------------
342
; "CDUP"
347
; "CDUP"
343
;
348
;
344
; Change the directory to move up one level.
349
; Change the directory to move up one level.
345
;
350
;
346
;------------------------------------------------
351
;------------------------------------------------
347
align 4
352
align 4
348
cmdCDUP:
353
cmdCDUP:
349
 
354
 
350
        test    [ebp + thread_data.permissions], PERMISSION_CD
355
        test    [ebp + thread_data.permissions], PERMISSION_CD
351
        jz      permission_denied
356
        jz      permission_denied
352
 
357
 
353
        cmp     byte [ebp + thread_data.work_dir+1], 0  ; are we in "/" ?
358
        cmp     byte [ebp + thread_data.work_dir+1], 0  ; are we in "/" ?
354
        je      .done                                   ; if so, we cant go up..
359
        je      .done                                   ; if so, we cant go up..
355
 
360
 
356
; find the end of asciiz string work_dir
361
; find the end of asciiz string work_dir
357
        mov     ecx, 1024
362
        mov     ecx, 1024
358
        xor     al, al
363
        xor     al, al
359
        lea     edi, [ebp + thread_data.work_dir]
364
        lea     edi, [ebp + thread_data.work_dir]
360
        repne   scasb
365
        repne   scasb
361
; return 2 characters (right before last /)
366
; return 2 characters (right before last /)
362
        sub     edi, 3
367
        sub     edi, 3
363
; and now search backwards, for a '/'
368
; and now search backwards, for a '/'
364
        mov     al,'/'
369
        mov     al,'/'
365
        neg     ecx
370
        neg     ecx
366
        add     ecx, 1024
371
        add     ecx, 1024
367
        std
372
        std
368
        repne   scasb
373
        repne   scasb
369
        cld
374
        cld
370
; terminate the string here
375
; terminate the string here
371
        mov     byte[edi+2], 0
376
        mov     byte[edi+2], 0
372
 
377
 
373
  .done:
378
  .done:
374
; Print the new working dir on the console
379
; Print the new working dir on the console
375
        lea     eax, [ebp + thread_data.work_dir]
380
        lea     eax, [ebp + thread_data.work_dir]
376
        invoke  con_write_asciiz, eax
381
        invoke  con_write_asciiz, eax
377
        invoke  con_write_asciiz, str_newline
382
        invoke  con_write_asciiz, str_newline
378
 
383
 
379
        sendFTP "250 Command succesul"
384
        sendFTP "250 Command succesul"
380
        ret
385
        ret
381
 
386
 
382
;------------------------------------------------
387
;------------------------------------------------
383
; "CWD"
388
; "CWD"
384
;
389
;
385
; Change Working Directory.
390
; Change Working Directory.
386
;
391
;
387
;------------------------------------------------
392
;------------------------------------------------
388
align 4
393
align 4
389
cmdCWD:
394
cmdCWD:
390
 
395
 
391
        test    [ebp + thread_data.permissions], PERMISSION_CD
396
        test    [ebp + thread_data.permissions], PERMISSION_CD
392
        jz      permission_denied
397
        jz      permission_denied
393
 
398
 
394
; do we have enough parameters?
399
; do we have enough parameters?
395
        sub     ecx, 4
400
        sub     ecx, 4
396
        jbe     .err
401
        jbe     .err
397
 
402
 
398
; get ready to copy the path
403
; get ready to copy the path
399
        add     esi, 4
404
        add     esi, 4
400
        mov     ecx, 1024
405
        mov     ecx, 1024
401
        lea     edi, [ebp + thread_data.work_dir]
406
        lea     edi, [ebp + thread_data.work_dir]
402
 
407
 
403
; if received dir starts with '/', we will simply copy it
408
; if received dir starts with '/', we will simply copy it
404
; If not, we will append the current path with the received path.
409
; If not, we will append the current path with the received path.
405
        cmp     byte [esi], '/'
410
        cmp     byte [esi], '/'
406
        je      .copyloop
411
        je      .copyloop
407
 
412
 
408
; Find the end of work_dir string.
413
; Find the end of work_dir string.
409
        xor     al, al
414
        xor     al, al
410
  .find_zero:
415
  .find_zero:
411
        repne   scasb
416
        repne   scasb
412
        dec     edi
417
        dec     edi
413
 
418
 
414
; and now append work_dir with received string
419
; and now append work_dir with received string
415
        mov     ecx, 1024
420
        mov     ecx, 1024
416
 
421
 
417
; scan for end byte, or '.'
422
; scan for end byte, or '.'
418
  .copyloop:
423
  .copyloop:
419
        lodsb
424
        lodsb
420
        cmp     al, 0x20
425
        cmp     al, 0x20
421
        jb      .done
426
        jb      .done
422
;;;        cmp     al, '.'         ; '..' means we must go up one dir   TODO
427
;;;        cmp     al, '.'         ; '..' means we must go up one dir   TODO
423
;;;        je      .up
428
;;;        je      .up
424
        stosb
429
        stosb
425
        loop    .copyloop
430
        loop    .copyloop
426
 
431
 
427
; now, now make sure it ends with '/', 0
432
; now, now make sure it ends with '/', 0
428
  .done:
433
  .done:
429
        cmp     byte [edi-1], '/'
434
        cmp     byte [edi-1], '/'
430
        je      @f
435
        je      @f
431
        mov     byte [edi], '/'
436
        mov     byte [edi], '/'
432
        inc     edi
437
        inc     edi
433
       @@:
438
       @@:
434
        mov     byte [edi], 0
439
        mov     byte [edi], 0
435
 
440
 
436
; Print the new working dir on the console
441
; Print the new working dir on the console
437
        lea     eax, [ebp + thread_data.work_dir]
442
        lea     eax, [ebp + thread_data.work_dir]
438
        invoke  con_write_asciiz, eax
443
        invoke  con_write_asciiz, eax
439
        invoke  con_write_asciiz, str_newline
444
        invoke  con_write_asciiz, str_newline
440
 
445
 
441
        sendFTP "250 Command succesful"
446
        sendFTP "250 Command succesful"
442
        ret
447
        ret
443
 
448
 
444
  .err:
449
  .err:
445
        sendFTP "550 Directory does not exist"
450
        sendFTP "550 Directory does not exist"
446
        ret
451
        ret
447
 
452
 
448
;------------------------------------------------
453
;------------------------------------------------
449
; "DELE"
454
; "DELE"
450
;
455
;
451
; Delete a file from the server.
456
; Delete a file from the server.
452
;
457
;
453
;------------------------------------------------
458
;------------------------------------------------
454
align 4
459
align 4
455
cmdDELE:
460
cmdDELE:
456
 
461
 
457
        test    [ebp + thread_data.permissions], PERMISSION_DELETE
462
        test    [ebp + thread_data.permissions], PERMISSION_DELETE
458
        jz      permission_denied
463
        jz      permission_denied
459
 
464
 
460
        ret
465
        ret
461
 
466
 
462
;------------------------------------------------
467
;------------------------------------------------
463
; "LIST"
468
; "LIST"
464
;
469
;
465
; List the files in the current working directory.
470
; List the files in the current working directory.
466
;
471
;
467
;------------------------------------------------
472
;------------------------------------------------
468
align 4
473
align 4
469
cmdLIST:
474
cmdLIST:
470
 
475
 
471
        test    [ebp + thread_data.permissions], PERMISSION_EXEC
476
        test    [ebp + thread_data.permissions], PERMISSION_EXEC
472
        jz      permission_denied
477
        jz      permission_denied
473
 
478
 
474
        call    open_datasock
479
        call    open_datasock
475
 
480
 
476
; Create fpath from home_dir and work_dir
481
; Create fpath from home_dir and work_dir
477
        call    create_path
482
        call    create_path
478
 
483
 
479
        lea     ebx, [ebp + thread_data.fpath]
484
        lea     ebx, [ebp + thread_data.fpath]
480
        invoke  con_write_asciiz, ebx
485
        invoke  con_write_asciiz, ebx
481
        invoke  con_write_asciiz, str_newline
486
        invoke  con_write_asciiz, str_newline
482
 
487
 
483
; Start the search
488
; Start the search
484
        invoke  file.find.first, ebx, str_mask, FA_READONLY+FA_FOLDER+FA_ARCHIVED;+FA_NORMAL
489
        invoke  file.find.first, ebx, str_mask, FA_READONLY+FA_FOLDER+FA_ARCHIVED;+FA_NORMAL
485
        test    eax, eax
490
        test    eax, eax
486
        jz      .nosuchdir
491
        jz      .nosuchdir
487
 
492
 
488
        lea     edi, [ebp + thread_data.buffer]
493
        lea     edi, [ebp + thread_data.buffer]
489
  .parse_file:
494
  .parse_file:
490
        test    eax, eax        ; did we find a file?
495
        test    eax, eax        ; did we find a file?
491
        jz      .done
496
        jz      .done
492
        mov     ebx, eax        ; yes, save the descripter in ebx
497
        mov     ebx, eax        ; yes, save the descripter in ebx
493
 
498
 
494
; first, convert the attributes
499
; first, convert the attributes
495
        test    [ebx + FileInfoA.Attributes], FA_FOLDER
500
        test    [ebx + FileInfoA.Attributes], FA_FOLDER
496
        jnz     .folder
501
        jnz     .folder
497
 
502
 
498
        test    [ebx + FileInfoA.Attributes], FA_READONLY
503
        test    [ebx + FileInfoA.Attributes], FA_READONLY
499
        jnz     .readonly
504
        jnz     .readonly
500
 
505
 
501
        mov     eax, '-rw-'
506
        mov     eax, '-rw-'
502
        stosd
507
        stosd
503
        jmp     .attr
508
        jmp     .attr
504
 
509
 
505
  .folder:
510
  .folder:
506
        mov     eax, 'drwx'
511
        mov     eax, 'drwx'
507
        stosd
512
        stosd
508
        jmp     .attr
513
        jmp     .attr
509
 
514
 
510
  .readonly:
515
  .readonly:
511
        mov     eax, '-r--'
516
        mov     eax, '-r--'
512
        stosd
517
        stosd
513
 
518
 
514
  .attr:
519
  .attr:
515
        mov     eax, 'rw-r'
520
        mov     eax, 'rw-r'
516
        stosd
521
        stosd
517
        mov     ax, 'w-'
522
        mov     ax, 'w-'
518
        stosw
523
        stosw
519
        mov     al, ' '
524
        mov     al, ' '
520
        stosb
525
        stosb
521
 
526
 
522
; now..
527
; now..
523
        mov     ax, '1 '
528
        mov     ax, '1 '
524
        stosw
529
        stosw
525
 
530
 
526
; now write owner, everything is owned by FTP, woohoo!
531
; now write owner, everything is owned by FTP, woohoo!
527
        mov     eax, 'FTP '
532
        mov     eax, 'FTP '
528
        stosd
533
        stosd
529
        stosd
534
        stosd
530
 
535
 
531
; now the filesize in ascii
536
; now the filesize in ascii
532
        mov     eax, dword[ebx + FileInfoA.FileSize]
537
        mov     eax, dword[ebx + FileInfoA.FileSize]
533
        call    dword_to_ascii
538
        call    dword_to_ascii
534
        mov     al, ' '
539
        mov     al, ' '
535
        stosb
540
        stosb
536
 
541
 
537
; then date (month/day/year)
542
; then date (month/day/year)
538
        movzx   eax, [ebx + FileInfoA.DateModify.month]
543
        movzx   eax, [ebx + FileInfoA.DateModify.month]
539
        cmp     eax, 12
544
        cmp     eax, 12
540
        ja      @f
545
        ja      @f
541
        mov     eax, [months - 4 + 4*eax]
546
        mov     eax, [months - 4 + 4*eax]
542
        stosd
547
        stosd
543
       @@:
548
       @@:
544
 
549
 
545
        movzx   eax, [ebx + FileInfoA.DateModify.day]
550
        movzx   eax, [ebx + FileInfoA.DateModify.day]
546
        call    dword_to_ascii
551
        call    dword_to_ascii
547
        mov     al, ' '
552
        mov     al, ' '
548
        stosb
553
        stosb
549
 
554
 
550
        movzx   eax, [ebx + FileInfoA.DateModify.year]
555
        movzx   eax, [ebx + FileInfoA.DateModify.year]
551
        call    dword_to_ascii
556
        call    dword_to_ascii
552
        mov     al, ' '
557
        mov     al, ' '
553
        stosb
558
        stosb
554
 
559
 
555
; and last but not least, filename
560
; and last but not least, filename
556
        lea     esi, [ebx + FileInfoA.FileName]
561
        lea     esi, [ebx + FileInfoA.FileName]
557
        mov     ecx, 264
562
        mov     ecx, 264
558
  .nameloop:
563
  .nameloop:
559
        lodsb
564
        lodsb
560
        test    al, al
565
        test    al, al
561
        jz      .namedone
566
        jz      .namedone
562
        stosb
567
        stosb
563
        loop    .nameloop
568
        loop    .nameloop
564
 
569
 
565
; insert a cr lf
570
; insert a cr lf
566
  .namedone:
571
  .namedone:
567
        mov     ax, 0x0a0d
572
        mov     ax, 0x0a0d
568
        stosw
573
        stosw
569
 
574
 
570
        test    [ebp + thread_data.permissions], ABORT          ; Did we receive ABOR command from client?
575
        test    [ebp + thread_data.permissions], ABORT          ; Did we receive ABOR command from client?
571
        jnz     abort_transfer
576
        jnz     abort_transfer
572
 
577
 
573
; check next file
578
; check next file
574
        invoke  file.find.next, ebx
579
        invoke  file.find.next, ebx
575
        jmp     .parse_file
580
        jmp     .parse_file
576
 
581
 
577
; close file desc
582
; close file desc
578
  .done:
583
  .done:
579
        invoke  file.find.close, ebx                            ; ebx is descriptor of last file, eax will be -1 !!
584
        invoke  file.find.close, ebx                            ; ebx is descriptor of last file, eax will be -1 !!
580
 
585
 
581
; append the string with a 0
586
; append the string with a 0
582
        xor     al, al
587
        xor     al, al
583
        stosb
588
        stosb
584
 
589
 
585
; Warn the client we're about to send the data
590
; Warn the client we're about to send the data
586
        push    edi
591
        push    edi
587
        sendFTP "150 Here it comes.."
592
        sendFTP "150 Here it comes.."
588
        pop     esi
593
        pop     esi
589
 
594
 
590
; and send it to the client
595
; and send it to the client
591
        mov     ecx, [ebp + thread_data.datasocketnum]          ; socket num
596
        mov     ecx, [ebp + thread_data.datasocketnum]          ; socket num
592
        lea     edx, [ebp + thread_data.buffer]                 ; buffer ptr
597
        lea     edx, [ebp + thread_data.buffer]                 ; buffer ptr
593
        sub     esi, edx                                        ; length
598
        sub     esi, edx                                        ; length
594
        xor     edi, edi                                        ; flags
599
        xor     edi, edi                                        ; flags
595
        mcall   send
600
        mcall   send
596
 
601
 
597
; close the data socket..
602
; close the data socket..
598
        mov     [ebp + thread_data.mode], MODE_NOTREADY
603
        mov     [ebp + thread_data.mode], MODE_NOTREADY
599
        mcall   close, [ebp + thread_data.datasocketnum]
604
        mcall   close, [ebp + thread_data.datasocketnum]
600
 
605
 
601
        sendFTP "226 Transfer OK"
606
        sendFTP "226 List OK"
602
        ret
607
        ret
603
 
608
 
604
  .nosuchdir:
609
  .nosuchdir:
605
        sendFTP "550 Directory does not exist"
610
        sendFTP "550 Directory does not exist"
606
        ret
611
        ret
607
 
612
 
608
;------------------------------------------------
613
;------------------------------------------------
609
; "NLST"
614
; "NLST"
610
;
615
;
611
; List the filenames of the files in the current working directory.
616
; List the filenames of the files in the current working directory.
612
;
617
;
613
;------------------------------------------------
618
;------------------------------------------------
614
align 4
619
align 4
615
cmdNLST:
620
cmdNLST:
616
 
621
 
617
        test    [ebp + thread_data.permissions], PERMISSION_EXEC
622
        test    [ebp + thread_data.permissions], PERMISSION_EXEC
618
        jz      permission_denied
623
        jz      permission_denied
619
 
624
 
620
        ; TODO: same as list but simpler output format
625
        ; TODO: same as list but simpler output format
621
 
626
 
622
        ret
627
        ret
623
 
628
 
624
;------------------------------------------------
629
;------------------------------------------------
625
; "NOOP"
630
; "NOOP"
626
;
631
;
627
; No operation, just keep the connection alive.
632
; No operation, just keep the connection alive.
628
;
633
;
629
;------------------------------------------------
634
;------------------------------------------------
630
align 4
635
align 4
631
cmdNOOP:
636
cmdNOOP:
632
 
637
 
633
        sendFTP "200 Command OK"
638
        sendFTP "200 Command OK"
634
        ret
639
        ret
635
 
640
 
636
;------------------------------------------------
641
;------------------------------------------------
637
; "PASS"
642
; "PASS"
638
;
643
;
639
; Second phase of login process, client provides password.
644
; Second phase of login process, client provides password.
640
;
645
;
641
;------------------------------------------------
646
;------------------------------------------------
642
align 4
647
align 4
643
cmdPASS:
648
cmdPASS:
644
 
649
 
645
; read the password from users.ini
650
; read the password from users.ini
646
        lea     edi, [ebp + thread_data.buffer + 512]           ; temp pass
651
        lea     edi, [ebp + thread_data.buffer + 512]           ; temp pass
647
        lea     ebx, [ebp + thread_data.fpath]                  ; temp username
652
        lea     ebx, [ebp + thread_data.fpath]                  ; temp username
648
        invoke  ini.get_str, path2, ebx, str_pass, edi, 512, str_infinity
653
        invoke  ini.get_str, path2, ebx, str_pass, edi, 512, str_infinity
649
        test    eax, eax                                        ; unable to read password? fail!
654
        test    eax, eax                                        ; unable to read password? fail!
650
        jnz     .incorrect
655
        jnz     .incorrect
651
        cmp     dword [edi], -1                                 ; no key, section or file found.. fail!
656
        cmp     dword [edi], -1                                 ; no key, section or file found.. fail!
652
        je      .incorrect
657
        je      .incorrect
653
        cmp     byte [edi], 0                                   ; zero password? ok!
658
        cmp     byte [edi], 0                                   ; zero password? ok!
654
        je      .ok
659
        je      .ok
655
 
660
 
656
        add     esi, 5
661
        add     esi, 5
657
        sub     ecx, 5
662
        sub     ecx, 5
658
        jbe     .incorrect                                      ; no password given? but hey, we need one! fail..
663
        jbe     .incorrect                                      ; no password given? but hey, we need one! fail..
659
 
664
 
660
; compare with received password
665
; compare with received password
661
        repe    cmpsb
666
        repe    cmpsb
662
        cmp     byte [esi-1], 0x20                              ; printeable characters left?
667
        cmp     byte [esi-1], 0x20                              ; printeable characters left?
663
        jae     .incorrect
668
        jae     .incorrect
664
        cmp     byte [edi-1], 0
669
        cmp     byte [edi-1], 0
665
        jne     .incorrect
670
        jne     .incorrect
666
 
671
 
667
  .ok:
672
  .ok:
668
        invoke  ini.get_int, path2, ebx, str_mode, 0
673
        invoke  ini.get_int, path2, ebx, str_mode, 0
669
        mov     [ebp + thread_data.permissions], eax
674
        mov     [ebp + thread_data.permissions], eax
670
 
675
 
671
        invoke  con_write_asciiz, str_pass_ok
676
        invoke  con_write_asciiz, str_pass_ok
672
        mov     [ebp + thread_data.state], STATE_ACTIVE
677
        mov     [ebp + thread_data.state], STATE_ACTIVE
673
        sendFTP "230 You are now logged in"
678
        sendFTP "230 You are now logged in"
674
        ret
679
        ret
675
 
680
 
676
  .2:
681
  .2:
677
  .incorrect:
682
  .incorrect:
678
        invoke  con_write_asciiz, str_pass_err
683
        invoke  con_write_asciiz, str_pass_err
679
        mov     [ebp + thread_data.state], STATE_CONNECTED      ; reset state
684
        mov     [ebp + thread_data.state], STATE_CONNECTED      ; reset state
680
        sendFTP "530 Login incorrect"
685
        sendFTP "530 Login incorrect"
681
        ret
686
        ret
682
 
687
 
683
  .0:
688
  .0:
684
        sendFTP "503 Login with USER first"
689
        sendFTP "503 Login with USER first"
685
        ret
690
        ret
686
 
691
 
687
  .3:
692
  .3:
688
        sendFTP "230 Already logged in"
693
        sendFTP "230 Already logged in"
689
        ret
694
        ret
690
 
695
 
691
;------------------------------------------------
696
;------------------------------------------------
692
; "PASV"
697
; "PASV"
693
;
698
;
694
; Initiate a passive dataconnection.
699
; Initiate a passive dataconnection.
695
;
700
;
696
;------------------------------------------------
701
;------------------------------------------------
697
align 4
702
align 4
698
cmdPASV:
703
cmdPASV:
699
 
704
 
700
;        cmp     [ebp + thread_data.passivesocknum], -1
705
;        cmp     [ebp + thread_data.passivesocknum], -1
701
;        je      @f
706
;        je      @f
702
;        mcall   close, [ebp + thread_data.passivesocknum]       ; if there is still a socket open, close it
707
;        mcall   close, [ebp + thread_data.passivesocknum]       ; if there is still a socket open, close it
703
;       @@:
708
;       @@:
704
 
709
 
705
; Open a new TCP socket
710
; Open a new TCP socket
706
        mcall   socket, AF_INET4, SOCK_STREAM, 0
711
        mcall   socket, AF_INET4, SOCK_STREAM, 0
707
        cmp     eax, -1
712
        cmp     eax, -1
708
        je      socketerror
713
        je      socketerror
709
        mov     [ebp + thread_data.passivesocknum], eax
714
        mov     [ebp + thread_data.passivesocknum], eax
710
 
715
 
711
; Bind it to a known local port
716
; Bind it to a known local port
712
        mov     [ebp + thread_data.datasock.sin_family], AF_INET4
717
        mov     [ebp + thread_data.datasock.sin_family], AF_INET4
713
        mov     [ebp + thread_data.datasock.sin_addr], 0
718
        mov     [ebp + thread_data.datasock.sin_addr], 0
714
 
719
 
715
        mov     ecx, eax                                        ; passivesocketnum
720
        mov     ecx, eax                                        ; passivesocketnum
716
        lea     edx, [ebp + thread_data.datasock]
721
        lea     edx, [ebp + thread_data.datasock]
717
        mov     esi, sizeof.thread_data.datasock
722
        mov     esi, sizeof.thread_data.datasock
718
 
723
 
719
  .next_port:                                                   ; TODO: break the endless loop
724
  .next_port:                                                   ; TODO: break the endless loop
720
        call    nextpasvport
725
        call    nextpasvport
721
        mov     ax, [pasv_port]
726
        mov     ax, [pasv_port]
722
        xchg    al, ah
727
        xchg    al, ah
723
        mov     [ebp + thread_data.datasock.sin_port], ax
728
        mov     [ebp + thread_data.datasock.sin_port], ax
724
 
729
 
725
        mcall   bind
730
        mcall   bind
726
        cmp     eax, -1
731
        cmp     eax, -1
727
        je      .next_port
732
        je      .next_port
728
 
733
 
729
; And set it to listen!
734
; And set it to listen!
730
        mcall   listen, , 1
735
        mcall   listen, , 1
731
        cmp     eax, -1
736
        cmp     eax, -1
732
        je      socketerror
737
        je      socketerror
733
 
738
 
734
; Tell our thread we are ready to accept incoming calls
739
; Tell our thread we are ready to accept incoming calls
735
        mov     [ebp + thread_data.mode], MODE_PASSIVE_WAIT
740
        mov     [ebp + thread_data.mode], MODE_PASSIVE_WAIT
736
 
741
 
737
; Now tell the client where to connect to in this format:
742
; Now tell the client where to connect to in this format:
738
; 227 Entering Passive Mode (a1,a2,a3,a4,p1,p2)
743
; 227 Entering Passive Mode (a1,a2,a3,a4,p1,p2)
739
; where a1.a2.a3.a4 is the IP address and p1*256+p2 is the port number.
744
; where a1.a2.a3.a4 is the IP address and p1*256+p2 is the port number.
740
 
745
 
741
; '227 Entering passive mode ('
746
; '227 Entering passive mode ('
742
        lea     edi, [ebp + thread_data.buffer]
747
        lea     edi, [ebp + thread_data.buffer]
743
        mov     ecx, str_227.length
748
        mov     ecx, str_227.length
744
        mov     esi, str_227
749
        mov     esi, str_227
745
        rep movsb
750
        rep movsb
746
; ip
751
; ip
747
        movzx   eax, byte [serverip]
752
        movzx   eax, byte [serverip]
748
        call    dword_to_ascii
753
        call    dword_to_ascii
749
        mov     al, ','
754
        mov     al, ','
750
        stosb
755
        stosb
751
        movzx   eax, byte [serverip+1]
756
        movzx   eax, byte [serverip+1]
752
        call    dword_to_ascii
757
        call    dword_to_ascii
753
        mov     al, ','
758
        mov     al, ','
754
        stosb
759
        stosb
755
        movzx   eax, byte [serverip+2]
760
        movzx   eax, byte [serverip+2]
756
        call    dword_to_ascii
761
        call    dword_to_ascii
757
        mov     al, ','
762
        mov     al, ','
758
        stosb
763
        stosb
759
        movzx   eax, byte [serverip+3]
764
        movzx   eax, byte [serverip+3]
760
        call    dword_to_ascii
765
        call    dword_to_ascii
761
        mov     al, ','
766
        mov     al, ','
762
        stosb
767
        stosb
763
; port
768
; port
764
        movzx   eax, byte [ebp + thread_data.datasock.sin_port]
769
        movzx   eax, byte [ebp + thread_data.datasock.sin_port]
765
        call    dword_to_ascii
770
        call    dword_to_ascii
766
        mov     al, ','
771
        mov     al, ','
767
        stosb
772
        stosb
768
        movzx   eax, byte [ebp + thread_data.datasock.sin_port+1]
773
        movzx   eax, byte [ebp + thread_data.datasock.sin_port+1]
769
        call    dword_to_ascii
774
        call    dword_to_ascii
770
; ')', 13, 10, 0
775
; ')', 13, 10, 0
771
        mov     eax, ')' + (0x000a0d shl 8)
776
        mov     eax, ')' + (0x000a0d shl 8)
772
        stosd
777
        stosd
773
 
778
 
774
        lea     esi, [edi - thread_data.buffer]
779
        lea     esi, [edi - thread_data.buffer - 1]      ; calculate length, do not cound the trailing 0 byte
775
        sub     esi, ebp
780
        sub     esi, ebp
776
        mov     ecx, [ebp + thread_data.socketnum]
781
        mov     ecx, [ebp + thread_data.socketnum]
777
        lea     edx, [ebp + thread_data.buffer]
782
        lea     edx, [ebp + thread_data.buffer]
778
        xor     edi, edi
783
        xor     edi, edi
779
        mcall   send
784
        mcall   send
780
 
785
 
781
        ret
786
        invoke  con_write_asciiz, edx
-
 
787
 
-
 
788
        ret
782
 
789
 
783
 
790
 
784
iglobal
791
iglobal
785
        str_227 db "227 Entering passive mode ("
792
        str_227 db "227 Entering passive mode ("
786
        .length = $ - str_227
793
        .length = $ - str_227
787
endg
794
endg
788
 
795
 
789
;------------------------------------------------
796
;------------------------------------------------
790
; "PWD"
797
; "PWD"
791
;
798
;
792
; Print the current working directory.
799
; Print the current working directory.
793
;
800
;
794
;------------------------------------------------
801
;------------------------------------------------
795
align 4
802
align 4
796
cmdPWD:
803
cmdPWD:
797
 
804
 
798
        mov     dword [ebp + thread_data.buffer], '257 '
805
        mov     dword [ebp + thread_data.buffer], '257 '
799
        mov     byte [ebp + thread_data.buffer+4], '"'
806
        mov     byte [ebp + thread_data.buffer+4], '"'
800
 
807
 
801
        lea     edi, [ebp + thread_data.buffer+5]
808
        lea     edi, [ebp + thread_data.buffer+5]
802
        lea     esi, [ebp + thread_data.work_dir]
809
        lea     esi, [ebp + thread_data.work_dir]
803
        mov     ecx, 1024
810
        mov     ecx, 1024
804
  .loop:
811
  .loop:
805
        lodsb
812
        lodsb
806
        or      al, al
813
        or      al, al
807
        jz      .ok
814
        jz      .ok
808
        stosb
815
        stosb
809
        dec     ecx
816
        dec     ecx
810
        jnz     .loop
817
        jnz     .loop
811
 
818
 
812
  .ok:
819
  .ok:
813
        mov     dword [edi], '"' + 0x000a0d00    ; '"',13,10,0
820
        mov     dword [edi], '"' + 0x000a0d00    ; '"',13,10,0
814
        lea     esi, [edi - thread_data.buffer + 4]
821
        lea     esi, [edi - thread_data.buffer + 3]
815
        sub     esi, ebp
822
        sub     esi, ebp
816
        mov     ecx, [ebp + thread_data.socketnum]
823
        mov     ecx, [ebp + thread_data.socketnum]
817
        lea     edx, [ebp + thread_data.buffer]
824
        lea     edx, [ebp + thread_data.buffer]
818
        xor     edi, edi
825
        xor     edi, edi
819
        mcall   send
826
        mcall   send
820
 
827
 
821
; Print the new working dir on the console
828
; Print the new working dir on the console
822
        lea     eax, [ebp + thread_data.work_dir]
829
        lea     eax, [ebp + thread_data.work_dir]
823
        invoke  con_write_asciiz, eax
830
        invoke  con_write_asciiz, eax
824
        invoke  con_write_asciiz, str_newline
831
        invoke  con_write_asciiz, str_newline
825
 
832
 
826
        ret
833
        ret
827
 
834
 
828
;------------------------------------------------
835
;------------------------------------------------
829
; "PORT"
836
; "PORT"
830
;
837
;
831
; Initiate an active dataconnection.
838
; Initiate an active dataconnection.
832
;
839
;
833
;------------------------------------------------
840
;------------------------------------------------
834
align 4
841
align 4
835
cmdPORT:
842
cmdPORT:
836
 
843
 
837
; PORT a1,a2,a3,a4,p1,p2
844
; PORT a1,a2,a3,a4,p1,p2
838
; IP address a1.a2.a3.a4, port p1*256+p2
845
; IP address a1.a2.a3.a4, port p1*256+p2
839
 
846
 
840
; Convert the IP
847
; Convert the IP
841
        lea     esi, [esi+5]
848
        lea     esi, [esi+5]
842
        mov     cl, ','
849
        mov     cl, ','
843
        call    ip_to_dword
850
        call    ip_to_dword
844
; And put it in datasock
851
; And put it in datasock
845
        mov     [ebp + thread_data.datasock.sin_addr], ebx
852
        mov     [ebp + thread_data.datasock.sin_addr], ebx
846
 
853
 
847
; Now the same with portnumber
854
; Now the same with portnumber
848
        inc     esi
855
        inc     esi
849
        call    ascii_to_byte
856
        call    ascii_to_byte
850
        mov     byte[ebp + thread_data.datasock.sin_port], al
857
        mov     byte[ebp + thread_data.datasock.sin_port], al
851
        inc     esi
858
        inc     esi
852
        call    ascii_to_byte
859
        call    ascii_to_byte
853
        mov     byte[ebp + thread_data.datasock.sin_port+1], al
860
        mov     byte[ebp + thread_data.datasock.sin_port+1], al
854
 
861
 
855
; We will open the socket, but do not connect yet!
862
; We will open the socket, but do not connect yet!
856
        mov     [ebp + thread_data.datasock.sin_family], AF_INET4
863
        mov     [ebp + thread_data.datasock.sin_family], AF_INET4
857
        mcall   socket, AF_INET4, SOCK_STREAM, 0
864
        mcall   socket, AF_INET4, SOCK_STREAM, 0
858
        cmp     eax, -1
865
        cmp     eax, -1
859
        je      socketerror
866
        je      socketerror
860
 
867
 
861
        mov     [ebp + thread_data.datasocketnum], eax
868
        mov     [ebp + thread_data.datasocketnum], eax
862
        mov     [ebp + thread_data.mode], MODE_ACTIVE
869
        mov     [ebp + thread_data.mode], MODE_ACTIVE
863
 
870
 
864
        sendFTP "225 Data connection open"
871
        sendFTP "225 Data connection open"
865
        ret
872
        ret
866
 
873
 
867
;------------------------------------------------
874
;------------------------------------------------
868
; "QUIT"
875
; "QUIT"
869
;
876
;
870
; Close the connection with client.
877
; Close the connection with client.
871
;
878
;
872
;------------------------------------------------
879
;------------------------------------------------
873
align 4
880
align 4
874
cmdQUIT:
881
cmdQUIT:
875
 
882
 
876
        sendFTP "221 Bye!"
883
        sendFTP "221 Bye!"
877
        mcall   close, [ebp + thread_data.datasocketnum]
884
        mcall   close, [ebp + thread_data.datasocketnum]
878
        mcall   close, [ebp + thread_data.socketnum]
885
        mcall   close, [ebp + thread_data.socketnum]
879
 
886
 
880
        add     esp, 4          ; get rid of call return address
887
        add     esp, 4          ; get rid of call return address
881
        jmp     thread_exit     ; now close this thread
888
        jmp     thread_exit     ; now close this thread
882
 
889
 
883
 
890
 
884
;------------------------------------------------
891
;------------------------------------------------
885
; "RETR"
892
; "RETR"
886
;
893
;
887
; Retrieve a file from the ftp server.
894
; Retrieve a file from the ftp server.
888
;
895
;
889
;------------------------------------------------
896
;------------------------------------------------
890
align 4
897
align 4
891
cmdRETR:
898
cmdRETR:
892
 
899
 
893
        test    [ebp + thread_data.permissions], PERMISSION_READ
900
        test    [ebp + thread_data.permissions], PERMISSION_READ
894
        jz      permission_denied
901
        jz      permission_denied
895
 
902
 
896
        cmp     ecx, 1024 + 5
903
        cmp     ecx, 1024 + 5
897
        jae     .cannot_open
904
        jae     .cannot_open
898
 
905
 
899
        sub     ecx, 5
906
        sub     ecx, 5
900
        jb      .cannot_open
907
        jb      .cannot_open
901
 
908
 
902
        call    open_datasock
909
        call    open_datasock
903
 
910
 
904
        call    create_path
911
        call    create_path
905
        dec     edi
912
        dec     edi
906
        lea     esi, [ebp + thread_data.buffer + 5]
913
        lea     esi, [ebp + thread_data.buffer + 5]
907
        mov     ecx, 1024
914
        mov     ecx, 1024
908
        cmp     byte [esi], '/'
915
        cmp     byte [esi], '/'
909
        jne     .loop
916
        jne     .loop
910
        inc     esi
917
        inc     esi
911
  .loop:
918
  .loop:
912
        lodsb
919
        lodsb
913
        cmp     al, 0x20
920
        cmp     al, 0x20
914
        jl      .done
921
        jl      .done
915
        stosb
922
        stosb
916
        loop    .loop
923
        loop    .loop
917
  .done:
924
  .done:
918
        xor     al, al
925
        xor     al, al
919
        stosb
926
        stosb
920
 
927
 
921
        lea     ebx, [ebp + thread_data.fpath]
928
        lea     ebx, [ebp + thread_data.fpath]
922
        invoke  con_write_asciiz, ebx
929
        invoke  con_write_asciiz, ebx
923
        invoke  con_write_asciiz, str_newline
930
        invoke  con_write_asciiz, str_newline
924
 
931
 
925
        invoke  file.open, ebx, O_READ
932
        invoke  file.open, ebx, O_READ
926
        test    eax, eax
933
        test    eax, eax
927
        jz      .cannot_open
934
        jz      .cannot_open
928
 
935
 
929
        push    eax
936
        push    eax
930
        sendFTP "150 Here it comes.."
937
        sendFTP "150 Here it comes.."
931
        pop     ebx
938
        pop     ebx
932
 
939
 
933
  .read_more:
940
  .read_more:
934
        test    [ebp + thread_data.permissions], ABORT
941
        test    [ebp + thread_data.permissions], ABORT
935
        jnz     abort_transfer
942
        jnz     abort_transfer
936
 
943
 
937
        lea     eax, [ebp + thread_data.buffer]                 ; FIXME: use another buffer!! if we receive something on control connection now, we screw up!
944
        lea     eax, [ebp + thread_data.buffer]                 ; FIXME: use another buffer!! if we receive something on control connection now, we screw up!
938
        invoke  file.read, ebx, eax, BUFFERSIZE
945
        invoke  file.read, ebx, eax, BUFFERSIZE
939
        cmp     eax, -1
946
        cmp     eax, -1
940
        je      .cannot_open                                    ; FIXME: this is not the correct error
947
        je      .cannot_open                                    ; FIXME: this is not the correct error
941
 
948
 
942
        invoke  con_write_asciiz, str2
949
        invoke  con_write_asciiz, str2
943
 
950
 
944
        push    eax ebx
951
        push    eax ebx
945
        mov     esi, eax
952
        mov     esi, eax
946
        mov     ecx, [ebp + thread_data.datasocketnum]
953
        mov     ecx, [ebp + thread_data.datasocketnum]
947
        lea     edx, [ebp + thread_data.buffer]
954
        lea     edx, [ebp + thread_data.buffer]
948
        xor     edi, edi
955
        xor     edi, edi
949
        mcall   send
956
        mcall   send
950
        pop     ebx ecx
957
        pop     ebx ecx
951
        cmp     eax, -1
958
        cmp     eax, -1
952
        je      socketerror                                     ; FIXME: not the correct error
959
        je      socketerror                                     ; FIXME: not the correct error
953
 
960
 
954
;        cmp     eax, ecx
961
;        cmp     eax, ecx
955
;        jne     not_all_byes_sent                               ; TODO
962
;        jne     not_all_byes_sent                               ; TODO
956
 
963
 
957
        cmp     ecx, BUFFERSIZE
964
        cmp     ecx, BUFFERSIZE
958
        je      .read_more
965
        je      .read_more
959
 
966
 
960
        invoke  file.close, ebx
967
        invoke  file.close, ebx
961
 
968
 
962
        invoke  con_write_asciiz, str2b
969
        invoke  con_write_asciiz, str2b
963
 
970
 
964
        mov     [ebp + thread_data.mode], MODE_NOTREADY
971
        mov     [ebp + thread_data.mode], MODE_NOTREADY
965
        mcall   close, [ebp + thread_data.datasocketnum]
972
        mcall   close, [ebp + thread_data.datasocketnum]
966
 
973
 
967
        sendFTP "226 Transfer OK, closing connection"
974
        sendFTP "226 Transfer OK, closing connection"
968
        ret
975
        ret
969
 
976
 
970
  .cannot_open:
977
  .cannot_open:
971
        invoke  con_set_flags, 0x0c
978
        invoke  con_set_flags, 0x0c
972
        invoke  con_write_asciiz, str_notfound
979
        invoke  con_write_asciiz, str_notfound
973
        invoke  con_set_flags, 0x07
980
        invoke  con_set_flags, 0x07
974
 
981
 
975
        sendFTP "550 No such file"
982
        sendFTP "550 No such file"
976
        ret
983
        ret
977
 
984
 
978
 
985
 
979
 
986
 
980
;------------------------------------------------
987
;------------------------------------------------
981
; "STOR"
988
; "STOR"
982
;
989
;
983
; Store a file on the server.
990
; Store a file on the server.
984
;
991
;
985
;------------------------------------------------
992
;------------------------------------------------
986
align 4
993
align 4
987
cmdSTOR:
994
cmdSTOR:
988
 
995
 
989
        test    [ebp + thread_data.permissions], PERMISSION_WRITE
996
        test    [ebp + thread_data.permissions], PERMISSION_WRITE
990
        jz      permission_denied
997
        jz      permission_denied
991
 
998
 
992
 
999
        sendFTP " Ready to receive"
-
 
1000
 
-
 
1001
 
-
 
1002
;;;;    TODO
-
 
1003
 
993
;;;;
-
 
994
        test    [ebp + thread_data.permissions], ABORT
1004
        test    [ebp + thread_data.permissions], ABORT
995
        jnz     abort_transfer
1005
        jnz     abort_transfer
996
 
1006
 
997
;;;;
1007
;;;;
998
 
1008
 
999
        ret
1009
        sendFTP "226 Transfer OK"
-
 
1010
 
-
 
1011
        ret
1000
 
1012
 
1001
;------------------------------------------------
1013
;------------------------------------------------
1002
; "SYST"
1014
; "SYST"
1003
;
1015
;
1004
; Send information about the system.
1016
; Send information about the system.
1005
;
1017
;
1006
;------------------------------------------------
1018
;------------------------------------------------
1007
align 4
1019
align 4
1008
cmdSYST:
1020
cmdSYST:
1009
 
1021
 
1010
        sendFTP "215 UNIX type: L8"
1022
        sendFTP "215 UNIX type: L8"
1011
        ret
1023
        ret
1012
 
1024
 
1013
;------------------------------------------------
1025
;------------------------------------------------
1014
; "TYPE"
1026
; "TYPE"
1015
;
1027
;
1016
; Choose the file transfer type.
1028
; Choose the file transfer type.
1017
;
1029
;
1018
;------------------------------------------------
1030
;------------------------------------------------
1019
align 4
1031
align 4
1020
cmdTYPE:
1032
cmdTYPE:
1021
 
1033
 
1022
        cmp     ecx, 6
1034
        cmp     ecx, 6
1023
        jb      parse_cmd.error
1035
        jb      parse_cmd.error
1024
 
1036
 
1025
        mov     al, byte[esi+5]
1037
        mov     al, byte[esi+5]
1026
        and     al, not 0x20
1038
        and     al, not 0x20
1027
 
1039
 
1028
        cmp     al, 'A'
1040
        cmp     al, 'A'
1029
        je      .ascii
1041
        je      .ascii
1030
        cmp     al, 'E'
1042
        cmp     al, 'E'
1031
        je      .ebdic
1043
        je      .ebdic
1032
        cmp     al, 'I'
1044
        cmp     al, 'I'
1033
        je      .image
1045
        je      .image
1034
        cmp     al, 'L'
1046
        cmp     al, 'L'
1035
        je      .local
1047
        je      .local
1036
 
1048
 
1037
        jmp     parse_cmd.error
1049
        jmp     parse_cmd.error
1038
 
1050
 
1039
  .ascii:
1051
  .ascii:
1040
        mov     [ebp + thread_data.type], TYPE_ASCII
1052
        mov     [ebp + thread_data.type], TYPE_ASCII
1041
        jmp     .subtype
1053
        jmp     .subtype
1042
 
1054
 
1043
  .ebdic:
1055
  .ebdic:
1044
        mov     [ebp + thread_data.type], TYPE_EBDIC
1056
        mov     [ebp + thread_data.type], TYPE_EBDIC
1045
 
1057
 
1046
  .subtype:
1058
  .subtype:
1047
        cmp     ecx, 8
1059
        cmp     ecx, 8
1048
        jb      .non_print
1060
        jb      .non_print
1049
 
1061
 
1050
        mov     al, byte[esi+7]
1062
        mov     al, byte[esi+7]
1051
        and     al, not 0x20
1063
        and     al, not 0x20
1052
 
1064
 
1053
        cmp     al, 'N'
1065
        cmp     al, 'N'
1054
        je      .non_print
1066
        je      .non_print
1055
        cmp     al, 'T'
1067
        cmp     al, 'T'
1056
        je      .telnet
1068
        je      .telnet
1057
        cmp     al, 'C'
1069
        cmp     al, 'C'
1058
        je      .asacc
1070
        je      .asacc
1059
        cmp     al, 0x20
1071
        cmp     al, 0x20
1060
        jb      .non_print
1072
        jb      .non_print
1061
 
1073
 
1062
        jmp     parse_cmd.error
1074
        jmp     parse_cmd.error
1063
 
1075
 
1064
  .non_print:
1076
  .non_print:
1065
        or      [ebp + thread_data.type], TYPE_NP
1077
        or      [ebp + thread_data.type], TYPE_NP
1066
        jmp     .ok
1078
        jmp     .ok
1067
 
1079
 
1068
  .telnet:
1080
  .telnet:
1069
        or      [ebp + thread_data.type], TYPE_TELNET
1081
        or      [ebp + thread_data.type], TYPE_TELNET
1070
        jmp     .ok
1082
        jmp     .ok
1071
 
1083
 
1072
  .asacc:
1084
  .asacc:
1073
        or      [ebp + thread_data.type], TYPE_ASA
1085
        or      [ebp + thread_data.type], TYPE_ASA
1074
        jmp     .ok
1086
        jmp     .ok
1075
 
1087
 
1076
  .image:
1088
  .image:
1077
        mov     [ebp + thread_data.type], TYPE_IMAGE
1089
        mov     [ebp + thread_data.type], TYPE_IMAGE
1078
        jmp     .ok
1090
        jmp     .ok
1079
 
1091
 
1080
  .local:
1092
  .local:
1081
        cmp     ecx, 8
1093
        cmp     ecx, 8
1082
        jb      parse_cmd.error
1094
        jb      parse_cmd.error
1083
 
1095
 
1084
        mov     al, byte[esi+7]
1096
        mov     al, byte[esi+7]
1085
        sub     al, '0'
1097
        sub     al, '0'
1086
        jb      parse_cmd.error                         ; FIXME: this is not the correct errormessage
1098
        jb      parse_cmd.error                         ; FIXME: this is not the correct errormessage
1087
        cmp     al, 9
1099
        cmp     al, 9
1088
        ja      parse_cmd.error                         ; FIXME
1100
        ja      parse_cmd.error                         ; FIXME
1089
        or      al, TYPE_LOCAL
1101
        or      al, TYPE_LOCAL
1090
        mov     [ebp + thread_data.type], al
1102
        mov     [ebp + thread_data.type], al
1091
 
1103
 
1092
  .ok:
1104
  .ok:
1093
        sendFTP "200 Command ok"
1105
        sendFTP "200 Command ok"
1094
        ret
1106
        ret
1095
 
1107
 
1096
;------------------------------------------------
1108
;------------------------------------------------
1097
; "USER"
1109
; "USER"
1098
;
1110
;
1099
; Login to the server, step one of two.                         ;;; TODO: prevent buffer overflow!
1111
; Login to the server, step one of two.                         ;;; TODO: prevent buffer overflow!
1100
;
1112
;
1101
;------------------------------------------------
1113
;------------------------------------------------
1102
align 4
1114
align 4
1103
cmdUSER:
1115
cmdUSER:
1104
 
1116
 
1105
        lea     esi, [esi + 5]
1117
        lea     esi, [esi + 5]
1106
        lea     edi, [ebp + thread_data.fpath]                  ; temp buffer for username
1118
        lea     edi, [ebp + thread_data.fpath]                  ; temp buffer for username
1107
  .loop:
1119
  .loop:
1108
        lodsb
1120
        lodsb
1109
        stosb
1121
        stosb
1110
        cmp     al, 0x20
1122
        cmp     al, 0x20
1111
        jae     .loop
1123
        jae     .loop
1112
        mov     byte [edi-1], 0
1124
        mov     byte [edi-1], 0
1113
 
1125
 
1114
        lea     esi, [ebp + thread_data.fpath]
1126
        lea     esi, [ebp + thread_data.fpath]
1115
        lea     eax, [ebp + thread_data.home_dir]
1127
        lea     eax, [ebp + thread_data.home_dir]
1116
        invoke  ini.get_str, path2, esi, str_home, eax, 1024, str_infinity
1128
        invoke  ini.get_str, path2, esi, str_home, eax, 1024, str_infinity
1117
        cmp     eax, -1
1129
        cmp     eax, -1
1118
        je      .login_fail
1130
        je      .login_fail
1119
        cmp     dword [esi], -1
1131
        cmp     dword [esi], -1
1120
        je      .login_fail
1132
        je      .login_fail
1121
 
1133
 
1122
        mov     word [ebp + thread_data.work_dir], "/"          ; "/", 0
1134
        mov     word [ebp + thread_data.work_dir], "/"          ; "/", 0
1123
 
1135
 
1124
        invoke  con_write_asciiz, str_logged_in
1136
        invoke  con_write_asciiz, str_logged_in
1125
        mov     [ebp + thread_data.state], STATE_LOGIN
1137
        mov     [ebp + thread_data.state], STATE_LOGIN
1126
  .sendstr:
1138
  .sendstr:
1127
        sendFTP "331 Please specify the password"
1139
        sendFTP "331 Please specify the password"
1128
        ret
1140
        ret
1129
 
1141
 
1130
  .login_fail:
1142
  .login_fail:
1131
        invoke  con_write_asciiz, str_pass_err
1143
        invoke  con_write_asciiz, str_pass_err
1132
        mov     [ebp + thread_data.state], STATE_LOGIN_FAIL
1144
        mov     [ebp + thread_data.state], STATE_LOGIN_FAIL
1133
        jmp     .sendstr
1145
        jmp     .sendstr
1134
 
1146
 
1135
align 4
1147
align 4
1136
  .2:
1148
  .2:
1137
        sendFTP "530 Can't change to another user"
1149
        sendFTP "530 Can't change to another user"
1138
        ret
1150
        ret