Subject: bin/23435: [PATCH] ftp and ftpd has broken ASCII transfer type implementation
To: None <gnats-bugs@gnats.netbsd.org>
From: Andrey Beresovsky <and@rsu.ru>
List: netbsd-bugs
Date: 11/14/2003 14:27:50
>Number: 23435
>Category: bin
>Synopsis: [PATCH] ftp and ftpd has broken ASCII transfer type implementation
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: bin-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Fri Nov 14 11:28:01 UTC 2003
>Closed-Date:
>Last-Modified:
>Originator: Andrey Beresovsky
>Release: FreeBSD 5.1-CURRENT i386
>Organization:
Rostov State University
>Environment:
System: FreeBSD 5.1-CURRENT #2: Fri Nov 7 22:15:49 MSK 2003 i386
>Description:
According to RFC 959 (FILE TRANSFER PROTOCOL) for ASCII transfer type "the <CRLF> sequence
should be used where necessary to denote the end of a line of text" (Chapter 3.1.1.1.).
NetBSD's ftp client and ftpd server implement ASCII transfer type by inserting <CR> before each <LF>
without checking that may be <CR> allready exists. It leads to <CR><CR><LF> sequences
in files which allready had <CR><LF> end of lines (ex.: text files from Windows systems).
Attached patches should fix this problem.
>How-To-Repeat:
1. Create a text file with <CRLF> end of lines.
For ftp:
2. Send this file to ftpd server using NetBSD's ftp program (ASCII transfer type).
3. You'll get a file with <CR><CR><LF> EOLs on windows and <CR><LF> on unixes.
For ftpd:
2. Receive (GET) this file from NetBSD's ftpd server.
3. Same as 3. for ftp program.
>Fix:
lukemftp (ftp.c rev. 1.122):
--- ftp.c.orig Thu Nov 13 21:51:56 2003
+++ ftp.c Thu Nov 13 22:44:28 2003
@@ -835,6 +835,7 @@
break;
case TYPE_A:
+ d = '\0'; /* using to store previous character */
while ((c = getc(fin)) != EOF) {
if (c == '\n') {
while (hash && (!progress || filesize < 0) &&
@@ -843,19 +844,16 @@
(void)fflush(ttyout);
hashbytes += mark;
}
- if (ferror(dout))
- break;
- (void)putc('\r', dout);
- bytes++;
+ if (d != '\r') {
+ if (ferror(dout))
+ break;
+ (void)putc('\r', dout);
+ bytes++;
+ }
}
(void)putc(c, dout);
bytes++;
-#if 0 /* this violates RFC */
- if (c == '\r') {
- (void)putc('\0', dout);
- bytes++;
- }
-#endif
+ d = c;
}
if (hash && (!progress || filesize < 0)) {
if (bytes < hashbytes)
lukemftpd (ftpd.c rev. 1.150):
--- ftpd.c.orig Thu Nov 13 23:16:54 2003
+++ ftpd.c Thu Nov 13 23:22:36 2003
@@ -1918,7 +1918,8 @@
static int
send_data(FILE *instr, FILE *outstr, const struct stat *st, int isdata)
{
- int c, filefd, netfd, rval;
+ int c, filefd, netfd, rval;
+ int d = '\0';
transflag = 1;
rval = -1;
@@ -1933,9 +1935,11 @@
while ((c = getc(instr)) != EOF) {
byte_count++;
if (c == '\n') {
- if (ferror(outstr))
- goto data_err;
- (void) putc('\r', outstr);
+ if (d != '\r') {
+ if (ferror(outstr))
+ goto data_err;
+ (void) putc('\r', outstr);
+ }
if (isdata) {
total_data_out++;
total_data++;
@@ -1952,6 +1956,7 @@
total_bytes++;
if ((byte_count % 4096) == 0)
(void) alarm(curclass.timeout);
+ d = c;
}
(void) alarm(0);
fflush(outstr);
>Release-Note:
>Audit-Trail:
>Unformatted: