Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 2609 → Rev 2610

/kernel/branches/net/applications/ftpd/commands.inc
4,9 → 4,10
rb 1024
stack rb 0
 
home_dir rb 1024
work_dir rb 1024
fpath rb 1024*3 ; Will also be used to temporarily store username
home_dir rb 1024 ; home directory in wich the user is locked, asciiz
work_dir rb 1024 ; working directory, must at all times begin and end with a '/', asciiz
fpath rb 1024*3 ; file path, combination of home_dir, work_dir and filename
; Will also be used to temporarily store username
 
type db ? ; ASCII/EBDIC/IMAGE/..
mode db ? ; active/passive
14,7 → 15,7
state dd ? ; disconnected/logging in/logged in/..
passivesocknum dd ? ; when in passive mode, this is the listening socket
datasocketnum dd ? ; socket used for data transfers
permissions dd ?
permissions dd ? ; read/write/execute/....
buffer_ptr dd ?
 
datasock sockaddr_in
266,6 → 267,27
stosb
ret
 
 
align 4
nextpasvport:
 
inc [pasv_port]
 
mov ax, [pasv_port]
cmp ax, [pasv_start]
jb .restart
cmp ax, [pasv_end]
ja .restart
 
ret
 
.restart:
pushw [pasv_start]
popw [pasv_port]
 
ret
 
 
;------------------------------------------------
; "ABOR"
;
292,28 → 314,30
jz permission_denied
 
cmp byte [ebp + thread_data.work_dir+1], 0 ; are we in "/" ?
je .done
je .done ; if so, we cant go up..
 
; find the end of asciiz string work_dir
mov ecx, 1024
xor al, al
lea edi, [ebp + thread_data.work_dir]
repne scasb
; return 2 characters (right before last /)
sub edi, 3
; and now search backwards, for a '/'
mov al,'/'
std
neg ecx
add ecx, 1024
std
repne scasb
cld
mov byte[edi+1], 0
; terminate the string here
mov byte[edi+2], 0
 
.done:
; Print the new working dir on the console
lea eax, [ebp + thread_data.work_dir]
push eax
call [con_write_asciiz]
push str_newline
call [con_write_asciiz]
invoke con_write_asciiz, eax
invoke con_write_asciiz, str_newline
 
sendFTP "250 Command succesul"
ret
330,44 → 354,40
test [ebp + thread_data.permissions], PERMISSION_CD
jz permission_denied
 
; do we have enough parameters?
sub ecx, 4
jb .err
jbe .err
 
; get ready to copy the path
add esi, 4
 
mov ecx, 1024
lea edi, [ebp + thread_data.work_dir]
 
; if received dir starts with '/', we will simply copy it
; If not, we will append the current path with the received path.
cmp byte [esi], '/'
je .loop
je .copyloop
 
.scan:
lea edi, [ebp + thread_data.work_dir + 1]
push ecx
mov ecx, 1024
; Find the end of work_dir string.
xor al, al
.find_zero:
cmp byte [edi], 0
je .found_zero
inc edi
loop .find_zero
.found_zero:
pop ecx
.scan2:
repne scasb
dec edi
 
cmp byte [esi], '/'
jne @f
inc esi
dec ecx
jz .done
@@:
; and now append work_dir with received string
mov ecx, 1024
 
.loop:
; scan for end byte, or '.'
.copyloop:
lodsb
cmp al, 0x20
jb .done
cmp al, '.'
je .up
.continue:
;;; cmp al, '.' ; '..' means we must go up one dir TODO
;;; je .up
stosb
loop .loop
loop .copyloop
 
; now, now make sure it ends with '/', 0
.done:
cmp byte [edi-1], '/'
je @f
378,24 → 398,12
 
; Print the new working dir on the console
lea eax, [ebp + thread_data.work_dir]
push eax
call [con_write_asciiz]
push str_newline
call [con_write_asciiz]
invoke con_write_asciiz, eax
invoke con_write_asciiz, str_newline
 
