105 lines
3.7 KiB
Plaintext
105 lines
3.7 KiB
Plaintext
|
From: Jeff Mahoney <jeffm@suse.com>
|
||
|
Subject: netfilter: Implement RFC 1123 for FTP conntrack
|
||
|
References: bnc#466279
|
||
|
Patch-mainline: Submitted via http://bugzilla.netfilter.org/show_bug.cgi?id=574 23 Jan 2011
|
||
|
|
||
|
The FTP conntrack code currently only accepts the following format for
|
||
|
the 227 response for PASV:
|
||
|
227 Entering Passive Mode (148,100,81,40,31,161).
|
||
|
|
||
|
It doesn't accept the following format from an obscure server:
|
||
|
227 Data transfer will passively listen to 67,218,99,134,50,144
|
||
|
|
||
|
From RFC 1123:
|
||
|
The format of the 227 reply to a PASV command is not
|
||
|
well standardized. In particular, an FTP client cannot
|
||
|
assume that the parentheses shown on page 40 of RFC-959
|
||
|
will be present (and in fact, Figure 3 on page 43 omits
|
||
|
them). Therefore, a User-FTP program that interprets
|
||
|
the PASV reply must scan the reply for the first digit
|
||
|
of the host and port numbers.
|
||
|
|
||
|
This patch adds support for the RFC 1123 clarification by:
|
||
|
- Allowing a search filter to specify NUL as the terminator so that
|
||
|
try_number will return successfully if the array of numbers has been
|
||
|
filled when an unexpected character is encountered.
|
||
|
- Using space as the separator for the 227 reply and then scanning for
|
||
|
the first digit of the number sequence. The number sequence is parsed
|
||
|
out using the existing try_rfc959 but with a NUL terminator.
|
||
|
|
||
|
Tracked in: https://bugzilla.novell.com/show_bug.cgi?id=466279
|
||
|
|
||
|
Reported-by: Mark Post <mpost@novell.com>
|
||
|
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
|
||
|
---
|
||
|
net/netfilter/nf_conntrack_ftp.c | 36 +++++++++++++++++++++++++++++++-----
|
||
|
1 file changed, 31 insertions(+), 5 deletions(-)
|
||
|
|
||
|
--- a/net/netfilter/nf_conntrack_ftp.c
|
||
|
+++ b/net/netfilter/nf_conntrack_ftp.c
|
||
|
@@ -53,6 +53,7 @@ unsigned int (*nf_nat_ftp_hook)(struct s
|
||
|
EXPORT_SYMBOL_GPL(nf_nat_ftp_hook);
|
||
|
|
||
|
static int try_rfc959(const char *, size_t, struct nf_conntrack_man *, char);
|
||
|
+static int try_rfc1123(const char *, size_t, struct nf_conntrack_man *, char);
|
||
|
static int try_eprt(const char *, size_t, struct nf_conntrack_man *, char);
|
||
|
static int try_epsv_response(const char *, size_t, struct nf_conntrack_man *,
|
||
|
char);
|
||
|
@@ -87,10 +88,10 @@ static struct ftp_search {
|
||
|
{
|
||
|
.pattern = "227 ",
|
||
|
.plen = sizeof("227 ") - 1,
|
||
|
- .skip = '(',
|
||
|
- .term = ')',
|
||
|
+ .skip = ' ',
|
||
|
+ .term = '\0',
|
||
|
.ftptype = NF_CT_FTP_PASV,
|
||
|
- .getnum = try_rfc959,
|
||
|
+ .getnum = try_rfc1123,
|
||
|
},
|
||
|
{
|
||
|
.pattern = "229 ",
|
||
|
@@ -129,8 +130,9 @@ static int try_number(const char *data,
|
||
|
i++;
|
||
|
else {
|
||
|
/* Unexpected character; true if it's the
|
||
|
- terminator and we're finished. */
|
||
|
- if (*data == term && i == array_size - 1)
|
||
|
+ terminator (or we don't care about one)
|
||
|
+ and we're finished. */
|
||
|
+ if ((*data == term || !term) && i == array_size - 1)
|
||
|
return len;
|
||
|
|
||
|
pr_debug("Char %u (got %u nums) `%u' unexpected\n",
|
||
|
@@ -160,6 +162,30 @@ static int try_rfc959(const char *data,
|
||
|
return length;
|
||
|
}
|
||
|
|
||
|
+/*
|
||
|
+ * From RFC 1123:
|
||
|
+ * The format of the 227 reply to a PASV command is not
|
||
|
+ * well standardized. In particular, an FTP client cannot
|
||
|
+ * assume that the parentheses shown on page 40 of RFC-959
|
||
|
+ * will be present (and in fact, Figure 3 on page 43 omits
|
||
|
+ * them). Therefore, a User-FTP program that interprets
|
||
|
+ * the PASV reply must scan the reply for the first digit
|
||
|
+ * of the host and port numbers.
|
||
|
+ */
|
||
|
+static int try_rfc1123(const char *data, size_t dlen,
|
||
|
+ struct nf_conntrack_man *cmd, char term)
|
||
|
+{
|
||
|
+ int i;
|
||
|
+ for (i = 0; i < dlen; i++)
|
||
|
+ if (isdigit(data[i]))
|
||
|
+ break;
|
||
|
+
|
||
|
+ if (i == dlen)
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ return try_rfc959(data + i, dlen - i, cmd, 0);
|
||
|
+}
|
||
|
+
|
||
|
/* Grab port: number up to delimiter */
|
||
|
static int get_port(const char *data, int start, size_t dlen, char delim,
|
||
|
__be16 *port)
|