Implemented Passive mode and LIST command in new FTP daemon (net branch)

git-svn-id: svn://kolibrios.org@2562 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
hidnplayr 2012-04-04 13:08:07 +00:00
parent 74a8292f46
commit 0833e5c02d
2 changed files with 249 additions and 33 deletions

View File

@ -31,57 +31,43 @@ parse_cmd: ; esi must point to command
align 4
commands: ; all commands must be in uppercase
commands: ; all commands must be in uppercase
db 'ABOR'
dd cmdABOR
db 'CWD', 0
dd cmdCWD
db 'DELE'
dd cmdDELE
db 'LIST'
dd cmdLIST
db 'NLST'
dd cmdNLST
db 'NOOP'
dd cmdNOOP
db 'PASS'
dd cmdPASS
db 'PASV'
dd cmdPASV
db 'PWD', 0 ; Print Working Directory
dd cmdPWD
db 'PORT'
dd cmdPORT
db 'QUIT'
dd cmdQUIT
db 'RETR'
dd cmdRETR
db 'STOR'
dd cmdSTOR
db 'SYST'
dd cmdSYST
db 'TYPE'
dd cmdTYPE
db 'USER'
dd cmdUSER
db 'XPWD'
dd cmdPWD
db 0 ; end marker
db 0 ; end marker
align 4
@ -102,6 +88,143 @@ cmdDELE:
align 4
cmdLIST:
cmp [mode], MODE_ACTIVE
jne @f
mcall connect, [datasocketnum], datasock, datasock.length
cmp eax, -1
je .err
@@:
mcall send, [socketnum2], str150, str150.length, 0 ; here it comes..
push FA_READONLY + FA_FOLDER
push str_mask
push home_dir
call [file.find.first]
mov edi, buffer
jmp .parse_file
.checknextfile:
push edx
call [file.find.next]
.parse_file:
test eax, eax
jz .done
mov edx, eax
; first, convert the attributes
test [eax + FileInfoA.Attributes], FA_FOLDER
jnz .folder
test [eax + FileInfoA.Attributes], FA_READONLY
jnz .readonly
mov eax, '-rw-'
stosd
jmp .attr
.folder:
mov eax, 'drwx'
stosb
jmp .attr
.readonly:
mov eax, '-r--'
stosd
.attr:
mov eax, 'rw-r'
stosd
mov ax, 'w-'
stosw
mov al, ' '
stosb
; now..
mov ax, '1 '
stosw
; now write owner, everything is owned by FTP, woohoo!
mov eax, 'FTP '
stosd
stosd
; now the filesize in ascii
mov ebx, dword [edx + FileInfoA.FileSize]
call dword_to_ascii
mov al, ' '
stosb
; then date (month/day/year)
movzx ebx, [edx + FileInfoA.DateModify + FileDateTime.month]
mov eax, [months + 4*ebx]
stosd
movzx ebx, [edx + FileInfoA.DateModify + FileDateTime.day]
call dword_to_ascii
mov al, ' '
stosb
movzx ebx, [edx + FileInfoA.DateModify + FileDateTime.year]
call dword_to_ascii
mov al, ' '
stosb
; and last but not least, filename
lea esi, [edx + FileInfoA.FileName]
mov ecx, 250
.nameloop:
lodsb
test al, al
jz .namedone
stosb
loop .nameloop
.namedone:
mov ax, 0x0d0a
stosw
jmp .checknextfile
.done:
push edx
call [file.find.close]
xor al, al
stosb
push buffer
call [con_write_asciiz]
lea esi, [edi - buffer]
mcall send, [datasocketnum], buffer, , 0
mcall close, [datasocketnum]
cmp [mode], MODE_PASSIVE_OK
jne @f
mov [mode], MODE_PASSIVE_WAIT
@@:
mcall send, [socketnum2], str226, str226.length, 0 ; transfer ok
ret
.err:
pushd 0x0c
call [con_set_flags]
push str_err1
call [con_write_asciiz]
pushd 0x07
call [con_set_flags]
ret
align 4
@ -129,13 +252,47 @@ cmdPASS:
align 4
cmdPASV:
mov [mode], MODE_PASSIVE
; TODO: open the UDP socket and return our IP + port
; 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.
mcall socket, AF_INET4, SOCK_STREAM, 0
cmp eax, -1
; je .err
mov [passivesocknum], eax
mov [datasock.port], 2000
mov [datasock.ip], 0
mcall bind, [passivesocknum], datasock, datasock.length
cmp eax, -1
je bind_err
mcall listen, [passivesocknum], 1
mov [mode], MODE_PASSIVE_WAIT
mov edi, buffer
mov eax, '227 ' ; FIXME (now hardcoded to 127.0.0.1:2000)
stosd
mov eax, '(127'
stosd
mov eax, ',0,0'
stosd
mov eax, ',1,7'
stosd
mov eax, ',208'
stosd
mov al, ')'
stosb
mov ax, 0x0d0a
stosw
xor al, al
stosb
lea esi, [edi - buffer]
mcall send, [socketnum2], buffer, ,0
ret
align 4
@ -161,6 +318,10 @@ cmdPWD:
mcall send, [socketnum2], buffer, , 0
; push work_dir
; push str_pwd
; call [con_printf]
ret
align 4
@ -198,15 +359,11 @@ cmdPORT:
mov [datasock.port], dx
mcall socket, AF_INET4, SOCK_DGRAM, 0
mcall socket, AF_INET4, SOCK_STREAM, 0
cmp eax, -1
je .err
mov [datasocketnum], eax
mcall connect, [datasocketnum], datasock, datasock.length
cmp eax, -1
je .err
mcall send, [socketnum2], str225, str225.length, 0
ret
@ -226,6 +383,23 @@ cmdQUIT:
align 4
cmdRETR:
; mcall connect, [datasocketnum], datasock, datasock.length
; cmp eax, -1
; je .err
; push O_READ
; push home_dir
; call [file.open]
; test eax, eax
; jz .cannot_open
;
; push BUFFERSIZE
; push buffer
; push eax
; call [file.read]
; cmp eax, -1
; jz .cannot_open
ret
align 4
@ -360,11 +534,20 @@ ascii_to_byte:
.done:
ret
align 4
dword_to_ascii: ; edi = ptr where to write, ebx is number
mov eax, '1'
stosb
ret
str150 db '150 Here it comes...', 13, 10
.length = $ - str150
str200 db '200 Command OK.', 13, 10
.length = $ - str200
str215 db '215 UNIX type: L8', 13, 10
@ -376,6 +559,7 @@ str221 db '221 Bye!', 13, 10
str225 db '225 Data connection open', 13, 10
.length = $ - str225
str226 db '226 Transfer OK, Closing connection', 13, 10
.length = $ - str226
str230 db '230 You are now logged in.', 13, 10
.length = $ - str230
str250 db '250 command successful', 13, 10