sendFTP "250 Command succesful"
ret
 
.up:
lodsb
cmp al, '.'
jne .continue
 
;;;; TODO: find second last '\' in work_dir and make next char zero
;;;; point edi to that 0
 
jmp .scan2
 
.err:
sendFTP "550 Directory does not exist"
ret
426,9 → 434,12
test [ebp + thread_data.permissions], PERMISSION_EXEC
jz permission_denied
 
cmp [ebp + thread_data.mode], MODE_PASSIVE_OK
je .start
 
; If we are in active mode, it's time to open a data socket..
cmp [ebp + thread_data.mode], MODE_ACTIVE
jne @f
jne .not_active
mov ecx, [ebp + thread_data.datasocketnum]
lea edx, [ebp + thread_data.datasock]
mov esi, sizeof.thread_data.datasock
435,8 → 446,32
mcall connect
cmp eax, -1
je socketerror
@@:
jmp .start
 
; If we are still in passive_wait, it's time we accept an incomming call..
.not_active:
cmp [ebp + thread_data.mode], MODE_PASSIVE_WAIT
jne socketerror
mov [ebp + thread_data.mode], MODE_PASSIVE_FAILED ; assume that we will fail
.try_now:
mov ecx, [ebp + thread_data.passivesocknum]
lea edx, [ebp + thread_data.datasock]
mov esi, sizeof.thread_data.datasock
mcall accept
cmp eax, -1
jne .pasv_ok
mcall 23, 200
mcall accept
cmp eax, -1
je socketerror
.pasv_ok:
mov [ebp + thread_data.datasocketnum], eax
mov [ebp + thread_data.mode], MODE_PASSIVE_OK
mcall close ; [ebp + thread_data.passivesocknum]
mov [ebp + thread_data.passivesocknum], -1
invoke con_write_asciiz, str_datasock
 
.start:
; Create fpath from home_dir and work_dir
call create_path
 
606,27 → 641,31
;------------------------------------------------
align 4
cmdPASS:
lea esi, [esi + 5]
 
; read the password from users.ini
lea edi, [ebp + thread_data.buffer + 512] ; temp pass
mov byte [edi], 0
lea ebx, [ebp + thread_data.fpath] ; temp username
invoke ini.get_str, path2, ebx, str_pass, edi, 512, str_infinity
test eax, eax
test eax, eax ; unable to read password? fail!
jnz .incorrect
cmp dword [edi], -1
cmp dword [edi], -1 ; no key, section or file found.. fail!
je .incorrect
cmp byte[edi], 0
je .pass_ok
cmp byte [edi], 0 ; zero password? ok!
je .ok
 
add esi, 5
sub ecx, 5
jbe .incorrect ; no password given? but hey, we need one! fail..
 
; compare with received password
repe cmpsb
cmp byte [esi], 0x20
cmp byte [esi-1], 0x20 ; printeable characters left?
jae .incorrect
cmp byte [edi], 0
cmp byte [edi-1], 0
jne .incorrect
 
.pass_ok:
.ok:
invoke ini.get_int, path2, ebx, str_mode, 0
mov [ebp + thread_data.permissions], eax
 
637,16 → 676,15
 
.2:
.incorrect:
mov [ebp + thread_data.state], STATE_CONNECTED
invoke con_write_asciiz, str_pass_err
mov [ebp + thread_data.state], STATE_CONNECTED ; reset state
sendFTP "530 Login incorrect"
ret
 
align 4
.0:
sendFTP "503 Login with USER first"
ret
 
align 4
.3:
sendFTP "230 Already logged in"
ret
660,6 → 698,11
align 4
cmdPASV:
 
cmp [ebp + thread_data.passivesocknum], -1
je @f
mcall close, [ebp + thread_data.passivesocknum] ; if there is still a socket open, close it
@@:
 
; Open a new TCP socket
mcall socket, AF_INET4, SOCK_STREAM, 0
cmp eax, -1
668,22 → 711,25
 
; Bind it to a known local port
mov [ebp + thread_data.datasock.sin_family], AF_INET4
pushw [pasvport]
popw [ebp + thread_data.datasock.sin_port]
inc [pasvport]
mov [ebp + thread_data.datasock.sin_addr], 0
 
mov ecx, eax ; passivesocketnum
lea edx, [ebp + thread_data.datasock]
mov esi, sizeof.thread_data.datasock
 
.next_port: ; TODO: break the endless loop
call nextpasvport
pushw [pasv_port]
popw [ebp + thread_data.datasock.sin_port]
 
mcall bind
cmp eax, -1
; je bind_err ; TODO
je .next_port
 
; And set it to listen!
mcall listen, , 1
cmp eax, -1
; je listen_err ; TODO
je socketerror
 
; Tell our thread we are ready to accept incoming calls
mov [ebp + thread_data.mode], MODE_PASSIVE_WAIT
694,24 → 740,24
 
; '227 ('
lea edi, [ebp + thread_data.buffer]
mov eax, '227 ' ; FIXME (now hardcoded to 127.0.0.1:2000)
mov eax, '227 '
stosd
mov al, '('
stosb
; ip
mov eax, 127
movzx eax, byte [serverip]
call dword_to_ascii
mov al, ','
stosb
mov eax, 0
movzx eax, byte [serverip+1]
call dword_to_ascii
mov al, ','
stosb
mov eax, 0
movzx eax, byte [serverip+2]
call dword_to_ascii
mov al, ','
stosb
mov eax, 1
movzx eax, byte [serverip+3]
call dword_to_ascii
mov al, ','
stosb
851,24 → 897,50
sub ecx, 5
jb .cannot_open
 
cmp [ebp + thread_data.mode], MODE_PASSIVE_OK
je .start
 
; If we are in active mode, it's time to open a data socket..
cmp [ebp + thread_data.mode], MODE_ACTIVE
jne @f
push ecx esi
jne .not_active
mov ecx, [ebp + thread_data.datasocketnum]
lea edx, [ebp + thread_data.datasock]
mov esi, sizeof.thread_data.datasock
mcall connect
pop esi ecx
cmp eax, -1
je socketerror
@@:
jmp .start
 
push ecx esi
; If we are still in passive_wait, it's time we accept an incomming call..
.not_active:
cmp [ebp + thread_data.mode], MODE_PASSIVE_WAIT
jne socketerror
mov [ebp + thread_data.mode], MODE_PASSIVE_FAILED ; assume that we will fail
.try_now:
mov ecx, [ebp + thread_data.passivesocknum]
lea edx, [ebp + thread_data.datasock]
mov esi, sizeof.thread_data.datasock
mcall accept
cmp eax, -1
jne .pasv_ok
mcall 23, 200
mcall accept
cmp eax, -1
je socketerror
.pasv_ok:
mov [ebp + thread_data.datasocketnum], eax
mov [ebp + thread_data.mode], MODE_PASSIVE_OK
mcall close ; [ebp + thread_data.passivesocknum]
mov [ebp + thread_data.passivesocknum], -1
invoke con_write_asciiz, str_datasock
 
.start:
call create_path
pop esi ecx
dec edi
add esi, 5
 
lea esi, [ebp + thread_data.buffer] ; FIXME
mov ecx, 1024
.loop:
lodsb
cmp al, 0x20
929,7 → 1001,6
invoke con_write_asciiz, str_notfound
invoke con_set_flags, 0x07
 
mov edx, [ebp]
sendFTP "550 No such file"
ret
 
1084,7 → 1155,7
ret
 
.login_fail:
invoke con_write_asciiz, str_login_invalid
invoke con_write_asciiz, str_pass_err
mov [ebp + thread_data.state], STATE_LOGIN_FAIL
jmp .sendstr
 
