Commit 25b86e05 authored by Patrick McHardy's avatar Patrick McHardy Committed by David S. Miller

[NETFILTER]: nf_conntrack_ftp: fix newline sequence number calculation

When the packet size is changed by the FTP NAT helper, the connection
tracking helper adjusts the sequence number of the newline character
by the size difference. This is wrong because NAT sequence number
adjustment happens after helpers are called, so the unadjusted number
is compared to the already adjusted one.

Based on report by YU, Haitao <yuhaitao@tsinghua.org.cn>
Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5fe26f53
...@@ -37,8 +37,7 @@ extern unsigned int (*nf_nat_ftp_hook)(struct sk_buff **pskb, ...@@ -37,8 +37,7 @@ extern unsigned int (*nf_nat_ftp_hook)(struct sk_buff **pskb,
enum nf_ct_ftp_type type, enum nf_ct_ftp_type type,
unsigned int matchoff, unsigned int matchoff,
unsigned int matchlen, unsigned int matchlen,
struct nf_conntrack_expect *exp, struct nf_conntrack_expect *exp);
u32 *seq);
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* _NF_CONNTRACK_FTP_H */ #endif /* _NF_CONNTRACK_FTP_H */
...@@ -40,8 +40,7 @@ mangle_rfc959_packet(struct sk_buff **pskb, ...@@ -40,8 +40,7 @@ mangle_rfc959_packet(struct sk_buff **pskb,
unsigned int matchoff, unsigned int matchoff,
unsigned int matchlen, unsigned int matchlen,
struct nf_conn *ct, struct nf_conn *ct,
enum ip_conntrack_info ctinfo, enum ip_conntrack_info ctinfo)
u32 *seq)
{ {
char buffer[sizeof("nnn,nnn,nnn,nnn,nnn,nnn")]; char buffer[sizeof("nnn,nnn,nnn,nnn,nnn,nnn")];
...@@ -50,7 +49,6 @@ mangle_rfc959_packet(struct sk_buff **pskb, ...@@ -50,7 +49,6 @@ mangle_rfc959_packet(struct sk_buff **pskb,
DEBUGP("calling nf_nat_mangle_tcp_packet\n"); DEBUGP("calling nf_nat_mangle_tcp_packet\n");
*seq += strlen(buffer) - matchlen;
return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff, return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff,
matchlen, buffer, strlen(buffer)); matchlen, buffer, strlen(buffer));
} }
...@@ -63,8 +61,7 @@ mangle_eprt_packet(struct sk_buff **pskb, ...@@ -63,8 +61,7 @@ mangle_eprt_packet(struct sk_buff **pskb,
unsigned int matchoff, unsigned int matchoff,
unsigned int matchlen, unsigned int matchlen,
struct nf_conn *ct, struct nf_conn *ct,
enum ip_conntrack_info ctinfo, enum ip_conntrack_info ctinfo)
u32 *seq)
{ {
char buffer[sizeof("|1|255.255.255.255|65535|")]; char buffer[sizeof("|1|255.255.255.255|65535|")];
...@@ -72,7 +69,6 @@ mangle_eprt_packet(struct sk_buff **pskb, ...@@ -72,7 +69,6 @@ mangle_eprt_packet(struct sk_buff **pskb,
DEBUGP("calling nf_nat_mangle_tcp_packet\n"); DEBUGP("calling nf_nat_mangle_tcp_packet\n");
*seq += strlen(buffer) - matchlen;
return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff, return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff,
matchlen, buffer, strlen(buffer)); matchlen, buffer, strlen(buffer));
} }
...@@ -85,8 +81,7 @@ mangle_epsv_packet(struct sk_buff **pskb, ...@@ -85,8 +81,7 @@ mangle_epsv_packet(struct sk_buff **pskb,
unsigned int matchoff, unsigned int matchoff,
unsigned int matchlen, unsigned int matchlen,
struct nf_conn *ct, struct nf_conn *ct,
enum ip_conntrack_info ctinfo, enum ip_conntrack_info ctinfo)
u32 *seq)
{ {
char buffer[sizeof("|||65535|")]; char buffer[sizeof("|||65535|")];
...@@ -94,14 +89,13 @@ mangle_epsv_packet(struct sk_buff **pskb, ...@@ -94,14 +89,13 @@ mangle_epsv_packet(struct sk_buff **pskb,
DEBUGP("calling nf_nat_mangle_tcp_packet\n"); DEBUGP("calling nf_nat_mangle_tcp_packet\n");
*seq += strlen(buffer) - matchlen;
return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff, return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff,
matchlen, buffer, strlen(buffer)); matchlen, buffer, strlen(buffer));
} }
static int (*mangle[])(struct sk_buff **, __be32, u_int16_t, static int (*mangle[])(struct sk_buff **, __be32, u_int16_t,
unsigned int, unsigned int, struct nf_conn *, unsigned int, unsigned int, struct nf_conn *,
enum ip_conntrack_info, u32 *seq) enum ip_conntrack_info)
= { = {
[NF_CT_FTP_PORT] = mangle_rfc959_packet, [NF_CT_FTP_PORT] = mangle_rfc959_packet,
[NF_CT_FTP_PASV] = mangle_rfc959_packet, [NF_CT_FTP_PASV] = mangle_rfc959_packet,
...@@ -116,8 +110,7 @@ static unsigned int nf_nat_ftp(struct sk_buff **pskb, ...@@ -116,8 +110,7 @@ static unsigned int nf_nat_ftp(struct sk_buff **pskb,
enum nf_ct_ftp_type type, enum nf_ct_ftp_type type,
unsigned int matchoff, unsigned int matchoff,
unsigned int matchlen, unsigned int matchlen,
struct nf_conntrack_expect *exp, struct nf_conntrack_expect *exp)
u32 *seq)
{ {
__be32 newip; __be32 newip;
u_int16_t port; u_int16_t port;
...@@ -145,8 +138,7 @@ static unsigned int nf_nat_ftp(struct sk_buff **pskb, ...@@ -145,8 +138,7 @@ static unsigned int nf_nat_ftp(struct sk_buff **pskb,
if (port == 0) if (port == 0)
return NF_DROP; return NF_DROP;
if (!mangle[type](pskb, newip, port, matchoff, matchlen, ct, ctinfo, if (!mangle[type](pskb, newip, port, matchoff, matchlen, ct, ctinfo)) {
seq)) {
nf_conntrack_unexpect_related(exp); nf_conntrack_unexpect_related(exp);
return NF_DROP; return NF_DROP;
} }
......
...@@ -48,8 +48,7 @@ unsigned int (*nf_nat_ftp_hook)(struct sk_buff **pskb, ...@@ -48,8 +48,7 @@ unsigned int (*nf_nat_ftp_hook)(struct sk_buff **pskb,
enum nf_ct_ftp_type type, enum nf_ct_ftp_type type,
unsigned int matchoff, unsigned int matchoff,
unsigned int matchlen, unsigned int matchlen,
struct nf_conntrack_expect *exp, struct nf_conntrack_expect *exp);
u32 *seq);
EXPORT_SYMBOL_GPL(nf_nat_ftp_hook); EXPORT_SYMBOL_GPL(nf_nat_ftp_hook);
#if 0 #if 0
...@@ -521,7 +520,7 @@ static int help(struct sk_buff **pskb, ...@@ -521,7 +520,7 @@ static int help(struct sk_buff **pskb,
nf_nat_ftp = rcu_dereference(nf_nat_ftp_hook); nf_nat_ftp = rcu_dereference(nf_nat_ftp_hook);
if (nf_nat_ftp && ct->status & IPS_NAT_MASK) if (nf_nat_ftp && ct->status & IPS_NAT_MASK)
ret = nf_nat_ftp(pskb, ctinfo, search[dir][i].ftptype, ret = nf_nat_ftp(pskb, ctinfo, search[dir][i].ftptype,
matchoff, matchlen, exp, &seq); matchoff, matchlen, exp);
else { else {
/* Can't expect this? Best to drop packet now. */ /* Can't expect this? Best to drop packet now. */
if (nf_conntrack_expect_related(exp) != 0) if (nf_conntrack_expect_related(exp) != 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment