wget: add EPSV support
function old new delta parse_pasv_epsv - 151 +151 wget_main 2440 2382 -58 xconnect_ftpdata 223 94 -129 ------------------------------------------------------------------------------ (add/remove: 2/0 grow/shrink: 0/2 up/down: 151/-187) Total: -36 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
403f2999f9
commit
1783ffa990
@ -787,6 +787,7 @@ ssize_t recv_from_to(int fd, void *buf, size_t len, int flags,
|
|||||||
socklen_t sa_size) FAST_FUNC;
|
socklen_t sa_size) FAST_FUNC;
|
||||||
|
|
||||||
uint16_t inet_cksum(uint16_t *addr, int len) FAST_FUNC;
|
uint16_t inet_cksum(uint16_t *addr, int len) FAST_FUNC;
|
||||||
|
int parse_pasv_epsv(char *buf) FAST_FUNC;
|
||||||
|
|
||||||
/* 0 if argv[0] is NULL: */
|
/* 0 if argv[0] is NULL: */
|
||||||
unsigned string_array_len(char **argv) FAST_FUNC;
|
unsigned string_array_len(char **argv) FAST_FUNC;
|
||||||
|
@ -152,57 +152,16 @@ static void ftp_login(void)
|
|||||||
|
|
||||||
static int xconnect_ftpdata(void)
|
static int xconnect_ftpdata(void)
|
||||||
{
|
{
|
||||||
char *buf_ptr;
|
int port_num;
|
||||||
unsigned port_num;
|
|
||||||
|
|
||||||
/*
|
if (ENABLE_FEATURE_IPV6 && ftpcmd("EPSV", NULL) == 229) {
|
||||||
PASV command will not work for IPv6. RFC2428 describes
|
/* good */
|
||||||
IPv6-capable "extended PASV" - EPSV.
|
} else if (ftpcmd("PASV", NULL) != 227) {
|
||||||
|
ftp_die("PASV");
|
||||||
"EPSV [protocol]" asks server to bind to and listen on a data port
|
|
||||||
in specified protocol. Protocol is 1 for IPv4, 2 for IPv6.
|
|
||||||
If not specified, defaults to "same as used for control connection".
|
|
||||||
If server understood you, it should answer "229 <some text>(|||port|)"
|
|
||||||
where "|" are literal pipe chars and "port" is ASCII decimal port#.
|
|
||||||
|
|
||||||
There is also an IPv6-capable replacement for PORT (EPRT),
|
|
||||||
but we don't need that.
|
|
||||||
|
|
||||||
NB: PASV may still work for some servers even over IPv6.
|
|
||||||
For example, vsftp happily answers
|
|
||||||
"227 Entering Passive Mode (0,0,0,0,n,n)" and proceeds as usual.
|
|
||||||
*/
|
|
||||||
if (!ENABLE_FEATURE_IPV6
|
|
||||||
|| ftpcmd("EPSV", NULL) != 229
|
|
||||||
) {
|
|
||||||
/* maybe also go straight to PAST if lsa->u.sa.sa_family == AF_INET? */
|
|
||||||
if (ftpcmd("PASV", NULL) != 227) {
|
|
||||||
ftp_die("PASV");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Response is "NNN garbageN1,N2,N3,N4,P1,P2[)garbage]"
|
|
||||||
* Server's IP is N1.N2.N3.N4 (we ignore it)
|
|
||||||
* Server's port for data connection is P1*256+P2 */
|
|
||||||
buf_ptr = strrchr(buf, ')');
|
|
||||||
if (buf_ptr) *buf_ptr = '\0';
|
|
||||||
|
|
||||||
buf_ptr = strrchr(buf, ',');
|
|
||||||
*buf_ptr = '\0';
|
|
||||||
port_num = xatoul_range(buf_ptr + 1, 0, 255);
|
|
||||||
|
|
||||||
buf_ptr = strrchr(buf, ',');
|
|
||||||
*buf_ptr = '\0';
|
|
||||||
port_num += xatoul_range(buf_ptr + 1, 0, 255) * 256;
|
|
||||||
} else {
|
|
||||||
/* Response is "NNN garbage(|||P1|)"
|
|
||||||
* Server's port for data connection is P1 */
|
|
||||||
buf_ptr = strrchr(buf, '|');
|
|
||||||
if (buf_ptr) *buf_ptr = '\0';
|
|
||||||
|
|
||||||
buf_ptr = strrchr(buf, '|');
|
|
||||||
*buf_ptr = '\0';
|
|
||||||
port_num = xatoul_range(buf_ptr + 1, 0, 65535);
|
|
||||||
}
|
}
|
||||||
|
port_num = parse_pasv_epsv(buf);
|
||||||
|
if (port_num < 0)
|
||||||
|
ftp_die("PASV");
|
||||||
|
|
||||||
set_nport(&lsa->u.sa, htons(port_num));
|
set_nport(&lsa->u.sa, htons(port_num));
|
||||||
return xconnect_stream(lsa);
|
return xconnect_stream(lsa);
|
||||||
|
66
networking/parse_pasv_epsv.c
Normal file
66
networking/parse_pasv_epsv.c
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Utility routines.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2018 Denys Vlasenko
|
||||||
|
*
|
||||||
|
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
|
||||||
|
*/
|
||||||
|
//kbuild:lib-$(CONFIG_FTPGET) += ftpgetput.o
|
||||||
|
//kbuild:lib-$(CONFIG_FTPPUT) += ftpgetput.o
|
||||||
|
//kbuild:lib-$(CONFIG_WGET) += parse_pasv_epsv.o
|
||||||
|
|
||||||
|
#include "libbb.h"
|
||||||
|
|
||||||
|
int FAST_FUNC parse_pasv_epsv(char *buf)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* PASV command will not work for IPv6. RFC2428 describes
|
||||||
|
* IPv6-capable "extended PASV" - EPSV.
|
||||||
|
*
|
||||||
|
* "EPSV [protocol]" asks server to bind to and listen on a data port
|
||||||
|
* in specified protocol. Protocol is 1 for IPv4, 2 for IPv6.
|
||||||
|
* If not specified, defaults to "same as used for control connection".
|
||||||
|
* If server understood you, it should answer "229 <some text>(|||port|)"
|
||||||
|
* where "|" are literal pipe chars and "port" is ASCII decimal port#.
|
||||||
|
*
|
||||||
|
* There is also an IPv6-capable replacement for PORT (EPRT),
|
||||||
|
* but we don't need that.
|
||||||
|
*
|
||||||
|
* NB: PASV may still work for some servers even over IPv6.
|
||||||
|
* For example, vsftp happily answers
|
||||||
|
* "227 Entering Passive Mode (0,0,0,0,n,n)" and proceeds as usual.
|
||||||
|
*/
|
||||||
|
char *ptr;
|
||||||
|
int port;
|
||||||
|
|
||||||
|
if (!ENABLE_FEATURE_IPV6 || buf[2] == '7' /* "227" */) {
|
||||||
|
/* Response is "227 garbageN1,N2,N3,N4,P1,P2[)garbage]"
|
||||||
|
* Server's IP is N1.N2.N3.N4 (we ignore it)
|
||||||
|
* Server's port for data connection is P1*256+P2 */
|
||||||
|
ptr = strrchr(buf, ')');
|
||||||
|
if (ptr) *ptr = '\0';
|
||||||
|
|
||||||
|
ptr = strrchr(buf, ',');
|
||||||
|
if (!ptr) return -1;
|
||||||
|
*ptr = '\0';
|
||||||
|
port = xatou_range(ptr + 1, 0, 255);
|
||||||
|
|
||||||
|
ptr = strrchr(buf, ',');
|
||||||
|
if (!ptr) return -1;
|
||||||
|
*ptr = '\0';
|
||||||
|
port += xatou_range(ptr + 1, 0, 255) * 256;
|
||||||
|
} else {
|
||||||
|
/* Response is "229 garbage(|||P1|)"
|
||||||
|
* Server's port for data connection is P1 */
|
||||||
|
ptr = strrchr(buf, '|');
|
||||||
|
if (!ptr) return -1;
|
||||||
|
*ptr = '\0';
|
||||||
|
|
||||||
|
ptr = strrchr(buf, '|');
|
||||||
|
if (!ptr) return -1;
|
||||||
|
*ptr = '\0';
|
||||||
|
port = xatou_range(ptr + 1, 0, 65535);
|
||||||
|
}
|
||||||
|
|
||||||
|
return port;
|
||||||
|
}
|
@ -791,22 +791,17 @@ static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_
|
|||||||
/*
|
/*
|
||||||
* Entering passive mode
|
* Entering passive mode
|
||||||
*/
|
*/
|
||||||
|
if (ENABLE_FEATURE_IPV6 && ftpcmd("EPSV", NULL, sfp) == 229) {
|
||||||
|
/* good */
|
||||||
|
} else
|
||||||
if (ftpcmd("PASV", NULL, sfp) != 227) {
|
if (ftpcmd("PASV", NULL, sfp) != 227) {
|
||||||
pasv_error:
|
pasv_error:
|
||||||
bb_error_msg_and_die("bad response to %s: %s", "PASV", sanitize_string(G.wget_buf));
|
bb_error_msg_and_die("bad response to %s: %s", "PASV", sanitize_string(G.wget_buf));
|
||||||
}
|
}
|
||||||
// Response is "227 garbageN1,N2,N3,N4,P1,P2[)garbage]
|
port = parse_pasv_epsv(G.wget_buf);
|
||||||
// Server's IP is N1.N2.N3.N4 (we ignore it)
|
if (port < 0)
|
||||||
// Server's port for data connection is P1*256+P2
|
goto pasv_error;
|
||||||
str = strrchr(G.wget_buf, ')');
|
|
||||||
if (str) str[0] = '\0';
|
|
||||||
str = strrchr(G.wget_buf, ',');
|
|
||||||
if (!str) goto pasv_error;
|
|
||||||
port = xatou_range(str+1, 0, 255);
|
|
||||||
*str = '\0';
|
|
||||||
str = strrchr(G.wget_buf, ',');
|
|
||||||
if (!str) goto pasv_error;
|
|
||||||
port += xatou_range(str+1, 0, 255) * 256;
|
|
||||||
set_nport(&lsa->u.sa, htons(port));
|
set_nport(&lsa->u.sa, htons(port));
|
||||||
|
|
||||||
*dfpp = open_socket(lsa);
|
*dfpp = open_socket(lsa);
|
||||||
|
Loading…
Reference in New Issue
Block a user