Subversion Repositories Kolibri OS

Rev

Rev 3824 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3545 hidnplayr 1
 
2
 
3
        stack           rb 0
4
5
        home_dir        rb 1024         ; home directory in wich the user is locked, asciiz
6
 
7
        fpath           rb 1024*3       ; file path, combination of home_dir, work_dir and filename
8
                                        ; Will also be used to temporarily store username
9
10
        type            db ?    ; ASCII/EBDIC/IMAGE/..
11
 
12
        socketnum       dd ?    ; Commands socket
13
        state           dd ?    ; disconnected/logging in/logged in/..
14
        passivesocknum  dd ?    ; when in passive mode, this is the listening socket
15
        datasocketnum   dd ?    ; socket used for data transfers
16
        permissions     dd ?    ; read/write/execute/....
17
        buffer_ptr      dd ?
18
        pid             dd ?    ; Process id of the current thread
19
20
        datasock        sockaddr_in
21
 
22
        buffer          rb BUFFERSIZE
23
 
24
25
;------------------------------------------------
26
 
27
;
28
; Internal function wich uses the 'commands'
29
;  table to call an appropriate cmd_xx function.
30
;
31
; input: esi = ptr to ascii commands
32
;        ecx = number of bytes input
33
;        ebp = pointer to thread_data structure
34
;
35
; output: none
36
;
37
;------------------------------------------------
38
align 4
39
parse_cmd:                              ; esi must point to command
40
41
        cmp     byte [esi], 0x20        ; skip all leading characters
42
 
43
        inc     esi
44
        dec     ecx
45
        cmp     ecx, 3
46
        jb      .error
47
        jmp     parse_cmd
48
  .ok:
49
        cmp     byte [esi+3], 0x20
50
        ja      @f
51
        mov     byte [esi+3], 0
52
       @@:
53
54
        mov     eax, [esi]
55
 
56
        mov     edi, commands           ; list of commands to scan
57
  .scanloop:
58
        cmp     eax, [edi]
59
        je      .got_it
60
61
        add     edi, 5*4
62
 
63
        jne     .scanloop
64
65
  .error:
66
 
67
        jb      login_first
68
        sendFTP "500 Unsupported command"
69
        ret
70
71
  .got_it:
72
 
73
        jmp     dword [edi + 4 + eax]
74
75
76
 
77
 
78
commands:               ; all commands must be in uppercase
79
80
        dd 'ABOR', login_first, login_first, login_first, cmdABOR
81
 
82
;        dd 'APPE', login_first, login_first, login_first, cmd_APPE
83
        dd 'CDUP', login_first, login_first, login_first, cmdCDUP
84
        dd 'CWD',  login_first, login_first, login_first, cmdCWD
85
        dd 'DELE', login_first, login_first, login_first, cmdDELE
86
;        dd 'HELP', login_first, login_first, login_first, cmd_HELP
87
        dd 'LIST', login_first, login_first, login_first, cmdLIST
88
;        dd 'MDTM', login_first, login_first, login_first, cmd_MDTM
89
;        dd 'MKD',  login_first, login_first, login_first, cmd_MKD
90
;        dd 'MODE', login_first, login_first, login_first, cmd_MODE
91
;        dd 'NLST', login_first, login_first, login_first, cmdNLST
92
        dd 'NOOP', login_first, login_first, login_first, cmdNOOP
3824 hidnplayr 93
        dd 'PASS', cmdPASS.0,   cmdPASS    , cmdPASS.2,   cmdPASS.3
3545 hidnplayr 94
        dd 'PASV', login_first, login_first, login_first, cmdPASV
95
        dd 'PORT', login_first, login_first, login_first, cmdPORT
96
        dd 'PWD',  login_first, login_first, login_first, cmdPWD
97
        dd 'QUIT', cmdQUIT,     cmdQUIT,     cmdQUIT,     cmdQUIT
98
;        dd 'REIN', login_first, login_first, login_first, cmd_REIN
99
;        dd 'REST', login_first, login_first, login_first, cmd_REST
100
        dd 'RETR', login_first, login_first, login_first, cmdRETR
101
;        dd 'RMD', login_first, login_first, login_first, cmd_RMD
102
;        dd 'RNFR', login_first, login_first, login_first, cmd_RNFR
103
;        dd 'RNTO', login_first, login_first, login_first, cmd_RNTO
104
;        dd 'SITE', login_first, login_first, login_first, cmd_SITE
105
;        dd 'SIZE', login_first, login_first, login_first, cmd_SIZE
106
;        dd 'STAT', login_first, login_first, login_first, cmd_STAT
107
        dd 'STOR', login_first, login_first, login_first, cmdSTOR
108
;        dd 'STOU', login_first, login_first, login_first, cmd_STOU
109
;        dd 'STRU', login_first, login_first, login_first, cmd_STRU
110
        dd 'SYST', login_first, login_first, login_first, cmdSYST
111
        dd 'TYPE', login_first, login_first, login_first, cmdTYPE
112
        dd 'USER', cmdUSER,     cmdUSER,     cmdUSER,     cmdUSER.2
113
        db 0    ; end marker
114
endg
115
116
align 4
117
 
118
        sendFTP "530 Please login with USER and PASS"
119
        ret
120
121
align 4
122
 
123
        sendFTP "550 Permission denied"
124
        ret
125
126
align 4
127
 
128
        invoke  con_set_flags, 0x0c
129
        invoke  con_write_asciiz, str_sockerr
130
        invoke  con_set_flags, 0x07
131
132
        sendFTP "425 Can't open data connection"
133
 
134
135
align 4
136
 
137
        and     [ebp + thread_data.permissions], not ABORT
138
        mov     [ebp + thread_data.mode], MODE_NOTREADY
139
        invoke  file.close, ebx
140
        mcall   close, [ebp + thread_data.datasocketnum]
141
142
        sendFTP "530 Transfer aborted"
143
 
144
145
align 4
146
 
147
148
        call    ascii_to_byte
149
 
150
        cmp     byte [esi], cl
151
        jne     .err
152
        inc     esi
153
154
        call    ascii_to_byte
155
 
156
        cmp     byte [esi], cl
157
        jne     .err
158
        inc     esi
159
160
        shl     ebx, 16
161
 
162
        call    ascii_to_byte
163
 
164
        cmp     byte [esi], cl
165
        jne     .err
166
        inc     esi
167
168
        call    ascii_to_byte
169
 
170
171
        ror     ebx, 16
172
 
173
174
  .err:
175
 
176
        ret
177
178
align 4         ; esi = ptr to str, output in eax
179
 
180
181
        xor     eax, eax
182
 
183
184
  .loop:
185
 
186
        sub     bl, '0'
187
        jb      .done
188
        cmp     bl, 9
189
        ja      .done
190
        lea     eax, [eax*4 + eax]      ;
191
        shl     eax, 1                  ; eax = eax * 10
192
        add     eax, ebx
193
        inc     esi
194
195
        jmp     .loop
196
 
197
  .done:
198
 
199
        ret
200
201
align 4
202
 
203
204
        push    edx ebx ecx
205
 
206
        xor     ecx, ecx
207
208
       @@:
209
 
210
        div     ebx
211
        add     edx, '0'
212
        pushw   dx
213
        inc     ecx
214
        test    eax, eax
215
        jnz     @r
216
217
       @@:
218
 
219
        stosb
220
        dec     ecx
221
        jnz     @r
222
223
        pop     ecx ebx edx
224
 
225
226
align 4
227
 
228
229
        lea     edi, [ebp + thread_data.fpath]
230
 
231
        mov     ecx, 1024
232
  .loop1:
233
        lodsb
234
        cmp     al, 0x20
235
        jb      .next
236
        stosb
237
        loop    .loop1
238
  .next:
239
240
        cmp     byte[edi-1], '/'
241
 
242
        dec     edi
243
       @@:
244
245
        lea     esi, [ebp + thread_data.work_dir]
246
 
247
  .loop2:
248
        lodsb
249
        cmp     al, 0x20
250
        jb      .done
251
        stosb
252
        loop    .loop2
253
254
  .done:
255
 
256
        stosb
257
        ret
258
259
260
 
261
 
262
263
        inc     [pasv_port]
264
 
265
        mov     ax, [pasv_port]
266
 
267
        jb      .restart
268
        cmp     ax, [pasv_end]
269
        ja      .restart
270
271
        ret
272
 
273
  .restart:
274
 
275
        popw    [pasv_port]
276
277
        ret
278
 
279
280
 
281
 
282
283
        cmp     [ebp + thread_data.mode], MODE_PASSIVE_OK
284
 
285
3824 hidnplayr 286
; If we are in active mode, it's time to open the data socket..
3545 hidnplayr 287
 
3824 hidnplayr 288
        jne     .not_active
3545 hidnplayr 289
        mov     ecx, [ebp + thread_data.datasocketnum]
290
        lea     edx, [ebp + thread_data.datasock]
291
        mov     esi, sizeof.thread_data.datasock
292
        mcall   connect
293
        cmp     eax, -1
294
        je      .socketerror
295
        invoke  con_write_asciiz, str_datasock2
3824 hidnplayr 296
        ret
297
298
  .already_open:
3545 hidnplayr 299
 
3824 hidnplayr 300
        ret
301
302
  .socketerror:
303
 
3545 hidnplayr 304
        jmp     socketerror
305
306
; If we are still in passive_wait, it's time we accept an incomming call..
307
 
308
        cmp     [ebp + thread_data.mode], MODE_PASSIVE_WAIT
309
        jne     .socketerror
310
311
  .try_now:
312
 
313
        lea     edx, [ebp + thread_data.datasock]
314
        mov     esi, sizeof.thread_data.datasock
315
        mcall   accept
316
        cmp     eax, -1
317
        jne     .pasv_ok
318
        mov     [ebp + thread_data.mode], MODE_PASSIVE_FAILED                   ; assume that we will fail
319
        mcall   23, 200
320
        mcall   accept
321
        cmp     eax, -1
322
        je      .socketerror
323
  .pasv_ok:
324
        mov     [ebp + thread_data.datasocketnum], eax
325
        mov     [ebp + thread_data.mode], MODE_PASSIVE_OK
326
        mcall   close   ; [ebp + thread_data.passivesocknum]
327
        mov     [ebp + thread_data.passivesocknum], -1
328
        invoke  con_write_asciiz, str_datasock
329
330
        ret
331
 
332
333
 
334
 
335
;
336
; This command aborts the current filetransfer.
337
;
338
;------------------------------------------------
339
align 4
340
cmdABOR:
341
342
        or      [ebp + thread_data.permissions], ABORT
343
 
344
        ret
345
346
;------------------------------------------------
347
 
348
;
349
; Change the directory to move up one level.
350
;
351
;------------------------------------------------
352
align 4
353
cmdCDUP:
354
355
        test    [ebp + thread_data.permissions], PERMISSION_CD
356
 
357
358
        cmp     byte [ebp + thread_data.work_dir+1], 0  ; are we in "/" ?
359
 
360
361
; find the end of asciiz string work_dir
362
 
363
        xor     al, al
364
        lea     edi, [ebp + thread_data.work_dir]
365
        repne   scasb
366
; return 2 characters (right before last /)
367
        sub     edi, 3
368
; and now search backwards, for a '/'
369
        mov     al,'/'
370
        neg     ecx
371
        add     ecx, 1024
372
        std
373
        repne   scasb
374
        cld
375
; terminate the string here
376
        mov     byte[edi+2], 0
377
378
  .done:
379
 
380
        lea     eax, [ebp + thread_data.work_dir]
381
        invoke  con_write_asciiz, eax
382
        invoke  con_write_asciiz, str_newline
383
384
        sendFTP "250 Command succesul"
385
 
386
387
;------------------------------------------------
388
 
389
;
390
; Change Working Directory.
391
;
392
;------------------------------------------------
393
align 4
394
cmdCWD:
395
396
        test    [ebp + thread_data.permissions], PERMISSION_CD
397
 
398
399
; do we have enough parameters?
400
 
401
        jbe     .err
402
403
; get ready to copy the path
404
 
405
        mov     ecx, 1024
406
        lea     edi, [ebp + thread_data.work_dir]
407
408
; if received dir starts with '/', we will simply copy it
409
 
410
        cmp     byte [esi], '/'
411
        je      .copyloop
412
413
; Find the end of work_dir string.
414
 
415
  .find_zero:
416
        repne   scasb
417
        dec     edi
418
419
; and now append work_dir with received string
420
 
421
422
; scan for end byte, or '.'
423
 
424
        lodsb
425
        cmp     al, 0x20
426
        jb      .done
427
;;;        cmp     al, '.'         ; '..' means we must go up one dir   TODO
428
;;;        je      .up
429
        stosb
430
        loop    .copyloop
431
432
; now, now make sure it ends with '/', 0
433
 
434
        cmp     byte [edi-1], '/'
435
        je      @f
436
        mov     byte [edi], '/'
437
        inc     edi
438
       @@:
439
        mov     byte [edi], 0
440
441
; TODO: Check directory on disk
442
 
9916 Doczom 443
444
 
445
 
3545 hidnplayr 446
        invoke  con_write_asciiz, eax
447
        invoke  con_write_asciiz, str_newline
448
449
        sendFTP "250 Command succesful"
450
 
451
452
  .err:
453
 
454
        ret
455
456
;------------------------------------------------
457
 
458
;
459
; Delete a file from the server.
460
;
461
;------------------------------------------------
462
align 4
463
cmdDELE:
464
465
        test    [ebp + thread_data.permissions], PERMISSION_DELETE
466
 
467
468
        ; Create path
469
 
9916 Doczom 470
        jae     .err
471
472
        sub     ecx, 5
473
 
474
475
        call    create_path
476
 
477
        lea     esi, [ebp + thread_data.buffer + 5]
478
        mov     ecx, 1024
479
        cmp     byte [esi], '/'
480
        jne     .loop
481
        inc     esi
482
  .loop:
483
        lodsb
484
        cmp     al, 0x20
485
        jl      .done
486
        stosb
487
        loop    .loop
488
  .done:
489
        xor     al, al
490
        stosb
491
492
        lea     ebx, [ebp + thread_data.fpath]
493
 
494
        invoke  con_write_asciiz, str_newline
495
        ; called fs function
496
        push    ebx
497
        dec     esp
498
        mov     byte[esp], 0
499
        push    dword 0
500
        push    dword 0
501
        push    dword 0
502
        push    dword 0
503
        push    dword 8
504
        mov     ebx, esp
505
        mcall   70
506
        add     esp, 6*4 + 1
507
508
        test    eax, eax
509
 
510
511
        sendFTP "250 Command succesful"
512
 
513
.err:
3545 hidnplayr 514
        sendFTP "550 No such file"
9916 Doczom 515
        ret
516
517
;------------------------------------------------
3545 hidnplayr 518
 
519
;
520
; List the files in the current working directory.
521
;
522
;------------------------------------------------
523
align 4
524
cmdLIST:
525
526
        test    [ebp + thread_data.permissions], PERMISSION_EXEC
527
 
528
529
        call    open_datasock
530
 
531
; Create fpath from home_dir and work_dir
532
 
533
534
        lea     ebx, [ebp + thread_data.fpath]
535
 
536
        invoke  con_write_asciiz, str_newline
537
538
; Start the search
539
 
540
        test    eax, eax
541
        jz      .nosuchdir
542
543
        lea     edi, [ebp + thread_data.buffer]
544
 
545
        test    eax, eax        ; did we find a file?
546
        jz      .done
547
        mov     ebx, eax        ; yes, save the descripter in ebx
548
549
; first, convert the attributes
550
 
551
        jnz     .folder
552
553
        test    [ebx + FileInfoA.Attributes], FA_READONLY
554
 
555
556
        mov     eax, '-rw-'
557
 
558
        jmp     .attr
559
560
  .folder:
561
 
562
        stosd
563
        jmp     .attr
564
565
  .readonly:
566
 
567
        stosd
568
569
  .attr:
570
 
571
        stosd
572
        mov     ax, 'w-'
573
        stosw
574
        mov     al, ' '
575
        stosb
576
577
; now..
578
 
579
        stosw
580
581
; now write owner, everything is owned by FTP, woohoo!
582
 
583
        stosd
584
        stosd
585
586
; now the filesize in ascii
587
 
588
        call    dword_to_ascii
3618 hidnplayr 589
        mov     al, ' '
3545 hidnplayr 590
        stosb
591
592
; then date (month/day/year)
593
 
594
        cmp     eax, 12
3618 hidnplayr 595
        ja      @f
3545 hidnplayr 596
        mov     eax, [months - 4 + 4*eax]
597
        stosd
598
       @@:
599
600
        movzx   eax, [ebx + FileInfoA.DateModify.day]
601
 
3618 hidnplayr 602
        mov     al, ' '
3545 hidnplayr 603
        stosb
604
605
        movzx   eax, [ebx + FileInfoA.DateModify.year]
606
 
3618 hidnplayr 607
        mov     al, ' '
3545 hidnplayr 608
        stosb
609
610
; and last but not least, filename
611
 
612
        mov     ecx, 264
613
  .nameloop:
614
        lodsb
615
        test    al, al
616
        jz      .namedone
617
        stosb
618
        loop    .nameloop
619
620
; insert a cr lf
621
 
622
        mov     ax, 0x0a0d
623
        stosw
624
625
        test    [ebp + thread_data.permissions], ABORT          ; Did we receive ABOR command from client?
626
 
627
628
; check next file
629
 
630
        jmp     .parse_file
631
632
; close file desc
633
 
634
        invoke  file.find.close, ebx                            ; ebx is descriptor of last file, eax will be -1 !!
635
636
; append the string with a 0
637
 
638
        stosb
