Subversion Repositories Kolibri OS

Rev

Rev 2602 | 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:
2609 hidnplayr 67
        mcall   68, 11                  ; init heap
68
        mcall   40, 1 shl 7             ; we only want network events
69
 
2554 hidnplayr 70
; load libraries
71
        stdcall dll.Load, @IMPORT
72
        test    eax, eax
73
        jnz     exit
74
 
2598 hidnplayr 75
; find path to main settings file (ftpd.ini)
2578 hidnplayr 76
        mov     edi, path               ; Calculate the length of zero-terminated string
2585 hidnplayr 77
        xor     al, al
2554 hidnplayr 78
        mov     ecx, 1024
79
        repne   scasb
80
        dec     edi
2598 hidnplayr 81
        mov     esi, str_ini            ; append it with '.ini', 0
2554 hidnplayr 82
        movsd
83
        movsb
84
 
2598 hidnplayr 85
; now create the second path (users.ini)
86
        std
87
        mov     al, '/'
88
        repne   scasb
89
        lea     ecx, [edi - path + 2]
90
        cld
91
        mov     esi, path
92
        mov     edi, path2
93
        rep     movsb
94
        mov     esi, str_users
95
        movsd
96
        movsd
97
        movsw
98
 
2554 hidnplayr 99
; initialize console
2602 hidnplayr 100
        invoke  con_start, 1
101
        invoke  con_init, -1, -1, -1, -1, title
2560 hidnplayr 102
 
2598 hidnplayr 103
        invoke  ini.get_str, path, str_ftpd, str_ip, ini_buf, 16, 0
104
        mov     esi, ini_buf
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
2554 hidnplayr 112
 
113
        mcall   socket, AF_INET4, SOCK_STREAM, 0
114
        cmp     eax, -1
115
        je      sock_err
116
        mov     [socketnum], eax
117
 
2602 hidnplayr 118
        invoke  con_write_asciiz, str2
2560 hidnplayr 119
 
2585 hidnplayr 120
;        mcall   setsockopt, [socketnum], SOL_SOCKET, SO_REUSEADDR, &yes,
121
;        cmp     eax, -1
122
;        je      opt_err
2554 hidnplayr 123
 
124
        mcall   bind, [socketnum], sockaddr1, sockaddr1.length
125
        cmp     eax, -1
126
        je      bind_err
127
 
2602 hidnplayr 128
        invoke  con_write_asciiz, str2
2560 hidnplayr 129
 
2554 hidnplayr 130
        invoke  ini.get_int, path, str_ftpd, str_conn, 1        ; Backlog (max connections)
131
        mov     edx, eax
2560 hidnplayr 132
 
2602 hidnplayr 133
        invoke  con_write_asciiz, str2
2560 hidnplayr 134
 
2554 hidnplayr 135
        mcall   listen, [socketnum]
136
        cmp     eax, -1
137
        je      listen_err
138
 
2602 hidnplayr 139
        invoke  con_write_asciiz, str2b
2554 hidnplayr 140
 
2609 hidnplayr 141
        mov     [pasvport], 2000        ;;;;;; FIXME
142
 
2578 hidnplayr 143
mainloop:
144
        mcall   10                              ; Wait here for incoming connections on the base socket (socketnum)
2554 hidnplayr 145
 
2578 hidnplayr 146
        mcall   51, 1, threadstart, 0           ; Start a new thread for every incoming connection
147
                                                ; NOTE: upon initialisation of the thread, stack will not be available!
148
        jmp     mainloop
149
 
2585 hidnplayr 150
        diff16  "threadstart", 0, $
2578 hidnplayr 151
threadstart:
2609 hidnplayr 152
;;;        mcall   68, 11                          ; init heap
2578 hidnplayr 153
        mcall   68, 12, sizeof.thread_data      ; allocate the thread data struct
2609 hidnplayr 154
        test    eax, eax
2578 hidnplayr 155
        je      exit
2554 hidnplayr 156
 
2578 hidnplayr 157
        lea     esp, [eax + thread_data.stack]  ; init stack
2609 hidnplayr 158
        mov     ebp, eax
2554 hidnplayr 159
 
2578 hidnplayr 160
        mcall   40, 1 shl 7                     ; we only want network events for this thread
2554 hidnplayr 161
 
2602 hidnplayr 162
        invoke  con_set_flags, 0x03
163
        invoke  con_write_asciiz, str8          ; print on the console that we have created the new thread successfully
164
        invoke  con_set_flags, 0x07
2578 hidnplayr 165
 
166
        mcall   accept, [socketnum], sockaddr1, sockaddr1.length                ; time to accept the awaiting connection..
167
        cmp     eax, -1
168
        je      thread_exit
2609 hidnplayr 169
        mov     [ebp + thread_data.socketnum], eax
2578 hidnplayr 170
 
2609 hidnplayr 171
        mov     [ebp + thread_data.state], STATE_CONNECTED
172
        mov     [ebp + thread_data.permissions], 0
173
        mov     [ebp + thread_data.mode], MODE_NOTREADY
