Subversion Repositories Kolibri OS

Rev

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

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