Subversion Repositories Kolibri OS

Rev

Rev 3545 | Rev 3819 | Go to most recent revision | 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
93
        dd 'PASS', cmdPASS.0,   cmdPASS    , cmdPASS.2,   cmdPASS.3
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
286
; If we are in active mode, it's time to open a data socket..
287
 
288
        jne     .not_active
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
        jne     .start
295
296
  .socketerror:
297
 
298
        jmp     socketerror
299
300
; If we are still in passive_wait, it's time we accept an incomming call..
301
 
302
        cmp     [ebp + thread_data.mode], MODE_PASSIVE_WAIT
303
        jne     .socketerror
304
305
  .try_now:
306
 
307
        lea     edx, [ebp + thread_data.datasock]
308
        mov     esi, sizeof.thread_data.datasock
309
        mcall   accept
310
        cmp     eax, -1
311
        jne     .pasv_ok
312
        mov     [ebp + thread_data.mode], MODE_PASSIVE_FAILED                   ; assume that we will fail
313
        mcall   23, 200
314
        mcall   accept
315
        cmp     eax, -1
316
        je      .socketerror
317
  .pasv_ok:
318
        mov     [ebp + thread_data.datasocketnum], eax
319
        mov     [ebp + thread_data.mode], MODE_PASSIVE_OK
320
        mcall   close   ; [ebp + thread_data.passivesocknum]
321
        mov     [ebp + thread_data.passivesocknum], -1
322
        invoke  con_write_asciiz, str_datasock
323
324
  .start:
325
 
326
327
328
 
329
 
330
;
331
; This command aborts the current filetransfer.
332
;
333
;------------------------------------------------
334
align 4
335
cmdABOR:
336
337
        or      [ebp + thread_data.permissions], ABORT
338
 
339
        ret
340
341
;------------------------------------------------
342
 
343
;
344
; Change the directory to move up one level.
345
;
346
;------------------------------------------------
347
align 4
348
cmdCDUP:
349
350
        test    [ebp + thread_data.permissions], PERMISSION_CD
351
 
352
353
        cmp     byte [ebp + thread_data.work_dir+1], 0  ; are we in "/" ?
354
 
355
356
; find the end of asciiz string work_dir
357
 
358
        xor     al, al
359
        lea     edi, [ebp + thread_data.work_dir]
360
        repne   scasb
361
; return 2 characters (right before last /)
362
        sub     edi, 3
363
; and now search backwards, for a '/'
364
        mov     al,'/'
365
        neg     ecx
366
        add     ecx, 1024
367
        std
368
        repne   scasb
369
        cld
370
; terminate the string here
371
        mov     byte[edi+2], 0
372
373
  .done:
374
 
375
        lea     eax, [ebp + thread_data.work_dir]
376
        invoke  con_write_asciiz, eax
377
        invoke  con_write_asciiz, str_newline
378
379
        sendFTP "250 Command succesul"
380
 
381
382
;------------------------------------------------
383
 
384
;
385
; Change Working Directory.
386
;
387
;------------------------------------------------
388
align 4
389
cmdCWD:
390
391
        test    [ebp + thread_data.permissions], PERMISSION_CD
392
 
393
394
; do we have enough parameters?
395
 
396
        jbe     .err
397
398
; get ready to copy the path
399
 
400
        mov     ecx, 1024
401
        lea     edi, [ebp + thread_data.work_dir]
402
403
; if received dir starts with '/', we will simply copy it
404
 
405
        cmp     byte [esi], '/'
406
        je      .copyloop
407
408
; Find the end of work_dir string.
409
 
410
  .find_zero:
411
        repne   scasb
412
        dec     edi
413
414
; and now append work_dir with received string
415
 
416
417
; scan for end byte, or '.'
418
 
419
        lodsb
420
        cmp     al, 0x20
421
        jb      .done
422
;;;        cmp     al, '.'         ; '..' means we must go up one dir   TODO
423
;;;        je      .up
424
        stosb
425
        loop    .copyloop
426
427
; now, now make sure it ends with '/', 0
428
 
429
        cmp     byte [edi-1], '/'
430
        je      @f
431
        mov     byte [edi], '/'
432
        inc     edi
433
       @@:
434
        mov     byte [edi], 0
435
436
; Print the new working dir on the console
437
 
438
        invoke  con_write_asciiz, eax
439
        invoke  con_write_asciiz, str_newline
440
441
        sendFTP "250 Command succesful"
442
 
443
444
  .err:
445
 
446
        ret
447
448
;------------------------------------------------
449
 
450
;
451
; Delete a file from the server.
452
;
453
;------------------------------------------------
454
align 4
455
cmdDELE:
456
457
        test    [ebp + thread_data.permissions], PERMISSION_DELETE
458
 
459
460
        ret
461
 
462
;------------------------------------------------
463
 
464
;
465
; List the files in the current working directory.
466
;
467
;------------------------------------------------
468
align 4
469
cmdLIST:
470
471
        test    [ebp + thread_data.permissions], PERMISSION_EXEC
472
 
473
474
        call    open_datasock
475
 
476
; Create fpath from home_dir and work_dir
477
 
478
479
        lea     ebx, [ebp + thread_data.fpath]
480
 
481
        invoke  con_write_asciiz, str_newline
482
483
; Start the search
484
 
485
        test    eax, eax
486
        jz      .nosuchdir
487
488
        lea     edi, [ebp + thread_data.buffer]
489
 
490
        test    eax, eax        ; did we find a file?
491
        jz      .done
492
        mov     ebx, eax        ; yes, save the descripter in ebx
493
494
; first, convert the attributes
495
 
496
        jnz     .folder
497
498
        test    [ebx + FileInfoA.Attributes], FA_READONLY
499
 
500
501
        mov     eax, '-rw-'
502
 
503
        jmp     .attr
504
505
  .folder:
506
 
507
        stosd
508
        jmp     .attr
509
510
  .readonly:
511
 
512
        stosd
513
514
  .attr:
515
 
516
        stosd
517
        mov     ax, 'w-'
518
        stosw
519
        mov     al, ' '
520
        stosb
521
522
; now..
523
 
524
        stosw
525
526
; now write owner, everything is owned by FTP, woohoo!
527
 
528
        stosd
529
        stosd
530
531
; now the filesize in ascii
532
 
533
        call    dword_to_ascii
3618 hidnplayr 534
        mov     al, ' '
3545 hidnplayr 535
        stosb
536
537
; then date (month/day/year)
538
 
539
        cmp     eax, 12
3618 hidnplayr 540
        ja      @f
3545 hidnplayr 541
        mov     eax, [months - 4 + 4*eax]
542
        stosd
543
       @@:
544
545
        movzx   eax, [ebx + FileInfoA.DateModify.day]
546
 
3618 hidnplayr 547
        mov     al, ' '
3545 hidnplayr 548
        stosb
549
550
        movzx   eax, [ebx + FileInfoA.DateModify.year]
551
 
3618 hidnplayr 552
        mov     al, ' '
3545 hidnplayr 553
        stosb
554
555
; and last but not least, filename
556
 
557
        mov     ecx, 264
558
  .nameloop:
559
        lodsb
560
        test    al, al
561
        jz      .namedone
562
        stosb
563
        loop    .nameloop
564
565
; insert a cr lf
566
 
567
        mov     ax, 0x0a0d
568
        stosw
569
570
        test    [ebp + thread_data.permissions], ABORT          ; Did we receive ABOR command from client?
571
 
572
573
; check next file
574
 
575
        jmp     .parse_file
576
577
; close file desc
578
 
579
        invoke  file.find.close, ebx                            ; ebx is descriptor of last file, eax will be -1 !!
580
581
; append the string with a 0
582
 
583
        stosb
584
585
; Warn the client we're about to send the data
586
 
587
        sendFTP "150 Here it comes.."
588
        pop     esi
589
590
; and send it to the client
591
 
592
        lea     edx, [ebp + thread_data.buffer]                 ; buffer ptr
593
        sub     esi, edx                                        ; length
594
        xor     edi, edi                                        ; flags
595
        mcall   send
596
597
; close the data socket..
598
 
599
        mcall   close, [ebp + thread_data.datasocketnum]
600
601
        sendFTP "226 Transfer OK"
602
 
603
604
  .nosuchdir:
605
 
606
        ret
607
608
;------------------------------------------------
609
 
610
;
611
; List the filenames of the files in the current working directory.
612
;
613
;------------------------------------------------
614
align 4
615
cmdNLST:
616
617
        test    [ebp + thread_data.permissions], PERMISSION_EXEC
618
 
619
620
        ; TODO: same as list but simpler output format
621
 
622
        ret
623
 
624
;------------------------------------------------
625
 
626
;
627
; No operation, just keep the connection alive.
628
;
629
;------------------------------------------------
630
align 4
631
cmdNOOP:
632
633
        sendFTP "200 Command OK"
634
 
635
636
;------------------------------------------------
637
 
638
;
639
; Second phase of login process, client provides password.
640
;
641
;------------------------------------------------
642
align 4
643
cmdPASS:
644
645
; read the password from users.ini
646
 
647
        lea     ebx, [ebp + thread_data.fpath]                  ; temp username
648
        invoke  ini.get_str, path2, ebx, str_pass, edi, 512, str_infinity
649
        test    eax, eax                                        ; unable to read password? fail!
650
        jnz     .incorrect
651
        cmp     dword [edi], -1                                 ; no key, section or file found.. fail!
652
        je      .incorrect
653
        cmp     byte [edi], 0                                   ; zero password? ok!
654
        je      .ok
655
656
        add     esi, 5
657
 
658
        jbe     .incorrect                                      ; no password given? but hey, we need one! fail..
659
660
; compare with received password
661
 
662
        cmp     byte [esi-1], 0x20                              ; printeable characters left?
663
        jae     .incorrect
664
        cmp     byte [edi-1], 0
665
        jne     .incorrect
666
667
  .ok:
668
 
669
        mov     [ebp + thread_data.permissions], eax
670
671
        invoke  con_write_asciiz, str_pass_ok
672
 
673
        sendFTP "230 You are now logged in"
674
        ret
675
676
  .2:
677
 
678
        invoke  con_write_asciiz, str_pass_err
679
        mov     [ebp + thread_data.state], STATE_CONNECTED      ; reset state
680
        sendFTP "530 Login incorrect"
681
        ret
682
683
  .0:
684
 
685
        ret
686
687
  .3:
688
 
689
        ret
690
691
;------------------------------------------------
692
 
693
;
694
; Initiate a passive dataconnection.
695
;
696
;------------------------------------------------
697
align 4
698
cmdPASV:
699
700
;        cmp     [ebp + thread_data.passivesocknum], -1
701
 
702
;        mcall   close, [ebp + thread_data.passivesocknum]       ; if there is still a socket open, close it
703
;       @@:
704
705
; Open a new TCP socket
706
 
707
        cmp     eax, -1
708
        je      socketerror
709
        mov     [ebp + thread_data.passivesocknum], eax
710
711
; Bind it to a known local port
712
 
713
        mov     [ebp + thread_data.datasock.sin_addr], 0
714
715
        mov     ecx, eax                                        ; passivesocketnum
716
 
717
        mov     esi, sizeof.thread_data.datasock
718
719
  .next_port:                                                   ; TODO: break the endless loop
720
 
721
        mov     ax, [pasv_port]
722
        xchg    al, ah
723
        mov     [ebp + thread_data.datasock.sin_port], ax
724
725
        mcall   bind
726
 
727
        je      .next_port
728
729
; And set it to listen!
730
 
731
        cmp     eax, -1
732
        je      socketerror
733
734
; Tell our thread we are ready to accept incoming calls
735
 
736
737
; Now tell the client where to connect to in this format:
738
 
739
; where a1.a2.a3.a4 is the IP address and p1*256+p2 is the port number.
740
741
; '227 ('
742
 
743
        mov     eax, '227 '
744
        stosd
745
        mov     al, '('
746
        stosb
747
; ip
748
        movzx   eax, byte [serverip]
749
        call    dword_to_ascii
750
        mov     al, ','
751
        stosb
752
        movzx   eax, byte [serverip+1]
753
        call    dword_to_ascii
754
        mov     al, ','
755
        stosb
756
        movzx   eax, byte [serverip+2]
757
        call    dword_to_ascii
758
        mov     al, ','
759
        stosb
760
        movzx   eax, byte [serverip+3]
761
        call    dword_to_ascii
762
        mov     al, ','
763
        stosb
764
; port
765
        movzx   eax, byte [ebp + thread_data.datasock.sin_port]
766
        call    dword_to_ascii
767
        mov     al, ','
768
        stosb
769
        movzx   eax, byte [ebp + thread_data.datasock.sin_port+1]
770
        call    dword_to_ascii
771
; ')', 13, 10, 0
772
        mov     eax, ')' + 0x000a0d00
773
        stosd
774
775
        lea     esi, [edi - thread_data.buffer]
776
 
777
        mov     ecx, [ebp + thread_data.socketnum]
778
        lea     edx, [ebp + thread_data.buffer]
779
        xor     edi, edi
780
        mcall   send
781
782
        ret
783
 
784
;------------------------------------------------
785
 
786
;
787
; Print the current working directory.
788
;
789
;------------------------------------------------
790
align 4
791
cmdPWD:
792
793
        mov     dword [ebp + thread_data.buffer], '257 '
794
 
795
796
        lea     edi, [ebp + thread_data.buffer+5]
797
 
798
        mov     ecx, 1024
799
  .loop:
800
        lodsb
801
        or      al, al
802
        jz      .ok
803
        stosb
804
        dec     ecx
805
        jnz     .loop
806
807
  .ok:
808
 
809
        lea     esi, [edi - thread_data.buffer + 4]
810
        sub     esi, ebp
811
        mov     ecx, [ebp + thread_data.socketnum]
812
        lea     edx, [ebp + thread_data.buffer]
813
        xor     edi, edi
814
        mcall   send
815
816
; Print the new working dir on the console
817
 
818
        invoke  con_write_asciiz, eax
819
        invoke  con_write_asciiz, str_newline
820
821
        ret
822
 
823
;------------------------------------------------
824
 
825
;
826
; Initiate an active dataconnection.
827
;
828
;------------------------------------------------
829
align 4
830
cmdPORT:
831
832
; PORT a1,a2,a3,a4,p1,p2
833
 
834
835
; Convert the IP
836
 
837
        mov     cl, ','
838
        call    ip_to_dword
839
; And put it in datasock
840
        mov     [ebp + thread_data.datasock.sin_addr], ebx
841
842
; Now the same with portnumber
843
 
844
        call    ascii_to_byte
845
        mov     byte[ebp + thread_data.datasock.sin_port], al
846
        inc     esi
847
        call    ascii_to_byte
848
        mov     byte[ebp + thread_data.datasock.sin_port+1], al
849
850
; We will open the socket, but do not connect yet!
851
 
852
        mcall   socket, AF_INET4, SOCK_STREAM, 0
853
        cmp     eax, -1
854
        je      socketerror
855
856
        mov     [ebp + thread_data.datasocketnum], eax
857
 
858
859
        sendFTP "225 Data connection open"
860
 
861
862
;------------------------------------------------
863
 
864
;
865
; Close the connection with client.
866
;
867
;------------------------------------------------
868
align 4
869
cmdQUIT:
870
871
        sendFTP "221 Bye!"
872
 
873
        mcall   close, [ebp + thread_data.socketnum]
874
875
        add     esp, 4          ; get rid of call return address
876
 
877
878
879
 
880
 
881
;
882
; Retrieve a file from the ftp server.
883
;
884
;------------------------------------------------
885
align 4
886
cmdRETR:
887
888
        test    [ebp + thread_data.permissions], PERMISSION_READ
889
 
890
891
        cmp     ecx, 1024 + 5
892
 
893
894
        sub     ecx, 5
895
 
896
897
        call    open_datasock
898
 
899
        call    create_path
900
 
901
        lea     esi, [ebp + thread_data.buffer + 5]
902
        mov     ecx, 1024
903
        cmp     byte [esi], '/'
904
        jne     .loop
905
        inc     esi
906
  .loop:
907
        lodsb
908
        cmp     al, 0x20
909
        jl      .done
910
        stosb
911
        loop    .loop
912
  .done:
913
        xor     al, al
914
        stosb
915
916
        lea     ebx, [ebp + thread_data.fpath]
917
 
918
        invoke  con_write_asciiz, str_newline
919
920
        invoke  file.open, ebx, O_READ
921
 
922
        jz      .cannot_open
923
924
        push    eax
925
 
926
        pop     ebx
927
928
  .read_more:
929
 
930
        jnz     abort_transfer
931
932
        lea     eax, [ebp + thread_data.buffer]                 ; FIXME: use another buffer!! if we receive something on control connection now, we screw up!
933
 
934
        cmp     eax, -1
935
        je      .cannot_open                                    ; FIXME: this is not the correct error
936
937
        invoke  con_write_asciiz, str2
938
 
939
        push    eax ebx
940
 
941
        mov     ecx, [ebp + thread_data.datasocketnum]
942
        lea     edx, [ebp + thread_data.buffer]
943
        xor     edi, edi
944
        mcall   send
945
        pop     ebx ecx
946
        cmp     eax, -1
947
        je      socketerror                                     ; FIXME: not the correct error
948
949
;        cmp     eax, ecx
950
 
951
952
        cmp     ecx, BUFFERSIZE
