Subversion Repositories Kolibri OS

Rev

Rev 2610 | 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
start:
2609 hidnplayr 66
        mcall   68, 11                  ; init heap
67
        mcall   40, 1 shl 7             ; we only want network events
68
 
2554 hidnplayr 69
; load libraries
70
        stdcall dll.Load, @IMPORT
71
        test    eax, eax
72
        jnz     exit
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
2602 hidnplayr 99
        invoke  con_start, 1
100
        invoke  con_init, -1, -1, -1, -1, title
2560 hidnplayr 101
 
2598 hidnplayr 102
        invoke  ini.get_str, path, str_ftpd, str_ip, ini_buf, 16, 0
103
        mov     esi, ini_buf
2610 hidnplayr 104
        mov     cl, '.'
2598 hidnplayr 105
        call    ip_to_dword
106
        mov     [serverip], ebx
107
 
2560 hidnplayr 108
        invoke  ini.get_int, path, str_ftpd, str_port, 21
109
        mov     [sockaddr1.port], ax
110
 
2602 hidnplayr 111
        invoke  con_printf, str1, eax
2624 hidnplayr 112
        add     esp, 8
2554 hidnplayr 113
 
114
        mcall   socket, AF_INET4, SOCK_STREAM, 0
115
        cmp     eax, -1
116
        je      sock_err
117
        mov     [socketnum], eax
118
 
2602 hidnplayr 119
        invoke  con_write_asciiz, str2
2560 hidnplayr 120
 
2585 hidnplayr 121
;        mcall   setsockopt, [socketnum], SOL_SOCKET, SO_REUSEADDR, &yes,
122
;        cmp     eax, -1
123
;        je      opt_err
2554 hidnplayr 124
 
125
        mcall   bind, [socketnum], sockaddr1, sockaddr1.length
126
        cmp     eax, -1
127
        je      bind_err
128
 
2602 hidnplayr 129
        invoke  con_write_asciiz, str2
2560 hidnplayr 130
 
2554 hidnplayr 131
        invoke  ini.get_int, path, str_ftpd, str_conn, 1        ; Backlog (max connections)
132
        mov     edx, eax
2560 hidnplayr 133
 
2602 hidnplayr 134
        invoke  con_write_asciiz, str2
2560 hidnplayr 135
 
2554 hidnplayr 136
        mcall   listen, [socketnum]
137
        cmp     eax, -1
138
        je      listen_err
139
 
2602 hidnplayr 140
        invoke  con_write_asciiz, str2b
2554 hidnplayr 141
 
2610 hidnplayr 142
        invoke  ini.get_int, path, str_pasv, str_start, 2000
143
        mov     [pasv_start], ax
144
        invoke  ini.get_int, path, str_pasv, str_end, 5000
145
        mov     [pasv_end], ax
2609 hidnplayr 146
 
2578 hidnplayr 147
mainloop:
2624 hidnplayr 148
        mcall   23, 100                         ; Wait here for incoming connections on the base socket (socketnum)
149
                                                ; One second timeout, we sill use this to check if console is still working
2554 hidnplayr 150
 
2624 hidnplayr 151
        test    eax, 1 shl 7                    ; network event?
152
        jz      .checkconsole
153
 
2578 hidnplayr 154
        mcall   51, 1, threadstart, 0           ; Start a new thread for every incoming connection
155
                                                ; NOTE: upon initialisation of the thread, stack will not be available!
156
        jmp     mainloop
157
 
2624 hidnplayr 158
  .checkconsole:
159
 
160
        invoke  con_get_flags                   ; Is console still running?
161
        test    eax, 0x0200
162
        jz      mainloop
163
        mcall   close, [socketnum]              ; kill the listening socket
164
        mcall   -1                              ; and exit
165
 
2585 hidnplayr 166
        diff16  "threadstart", 0, $
2624 hidnplayr 167
 
2578 hidnplayr 168
threadstart:
2609 hidnplayr 169
;;;        mcall   68, 11                          ; init heap
2578 hidnplayr 170
        mcall   68, 12, sizeof.thread_data      ; allocate the thread data struct
2609 hidnplayr 171
        test    eax, eax