View File

@ -28,7 +28,8 @@ TYPE_LOCAL = 10000000b ; bits per byte must be specified
MODE_NOTREADY = 0
MODE_ACTIVE = 1
MODE_PASSIVE = 2
MODE_PASSIVE_WAIT = 2
MODE_PASSIVE_OK = 3
use32
db 'MENUET01' ; signature
@ -44,6 +45,8 @@ include '../macros.inc'
purge mov,add,sub
include '../proc32.inc'
include '../dll.inc'
include '../struct.inc'
include '../libio.inc'
include '../network.inc'
include 'commands.inc'
@ -131,14 +134,27 @@ start:
.loop:
mcall 10
cmp [mode], MODE_PASSIVE_WAIT
jne @f
mcall accept, [passivesocknum], datasock, datasock.length
cmp eax, -1
je @f
mov [datasocketnum], eax
mov [mode], MODE_PASSIVE_OK
push str_datasock
call [con_write_asciiz]
@@:
mcall recv, [socketnum2], buffer, buffer.length
cmp eax, -1
je .loop
or eax, eax
jz .loop
push eax
mov byte[buffer+eax], 0
pushd 0x0a
call [con_set_flags]
@ -211,8 +227,20 @@ str6 db 'Could not open socket',10,10,0
str7 db 'Got data!',10,10,0
str8 db 'Error accepting connection',10,10,0
str_logged_in db 'Login ok',10,10,0
str_pass_ok db 'Password ok - Logged in',10,10,0
str_logged_in db 'Login ok',10,10,0
str_pass_ok db 'Password ok - Logged in',10,10,0
str_pwd db 'Current directory is "%s"\n',0
str_err1 db 'ERROR: cannot connect to remote socket',10,10,0
str_err2 db 'ERROR: cannot open directory',10,10,0
str_datasock db 'Passive data socket connected!',10,10,0
str_mask db '*', 0
months:
dd 'Jan ','Feb ','Mar ','Apr ','May ','Jun '
dd 'Jul ','Aug ','Sep ','Oct ','Nov ','Dec '
filename db '.ini', 0
str_port db 'port', 0
@ -255,7 +283,10 @@ import libio, \
file.size , 'file_size' , \
file.open , 'file_open' , \
file.read , 'file_read' , \
file.close , 'file_close'
file.close , 'file_close' , \
file.find.first , 'file_find_first', \
file.find.next , 'file_find_next', \
file.find.close , 'file_find_close'
i_end:
@ -266,11 +297,12 @@ socketnum dd ?
; thread specific data
socketnum2 dd ?
state dd ?
home_dir rb 1024
home_dir db '/rd/1/',0
work_dir rb 1024
type db ?
mode db ? ; active/passive
passivesocknum dd ?
datasocketnum dd ?
datasock: