Subversion Repositories Kolibri OS

Rev

Rev 2585 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2554 hidnplayr 1
;
2
; Kolibrios FTP Daemon
3
;
4
; hidnplayr@gmail.com
5
;
6
; GPLv2
7
;
8
 
2571 hidnplayr 9
BUFFERSIZE              = 8192
2554 hidnplayr 10
 
2598 hidnplayr 11
; using multiple's of 4
12
STATE_CONNECTED         = 4*0
13
STATE_LOGIN             = 4*1
14
STATE_LOGIN_FAIL        = 4*2           ; When an invalid username was given
15
STATE_ACTIVE            = 4*3
2554 hidnplayr 16
 
2560 hidnplayr 17
TYPE_UNDEF              = 0
2557 hidnplayr 18
 
2560 hidnplayr 19
TYPE_ASCII              = 00000100b
20
TYPE_EBDIC              = 00001000b
21
; subtypes for ascii & ebdic (np = default)
22
TYPE_NP                 = 00000001b     ; non printable
23
TYPE_TELNET             = 00000010b
24
TYPE_ASA                = 00000011b
25
 
26
TYPE_IMAGE              = 01000000b     ; binary data
27
TYPE_LOCAL              = 10000000b     ; bits per byte must be specified
28
                                        ; lower 4 bits will hold this value
29
MODE_NOTREADY           = 0
30
MODE_ACTIVE             = 1
2562 hidnplayr 31
MODE_PASSIVE_WAIT       = 2
32
MODE_PASSIVE_OK         = 3
2598 hidnplayr 33
MODE_PASSIVE_FAILED     = 4
2560 hidnplayr 34
 
2598 hidnplayr 35
PERMISSION_EXEC         = 1b            ; LIST
36
PERMISSION_READ         = 10b
37
PERMISSION_WRITE        = 100b
38
PERMISSION_DELETE       = 1000b
39
PERMISSION_CD           = 10000b        ; Change Directory
40
 
41
ABORT                   = 1 shl 31
42
 
2581 hidnplayr 43
format binary as ""
44
 
2554 hidnplayr 45
use32
46
        db      'MENUET01'      ; signature
47
        dd      1               ; header version
48
        dd      start           ; entry point
49
        dd      i_end           ; initialized size
50
        dd      mem+0x1000      ; required memory
51
        dd      mem+0x1000      ; stack pointer
2578 hidnplayr 52
        dd      params          ; parameters
2554 hidnplayr 53
        dd      path            ; path
54
 
55
include '../macros.inc'
56
purge mov,add,sub
57
include '../proc32.inc'
58
include '../dll.inc'
2562 hidnplayr 59
include '../struct.inc'
60
include '../libio.inc'
2554 hidnplayr 61
 
62
include '../network.inc'
63
include 'commands.inc'
64
 
65
align 4
66
start:
67
; load libraries
68
        stdcall dll.Load, @IMPORT
69
        test    eax, eax
70
        jnz     exit
71
 
2578 hidnplayr 72
        mcall   68, 11                  ; init heap
73
 
2598 hidnplayr 74
; find path to main settings file (ftpd.ini)
2578 hidnplayr 75
        mov     edi, path               ; Calculate the length of zero-terminated string
2585 hidnplayr 76
        xor     al, al
2554 hidnplayr 77
        mov     ecx, 1024
78
        repne   scasb
79
        dec     edi
2598 hidnplayr 80
        mov     esi, str_ini            ; append it with '.ini', 0
2554 hidnplayr 81
        movsd
82
        movsb
83
 
2598 hidnplayr 84
; now create the second path (users.ini)
85
        std
86
        mov     al, '/'
87
        repne   scasb
88
        lea     ecx, [edi - path + 2]
89
        cld
90
        mov     esi, path
91
        mov     edi, path2
92
        rep     movsb
93
        mov     esi, str_users
94
        movsd
95
        movsd
96
        movsw
97
 
2554 hidnplayr 98
; initialize console
99
        push    1
100
        call    [con_start]
2560 hidnplayr 101
 
2554 hidnplayr 102
        push    title
2560 hidnplayr 103
        push    -1
104
        push    -1
105
        push    -1
106
        push    -1
2554 hidnplayr 107
        call    [con_init]
108
 
2578 hidnplayr 109
        mcall   40, 1 shl 7             ; we only want network events
2554 hidnplayr 110
 
2598 hidnplayr 111
        invoke  ini.get_str, path, str_ftpd, str_ip, ini_buf, 16, 0
112
        mov     esi, ini_buf
113
        call    ip_to_dword
114
        mov     [serverip], ebx
115
 
2560 hidnplayr 116
        invoke  ini.get_int, path, str_ftpd, str_port, 21
117
        mov     [sockaddr1.port], ax
118
 
119
        push    eax
2554 hidnplayr 120
        push    str1
2560 hidnplayr 121
        call    [con_printf]
2554 hidnplayr 122
 
123
        mcall   socket, AF_INET4, SOCK_STREAM, 0
124
        cmp     eax, -1
125
        je      sock_err
126
 
127
        mov     [socketnum], eax
128
 
2560 hidnplayr 129
        push    str2
130
        call    [con_write_asciiz]
131
 
2585 hidnplayr 132
;        mcall   setsockopt, [socketnum], SOL_SOCKET, SO_REUSEADDR, &yes,
133
;        cmp     eax, -1
134
;        je      opt_err
2554 hidnplayr 135
 
136
        mcall   bind, [socketnum], sockaddr1, sockaddr1.length
137
        cmp     eax, -1
138
        je      bind_err
139
 
2560 hidnplayr 140
        push    str2
141
        call    [con_write_asciiz]
142
 
2554 hidnplayr 143
        invoke  ini.get_int, path, str_ftpd, str_conn, 1        ; Backlog (max connections)
144
        mov     edx, eax
2560 hidnplayr 145
 
146
        push    str2
147
        call    [con_write_asciiz]
148
 
2554 hidnplayr 149
        mcall   listen, [socketnum]
150
        cmp     eax, -1
151
        je      listen_err
152
 
2560 hidnplayr 153
        push    str2b
2554 hidnplayr 154
        call    [con_write_asciiz]
155
 
2578 hidnplayr 156
mainloop:
157
        mcall   10                              ; Wait here for incoming connections on the base socket (socketnum)
2554 hidnplayr 158
 
2578 hidnplayr 159
        mcall   51, 1, threadstart, 0           ; Start a new thread for every incoming connection
160
                                                ; NOTE: upon initialisation of the thread, stack will not be available!
161
        jmp     mainloop
162
 
2585 hidnplayr 163
        diff16  "threadstart", 0, $
2578 hidnplayr 164
threadstart:
165
        mcall   68, 12, sizeof.thread_data      ; allocate the thread data struct
2554 hidnplayr 166
        cmp     eax, -1
2578 hidnplayr 167
        je      exit
2554 hidnplayr 168
 
2578 hidnplayr 169
        lea     esp, [eax + thread_data.stack]  ; init stack
170
        push    eax                             ; save pointer to thread_data on stack
2598 hidnplayr 171
        mov     ebp, esp
2554 hidnplayr 172
 
2578 hidnplayr 173
        mcall   40, 1 shl 7                     ; we only want network events for this thread
2554 hidnplayr 174
 
2585 hidnplayr 175
        pushd   0x03
176
        call    [con_set_flags]
2578 hidnplayr 177
        push    str8
178
        call    [con_write_asciiz]                                              ; print on the console that we have created the new thread successfully
2585 hidnplayr 179
        pushd   0x07
180
        call    [con_set_flags]
2578 hidnplayr 181
 
182
        mcall   accept, [socketnum], sockaddr1, sockaddr1.length                ; time to accept the awaiting connection..
183
        cmp     eax, -1
184
        je      thread_exit
2598 hidnplayr 185
        mov     edx, [ebp]                                                      ; pointer to thread_data
2578 hidnplayr 186
        mov     [edx + thread_data.socketnum], eax
187
 
2598 hidnplayr 188
        mov     [edx + thread_data.state], STATE_CONNECTED
189
        mov     [edx + thread_data.permissions], 0
190
        mov     [edx + thread_data.mode], MODE_NOTREADY
191
        lea     eax, [edx + thread_data.buffer]
192
        mov     [edx + thread_data.buffer_ptr], eax
2578 hidnplayr 193
 
2598 hidnplayr 194
        sendFTP "220 Welcome to KolibriOS FTP daemon"
195
 
2578 hidnplayr 196
threadloop:
2554 hidnplayr 197
        mcall   10
198
 
2598 hidnplayr 199
        mov     edx, [ebp]                                                      ; pointer to thread_data
2578 hidnplayr 200
 
201
        cmp     [edx + thread_data.mode], MODE_PASSIVE_WAIT
2598 hidnplayr 202
        jne     .not_passive
2578 hidnplayr 203
        mov     ecx, [edx + thread_data.passivesocknum]
204
        lea     edx, [edx + thread_data.datasock]
205
        mov     esi, sizeof.thread_data.datasock
206
        mcall   accept
2598 hidnplayr 207
        mov     edx, [ebp]                                                      ; pointer to thread_data
2562 hidnplayr 208
        cmp     eax, -1
2598 hidnplayr 209
        je      .not_passive
2578 hidnplayr 210
        mov     [edx + thread_data.datasocketnum], eax
2598 hidnplayr 211
        mov     [edx + thread_data.mode], MODE_PASSIVE_FAILED
2562 hidnplayr 212
 
213
        push    str_datasock
2578 hidnplayr 214
        call    [con_write_asciiz]                                              ; print on the console that the datasock is now ready
2598 hidnplayr 215
  .not_passive:
2562 hidnplayr 216
 
2578 hidnplayr 217
        mov     ecx, [edx + thread_data.socketnum]
2598 hidnplayr 218
        mov     edx, [edx + thread_data.buffer_ptr]
219
        mov     esi, sizeof.thread_data.buffer    ;;; FIXME
2578 hidnplayr 220
        mcall   recv
2598 hidnplayr 221
        inc     eax                                                             ; error? (-1)
2578 hidnplayr 222
        jz      threadloop
2598 hidnplayr 223
        dec     eax                                                             ; 0 bytes read?
224
        jz      threadloop
2554 hidnplayr 225
 
2598 hidnplayr 226
        mov     edx, [ebp]                                                      ; pointer to thread_data
227
        mov     edi, [edx + thread_data.buffer_ptr]
228
        add     [edx + thread_data.buffer_ptr], eax
2560 hidnplayr 229
 
2598 hidnplayr 230
; Check if we received a newline character, if not, wait for more data
231
        mov     ecx, eax
232
        mov     al, 13
233
        repne   scasb
234
        jne     threadloop
235
 
236
; We got a command!
237
        lea     eax, [edx + thread_data.buffer]
238
        mov     ecx, [edx + thread_data.buffer_ptr]
239
        sub     ecx, eax
240
        push    ecx                                                             ; push full data size on stack
241
        mov     [edx + thread_data.buffer_ptr], eax                             ; reset buffer ptr
242
 
243
        push    eax;;;;
2585 hidnplayr 244
        pushd   0x02                                                            ; print received data to console (in green color)
2560 hidnplayr 245
        call    [con_set_flags]
2585 hidnplayr 246
        push    str_newline
247
        call    [con_write_asciiz]
2598 hidnplayr 248
;;;;        push    eax
2554 hidnplayr 249
        call    [con_write_asciiz]
2560 hidnplayr 250
        pushd   0x07
251
        call    [con_set_flags]
252
 
2598 hidnplayr 253
        mov     edx, [ebp]
2578 hidnplayr 254
        pop     ecx                                                             ; number of bytes read
255
        lea     esi, [edx + thread_data.buffer]
2554 hidnplayr 256
        call    parse_cmd
257
 
2578 hidnplayr 258
        jmp     threadloop
2554 hidnplayr 259
 
260
listen_err:
2560 hidnplayr 261
        pushd   0x0c
262
        call    [con_set_flags]
2554 hidnplayr 263
        push    str3
264
        call    [con_write_asciiz]
265
        jmp     done
266
 
267
bind_err:
2560 hidnplayr 268
        pushd   0x0c
269
        call    [con_set_flags]
2554 hidnplayr 270
        push    str4
271
        call    [con_write_asciiz]
272
        jmp     done
273
 
274
sock_err:
2560 hidnplayr 275
        pushd   0x0c
276
        call    [con_set_flags]
2554 hidnplayr 277
        push    str6
278
        call    [con_write_asciiz]
279
        jmp     done
280
 
281
done:
282
        call    [con_getch2]
283
        push    1
284
        call    [con_exit]
285
exit:
286
        mcall   -1
287
 
288
 
2578 hidnplayr 289
thread_exit:
290
        push    str_bye
291
        call    [con_write_asciiz]      ; say bye bye
292
        pop     ecx                     ; get the thread_data pointer from stack
293
        mcall   68, 13                  ; free the memory
294
        mcall   -1                      ; and kill the thread
2554 hidnplayr 295
 
296
 
2578 hidnplayr 297
 
298
; initialized data
299
 
300
title           db 'KolibriOS FTP daemon 0.1', 0
301
str1            db 'Starting FTP daemon on port %u', 0
302
str2            db '.', 0
2585 hidnplayr 303
str2b           db ' OK!',10,0
304
str3            db 'Listen error',10,0
305
str4            db 'Bind error',10,0
2578 hidnplayr 306
;str5            db 'Setsockopt error.',10,10,0
2585 hidnplayr 307
str6            db 'Could not open socket',10,0
2578 hidnplayr 308
str7            db 'Got data!',10,10,0
2585 hidnplayr 309
str8            db 10,'New thread created!',10,0
310
str_bye         db 10,'Closing thread!',10,0
2578 hidnplayr 311
 
2585 hidnplayr 312
str_logged_in   db 'Login ok',10,0
313
str_pass_ok     db 'Password ok - Logged in',10,0
2562 hidnplayr 314
str_pwd         db 'Current directory is "%s"\n',0
2585 hidnplayr 315
str_err2        db 'ERROR: cannot open directory',10,0
316
str_datasock    db 'Passive data socket connected!',10,0
317
str_notfound    db 'ERROR: file not found',10,0
318
str_sockerr     db 'ERROR: socket error',10,0
2560 hidnplayr 319
 
2598 hidnplayr 320
str_login_invalid db 'Login invalid',10,0
321
 
2578 hidnplayr 322
str_newline     db 10, 0
2562 hidnplayr 323
str_mask        db '*', 0
324
 
2578 hidnplayr 325
months          dd 'Jan '
326
                dd 'Feb '
327
                dd 'Mar '
328
                dd 'Apr '
329
                dd 'May '
330
                dd 'Jun '
331
                dd 'Jul '
332
                dd 'Aug '
333
                dd 'Sep '
334
                dd 'Oct '
335
                dd 'Nov '
336
                dd 'Dec '
2562 hidnplayr 337
 
2598 hidnplayr 338
str_users       db 'users'
339
str_ini         db '.ini', 0
2578 hidnplayr 340
str_port        db 'port', 0
341
str_ftpd        db 'ftpd', 0
342
str_conn        db 'conn', 0
2598 hidnplayr 343
str_ip          db 'ip', 0
344
str_pass        db 'pass', 0
345
str_home        db 'home', 0
346
str_mode        db 'mode', 0
2562 hidnplayr 347
 
2598 hidnplayr 348
 
2554 hidnplayr 349
sockaddr1:
2578 hidnplayr 350
                dw AF_INET4
351
  .port         dw 21
352
  .ip           dd 0
353
                rb 10
354
  .length       = $ - sockaddr1
2554 hidnplayr 355
 
356
; import
2578 hidnplayr 357
 
2554 hidnplayr 358
align 4
359
@IMPORT:
360
 
2578 hidnplayr 361
library console,                'console.obj',\
362
        libini,                 'libini.obj', \
363
        libio,                  'libio.obj'
2554 hidnplayr 364
 
2578 hidnplayr 365
import  console,\
366
        con_start,              'START',\
367
        con_init,               'con_init',\
368
        con_write_asciiz,       'con_write_asciiz',\
369
        con_exit,               'con_exit',\
370
        con_gets,               'con_gets',\
371
        con_cls,                'con_cls',\
372
        con_printf,             'con_printf',\
373
        con_getch2,             'con_getch2',\
374
        con_set_cursor_pos,     'con_set_cursor_pos',\
375
        con_set_flags,          'con_set_flags'
2554 hidnplayr 376
 
2578 hidnplayr 377
import  libini,\
378
        ini.get_str,            'ini_get_str',\
379
        ini.get_int,            'ini_get_int'
2554 hidnplayr 380
 
2578 hidnplayr 381
import  libio,\
382
        libio.init,             'lib_init',\
383
        file.size,              'file_size',\
384
        file.open,              'file_open',\
385
        file.read,              'file_read',\
386
        file.close,             'file_close',\
387
        file.find.first,        'file_find_first',\
388
        file.find.next,         'file_find_next',\
389
        file.find.close,        'file_find_close'
2554 hidnplayr 390
 
391
 
392
i_end:
393
 
2578 hidnplayr 394
; uninitialised data
2557 hidnplayr 395
 
2578 hidnplayr 396
        socketnum       dd ?
397
        path            rb 1024
2598 hidnplayr 398
        path2           rb 1024
2578 hidnplayr 399
        params          rb 1024
2598 hidnplayr 400
        serverip        dd ?
2557 hidnplayr 401
 
2598 hidnplayr 402
        ini_buf         rb 3*4+3+1
403
 
2578 hidnplayr 404
mem:
2563 hidnplayr 405