2578 hidnplayr 172
        je      exit
2554 hidnplayr 173
 
2578 hidnplayr 174
        lea     esp, [eax + thread_data.stack]  ; init stack
2609 hidnplayr 175
        mov     ebp, eax
2554 hidnplayr 176
 
2578 hidnplayr 177
        mcall   40, 1 shl 7                     ; we only want network events for this thread
2554 hidnplayr 178
 
2624 hidnplayr 179
        lea     ebx, [ebp + thread_data.buffer] ; get information about the current process
180
        or      ecx, -1
181
        mcall   9
182
        mov     eax, dword [ebp + thread_data.buffer + 30]              ; PID is at offset 30
183
        mov     [ebp + thread_data.pid], eax
184
 
2602 hidnplayr 185
        invoke  con_set_flags, 0x03
2624 hidnplayr 186
        invoke  con_printf, str8, [ebp + thread_data.pid]               ; print on the console that we have created the new thread successfully
187
        add     esp, 8                                                  ; balance stack
2602 hidnplayr 188
        invoke  con_set_flags, 0x07
2578 hidnplayr 189
 
2610 hidnplayr 190
        mcall   accept, [socketnum], sockaddr1, sockaddr1.length        ; time to accept the awaiting connection..
2578 hidnplayr 191
        cmp     eax, -1
192
        je      thread_exit
2609 hidnplayr 193
        mov     [ebp + thread_data.socketnum], eax
2578 hidnplayr 194
 
2609 hidnplayr 195
        mov     [ebp + thread_data.state], STATE_CONNECTED
196
        mov     [ebp + thread_data.permissions], 0
197
        mov     [ebp + thread_data.mode], MODE_NOTREADY
198
        lea     eax, [ebp + thread_data.buffer]
199
        mov     [ebp + thread_data.buffer_ptr], eax
2610 hidnplayr 200
        mov     [ebp + thread_data.passivesocknum], -1
2578 hidnplayr 201
 
2598 hidnplayr 202
        sendFTP "220 Welcome to KolibriOS FTP daemon"
203
 
2624 hidnplayr 204
        diff16  "threadloop", 0, $
2578 hidnplayr 205
threadloop:
2624 hidnplayr 206
; Check if our socket is still connected
207
        mcall   send, [ebp + thread_data.socketnum], 0, 0       ; Try to send zero bytes, if socket is closed, this will return -1
208
        cmp     eax, -1
209
        je      thread_exit
2578 hidnplayr 210
 
2624 hidnplayr 211
        mcall   10                                              ; Wait for network event
212
 
2609 hidnplayr 213
        cmp     [ebp + thread_data.mode], MODE_PASSIVE_WAIT
2598 hidnplayr 214
        jne     .not_passive
2609 hidnplayr 215
        mov     ecx, [ebp + thread_data.passivesocknum]
216
        lea     edx, [ebp + thread_data.datasock]
2578 hidnplayr 217
        mov     esi, sizeof.thread_data.datasock
218
        mcall   accept
2562 hidnplayr 219
        cmp     eax, -1
2598 hidnplayr 220
        je      .not_passive
2609 hidnplayr 221
        mov     [ebp + thread_data.datasocketnum], eax
222
        mov     [ebp + thread_data.mode], MODE_PASSIVE_OK
2610 hidnplayr 223
        mcall   close   ; [ebp + thread_data.passivesocknum]
224
        mov     [ebp + thread_data.passivesocknum], -1
2562 hidnplayr 225
 
2602 hidnplayr 226
        invoke  con_write_asciiz, str_datasock
2598 hidnplayr 227
  .not_passive:
2562 hidnplayr 228
 
2609 hidnplayr 229
        mov     ecx, [ebp + thread_data.socketnum]
230
        mov     edx, [ebp + thread_data.buffer_ptr]
2598 hidnplayr 231
        mov     esi, sizeof.thread_data.buffer    ;;; FIXME
2578 hidnplayr 232
        mcall   recv
2610 hidnplayr 233
        inc     eax                                     ; error? (-1)
2578 hidnplayr 234
        jz      threadloop
2610 hidnplayr 235
        dec     eax                                     ; 0 bytes read?