639
640
; Warn the client we're about to send the data
641
 
642
        sendFTP "150 Here it comes.."
643
        pop     esi
644
645
; and send it to the client
646
 
647
        lea     edx, [ebp + thread_data.buffer]                 ; buffer ptr
648
        sub     esi, edx                                        ; length
649
        xor     edi, edi                                        ; flags
650
        mcall   send
651
652
; close the data socket..
653
 
654
        mcall   close, [ebp + thread_data.datasocketnum]
655
656
        sendFTP "226 List OK"
657
 
3824 hidnplayr 658
3545 hidnplayr 659
  .nosuchdir:
660
 
661
        ret
662
663
;------------------------------------------------
664
 
665
;
666
; List the filenames of the files in the current working directory.
667
;
668
;------------------------------------------------
669
align 4
670
cmdNLST:
671
672
        test    [ebp + thread_data.permissions], PERMISSION_EXEC
673
 
674
675
        ; TODO: same as list but simpler output format
676
 
677
        ret
678
 
679
;------------------------------------------------
680
 
681
;
682
; No operation, just keep the connection alive.
683
;
684
;------------------------------------------------
685
align 4
686
cmdNOOP:
687
688
        sendFTP "200 Command OK"
689
 
690
691
;------------------------------------------------
692
 
693
;
694
; Second phase of login process, client provides password.
695
;
696
;------------------------------------------------
697
align 4
698
cmdPASS:
699
700
; read the password from users.ini
701
 
702
        lea     ebx, [ebp + thread_data.fpath]                  ; temp username
703
        invoke  ini.get_str, path2, ebx, str_pass, edi, 512, str_infinity
704
        test    eax, eax                                        ; unable to read password? fail!
705
        jnz     .incorrect
706
        cmp     dword [edi], -1                                 ; no key, section or file found.. fail!
707
        je      .incorrect
708
        cmp     byte [edi], 0                                   ; zero password? ok!
709
        je      .ok
710
711
        add     esi, 5
712
 
713
        jbe     .incorrect                                      ; no password given? but hey, we need one! fail..
714
715
; compare with received password
716
 
717
        cmp     byte [esi-1], 0x20                              ; printeable characters left?
718
        jae     .incorrect
719
        cmp     byte [edi-1], 0
720
        jne     .incorrect
721
722
  .ok:
723
 
724
        mov     [ebp + thread_data.permissions], eax
725
726
        invoke  con_write_asciiz, str_pass_ok
727
 
728
        sendFTP "230 You are now logged in"
729
        ret
730
731
  .2:
732
 
733
        invoke  con_write_asciiz, str_pass_err
734
        mov     [ebp + thread_data.state], STATE_CONNECTED      ; reset state
735
        sendFTP "530 Login incorrect"
736
        ret
737
738
  .0:
739
 
740
        ret
741
742
  .3:
743
 
744
        ret
745
746
;------------------------------------------------
747
 
748
;
749
; Initiate a passive dataconnection.
750
;
751
;------------------------------------------------
752
align 4
753
cmdPASV:
754
755
;        cmp     [ebp + thread_data.passivesocknum], -1
756
 
757
;        mcall   close, [ebp + thread_data.passivesocknum]       ; if there is still a socket open, close it
758
;       @@:
759
760
; Open a new TCP socket
761
 
762
        cmp     eax, -1
763
        je      socketerror
764
        mov     [ebp + thread_data.passivesocknum], eax
765
766
; Bind it to a known local port
767
 
768
        mov     [ebp + thread_data.datasock.sin_addr], 0
769
770
        mov     ecx, eax                                        ; passivesocketnum
771
 
772
        mov     esi, sizeof.thread_data.datasock
773
774
  .next_port:                                                   ; TODO: break the endless loop
775
 
776
        mov     ax, [pasv_port]
777
        xchg    al, ah
778
        mov     [ebp + thread_data.datasock.sin_port], ax
779
780
        mcall   bind
781
 
782
        je      .next_port
783
784
; And set it to listen!
785
 
786
        cmp     eax, -1
787
        je      socketerror
788
789
; Tell our thread we are ready to accept incoming calls
790
 
791
792
; Now tell the client where to connect to in this format:
793
 
794
; where a1.a2.a3.a4 is the IP address and p1*256+p2 is the port number.
795
796
; '227 Entering passive mode ('
797
 
3819 hidnplayr 798
        mov     ecx, str_227.length
3545 hidnplayr 799
        mov     esi, str_227
3819 hidnplayr 800
        rep movsb
801
; ip
802
        movzx   eax, byte [serverip]
3545 hidnplayr 803
        call    dword_to_ascii
804
        mov     al, ','
805
        stosb
806
        movzx   eax, byte [serverip+1]
807
        call    dword_to_ascii
808
        mov     al, ','
809
        stosb
810
        movzx   eax, byte [serverip+2]
811
        call    dword_to_ascii
812
        mov     al, ','
813
        stosb
814
        movzx   eax, byte [serverip+3]
815
        call    dword_to_ascii
816
        mov     al, ','
817
        stosb
818
; port
819
        movzx   eax, byte [ebp + thread_data.datasock.sin_port]
820
        call    dword_to_ascii
821
        mov     al, ','
822
        stosb
823
        movzx   eax, byte [ebp + thread_data.datasock.sin_port+1]
824
        call    dword_to_ascii
825
; ')', 13, 10, 0
826
        mov     eax, ')' + (0x000a0d shl 8)
827
        stosd
3819 hidnplayr 828
3545 hidnplayr 829
        lea     esi, [edi - thread_data.buffer - 1]      ; calculate length, do not cound the trailing 0 byte
830
 
3824 hidnplayr 831
        mov     ecx, [ebp + thread_data.socketnum]
3545 hidnplayr 832
        lea     edx, [ebp + thread_data.buffer]
833
        xor     edi, edi
834
        mcall   send
835
836
        invoke  con_write_asciiz, edx
837
 
3824 hidnplayr 838
        ret
839
 
3545 hidnplayr 840
841
 
3819 hidnplayr 842
 
843
        .length = $ - str_227
844
endg
845
846
;------------------------------------------------
847
 
3545 hidnplayr 848
;
849
; Print the current working directory.
850
;
851
;------------------------------------------------
852
align 4
853
cmdPWD:
854
855
        mov     dword [ebp + thread_data.buffer], '257 '
856
 
857
858
        lea     edi, [ebp + thread_data.buffer+5]
859
 
860
        mov     ecx, 1024
861
  .loop:
862
        lodsb
863
        or      al, al
864
        jz      .ok
865
        stosb
866
        dec     ecx
867
        jnz     .loop
868
869
  .ok:
870
 
871
        lea     esi, [edi - thread_data.buffer + 3]
872
        sub     esi, ebp
3824 hidnplayr 873
        mov     ecx, [ebp + thread_data.socketnum]
3545 hidnplayr 874
        lea     edx, [ebp + thread_data.buffer]
875
        xor     edi, edi
876
        mcall   send
877
878
; Print the new working dir on the console
879
 
880
        invoke  con_write_asciiz, eax
881
        invoke  con_write_asciiz, str_newline
882
883
        ret
884
 
885
;------------------------------------------------
886
 
887
;
888
; Initiate an active dataconnection.
889
;
890
;------------------------------------------------
891
align 4
892
cmdPORT:
893
894
; PORT a1,a2,a3,a4,p1,p2
895
 
896
897
; Convert the IP
898
 
899
        mov     cl, ','
900
        call    ip_to_dword
901
; And put it in datasock
902
        mov     [ebp + thread_data.datasock.sin_addr], ebx
903
904
; Now the same with portnumber
905
 
906
        call    ascii_to_byte
907
        mov     byte[ebp + thread_data.datasock.sin_port], al
908
        inc     esi
909
        call    ascii_to_byte
910
        mov     byte[ebp + thread_data.datasock.sin_port+1], al
911
912
; We will open the socket, but do not connect yet!
913
 
914
        mcall   socket, AF_INET4, SOCK_STREAM, 0
915
        cmp     eax, -1
916
        je      socketerror
917
918
        mov     [ebp + thread_data.datasocketnum], eax
919
 
920
921
        sendFTP "225 Data connection open"
922
 
923
924
;------------------------------------------------
925
 
926
;
927
; Close the connection with client.
928
;
929
;------------------------------------------------
930
align 4
931
cmdQUIT:
932
933
        sendFTP "221 Bye!"
934
 
935
        mcall   close, [ebp + thread_data.socketnum]
936
937
        add     esp, 4          ; get rid of call return address
938
 
939
940
941
 
942
 
943
;
944
; Retrieve a file from the ftp server.
945
;
946
;------------------------------------------------
947
align 4
948
cmdRETR:
949
950
        test    [ebp + thread_data.permissions], PERMISSION_READ
951
 
952
953
        cmp     ecx, 1024 + 5
954
 
955
956
        sub     ecx, 5
957
 
958
959
        call    open_datasock
960
 
961
        call    create_path