174
        lea     eax, [ebp + thread_data.buffer]
175
        mov     [ebp + thread_data.buffer_ptr], eax
2578 hidnplayr 176
 
2598 hidnplayr 177
        sendFTP "220 Welcome to KolibriOS FTP daemon"
178
 
2578 hidnplayr 179
threadloop:
2554 hidnplayr 180
        mcall   10
2598 hidnplayr 181
        mov     edx, [ebp]                                                      ; pointer to thread_data
2578 hidnplayr 182
 
2609 hidnplayr 183
        cmp     [ebp + thread_data.mode], MODE_PASSIVE_WAIT
2598 hidnplayr 184
        jne     .not_passive
2609 hidnplayr 185
        mov     [ebp + thread_data.mode], MODE_PASSIVE_FAILED                   ; assume that we will fail
186
        mov     ecx, [ebp + thread_data.passivesocknum]
187
        lea     edx, [ebp + thread_data.datasock]
2578 hidnplayr 188
        mov     esi, sizeof.thread_data.datasock
189
        mcall   accept
2562 hidnplayr 190
        cmp     eax, -1
2598 hidnplayr 191
        je      .not_passive
2609 hidnplayr 192
        mov     [ebp + thread_data.datasocketnum], eax
193
        mov     [ebp + thread_data.mode], MODE_PASSIVE_OK
2562 hidnplayr 194
 
2602 hidnplayr 195
        invoke  con_write_asciiz, str_datasock
2598 hidnplayr 196
  .not_passive:
2562 hidnplayr 197
 
2609 hidnplayr 198
        mov     ecx, [ebp + thread_data.socketnum]
199
        mov     edx, [ebp + thread_data.buffer_ptr]
2598 hidnplayr 200
        mov     esi, sizeof.thread_data.buffer    ;;; FIXME
2578 hidnplayr 201
        mcall   recv
2598 hidnplayr 202
        inc     eax                                                             ; error? (-1)
2578 hidnplayr 203
        jz      threadloop
2598 hidnplayr 204
        dec     eax                                                             ; 0 bytes read?
205
        jz      threadloop
2554 hidnplayr 206
 
2609 hidnplayr 207
        mov     edi, [ebp + thread_data.buffer_ptr]
208
        add     [ebp + thread_data.buffer_ptr], eax
2560 hidnplayr 209
 
2598 hidnplayr 210
; Check if we received a newline character, if not, wait for more data
211
        mov     ecx, eax
212
        mov     al, 13
213
        repne   scasb
214
        jne     threadloop
215
 
216
; We got a command!
2602 hidnplayr 217
        mov     byte [edi + 1], 0                                               ; append string with zero byte
2609 hidnplayr 218
        lea     esi, [ebp + thread_data.buffer]
219
        mov     ecx, [ebp + thread_data.buffer_ptr]
2602 hidnplayr 220
        sub     ecx, esi
2609 hidnplayr 221
        mov     [ebp + thread_data.buffer_ptr], esi                             ; reset buffer ptr
2598 hidnplayr 222
 
2602 hidnplayr 223
        invoke  con_set_flags, 0x02                                                            ; print received data to console (in green color)
224
        invoke  con_write_asciiz, str_newline
225
        invoke  con_write_asciiz, esi
226
        invoke  con_set_flags, 0x07
2560 hidnplayr 227
 
2602 hidnplayr 228
        push    threadloop
229
        jmp     parse_cmd
2554 hidnplayr 230
 
231
listen_err:
2602 hidnplayr 232
        invoke  con_set_flags, 0x0c                                                            ; print received data to console (in green color)
233
        invoke  con_write_asciiz, str3
2554 hidnplayr 234
        jmp     done
235
 
236
bind_err:
2602 hidnplayr 237
        invoke  con_set_flags, 0x0c                                                            ; print received data to console (in green color)
238
        invoke  con_write_asciiz, str4
2554 hidnplayr 239
        jmp     done
240
 
241
sock_err:
2602 hidnplayr 242
        invoke  con_set_flags, 0x0c                                                            ; print received data to console (in green color)
243
        invoke  con_write_asciiz, str6
2554 hidnplayr 244
        jmp     done
245
 
246
done:
2602 hidnplayr 247
        invoke  con_getch2
248
        invoke  con_exit, 1
2554 hidnplayr 249
exit:
250
        mcall   -1
251
 
252
 
2578 hidnplayr 253
thread_exit:
2602 hidnplayr 254
        invoke  con_set_flags, 0x02                                                            ; print received data to console (in green color)
255
        invoke  con_write_asciiz, str_bye
2578 hidnplayr 256
        pop     ecx                     ; get the thread_data pointer from stack
257
        mcall   68, 13                  ; free the memory
258
        mcall   -1                      ; and kill the thread
2554 hidnplayr 259
 
260
 
2578 hidnplayr 261
 
262
; initialized data
263
 
