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 |