2598 hidnplayr 236
        jz      threadloop
2554 hidnplayr 237
 
2609 hidnplayr 238
        mov     edi, [ebp + thread_data.buffer_ptr]
239
        add     [ebp + thread_data.buffer_ptr], eax
2560 hidnplayr 240
 
2598 hidnplayr 241
; Check if we received a newline character, if not, wait for more data
242
        mov     ecx, eax
243
        mov     al, 13
244
        repne   scasb
245
        jne     threadloop
246
 
247
; We got a command!
2610 hidnplayr 248
        mov     byte [edi + 1], 0                       ; append string with zero byte
2609 hidnplayr 249
        lea     esi, [ebp + thread_data.buffer]
250
        mov     ecx, [ebp + thread_data.buffer_ptr]
2602 hidnplayr 251
        sub     ecx, esi
2610 hidnplayr 252
        mov     [ebp + thread_data.buffer_ptr], esi     ; reset buffer ptr
2598 hidnplayr 253
 
2610 hidnplayr 254
        invoke  con_set_flags, 0x02                     ; print received data to console (in green color)
2602 hidnplayr 255
        invoke  con_write_asciiz, str_newline
256
        invoke  con_write_asciiz, esi
257
        invoke  con_set_flags, 0x07
2560 hidnplayr 258
 
2602 hidnplayr 259
        push    threadloop
260
        jmp     parse_cmd
2554 hidnplayr 261
 
262
listen_err:
2610 hidnplayr 263
        invoke  con_set_flags, 0x0c                     ; print errors in red
2602 hidnplayr 264
        invoke  con_write_asciiz, str3
2554 hidnplayr 265
        jmp     done
266
 
267
bind_err:
2610 hidnplayr 268
        invoke  con_set_flags, 0x0c                     ; print errors in red
2602 hidnplayr 269
        invoke  con_write_asciiz, str4
2554 hidnplayr 270
        jmp     done
271
 
272
sock_err:
2610 hidnplayr 273
        invoke  con_set_flags, 0x0c                     ; print errors in red
2602 hidnplayr 274
        invoke  con_write_asciiz, str6
2554 hidnplayr 275
        jmp     done
276
 
277
done:
2624 hidnplayr 278
        invoke  con_exit, 0
2554 hidnplayr 279
exit:
280
        mcall   -1
281
 
282
 
2578 hidnplayr 283
thread_exit:
2624 hidnplayr 284
        invoke  con_set_flags, 0x03                             ; print thread info in blue
285
        invoke  con_printf, str_bye, [ebp + thread_data.pid]    ; print on the console that we are about to kill the thread
286
        add     esp, 8                                          ; balance stack
287
        mcall   68, 13, ebp                                     ; free the memory
288
        mcall   -1                                              ; and kill the thread
2554 hidnplayr 289
 
290
 
2578 hidnplayr 291
; initialized data
292
 
293
title           db 'KolibriOS FTP daemon 0.1', 0
2624 hidnplayr 294
str1            db 'Starting FTP daemon on port %u.', 0
2578 hidnplayr 295
str2            db '.', 0
2585 hidnplayr 296
str2b           db ' OK!',10,0
297
str3            db 'Listen error',10,0
2624 hidnplayr 298
str4            db 10,'ERROR: local port is already in use.',10,0
2578 hidnplayr 299
;str5            db 'Setsockopt error.',10,10,0
2624 hidnplayr 300
str6            db 'ERROR: Could not open socket.',10,0
2578 hidnplayr 301
str7            db 'Got data!',10,10,0
2624 hidnplayr 302
str8            db 10,'Thread %d created',10,0
303
str_bye         db 10,'Thread %d killed',10,0
2578 hidnplayr 304
 
2585 hidnplayr 305
str_logged_in   db 'Login ok',10,0
2602 hidnplayr 306
str_pass_ok     db 'Password ok',10,0
2610 hidnplayr 307
str_pass_err    db 'Password/Username incorrect',10,0
2562 hidnplayr 308
str_pwd         db 'Current directory is "%s"\n',0
2624 hidnplayr 309
str_err2        db 'ERROR: cannot open the directory.',10,0
310
str_datasock    db 'Passive data socket connected.',10,0
311
str_notfound    db 'ERROR: file not found.',10,0
312
str_sockerr     db 'ERROR: socket error.',10,0
2560 hidnplayr 313
 
