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 |