From: fcartegnie at nordnet dot fr
Operating system: Linux
PHP version: 4.4.0
PHP Bug Type: FTP related
Bug description: FTP Fopen Wrappers doesn't work work with every server
Description:
------------
I was stuck with a fopen("ftp://...
resulting in a
"failed to open stream: FTP server reports 220 Serv-U FTP Server v6.0 for
WinSock ready..."
This URL was working with any other software (WGET, CURL).
After analysing and tracing the code, I found the reason: This ftpserver
(or maybe firewall) expects only full line commands. The FTP_fopen_wrapper
outputs commands while generating then. TCPdumping the flow shows the php
client
sends "USER " in a single packet, then the remaining of the command.
Thoses servers answers after the packet, and php read a wrong command
result so.
Reproduce code:
---------------
I can give privately IP/login/pass for reproducing.
Expected result:
----------------
Commands in a single line/packet.
Patch follows.
Actual result:
--------------
--- php-4.4.0/ext/standard/ftp_fopen_wrapper.c 2005-06-27
10:27:23.000000000 +0200
+++ php-4.4.0_modifie/ext/standard/ftp_fopen_wrapper.c 2005-10-05
16:46:03.000000000 +0200
@@ -139,7 +139,7 @@
php_url *resource=NULL;
char tmp_line[512];
char ip[sizeof("123.123.123.123")];
- unsigned short portno;
+ unsigned short portno;char *commandbuffer=NULL;
char *scratch;
int result;
int i, use_ssl, tmp_len;
@@ -255,18 +255,19 @@
}
/* send the user name */
- php_stream_write_string(stream, "USER ");
if (resource->user != NULL) {
unsigned char *s, *e;
tmp_len = php_raw_url_decode(resource->user,
strlen(resource->user));
PHP_FTP_CNTRL_CHK(resource->user, tmp_len, "Invalid login %s")
- php_stream_write_string(stream, resource->user);
+ commandbuffer = (char *) malloc((strlen("USER \r\n") +
strlen(resource->user) + 1) * sizeof(char));
+ commandbuffer[0]='\0'; commandbuffer = strcat( strcat(
strcat(commandbuffer,"USER "), resource->user), "\r\n");
+ php_stream_write_string(stream, commandbuffer);
+ free(commandbuffer);
} else {
- php_stream_write_string(stream, "anonymous");
+ php_stream_write_string(stream, "USER anonymous\r\n");
}
- php_stream_write_string(stream, "\r\n");
/* get the response */
result = GET_FTP_RESULT(stream);
@@ -275,23 +276,27 @@
if (result >= 300 && result <= 399) {
php_stream_notify_info(context, PHP_STREAM_NOTIFY_AUTH_REQUIRED,
tmp_line, 0);
- php_stream_write_string(stream, "PASS ");
if (resource->pass != NULL) {
tmp_len = php_raw_url_decode(resource->pass,
strlen(resource->pass));
PHP_FTP_CNTRL_CHK(resource->pass, tmp_len, "Invalid
password %s")
- php_stream_write_string(stream, resource->pass);
+ commandbuffer = (char *) malloc((strlen("PASS \r\n") +
strlen(resource->pass) + 1) * sizeof(char));
+ commandbuffer[0]='\0'; commandbuffer = strcat( strcat(
strcat(commandbuffer,"PASS "), resource->pass), "\r\n");
+ php_stream_write_string(stream, commandbuffer);
+ free(commandbuffer);
} else {
/* if the user has configured who they are,
send that as the password */
if (cfg_get_string("from", &scratch) == SUCCESS) {
- php_stream_write_string(stream, scratch);
+ commandbuffer = (char *) malloc((strlen("PASS
\r\n") +
strlen(scratch) + 1) * sizeof(char));
+ commandbuffer[0]='\0'; commandbuffer = strcat(
strcat(
strcat(commandbuffer,"PASS "), scratch), "\r\n");
+ php_stream_write_string(stream, commandbuffer);
+ free(commandbuffer);
} else {
- php_stream_write_string(stream, "anonymous");
+ php_stream_write_string(stream, "PASS
anonymous\r\n");
}
}
- php_stream_write_string(stream, "\r\n");
/* read the response */
result = GET_FTP_RESULT(stream);
@@ -312,9 +317,10 @@
goto errexit;
/* find out the size of the file (verifying it exists) */
- php_stream_write_string(stream, "SIZE ");
- php_stream_write_string(stream, resource->path);
- php_stream_write_string(stream, "\r\n");
+ commandbuffer = (char *) malloc((strlen("SIZE \r\n") +
strlen(resource->path) + 1) * sizeof(char));
+ commandbuffer[0]='\0'; commandbuffer = strcat( strcat(
strcat(commandbuffer,"SIZE "), resource->path), "\r\n");
+ php_stream_write_string(stream, commandbuffer);
+ free(commandbuffer);
/* read the response */
result = GET_FTP_RESULT(stream);
@@ -411,17 +417,27 @@
if (mode[0] == 'r') {
/* retrieve file */
- php_stream_write_string(stream, "RETR ");
+ if (resource->path == NULL) {
+ php_stream_write_string(stream, "RETR / \r\n");
+ } else {
+ commandbuffer = (char *) malloc((strlen("RETR \r\n") +
strlen(resource->path) + 1) * sizeof(char));
+ commandbuffer[0]='\0';
+ commandbuffer = strcat( strcat( strcat(commandbuffer,
"RETR "),
resource->path), "\r\n");
+ php_stream_write_string(stream, commandbuffer);
+ free(commandbuffer);
+ }
} else {
/* store file */
- php_stream_write_string(stream, "STOR ");
- }
- if (resource->path != NULL) {
- php_stream_write_string(stream, resource->path);
- } else {
- php_stream_write_string(stream, "/");
+ if (resource->path == NULL) {
+ php_stream_write_string(stream, "STOR / \r\n");
+ } else {
+ commandbuffer = (char *) malloc((strlen("STOR \r\n") +
strlen(resource->path) + 1) * sizeof(char));
+ commandbuffer[0]='\0';
+ commandbuffer = strcat( strcat( strcat(commandbuffer,
"STOR "),
resource->path), "\r\n");
+ php_stream_write_string(stream, commandbuffer);
+ free(commandbuffer);
+ }
}
- php_stream_write_string(stream, "\r\n");
/* open the data channel */
if (hoststart == NULL) {
--
Edit bug report at http://bugs.php.net/?id=34742&edit=1
--
Try a CVS snapshot (php4): http://bugs.php.net/fix.php?id=34742&r=trysnapshot4
Try a CVS snapshot (php5.0):
http://bugs.php.net/fix.php?id=34742&r=trysnapshot50
Try a CVS snapshot (php5.1):
http://bugs.php.net/fix.php?id=34742&r=trysnapshot51
Fixed in CVS: http://bugs.php.net/fix.php?id=34742&r=fixedcvs
Fixed in release: http://bugs.php.net/fix.php?id=34742&r=alreadyfixed
Need backtrace: http://bugs.php.net/fix.php?id=34742&r=needtrace
Need Reproduce Script: http://bugs.php.net/fix.php?id=34742&r=needscript
Try newer version: http://bugs.php.net/fix.php?id=34742&r=oldversion
Not developer issue: http://bugs.php.net/fix.php?id=34742&r=support
Expected behavior: http://bugs.php.net/fix.php?id=34742&r=notwrong
Not enough info:
http://bugs.php.net/fix.php?id=34742&r=notenoughinfo
Submitted twice:
http://bugs.php.net/fix.php?id=34742&r=submittedtwice
register_globals: http://bugs.php.net/fix.php?id=34742&r=globals
PHP 3 support discontinued: http://bugs.php.net/fix.php?id=34742&r=php3
Daylight Savings: http://bugs.php.net/fix.php?id=34742&r=dst
IIS Stability: http://bugs.php.net/fix.php?id=34742&r=isapi
Install GNU Sed: http://bugs.php.net/fix.php?id=34742&r=gnused
Floating point limitations: http://bugs.php.net/fix.php?id=34742&r=float
No Zend Extensions: http://bugs.php.net/fix.php?id=34742&r=nozend
MySQL Configuration Error: http://bugs.php.net/fix.php?id=34742&r=mysqlcfg