/kernel/branches/net/applications/ftpd/ftpd.asm
102,6 → 102,7
 
invoke ini.get_str, path, str_ftpd, str_ip, ini_buf, 16, 0
mov esi, ini_buf
mov cl, '.'
call ip_to_dword
mov [serverip], ebx
 
138,7 → 139,10
 
invoke con_write_asciiz, str2b
 
mov [pasvport], 2000 ;;;;;; FIXME
invoke ini.get_int, path, str_pasv, str_start, 2000
mov [pasv_start], ax
invoke ini.get_int, path, str_pasv, str_end, 5000
mov [pasv_end], ax
 
mainloop:
mcall 10 ; Wait here for incoming connections on the base socket (socketnum)
173,12 → 177,12
mov [ebp + thread_data.mode], MODE_NOTREADY
lea eax, [ebp + thread_data.buffer]
mov [ebp + thread_data.buffer_ptr], eax
mov [ebp + thread_data.passivesocknum], -1
 
sendFTP "220 Welcome to KolibriOS FTP daemon"
 
threadloop:
mcall 10
mov edx, [ebp] ; pointer to thread_data
 
cmp [ebp + thread_data.mode], MODE_PASSIVE_WAIT
jne .not_passive
191,6 → 195,8
je .not_passive
mov [ebp + thread_data.datasocketnum], eax
mov [ebp + thread_data.mode], MODE_PASSIVE_OK
mcall close ; [ebp + thread_data.passivesocknum]
mov [ebp + thread_data.passivesocknum], -1
 
invoke con_write_asciiz, str_datasock
.not_passive:
229,17 → 235,17
jmp parse_cmd
 
listen_err:
invoke con_set_flags, 0x0c ; print received data to console (in green color)
invoke con_set_flags, 0x0c ; print errors in red
invoke con_write_asciiz, str3
jmp done
 
bind_err:
invoke con_set_flags, 0x0c ; print received data to console (in green color)
invoke con_set_flags, 0x0c ; print errors in red
invoke con_write_asciiz, str4
jmp done
 
sock_err:
invoke con_set_flags, 0x0c ; print received data to console (in green color)
invoke con_set_flags, 0x0c ; print errors in red
invoke con_write_asciiz, str6
jmp done
 
251,7 → 257,7
 
 
thread_exit:
invoke con_set_flags, 0x02 ; print received data to console (in green color)
invoke con_set_flags, 0x02 ; print thread info in blue
invoke con_write_asciiz, str_bye
pop ecx ; get the thread_data pointer from stack
mcall 68, 13 ; free the memory
258,7 → 264,6
mcall -1 ; and kill the thread
 
 
 
; initialized data
 
title db 'KolibriOS FTP daemon 0.1', 0
275,6 → 280,7
 
str_logged_in db 'Login ok',10,0
str_pass_ok db 'Password ok',10,0
str_pass_err db 'Password/Username incorrect',10,0
str_pwd db 'Current directory is "%s"\n',0
str_err2 db 'ERROR: cannot open directory',10,0
str_datasock db 'Passive data socket connected!',10,0
281,10 → 287,6
str_notfound db 'ERROR: file not found',10,0
str_sockerr db 'ERROR: socket error',10,0
 
str_login_invalid db 'Login invalid',10,0
 
str_test db 'test: %x ', 0
 
str_newline db 10, 0
str_mask db '*', 0
str_infinity db 0xff, 0xff, 0xff, 0xff, 0
311,6 → 313,9
str_pass db 'pass', 0
str_home db 'home', 0
str_mode db 'mode', 0
str_pasv db 'pasv', 0
str_start db 'start', 0
str_end db 'end', 0
 
 
sockaddr1:
369,7 → 374,9
path2 rb 1024
params rb 1024
serverip dd ?
pasvport dw ?
pasv_start dw ?
pasv_end dw ?
pasv_port dw ?
 
ini_buf rb 3*4+3+1