Updates and bugfixes for FTPd (net branch)

git-svn-id: svn://kolibrios.org@2609 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
hidnplayr 2012-04-12 23:32:43 +00:00
parent ba524f3821
commit ea68a6e1ce
3 changed files with 181 additions and 219 deletions

View File

@ -26,7 +26,7 @@ ends
macro sendFTP str { macro sendFTP str {
local .string, .length, .label local .string, .length, .label
xor edi, edi xor edi, edi
mcall send, [edx + thread_data.socketnum], .string, .length mcall send, [ebp + thread_data.socketnum], .string, .length
jmp @f jmp @f
.string db str, 13, 10 .string db str, 13, 10
.length = $ - .string .length = $ - .string
@ -42,7 +42,7 @@ local .string, .length, .label
; ;
; input: esi = ptr to ascii commands ; input: esi = ptr to ascii commands
; ecx = number of bytes input ; ecx = number of bytes input
; edx = pointer to thread_data structure ; ebp = pointer to thread_data structure
; ;
; output: none ; output: none
; ;
@ -70,91 +70,58 @@ parse_cmd: ; esi must point to command
cmp eax, [edi] cmp eax, [edi]
je .got_it je .got_it
add edi, 4+4*4 add edi, 5*4
cmp byte [edi], 0 cmp byte [edi], 0
jne .scanloop jne .scanloop
.error: .error:
cmp [edx + thread_data.state], STATE_ACTIVE cmp [ebp + thread_data.state], STATE_ACTIVE
jb login_first jb login_first
sendFTP "500 Unsupported command" sendFTP "500 Unsupported command"
ret ret
.got_it: .got_it:
mov eax, [edx + thread_data.state] mov eax, [ebp + thread_data.state]
jmp dword [edi + 4 + eax] jmp dword [edi + 4 + eax]
align 4 align 4
commands: ; all commands must be in uppercase commands: ; all commands must be in uppercase
dd 'ABOR' dd 'ABOR', login_first, login_first, login_first, cmdABOR
dd login_first, login_first, login_first, cmdABOR ; dd 'ACCT', login_first, login_first, login_first, cmd_ACCT
; dd 'ACCT ; dd 'APPE', login_first, login_first, login_first, cmd_APPE
; dd login_first, login_first, login_first, cmd_ACCT dd 'CDUP', login_first, login_first, login_first, cmdCDUP
; dd 'APPE' dd 'CWD', login_first, login_first, login_first, cmdCWD
; dd login_first, login_first, login_first, cmd_APPE dd 'DELE', login_first, login_first, login_first, cmdDELE
dd 'CDUP' ; dd 'HELP', login_first, login_first, login_first, cmd_HELP
dd login_first, login_first, login_first, cmdCDUP dd 'LIST', login_first, login_first, login_first, cmdLIST
dd 'CWD' ; dd 'MDTM', login_first, login_first, login_first, cmd_MDTM
dd login_first, login_first, login_first, cmdCWD ; dd 'MKD', login_first, login_first, login_first, cmd_MKD
dd 'DELE' ; dd 'MODE', login_first, login_first, login_first, cmd_MODE
dd login_first, login_first, login_first, cmdDELE dd 'NLST', login_first, login_first, login_first, cmdNLST
; dd 'HELP' dd 'NOOP', login_first, login_first, login_first, cmdNOOP
; dd login_first, login_first, login_first, cmd_HELP dd 'PASS', cmdPASS.0, cmdPASS , cmdPASS.2, cmdPASS.3
dd 'LIST' dd 'PASV', login_first, login_first, login_first, cmdPASV
dd login_first, login_first, login_first, cmdLIST dd 'PORT', login_first, login_first, login_first, cmdPORT
; dd 'MDTM' dd 'PWD', login_first, login_first, login_first, cmdPWD
; dd login_first, login_first, login_first, cmd_MDTM dd 'QUIT', cmdQUIT, cmdQUIT, cmdQUIT, cmdQUIT
; dd 'MKD' ; dd 'REIN', login_first, login_first, login_first, cmd_REIN
; dd login_first, login_first, login_first, cmd_MKD ; dd 'REST', login_first, login_first, login_first, cmd_REST
; dd 'MODE' dd 'RETR', login_first, login_first, login_first, cmdRETR
; dd login_first, login_first, login_first, cmd_MODE ; dd 'RMD', login_first, login_first, login_first, cmd_RMD
dd 'NLST' ; dd 'RNFR', login_first, login_first, login_first, cmd_RNFR
dd login_first, login_first, login_first, cmdNLST ; dd 'RNTO', login_first, login_first, login_first, cmd_RNTO
dd 'NOOP' ; dd 'SITE', login_first, login_first, login_first, cmd_SITE
dd login_first, login_first, login_first, cmdNOOP ; dd 'SIZE', login_first, login_first, login_first, cmd_SIZE
dd 'PASS' ; dd 'STAT', login_first, login_first, login_first, cmd_STAT
dd cmdPASS.0, cmdPASS , cmdPASS.2, cmdPASS.3 dd 'STOR', login_first, login_first, login_first, cmdSTOR
dd 'PASV' ; dd 'STOU', login_first, login_first, login_first, cmd_STOU
dd login_first, login_first, login_first, cmdPASV ; dd 'STRU', login_first, login_first, login_first, cmd_STRU
dd 'PORT' dd 'SYST', login_first, login_first, login_first, cmdSYST
dd login_first, login_first, login_first, cmdPORT dd 'TYPE', login_first, login_first, login_first, cmdTYPE
dd 'PWD' dd 'USER', cmdUSER, cmdUSER, cmdUSER, cmdUSER.2
dd login_first, login_first, login_first, cmdPWD db 0 ; end marker
dd 'QUIT'
dd cmdQUIT, cmdQUIT, cmdQUIT, cmdQUIT
; dd 'REIN'
; dd login_first, login_first, login_first, cmd_REIN
; dd 'REST'
; dd login_first, login_first, login_first, cmd_REST
dd 'RETR'
dd login_first, login_first, login_first, cmdRETR
; dd 'RMD'
; dd login_first, login_first, login_first, cmd_RMD
; dd 'RNFR'
; dd login_first, login_first, login_first, cmd_RNFR
; dd 'RNTO'
; dd login_first, login_first, login_first, cmd_RNTO
; dd 'SITE'
; dd login_first, login_first, login_first, cmd_SITE
; dd 'SIZE'
; dd login_first, login_first, login_first, cmd_SIZE
; dd 'STAT'
; dd login_first, login_first, login_first, cmd_STAT
dd 'STOR'
dd login_first, login_first, login_first, cmdSTOR
; dd 'STOU'
; dd login_first, login_first, login_first, cmd_STOU
; dd 'STRU'
; dd login_first, login_first, login_first, cmd_STRU
dd 'SYST'
dd login_first, login_first, login_first, cmdSYST
dd 'TYPE'
dd login_first, login_first, login_first, cmdTYPE
dd 'USER'
dd cmdUSER, cmdUSER, cmdUSER, cmdUSER.2
db 0 ; end marker
align 4 align 4
login_first: login_first:
@ -177,12 +144,11 @@ socketerror:
align 4 align 4
abort_transfer: abort_transfer:
and [edx + thread_data.permissions], not ABORT and [ebp + thread_data.permissions], not ABORT
mov [edx + thread_data.mode], MODE_NOTREADY mov [ebp + thread_data.mode], MODE_NOTREADY
invoke file.close, ebx invoke file.close, ebx
mcall close, [edx + thread_data.datasocketnum] mcall close, [ebp + thread_data.datasocketnum]
mov edx, [ebp]
sendFTP "530 Transfer aborted" sendFTP "530 Transfer aborted"
ret ret
@ -270,9 +236,8 @@ dword_to_ascii: ; edi = ptr where to write, eax is number
align 4 align 4
create_path: ; combine home_dir and work_dir strings into fpath create_path: ; combine home_dir and work_dir strings into fpath
mov edx, [ebp] lea edi, [ebp + thread_data.fpath]
lea edi, [edx + thread_data.fpath] lea esi, [ebp + thread_data.home_dir]
lea esi, [edx + thread_data.home_dir]
mov ecx, 1024 mov ecx, 1024
.loop1: .loop1:
lodsb lodsb
@ -287,7 +252,7 @@ create_path: ; combine home_dir and work_dir strings into fpath
dec edi dec edi
@@: @@:
lea esi, [edx + thread_data.work_dir] lea esi, [ebp + thread_data.work_dir]
mov ecx, 1024 mov ecx, 1024
.loop2: .loop2:
lodsb lodsb
@ -310,7 +275,7 @@ create_path: ; combine home_dir and work_dir strings into fpath
align 4 align 4
cmdABOR: cmdABOR:
or [edx + thread_data.permissions], ABORT or [ebp + thread_data.permissions], ABORT
sendFTP "250 Command succesul" sendFTP "250 Command succesul"
ret ret
@ -323,28 +288,28 @@ cmdABOR:
align 4 align 4
cmdCDUP: cmdCDUP:
test [edx + thread_data.permissions], PERMISSION_CD test [ebp + thread_data.permissions], PERMISSION_CD
jz permission_denied jz permission_denied
cmp byte [edx + thread_data.work_dir+1], 0 ; are we in "/" ? cmp byte [ebp + thread_data.work_dir+1], 0 ; are we in "/" ?
je .done je .done
mov ecx, 1024 mov ecx, 1024
xor al, al xor al, al
lea edi, [edx + thread_data.work_dir] lea edi, [ebp + thread_data.work_dir]
repne scasb repne scasb
std sub edi, 3
dec edi
dec edi
dec edi
mov al,'/' mov al,'/'
std
neg ecx
add ecx, 1024
repne scasb repne scasb
cld cld
mov byte[edi+1], 0 mov byte[edi+1], 0
.done: .done:
; Print the new working dir on the console ; Print the new working dir on the console
lea eax, [edx + thread_data.work_dir] lea eax, [ebp + thread_data.work_dir]
push eax push eax
call [con_write_asciiz] call [con_write_asciiz]
push str_newline push str_newline
@ -362,15 +327,20 @@ cmdCDUP:
align 4 align 4
cmdCWD: cmdCWD:
test [edx + thread_data.permissions], PERMISSION_CD test [ebp + thread_data.permissions], PERMISSION_CD
jz permission_denied jz permission_denied
sub ecx, 4 sub ecx, 4
jb .err jb .err
add esi, 4 add esi, 4
mov ecx, 1024
lea edi, [ebp + thread_data.work_dir]
cmp byte [esi], '/'
je .loop
.scan: .scan:
lea edi, [edx + thread_data.work_dir + 1] lea edi, [ebp + thread_data.work_dir + 1]
push ecx push ecx
mov ecx, 1024 mov ecx, 1024
.find_zero: .find_zero:
@ -407,7 +377,7 @@ cmdCWD:
mov byte [edi], 0 mov byte [edi], 0
; Print the new working dir on the console ; Print the new working dir on the console
lea eax, [edx + thread_data.work_dir] lea eax, [ebp + thread_data.work_dir]
push eax push eax
call [con_write_asciiz] call [con_write_asciiz]
push str_newline push str_newline
@ -439,7 +409,7 @@ cmdCWD:
align 4 align 4
cmdDELE: cmdDELE:
test [edx + thread_data.permissions], PERMISSION_DELETE test [ebp + thread_data.permissions], PERMISSION_DELETE
jz permission_denied jz permission_denied
ret ret
@ -453,38 +423,33 @@ cmdDELE:
align 4 align 4
cmdLIST: cmdLIST:
test [edx + thread_data.permissions], PERMISSION_EXEC test [ebp + thread_data.permissions], PERMISSION_EXEC
jz permission_denied jz permission_denied
; If we are in active mode, it's time to open a data socket.. ; If we are in active mode, it's time to open a data socket..
cmp [edx + thread_data.mode], MODE_ACTIVE cmp [ebp + thread_data.mode], MODE_ACTIVE
jne @f jne @f
mov ecx, [edx + thread_data.datasocketnum] mov ecx, [ebp + thread_data.datasocketnum]
lea edx, [edx + thread_data.datasock] lea edx, [ebp + thread_data.datasock]
mov esi, sizeof.thread_data.datasock mov esi, sizeof.thread_data.datasock
mcall connect mcall connect
cmp eax, -1 cmp eax, -1
je socketerror je socketerror
@@: @@:
mov edx, [ebp]
; Create fpath from home_dir and work_dir ; Create fpath from home_dir and work_dir
call create_path call create_path
lea ebx, [edx + thread_data.fpath] lea ebx, [ebp + thread_data.fpath]
invoke con_write_asciiz, ebx invoke con_write_asciiz, ebx
invoke con_write_asciiz, str_newline invoke con_write_asciiz, str_newline
mov edx, [ebp] ;;;
lea ebx, [edx + thread_data.fpath] ;;;;
; Start the search ; Start the search
invoke file.find.first, ebx, str_mask, FA_ANY invoke file.find.first, ebx, str_mask, FA_READONLY+FA_FOLDER+FA_NORMAL+FA_ARCHIVED
test eax, eax test eax, eax
jz .nosuchdir jz .nosuchdir
mov edx, [ebp] ;;; lea edi, [ebp + thread_data.buffer]
lea edi, [edx + thread_data.buffer]
.parse_file: .parse_file:
test eax, eax ; did we find a file? test eax, eax ; did we find a file?
jz .done jz .done
@ -566,17 +531,17 @@ cmdLIST:
mov ax, 0x0a0d mov ax, 0x0a0d
stosw stosw
test [edx + thread_data.permissions], ABORT ; Did we receive ABOR command from client? test [ebp + thread_data.permissions], ABORT ; Did we receive ABOR command from client?
;;; jnz .abort ; TODO ;;; jnz .abort ; TODO
; check next file ; check next file
;;; invoke file.find.next, ebx invoke file.find.next, ebx
;;; jmp .parse_file jmp .parse_file
mov eax, ebx ;;;;; ;;; mov eax, ebx ;;;;;
; close file desc ; close file desc
.done: .done:
invoke file.find.close, eax ; file discriptor is still in eax at this point! invoke file.find.close, ebx ; ebx is the
; append the string with a 0 ; append the string with a 0
xor al, al xor al, al
@ -584,22 +549,19 @@ cmdLIST:
; Warn the client we're about to send the data ; Warn the client we're about to send the data
push edi push edi
mov edx, [ebp] ;;;;;;;
sendFTP "150 Here it comes.." sendFTP "150 Here it comes.."
pop esi pop esi
; and send it to the client ; and send it to the client
mov edx, [ebp] mov ecx, [ebp + thread_data.datasocketnum]
mov ecx, [edx + thread_data.datasocketnum] lea edx, [ebp + thread_data.buffer]
lea edx, [edx + thread_data.buffer]
sub esi, edx sub esi, edx
xor edi, edi xor edi, edi
mcall send mcall send
; close the data socket.. ; close the data socket..
mov edx, [ebp] ; thread_data pointer mov [ebp + thread_data.mode], MODE_NOTREADY
mov [edx + thread_data.mode], MODE_NOTREADY mcall close, [ebp + thread_data.datasocketnum]
mcall close, [edx + thread_data.datasocketnum]
sendFTP "226 Transfer OK" sendFTP "226 Transfer OK"
ret ret
@ -617,7 +579,7 @@ cmdLIST:
align 4 align 4
cmdNLST: cmdNLST:
test [edx + thread_data.permissions], PERMISSION_EXEC test [ebp + thread_data.permissions], PERMISSION_EXEC
jz permission_denied jz permission_denied
; TODO: same as list but simpler output format ; TODO: same as list but simpler output format
@ -647,8 +609,8 @@ cmdPASS:
lea esi, [esi + 5] lea esi, [esi + 5]
; read the password from users.ini ; read the password from users.ini
lea edi, [edx + thread_data.buffer + 512] ; temp pass lea edi, [ebp + thread_data.buffer + 512] ; temp pass
lea ebx, [edx + thread_data.fpath] ; temp username lea ebx, [ebp + thread_data.fpath] ; temp username
invoke ini.get_str, path2, ebx, str_pass, edi, 512, str_infinity invoke ini.get_str, path2, ebx, str_pass, edi, 512, str_infinity
test eax, eax test eax, eax
jnz .incorrect jnz .incorrect
@ -666,17 +628,16 @@ cmdPASS:
.pass_ok: .pass_ok:
invoke ini.get_int, path2, ebx, str_mode, 0 invoke ini.get_int, path2, ebx, str_mode, 0
mov edx, [ebp] ; because libini destroys edx! mov [ebp + thread_data.permissions], eax
mov [edx + thread_data.permissions], eax
invoke con_write_asciiz, str_pass_ok invoke con_write_asciiz, str_pass_ok
mov [edx + thread_data.state], STATE_ACTIVE mov [ebp + thread_data.state], STATE_ACTIVE
sendFTP "230 You are now logged in" sendFTP "230 You are now logged in"
ret ret
.2: .2:
.incorrect: .incorrect:
mov [edx + thread_data.state], STATE_CONNECTED mov [ebp + thread_data.state], STATE_CONNECTED
sendFTP "530 Login incorrect" sendFTP "530 Login incorrect"
ret ret
@ -703,16 +664,17 @@ cmdPASV:
mcall socket, AF_INET4, SOCK_STREAM, 0 mcall socket, AF_INET4, SOCK_STREAM, 0
cmp eax, -1 cmp eax, -1
je socketerror je socketerror
mov edx, [ebp] ; thread_data pointer mov [ebp + thread_data.passivesocknum], eax
mov [edx + thread_data.passivesocknum], eax
; Bind it to a known local port ; Bind it to a known local port
mov [edx + thread_data.datasock.sin_family], AF_INET4 mov [ebp + thread_data.datasock.sin_family], AF_INET4
mov [edx + thread_data.datasock.sin_port], 2000 pushw [pasvport]
mov [edx + thread_data.datasock.sin_addr], 0 popw [ebp + thread_data.datasock.sin_port]
inc [pasvport]
mov [ebp + thread_data.datasock.sin_addr], 0
mov ecx, eax ; passivesocketnum mov ecx, eax ; passivesocketnum
lea edx, [edx + thread_data.datasock] lea edx, [ebp + thread_data.datasock]
mov esi, sizeof.thread_data.datasock mov esi, sizeof.thread_data.datasock
mcall bind mcall bind
cmp eax, -1 cmp eax, -1
@ -724,15 +686,14 @@ cmdPASV:
; je listen_err ; TODO ; je listen_err ; TODO
; Tell our thread we are ready to accept incoming calls ; Tell our thread we are ready to accept incoming calls
mov edx, [ebp] ; thread_data pointer mov [ebp + thread_data.mode], MODE_PASSIVE_WAIT
mov [edx + thread_data.mode], MODE_PASSIVE_WAIT
; Now tell the client where to connect to in this format: ; Now tell the client where to connect to in this format:
; 227 Entering Passive Mode (a1,a2,a3,a4,p1,p2) ; 227 Entering Passive Mode (a1,a2,a3,a4,p1,p2)
; where a1.a2.a3.a4 is the IP address and p1*256+p2 is the port number. ; where a1.a2.a3.a4 is the IP address and p1*256+p2 is the port number.
; '227 (' ; '227 ('
lea edi, [edx + thread_data.buffer] lea edi, [ebp + thread_data.buffer]
mov eax, '227 ' ; FIXME (now hardcoded to 127.0.0.1:2000) mov eax, '227 ' ; FIXME (now hardcoded to 127.0.0.1:2000)
stosd stosd
mov al, '(' mov al, '('
@ -755,20 +716,20 @@ cmdPASV:
mov al, ',' mov al, ','
stosb stosb
; port ; port
mov eax, 7 movzx eax, byte [ebp + thread_data.datasock.sin_port + 1]
call dword_to_ascii call dword_to_ascii
mov al, ',' mov al, ','
stosb stosb
mov eax, 208 movzx eax, byte [ebp + thread_data.datasock.sin_port]
call dword_to_ascii call dword_to_ascii
; ')', 13, 10, 0 ; ')', 13, 10, 0
mov eax, ')' + 0x000a0d00 mov eax, ')' + 0x000a0d00
stosd stosd
lea esi, [edi - thread_data.buffer] lea esi, [edi - thread_data.buffer]
sub esi, edx sub esi, ebp
mov ecx, [edx + thread_data.socketnum] mov ecx, [ebp + thread_data.socketnum]
lea edx, [edx + thread_data.buffer] lea edx, [ebp + thread_data.buffer]
xor edi, edi xor edi, edi
mcall send mcall send
@ -783,11 +744,11 @@ cmdPASV:
align 4 align 4
cmdPWD: cmdPWD:
mov dword [edx + thread_data.buffer], '257 ' mov dword [ebp + thread_data.buffer], '257 '
mov byte [edx + thread_data.buffer+4], '"' mov byte [ebp + thread_data.buffer+4], '"'
lea edi, [edx + thread_data.buffer+5] lea edi, [ebp + thread_data.buffer+5]
lea esi, [edx + thread_data.work_dir] lea esi, [ebp + thread_data.work_dir]
mov ecx, 1024 mov ecx, 1024
.loop: .loop:
lodsb lodsb
@ -800,15 +761,14 @@ cmdPWD:
.ok: .ok:
mov dword [edi], '"' + 0x000a0d00 ; '"',13,10,0 mov dword [edi], '"' + 0x000a0d00 ; '"',13,10,0
lea esi, [edi - thread_data.buffer + 4] lea esi, [edi - thread_data.buffer + 4]
sub esi, edx sub esi, ebp
mov ecx, [edx + thread_data.socketnum] mov ecx, [ebp + thread_data.socketnum]
lea edx, [edx + thread_data.buffer] lea edx, [ebp + thread_data.buffer]
xor edi, edi xor edi, edi
mcall send mcall send
mov edx, [ebp]
; Print the new working dir on the console ; Print the new working dir on the console
lea eax, [edx + thread_data.work_dir] lea eax, [ebp + thread_data.work_dir]
invoke con_write_asciiz, eax invoke con_write_asciiz, eax
invoke con_write_asciiz, str_newline invoke con_write_asciiz, str_newline
@ -831,8 +791,7 @@ cmdPORT:
mov cl, ',' mov cl, ','
call ip_to_dword call ip_to_dword
; And put it in datasock ; And put it in datasock
;;; mov edx, [ebp] mov [ebp + thread_data.datasock.sin_addr], ebx
mov [edx + thread_data.datasock.sin_addr], ebx
; Now the same with portnumber ; Now the same with portnumber
inc esi inc esi
@ -843,17 +802,16 @@ cmdPORT:
mov bl, al mov bl, al
; Save it in datasock too ; Save it in datasock too
mov [edx + thread_data.datasock.sin_port], bx mov [ebp + thread_data.datasock.sin_port], bx
; We will open the socket, but do not connect yet! ; We will open the socket, but do not connect yet!
mov [edx + thread_data.datasock.sin_family], AF_INET4 mov [ebp + thread_data.datasock.sin_family], AF_INET4
mcall socket, AF_INET4, SOCK_STREAM, 0 mcall socket, AF_INET4, SOCK_STREAM, 0
cmp eax, -1 cmp eax, -1
je socketerror je socketerror
mov edx, [ebp] ; thread_data pointer mov [ebp + thread_data.datasocketnum], eax
mov [edx + thread_data.datasocketnum], eax mov [ebp + thread_data.mode], MODE_ACTIVE
mov [edx + thread_data.mode], MODE_ACTIVE
sendFTP "225 Data connection open" sendFTP "225 Data connection open"
ret ret
@ -868,9 +826,8 @@ align 4
cmdQUIT: cmdQUIT:
sendFTP "221 Bye!" sendFTP "221 Bye!"
mov edx, [ebp] mcall close, [ebp + thread_data.datasocketnum]
mcall close, [edx + thread_data.datasocketnum] mcall close, [ebp + thread_data.socketnum]
mcall close, [edx + thread_data.socketnum]
add esp, 4 ; get rid of call return address add esp, 4 ; get rid of call return address
jmp thread_exit ; now close this thread jmp thread_exit ; now close this thread
@ -885,7 +842,7 @@ cmdQUIT:
align 4 align 4
cmdRETR: cmdRETR:
test [edx + thread_data.permissions], PERMISSION_READ test [ebp + thread_data.permissions], PERMISSION_READ
jz permission_denied jz permission_denied
cmp ecx, 1024 + 5 cmp ecx, 1024 + 5
@ -894,11 +851,11 @@ cmdRETR:
sub ecx, 5 sub ecx, 5
jb .cannot_open jb .cannot_open
cmp [edx + thread_data.mode], MODE_ACTIVE cmp [ebp + thread_data.mode], MODE_ACTIVE
jne @f jne @f
push ecx esi push ecx esi
mov ecx, [edx + thread_data.datasocketnum] mov ecx, [ebp + thread_data.datasocketnum]
lea edx, [edx + thread_data.datasock] lea edx, [ebp + thread_data.datasock]
mov esi, sizeof.thread_data.datasock mov esi, sizeof.thread_data.datasock
mcall connect mcall connect
pop esi ecx pop esi ecx
@ -922,7 +879,7 @@ cmdRETR:
xor al, al xor al, al
stosb stosb
lea ebx, [edx + thread_data.fpath] lea ebx, [ebp + thread_data.fpath]
invoke con_write_asciiz, ebx invoke con_write_asciiz, ebx
invoke con_write_asciiz, str_newline invoke con_write_asciiz, str_newline
@ -931,29 +888,27 @@ cmdRETR:
jz .cannot_open jz .cannot_open
push eax push eax
mov edx, [ebp]
sendFTP "150 Here it comes.." sendFTP "150 Here it comes.."
pop ebx pop ebx
.read_more: .read_more:
mov edx, [ebp] test [ebp + thread_data.permissions], ABORT
test [edx + thread_data.permissions], ABORT
jnz abort_transfer jnz abort_transfer
lea eax, [edx + thread_data.buffer] ; FIXME: use another buffer!! if we receive something on control connection now, we screw up! lea eax, [ebp + thread_data.buffer] ; FIXME: use another buffer!! if we receive something on control connection now, we screw up!
invoke file.read, ebx, eax, BUFFERSIZE invoke file.read, ebx, eax, BUFFERSIZE
cmp eax, -1 cmp eax, -1
je .cannot_open ; FIXME: this is not the correct error je .cannot_open ; FIXME: this is not the correct error
push eax ebx push eax ebx
mov esi, eax mov esi, eax
mov ecx, [edx + thread_data.datasocketnum] mov ecx, [ebp + thread_data.datasocketnum]
lea edx, [edx + thread_data.buffer] lea edx, [ebp + thread_data.buffer]
xor esi, esi xor edi, edi
mcall send mcall send
pop ebx ecx pop ebx ecx
cmp eax, -1 cmp eax, -1
je socketerror je socketerror ; FIXME: not the correct error
; cmp eax, ecx ; cmp eax, ecx
; jne not_all_byes_sent ; TODO ; jne not_all_byes_sent ; TODO
@ -963,11 +918,9 @@ cmdRETR:
invoke file.close, ebx invoke file.close, ebx
mov edx, [ebp] mov [ebp + thread_data.mode], MODE_NOTREADY
mov [edx + thread_data.mode], MODE_NOTREADY mcall close, [ebp + thread_data.datasocketnum]
mcall close, [edx + thread_data.datasocketnum]
mov edx, [ebp]
sendFTP "226 Transfer OK, closing connection" sendFTP "226 Transfer OK, closing connection"
ret ret
@ -991,12 +944,12 @@ cmdRETR:
align 4 align 4
cmdSTOR: cmdSTOR:
test [edx + thread_data.permissions], PERMISSION_WRITE test [ebp + thread_data.permissions], PERMISSION_WRITE
jz permission_denied jz permission_denied
;;;; ;;;;
test [edx + thread_data.permissions], ABORT test [ebp + thread_data.permissions], ABORT
jnz abort_transfer jnz abort_transfer
;;;; ;;;;
@ -1042,11 +995,11 @@ cmdTYPE:
jmp parse_cmd.error jmp parse_cmd.error
.ascii: .ascii:
mov [edx + thread_data.type], TYPE_ASCII mov [ebp + thread_data.type], TYPE_ASCII
jmp .subtype jmp .subtype
.ebdic: .ebdic:
mov [edx + thread_data.type], TYPE_EBDIC mov [ebp + thread_data.type], TYPE_EBDIC
.subtype: .subtype:
cmp ecx, 8 cmp ecx, 8
@ -1065,19 +1018,19 @@ cmdTYPE:
jmp parse_cmd.error jmp parse_cmd.error
.non_print: .non_print:
or [edx + thread_data.type], TYPE_NP or [ebp + thread_data.type], TYPE_NP
jmp .ok jmp .ok
.telnet: .telnet:
or [edx + thread_data.type], TYPE_TELNET or [ebp + thread_data.type], TYPE_TELNET
jmp .ok jmp .ok
.asacc: .asacc:
or [edx + thread_data.type], TYPE_ASA or [ebp + thread_data.type], TYPE_ASA
jmp .ok jmp .ok
.image: .image:
mov [edx + thread_data.type], TYPE_IMAGE mov [ebp + thread_data.type], TYPE_IMAGE
jmp .ok jmp .ok
.local: .local:
@ -1090,7 +1043,7 @@ cmdTYPE:
cmp al, 9 cmp al, 9
ja parse_cmd.error ; FIXME ja parse_cmd.error ; FIXME
or al, TYPE_LOCAL or al, TYPE_LOCAL
mov [edx + thread_data.type], al mov [ebp + thread_data.type], al
.ok: .ok:
sendFTP "200 Command ok" sendFTP "200 Command ok"
@ -1106,7 +1059,7 @@ align 4
cmdUSER: cmdUSER:
lea esi, [esi + 5] lea esi, [esi + 5]
lea edi, [edx + thread_data.fpath] ; temp buffer for username lea edi, [ebp + thread_data.fpath] ; temp buffer for username
.loop: .loop:
lodsb lodsb
stosb stosb
@ -1114,25 +1067,25 @@ cmdUSER:
jae .loop jae .loop
mov byte [edi-1], 0 mov byte [edi-1], 0
lea esi, [edx + thread_data.fpath] lea esi, [ebp + thread_data.fpath]
lea eax, [edx + thread_data.home_dir] lea eax, [ebp + thread_data.home_dir]
invoke ini.get_str, path2, esi, str_home, eax, 1024, str_infinity invoke ini.get_str, path2, esi, str_home, eax, 1024, str_infinity
cmp eax, -1 cmp eax, -1
je .login_fail je .login_fail
cmp dword [esi], -1 cmp dword [esi], -1
je .login_fail je .login_fail
mov word [edx + thread_data.work_dir], "/" ; "/", 0 mov word [ebp + thread_data.work_dir], "/" ; "/", 0
invoke con_write_asciiz, str_logged_in invoke con_write_asciiz, str_logged_in
mov [edx + thread_data.state], STATE_LOGIN mov [ebp + thread_data.state], STATE_LOGIN
.sendstr: .sendstr:
sendFTP "331 Please specify the password" sendFTP "331 Please specify the password"
ret ret
.login_fail: .login_fail:
invoke con_write_asciiz, str_login_invalid invoke con_write_asciiz, str_login_invalid
mov [edx + thread_data.state], STATE_LOGIN_FAIL mov [ebp + thread_data.state], STATE_LOGIN_FAIL
jmp .sendstr jmp .sendstr
align 4 align 4

View File

@ -64,13 +64,14 @@ include 'commands.inc'
align 4 align 4
start: start:
mcall 68, 11 ; init heap
mcall 40, 1 shl 7 ; we only want network events
; load libraries ; load libraries
stdcall dll.Load, @IMPORT stdcall dll.Load, @IMPORT
test eax, eax test eax, eax
jnz exit jnz exit
mcall 68, 11 ; init heap
; find path to main settings file (ftpd.ini) ; find path to main settings file (ftpd.ini)
mov edi, path ; Calculate the length of zero-terminated string mov edi, path ; Calculate the length of zero-terminated string
xor al, al xor al, al
@ -99,8 +100,6 @@ start:
invoke con_start, 1 invoke con_start, 1
invoke con_init, -1, -1, -1, -1, title invoke con_init, -1, -1, -1, -1, title
mcall 40, 1 shl 7 ; we only want network events
invoke ini.get_str, path, str_ftpd, str_ip, ini_buf, 16, 0 invoke ini.get_str, path, str_ftpd, str_ip, ini_buf, 16, 0
mov esi, ini_buf mov esi, ini_buf
call ip_to_dword call ip_to_dword
@ -139,6 +138,8 @@ start:
invoke con_write_asciiz, str2b invoke con_write_asciiz, str2b
mov [pasvport], 2000 ;;;;;; FIXME
mainloop: mainloop:
mcall 10 ; Wait here for incoming connections on the base socket (socketnum) mcall 10 ; Wait here for incoming connections on the base socket (socketnum)
@ -148,13 +149,13 @@ mainloop:
diff16 "threadstart", 0, $ diff16 "threadstart", 0, $
threadstart: threadstart:
;;; mcall 68, 11 ; init heap
mcall 68, 12, sizeof.thread_data ; allocate the thread data struct mcall 68, 12, sizeof.thread_data ; allocate the thread data struct
cmp eax, -1 test eax, eax
je exit je exit
lea esp, [eax + thread_data.stack] ; init stack lea esp, [eax + thread_data.stack] ; init stack
push eax ; save pointer to thread_data on stack mov ebp, eax
mov ebp, esp
mcall 40, 1 shl 7 ; we only want network events for this thread mcall 40, 1 shl 7 ; we only want network events for this thread
@ -165,14 +166,13 @@ threadstart:
mcall accept, [socketnum], sockaddr1, sockaddr1.length ; time to accept the awaiting connection.. mcall accept, [socketnum], sockaddr1, sockaddr1.length ; time to accept the awaiting connection..
cmp eax, -1 cmp eax, -1
je thread_exit je thread_exit
mov edx, [ebp] ; pointer to thread_data mov [ebp + thread_data.socketnum], eax
mov [edx + thread_data.socketnum], eax
mov [edx + thread_data.state], STATE_CONNECTED mov [ebp + thread_data.state], STATE_CONNECTED
mov [edx + thread_data.permissions], 0 mov [ebp + thread_data.permissions], 0
mov [edx + thread_data.mode], MODE_NOTREADY mov [ebp + thread_data.mode], MODE_NOTREADY
lea eax, [edx + thread_data.buffer] lea eax, [ebp + thread_data.buffer]
mov [edx + thread_data.buffer_ptr], eax mov [ebp + thread_data.buffer_ptr], eax
sendFTP "220 Welcome to KolibriOS FTP daemon" sendFTP "220 Welcome to KolibriOS FTP daemon"
@ -180,24 +180,23 @@ threadloop:
mcall 10 mcall 10
mov edx, [ebp] ; pointer to thread_data mov edx, [ebp] ; pointer to thread_data
cmp [edx + thread_data.mode], MODE_PASSIVE_WAIT cmp [ebp + thread_data.mode], MODE_PASSIVE_WAIT
jne .not_passive jne .not_passive
mov [edx + thread_data.mode], MODE_PASSIVE_FAILED ; assume that we will fail mov [ebp + thread_data.mode], MODE_PASSIVE_FAILED ; assume that we will fail
mov ecx, [edx + thread_data.passivesocknum] mov ecx, [ebp + thread_data.passivesocknum]
lea edx, [edx + thread_data.datasock] lea edx, [ebp + thread_data.datasock]
mov esi, sizeof.thread_data.datasock mov esi, sizeof.thread_data.datasock
mcall accept mcall accept
mov edx, [ebp] ; pointer to thread_data
cmp eax, -1 cmp eax, -1
je .not_passive je .not_passive
mov [edx + thread_data.datasocketnum], eax mov [ebp + thread_data.datasocketnum], eax
mov [edx + thread_data.mode], MODE_PASSIVE_OK mov [ebp + thread_data.mode], MODE_PASSIVE_OK
invoke con_write_asciiz, str_datasock invoke con_write_asciiz, str_datasock
.not_passive: .not_passive:
mov ecx, [edx + thread_data.socketnum] mov ecx, [ebp + thread_data.socketnum]
mov edx, [edx + thread_data.buffer_ptr] mov edx, [ebp + thread_data.buffer_ptr]
mov esi, sizeof.thread_data.buffer ;;; FIXME mov esi, sizeof.thread_data.buffer ;;; FIXME
mcall recv mcall recv
inc eax ; error? (-1) inc eax ; error? (-1)
@ -205,9 +204,8 @@ threadloop:
dec eax ; 0 bytes read? dec eax ; 0 bytes read?
jz threadloop jz threadloop
mov edx, [ebp] ; pointer to thread_data mov edi, [ebp + thread_data.buffer_ptr]
mov edi, [edx + thread_data.buffer_ptr] add [ebp + thread_data.buffer_ptr], eax
add [edx + thread_data.buffer_ptr], eax
; Check if we received a newline character, if not, wait for more data ; Check if we received a newline character, if not, wait for more data
mov ecx, eax mov ecx, eax
@ -217,10 +215,10 @@ threadloop:
; We got a command! ; We got a command!
mov byte [edi + 1], 0 ; append string with zero byte mov byte [edi + 1], 0 ; append string with zero byte
lea esi, [edx + thread_data.buffer] lea esi, [ebp + thread_data.buffer]
mov ecx, [edx + thread_data.buffer_ptr] mov ecx, [ebp + thread_data.buffer_ptr]
sub ecx, esi sub ecx, esi
mov [edx + thread_data.buffer_ptr], esi ; reset buffer ptr mov [ebp + thread_data.buffer_ptr], esi ; reset buffer ptr
invoke con_set_flags, 0x02 ; print received data to console (in green color) invoke con_set_flags, 0x02 ; print received data to console (in green color)
invoke con_write_asciiz, str_newline invoke con_write_asciiz, str_newline
@ -285,6 +283,8 @@ str_sockerr db 'ERROR: socket error',10,0
str_login_invalid db 'Login invalid',10,0 str_login_invalid db 'Login invalid',10,0
str_test db 'test: %x ', 0
str_newline db 10, 0 str_newline db 10, 0
str_mask db '*', 0 str_mask db '*', 0
str_infinity db 0xff, 0xff, 0xff, 0xff, 0 str_infinity db 0xff, 0xff, 0xff, 0xff, 0
@ -325,6 +325,8 @@ sockaddr1:
align 4 align 4
@IMPORT: @IMPORT:
diff16 "import", 0, $
library console, 'console.obj',\ library console, 'console.obj',\
libini, 'libini.obj', \ libini, 'libini.obj', \
libio, 'libio.obj' libio, 'libio.obj'
@ -358,6 +360,8 @@ import libio,\
i_end: i_end:
diff16 "i_end", 0, $
; uninitialised data ; uninitialised data
socketnum dd ? socketnum dd ?
@ -365,6 +369,7 @@ i_end:
path2 rb 1024 path2 rb 1024
params rb 1024 params rb 1024
serverip dd ? serverip dd ?
pasvport dw ?
ini_buf rb 3*4+3+1 ini_buf rb 3*4+3+1

View File

@ -1,4 +1,8 @@
[ftpd] [ftpd]
port=21 port=21
conn=10 conn=10
ip=127.0.0.1 ip=127.0.0.1
[pasv]
start=2000
end=5000