264
title           db 'KolibriOS FTP daemon 0.1', 0
265
str1            db 'Starting FTP daemon on port %u', 0
266
str2            db '.', 0
2585 hidnplayr 267
str2b           db ' OK!',10,0
268
str3            db 'Listen error',10,0
269
str4            db 'Bind error',10,0
2578 hidnplayr 270
;str5            db 'Setsockopt error.',10,10,0
2585 hidnplayr 271
str6            db 'Could not open socket',10,0
2578 hidnplayr 272
str7            db 'Got data!',10,10,0
2585 hidnplayr 273
str8            db 10,'New thread created!',10,0
274
str_bye         db 10,'Closing thread!',10,0
2578 hidnplayr 275
 
2585 hidnplayr 276
str_logged_in   db 'Login ok',10,0
2602 hidnplayr 277
str_pass_ok     db 'Password ok',10,0
2562 hidnplayr 278
str_pwd         db 'Current directory is "%s"\n',0
2585 hidnplayr 279
str_err2        db 'ERROR: cannot open directory',10,0
280
str_datasock    db 'Passive data socket connected!',10,0
281
str_notfound    db 'ERROR: file not found',10,0
282
str_sockerr     db 'ERROR: socket error',10,0
2560 hidnplayr 283
 
2598 hidnplayr 284
str_login_invalid db 'Login invalid',10,0
285
 
2609 hidnplayr 286
str_test db 'test: %x ', 0
287
 
2578 hidnplayr 288
str_newline     db 10, 0
2562 hidnplayr 289
str_mask        db '*', 0
2602 hidnplayr 290
str_infinity    db 0xff, 0xff, 0xff, 0xff, 0
2562 hidnplayr 291
 
2578 hidnplayr 292
months          dd 'Jan '
293
                dd 'Feb '
294
                dd 'Mar '
295
                dd 'Apr '
296
                dd 'May '
297
                dd 'Jun '
298
                dd 'Jul '
299
                dd 'Aug '
300
                dd 'Sep '
301
                dd 'Oct '
302
                dd 'Nov '
303
                dd 'Dec '
2562 hidnplayr 304
 
2598 hidnplayr 305
str_users       db 'users'
306
str_ini         db '.ini', 0
2578 hidnplayr 307
str_port        db 'port', 0
308
str_ftpd        db 'ftpd', 0
309
str_conn        db 'conn', 0
2598 hidnplayr 310
str_ip          db 'ip', 0
311
str_pass        db 'pass', 0
312
str_home        db 'home', 0
313
str_mode        db 'mode', 0
2562 hidnplayr 314
 
2598 hidnplayr 315
 
2554 hidnplayr 316
sockaddr1:
2578 hidnplayr 317
                dw AF_INET4
318
  .port         dw 21
319
  .ip           dd 0
320
                rb 10
321
  .length       = $ - sockaddr1
2554 hidnplayr 322
 
323
; import
2578 hidnplayr 324
 
2554 hidnplayr 325
align 4
326
@IMPORT:
327
 
2609 hidnplayr 328
diff16 "import", 0, $
329
 
2578 hidnplayr 330
library console,                'console.obj',\
331
        libini,                 'libini.obj', \
332
        libio,                  'libio.obj'
2554 hidnplayr 333
 
2578 hidnplayr 334
import  console,\
335
        con_start,              'START',\
336
        con_init,               'con_init',\
337
        con_write_asciiz,       'con_write_asciiz',\
338
        con_exit,               'con_exit',\
339
        con_gets,               'con_gets',\
340
        con_cls,                'con_cls',\
341
        con_printf,             'con_printf',\
342
        con_getch2,             'con_getch2',\
343
        con_set_cursor_pos,     'con_set_cursor_pos',\
344
        con_set_flags,          'con_set_flags'
2554 hidnplayr 345
 
2578 hidnplayr 346
import  libini,\
347
        ini.get_str,            'ini_get_str',\
348
        ini.get_int,            'ini_get_int'
2554 hidnplayr 349
 
2578 hidnplayr 350
import  libio,\
351
        libio.init,             'lib_init',\
352
        file.size,              'file_size',\
353
        file.open,              'file_open',\
354
        file.read,              'file_read',\
355
        file.close,             'file_close',\
356
        file.find.first,        'file_find_first',\
357
        file.find.next,         'file_find_next',\
358
        file.find.close,        'file_find_close'
2554 hidnplayr 359
 
360
 
361
i_end:
362
 
2609 hidnplayr 363
diff16 "i_end", 0, $
364
 
2578 hidnplayr 365
; uninitialised data
2557 hidnplayr 366
 
2578 hidnplayr 367
        socketnum       dd ?
368
        path            rb 1024
2598 hidnplayr 369
        path2           rb 1024
2578 hidnplayr 370
        params          rb 1024
2598 hidnplayr 371
        serverip        dd ?
2609 hidnplayr 372
        pasvport        dw ?
2557 hidnplayr 373
 
2598 hidnplayr 374
        ini_buf         rb 3*4+3+1
375
 
2578 hidnplayr 376
mem:
2563 hidnplayr 377