2578 hidnplayr 314
str_newline     db 10, 0
2562 hidnplayr 315
str_mask        db '*', 0
2602 hidnplayr 316
str_infinity    db 0xff, 0xff, 0xff, 0xff, 0
2562 hidnplayr 317
 
2578 hidnplayr 318
months          dd 'Jan '
319
                dd 'Feb '
320
                dd 'Mar '
321
                dd 'Apr '
322
                dd 'May '
323
                dd 'Jun '
324
                dd 'Jul '
325
                dd 'Aug '
326
                dd 'Sep '
327
                dd 'Oct '
328
                dd 'Nov '
329
                dd 'Dec '
2562 hidnplayr 330
 
2598 hidnplayr 331
str_users       db 'users'
332
str_ini         db '.ini', 0
2578 hidnplayr 333
str_port        db 'port', 0
334
str_ftpd        db 'ftpd', 0
335
str_conn        db 'conn', 0
2598 hidnplayr 336
str_ip          db 'ip', 0
337
str_pass        db 'pass', 0
338
str_home        db 'home', 0
339
str_mode        db 'mode', 0
2610 hidnplayr 340
str_pasv        db 'pasv', 0
341
str_start       db 'start', 0
342
str_end         db 'end', 0
2562 hidnplayr 343
 
2598 hidnplayr 344
 
2554 hidnplayr 345
sockaddr1:
2578 hidnplayr 346
                dw AF_INET4
347
  .port         dw 21
348
  .ip           dd 0
349
                rb 10
350
  .length       = $ - sockaddr1
2554 hidnplayr 351
 
352
; import
2578 hidnplayr 353
 
2554 hidnplayr 354
align 4
355
@IMPORT:
356
 
2609 hidnplayr 357
diff16 "import", 0, $
358
 
2578 hidnplayr 359
library console,                'console.obj',\
360
        libini,                 'libini.obj', \
361
        libio,                  'libio.obj'
2554 hidnplayr 362
 
2578 hidnplayr 363
import  console,\
364
        con_start,              'START',\
365
        con_init,               'con_init',\
366
        con_write_asciiz,       'con_write_asciiz',\
367
        con_exit,               'con_exit',\
368
        con_gets,               'con_gets',\
369
        con_cls,                'con_cls',\
370
        con_printf,             'con_printf',\
371
        con_getch2,             'con_getch2',\
372
        con_set_cursor_pos,     'con_set_cursor_pos',\
2624 hidnplayr 373
        con_set_flags,          'con_set_flags',\
374
        con_get_flags,          'con_get_flags'
2554 hidnplayr 375
 
2578 hidnplayr 376
import  libini,\
377
        ini.get_str,            'ini_get_str',\
378
        ini.get_int,            'ini_get_int'
2554 hidnplayr 379
 
2578 hidnplayr 380
import  libio,\
381
        libio.init,             'lib_init',\
382
        file.size,              'file_size',\
383
        file.open,              'file_open',\
384
        file.read,              'file_read',\
385
        file.close,             'file_close',\
386
        file.find.first,        'file_find_first',\
387
        file.find.next,         'file_find_next',\
388
        file.find.close,        'file_find_close'
2554 hidnplayr 389
 
390
 
391
i_end:
392
 
2609 hidnplayr 393
diff16 "i_end", 0, $
394
 
2578 hidnplayr 395
; uninitialised data
2557 hidnplayr 396
 
2578 hidnplayr 397
        socketnum       dd ?
398
        path            rb 1024
2598 hidnplayr 399
        path2           rb 1024
2578 hidnplayr 400
        params          rb 1024
2598 hidnplayr 401
        serverip        dd ?
2610 hidnplayr 402
        pasv_start      dw ?
403
        pasv_end        dw ?
404
        pasv_port       dw ?
2557 hidnplayr 405
 
2598 hidnplayr 406
        ini_buf         rb 3*4+3+1
407
 
2578 hidnplayr 408
mem:
2563 hidnplayr 409