953
 
954
955
        invoke  file.close, ebx
956
 
957
        invoke  con_write_asciiz, str2b
958
 
959
        mov     [ebp + thread_data.mode], MODE_NOTREADY
960
 
961
962
        sendFTP "226 Transfer OK, closing connection"
963
 
964
965
  .cannot_open:
966
 
967
        invoke  con_write_asciiz, str_notfound
968
        invoke  con_set_flags, 0x07
969
970
        sendFTP "550 No such file"
971
 
972
973
974
 
975
 
976
 
977
;
978
; Store a file on the server.
979
;
980
;------------------------------------------------
981
align 4
982
cmdSTOR:
983
984
        test    [ebp + thread_data.permissions], PERMISSION_WRITE
985
 
986
987
988
 
989
 
990
        jnz     abort_transfer
991
992
;;;;
993
 
994
        ret
995
 
996
;------------------------------------------------
997
 
998
;
999
; Send information about the system.
1000
;
1001
;------------------------------------------------
1002
align 4
1003
cmdSYST:
1004
1005
        sendFTP "215 UNIX type: L8"
1006
 
1007
1008
;------------------------------------------------
1009
 
1010
;
1011
; Choose the file transfer type.
1012
;
1013
;------------------------------------------------
1014
align 4
1015
cmdTYPE:
1016
1017
        cmp     ecx, 6
1018
 
1019
1020
        mov     al, byte[esi+5]
1021
 
1022
1023
        cmp     al, 'A'
1024
 
1025
        cmp     al, 'E'
1026
        je      .ebdic
1027
        cmp     al, 'I'
1028
        je      .image
1029
        cmp     al, 'L'
1030
        je      .local
1031
1032
        jmp     parse_cmd.error
1033
 
1034
  .ascii:
1035
 
1036
        jmp     .subtype
1037
1038
  .ebdic:
1039
 
1040
1041
  .subtype:
1042
 
1043
        jb      .non_print
1044
1045
        mov     al, byte[esi+7]
1046
 
1047
1048
        cmp     al, 'N'
1049
 
1050
        cmp     al, 'T'
1051
        je      .telnet
1052
        cmp     al, 'C'
1053
        je      .asacc
1054
        cmp     al, 0x20
1055
        jb      .non_print
1056
1057
        jmp     parse_cmd.error
1058
 
1059
  .non_print:
1060
 
1061
        jmp     .ok
1062
1063
  .telnet:
1064
 
1065
        jmp     .ok
1066
1067
  .asacc:
1068
 
1069
        jmp     .ok
1070
1071
  .image:
1072
 
1073
        jmp     .ok
1074
1075
  .local:
1076
 
1077
        jb      parse_cmd.error
1078
1079
        mov     al, byte[esi+7]
1080
 
1081
        jb      parse_cmd.error                         ; FIXME: this is not the correct errormessage
1082
        cmp     al, 9
1083
        ja      parse_cmd.error                         ; FIXME
1084
        or      al, TYPE_LOCAL
1085
        mov     [ebp + thread_data.type], al
1086
1087
  .ok:
1088
 
1089
        ret
1090
1091
;------------------------------------------------
1092
 
1093
;
1094
; Login to the server, step one of two.                         ;;; TODO: prevent buffer overflow!
1095
;
1096
;------------------------------------------------
1097
align 4
1098
cmdUSER:
1099
1100
        lea     esi, [esi + 5]
1101
 
1102
  .loop:
1103
        lodsb
1104
        stosb
1105
        cmp     al, 0x20
1106
        jae     .loop
1107
        mov     byte [edi-1], 0
1108
1109
        lea     esi, [ebp + thread_data.fpath]
1110
 
1111
        invoke  ini.get_str, path2, esi, str_home, eax, 1024, str_infinity
1112
        cmp     eax, -1
1113
        je      .login_fail
1114
        cmp     dword [esi], -1
1115
        je      .login_fail
1116
1117
        mov     word [ebp + thread_data.work_dir], "/"          ; "/", 0
1118
 
1119
        invoke  con_write_asciiz, str_logged_in
1120
 
1121
  .sendstr:
1122
        sendFTP "331 Please specify the password"
1123
        ret
1124
1125
  .login_fail:
1126
 
1127
        mov     [ebp + thread_data.state], STATE_LOGIN_FAIL
1128
        jmp     .sendstr
1129
1130
align 4
1131
 
1132
        sendFTP "530 Can't change to another user"
1133
        ret
1134