Subversion Repositories Kolibri OS

Rev

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