mirror of
https://github.com/torvalds/linux.git
synced 2025-12-07 20:06:24 +00:00
net/tcp: Add tcp_parse_auth_options()
Introduce a helper that:
(1) shares the common code with TCP-MD5 header options parsing
(2) looks for hash signature only once for both TCP-MD5 and TCP-AO
(3) fails with -EEXIST if any TCP sign option is present twice, see
RFC5925 (2.2):
">> A single TCP segment MUST NOT have more than one TCP-AO in its
options sequence. When multiple TCP-AOs appear, TCP MUST discard
the segment."
Co-developed-by: Francesco Ruggeri <fruggeri@arista.com>
Signed-off-by: Francesco Ruggeri <fruggeri@arista.com>
Co-developed-by: Salam Noureddine <noureddine@arista.com>
Signed-off-by: Salam Noureddine <noureddine@arista.com>
Signed-off-by: Dmitry Safonov <dima@arista.com>
Acked-by: David Ahern <dsahern@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
1e03d32bea
commit
f7dca36fc5
@@ -4255,39 +4255,58 @@ static bool tcp_fast_parse_options(const struct net *net,
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TCP_MD5SIG
|
||||
#if defined(CONFIG_TCP_MD5SIG) || defined(CONFIG_TCP_AO)
|
||||
/*
|
||||
* Parse MD5 Signature option
|
||||
* Parse Signature options
|
||||
*/
|
||||
const u8 *tcp_parse_md5sig_option(const struct tcphdr *th)
|
||||
int tcp_do_parse_auth_options(const struct tcphdr *th,
|
||||
const u8 **md5_hash, const u8 **ao_hash)
|
||||
{
|
||||
int length = (th->doff << 2) - sizeof(*th);
|
||||
const u8 *ptr = (const u8 *)(th + 1);
|
||||
unsigned int minlen = TCPOLEN_MD5SIG;
|
||||
|
||||
if (IS_ENABLED(CONFIG_TCP_AO))
|
||||
minlen = sizeof(struct tcp_ao_hdr) + 1;
|
||||
|
||||
*md5_hash = NULL;
|
||||
*ao_hash = NULL;
|
||||
|
||||
/* If not enough data remaining, we can short cut */
|
||||
while (length >= TCPOLEN_MD5SIG) {
|
||||
while (length >= minlen) {
|
||||
int opcode = *ptr++;
|
||||
int opsize;
|
||||
|
||||
switch (opcode) {
|
||||
case TCPOPT_EOL:
|
||||
return NULL;
|
||||
return 0;
|
||||
case TCPOPT_NOP:
|
||||
length--;
|
||||
continue;
|
||||
default:
|
||||
opsize = *ptr++;
|
||||
if (opsize < 2 || opsize > length)
|
||||
return NULL;
|
||||
if (opcode == TCPOPT_MD5SIG)
|
||||
return opsize == TCPOLEN_MD5SIG ? ptr : NULL;
|
||||
return -EINVAL;
|
||||
if (opcode == TCPOPT_MD5SIG) {
|
||||
if (opsize != TCPOLEN_MD5SIG)
|
||||
return -EINVAL;
|
||||
if (unlikely(*md5_hash || *ao_hash))
|
||||
return -EEXIST;
|
||||
*md5_hash = ptr;
|
||||
} else if (opcode == TCPOPT_AO) {
|
||||
if (opsize <= sizeof(struct tcp_ao_hdr))
|
||||
return -EINVAL;
|
||||
if (unlikely(*md5_hash || *ao_hash))
|
||||
return -EEXIST;
|
||||
*ao_hash = ptr;
|
||||
}
|
||||
}
|
||||
ptr += opsize - 2;
|
||||
length -= opsize;
|
||||
}
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(tcp_parse_md5sig_option);
|
||||
EXPORT_SYMBOL(tcp_do_parse_auth_options);
|
||||
#endif
|
||||
|
||||
/* Sorry, PAWS as specified is broken wrt. pure-ACKs -DaveM
|
||||
|
||||
Reference in New Issue
Block a user