962
 
963
        lea     esi, [ebp + thread_data.buffer + 5]
964
        mov     ecx, 1024
965
        cmp     byte [esi], '/'
966
        jne     .loop
967
        inc     esi
968
  .loop:
969
        lodsb
970
        cmp     al, 0x20
971
        jl      .done
972
        stosb
973
        loop    .loop
974
  .done:
975
        xor     al, al
976
        stosb
977
978
        lea     ebx, [ebp + thread_data.fpath]
979
 
980
        invoke  con_write_asciiz, str_newline
981
982
        invoke  file.open, ebx, O_READ
983
 
984
        jz      .cannot_open
985
986
        push    eax
987
 
988
        pop     ebx
989
990
  .read_more:
991
 
992
        jnz     abort_transfer
993
994
        lea     eax, [ebp + thread_data.buffer]                 ; FIXME: use another buffer!! if we receive something on control connection now, we screw up!
995
 
996
        cmp     eax, -1
997
        je      .cannot_open                                    ; FIXME: this is not the correct error
998
999
        invoke  con_write_asciiz, str2
1000
 
1001
        push    eax ebx
1002
 
1003
        mov     ecx, [ebp + thread_data.datasocketnum]
1004
        lea     edx, [ebp + thread_data.buffer]
1005
        xor     edi, edi
1006
        mcall   send
1007
        pop     ebx ecx
1008
        cmp     eax, -1
1009
        je      socketerror                                     ; FIXME: not the correct error
1010
1011
;        cmp     eax, ecx
1012
 
1013
1014
        cmp     ecx, BUFFERSIZE
1015
 
1016
1017
        invoke  file.close, ebx
1018
 
1019
        invoke  con_write_asciiz, str2b
1020
 
1021
        mov     [ebp + thread_data.mode], MODE_NOTREADY
1022
 
1023
1024
        sendFTP "226 Transfer OK, closing connection"
1025
 
1026
1027
  .cannot_open:
1028
 
1029
        invoke  con_write_asciiz, str_notfound
1030
        invoke  con_set_flags, 0x07
1031
1032
        sendFTP "550 No such file"
1033
 
1034
1035
1036
 
1037
 
1038
 
1039
;
1040
; Store a file on the server.
1041
;
1042
;------------------------------------------------
1043
align 4
1044
cmdSTOR:
1045
1046
        test    [ebp + thread_data.permissions], PERMISSION_WRITE
1047
 
1048
1049
        ;sendFTP " Ready to receive"
1050
 
9916 Doczom 1051
        cmp     ecx, 1024 + 5
1052
        jae     .cannot_open
1053
1054
        sub     ecx, 5
3545 hidnplayr 1055
 
9916 Doczom 1056
1057
        call    open_datasock
3824 hidnplayr 1058
 
9916 Doczom 1059
        ; creat path
3824 hidnplayr 1060
 
9916 Doczom 1061
        dec     edi
1062
        lea     esi, [ebp + thread_data.buffer + 5]
1063
        mov     ecx, 1024
1064
        cmp     byte [esi], '/'
1065
        jne     .loop
1066
        inc     esi
1067
  .loop:
1068
        lodsb
1069
        cmp     al, 0x20
1070
        jl      .done
1071
        stosb
1072
        loop    .loop
1073
  .done:
1074
        xor     al, al
1075
        stosb
1076
1077
        lea     ebx, [ebp + thread_data.fpath]
1078
 
1079
        invoke  con_write_asciiz, str_newline
1080
1081
        ; open file
1082
 
1083
        test    eax, eax
1084
        jz      .cannot_open
1085
1086
        push    eax
1087
 
1088
        pop     ebx
1089
1090
  .write_more:
1091
 
1092
        jnz     abort_transfer
3545 hidnplayr 1093
1094
        push    eax ebx
1095
 
9916 Doczom 1096
        mov     ecx, [ebp + thread_data.datasocketnum]
1097
        lea     edx, [ebp + thread_data.buffer]
1098
        xor     edi, edi
1099
        mcall   recv
1100
        pop     ebx ecx
1101
        cmp     eax, -1
1102
        je      socketerror                                     ; FIXME: not the correct error
1103
1104
        test    eax, eax
1105
 
1106
1107
        push    edx
1108
 
1109
        lea     eax, [ebp + thread_data.buffer]                 ; FIXME: use another buffer!! if we receive something on control connection now, we screw up!
1110
        invoke  file.write, ebx, eax, edx
1111
        pop     edx
1112
1113
        cmp     eax, -1
1114
 
1115
1116
        invoke  con_write_asciiz, str2
1117
 
1118
;        cmp     eax, ecx
1119
 
1120
1121
        ;cmp     ecx, BUFFERSIZE
1122
 
1123
        jmp      .write_more
1124
@@:
1125
1126
        invoke  file.close, ebx
1127
 
1128
        invoke  con_write_asciiz, str2b
1129
 
1130
        mov     [ebp + thread_data.mode], MODE_NOTREADY
1131
 
1132
1133
1134
 
1135
 
1136
 
1137
;        test    [ebp + thread_data.permissions], ABORT
1138
;        jnz     abort_transfer
1139
;
1140
;;;;
1141
3545 hidnplayr 1142
        sendFTP "226 Transfer OK"
1143
 
3824 hidnplayr 1144
9916 Doczom 1145
.cannot_open:
3824 hidnplayr 1146
 
9916 Doczom 1147
        ret
1148
3545 hidnplayr 1149
;------------------------------------------------
1150
 
1151
;
1152
; Send information about the system.
1153
;
1154
;------------------------------------------------
1155
align 4
1156
cmdSYST:
1157
1158
        sendFTP "215 UNIX type: L8"
1159
 
1160
1161
;------------------------------------------------
1162
 
1163
;
1164
; Choose the file transfer type.
1165
;
1166
;------------------------------------------------
1167
align 4
1168
cmdTYPE:
1169
1170
        cmp     ecx, 6
1171
 
1172
1173
        mov     al, byte[esi+5]
1174
 
1175
1176
        cmp     al, 'A'
1177
 
1178
        cmp     al, 'E'
1179
        je      .ebdic
1180
        cmp     al, 'I'
1181
        je      .image
1182
        cmp     al, 'L'
1183
        je      .local
1184
1185
        jmp     parse_cmd.error
1186
 
1187
  .ascii:
1188
 
1189
        jmp     .subtype
1190
1191
  .ebdic:
1192
 
1193
1194
  .subtype:
1195
 
1196
        jb      .non_print
1197
1198
        mov     al, byte[esi+7]
1199
 
1200
1201
        cmp     al, 'N'
1202
 
1203
        cmp     al, 'T'
1204
        je      .telnet
1205
        cmp     al, 'C'
1206
        je      .asacc
1207
        cmp     al, 0x20
1208
        jb      .non_print
1209
1210
        jmp     parse_cmd.error
1211
 
1212
  .non_print:
1213
 
1214
        jmp     .ok
1215
1216
  .telnet:
1217
 
1218
        jmp     .ok
1219
1220
  .asacc:
1221
 
1222
        jmp     .ok
1223
1224
  .image:
1225
 
1226
        jmp     .ok
1227
1228
  .local:
1229
 
1230
        jb      parse_cmd.error
1231
1232
        mov     al, byte[esi+7]
1233
 
1234
        jb      parse_cmd.error                         ; FIXME: this is not the correct errormessage
1235
        cmp     al, 9
1236
        ja      parse_cmd.error                         ; FIXME
1237
        or      al, TYPE_LOCAL
1238
        mov     [ebp + thread_data.type], al
1239
1240
  .ok:
1241
 
1242
        ret
1243
1244
;------------------------------------------------
1245
 
1246
;
1247
; Login to the server, step one of two.                         ;;; TODO: prevent buffer overflow!
1248
;
1249
;------------------------------------------------
1250
align 4
1251
cmdUSER:
1252
1253
        lea     esi, [esi + 5]
1254
 
1255
  .loop:
1256
        lodsb
1257
        stosb
1258
        cmp     al, 0x20
1259
        jae     .loop
1260
        mov     byte [edi-1], 0
1261
1262
        lea     esi, [ebp + thread_data.fpath]
1263
 
1264
        invoke  ini.get_str, path2, esi, str_home, eax, 1024, str_infinity
1265
        cmp     eax, -1
1266
        je      .login_fail
1267
        cmp     dword [esi], -1
1268
        je      .login_fail
1269
1270
        mov     word [ebp + thread_data.work_dir], "/"          ; "/", 0
1271
 
1272
        invoke  con_write_asciiz, str_logged_in
1273
 
1274
  .sendstr:
1275
        sendFTP "331 Please specify the password"
1276
        ret
1277
1278
  .login_fail:
1279
 
1280
        mov     [ebp + thread_data.state], STATE_LOGIN_FAIL
1281
        jmp     .sendstr
1282
1283
align 4
1284
 
1285
        sendFTP "530 Can't change to another user"
1286
        ret
1287