* Split tcp_signature_compute() into 2 pieces:
- tcp_get_sav() - SADB key lookup - tcp_signature_do_compute() - actual computation * Fix TCP signature case for listening socket: do not assume EVERY connection coming to socket with TCP_SIGNATURE set to be md5 signed regardless of SADB key existance for particular address. This fixes the case for routing software having _some_ BGP sessions secured by md5. * Simplify TCP_SIGNATURE handling in tcp_input() MFC after: 2 weeks
This commit is contained in:
parent
2d8910854b
commit
29c47f18da
@ -1928,55 +1928,20 @@ tcp_signature_apply(void *fstate, void *data, u_int len)
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute TCP-MD5 hash of a TCP segment. (RFC2385)
|
||||
*
|
||||
* Parameters:
|
||||
* m pointer to head of mbuf chain
|
||||
* _unused
|
||||
* len length of TCP segment data, excluding options
|
||||
* optlen length of TCP segment options
|
||||
* buf pointer to storage for computed MD5 digest
|
||||
* direction direction of flow (IPSEC_DIR_INBOUND or OUTBOUND)
|
||||
*
|
||||
* We do this over ip, tcphdr, segment data, and the key in the SADB.
|
||||
* When called from tcp_input(), we can be sure that th_sum has been
|
||||
* zeroed out and verified already.
|
||||
*
|
||||
* Return 0 if successful, otherwise return -1.
|
||||
*
|
||||
* XXX The key is retrieved from the system's PF_KEY SADB, by keying a
|
||||
* search with the destination IP address, and a 'magic SPI' to be
|
||||
* determined by the application. This is hardcoded elsewhere to 1179
|
||||
* right now. Another branch of this code exists which uses the SPD to
|
||||
* specify per-application flows but it is unstable.
|
||||
*/
|
||||
int
|
||||
tcp_signature_compute(struct mbuf *m, int _unused, int len, int optlen,
|
||||
u_char *buf, u_int direction)
|
||||
*/
|
||||
struct secasvar *
|
||||
tcp_get_sav(struct mbuf *m, u_int direction)
|
||||
{
|
||||
union sockaddr_union dst;
|
||||
#ifdef INET
|
||||
struct ippseudo ippseudo;
|
||||
#endif
|
||||
MD5_CTX ctx;
|
||||
int doff;
|
||||
struct ip *ip;
|
||||
#ifdef INET
|
||||
struct ipovly *ipovly;
|
||||
#endif
|
||||
struct secasvar *sav;
|
||||
struct tcphdr *th;
|
||||
struct ip *ip;
|
||||
#ifdef INET6
|
||||
struct ip6_hdr *ip6;
|
||||
struct in6_addr in6;
|
||||
char ip6buf[INET6_ADDRSTRLEN];
|
||||
uint32_t plen;
|
||||
uint16_t nhdr;
|
||||
#endif
|
||||
u_short savecsum;
|
||||
|
||||
KASSERT(m != NULL, ("NULL mbuf chain"));
|
||||
KASSERT(buf != NULL, ("NULL signature pointer"));
|
||||
|
||||
/* Extract the destination from the IP header in the mbuf. */
|
||||
bzero(&dst, sizeof(union sockaddr_union));
|
||||
@ -2003,7 +1968,7 @@ tcp_signature_compute(struct mbuf *m, int _unused, int len, int optlen,
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return (EINVAL);
|
||||
return (NULL);
|
||||
/* NOTREACHED */
|
||||
break;
|
||||
}
|
||||
@ -2018,9 +1983,61 @@ tcp_signature_compute(struct mbuf *m, int _unused, int len, int optlen,
|
||||
ip6_sprintf(ip6buf, &dst.sin6.sin6_addr) :
|
||||
#endif
|
||||
"(unsupported)"));
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
return (sav);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute TCP-MD5 hash of a TCP segment. (RFC2385)
|
||||
*
|
||||
* Parameters:
|
||||
* m pointer to head of mbuf chain
|
||||
* len length of TCP segment data, excluding options
|
||||
* optlen length of TCP segment options
|
||||
* buf pointer to storage for computed MD5 digest
|
||||
* sav pointer to security assosiation
|
||||
*
|
||||
* We do this over ip, tcphdr, segment data, and the key in the SADB.
|
||||
* When called from tcp_input(), we can be sure that th_sum has been
|
||||
* zeroed out and verified already.
|
||||
*
|
||||
* Releases reference to SADB key before return.
|
||||
*
|
||||
* Return 0 if successful, otherwise return -1.
|
||||
*
|
||||
*/
|
||||
int
|
||||
tcp_signature_do_compute(struct mbuf *m, int len, int optlen,
|
||||
u_char *buf, struct secasvar *sav)
|
||||
{
|
||||
#ifdef INET
|
||||
struct ippseudo ippseudo;
|
||||
#endif
|
||||
MD5_CTX ctx;
|
||||
int doff;
|
||||
struct ip *ip;
|
||||
#ifdef INET
|
||||
struct ipovly *ipovly;
|
||||
#endif
|
||||
struct tcphdr *th;
|
||||
#ifdef INET6
|
||||
struct ip6_hdr *ip6;
|
||||
struct in6_addr in6;
|
||||
uint32_t plen;
|
||||
uint16_t nhdr;
|
||||
#endif
|
||||
u_short savecsum;
|
||||
|
||||
KASSERT(m != NULL, ("NULL mbuf chain"));
|
||||
KASSERT(buf != NULL, ("NULL signature pointer"));
|
||||
|
||||
/* Extract the destination from the IP header in the mbuf. */
|
||||
ip = mtod(m, struct ip *);
|
||||
#ifdef INET6
|
||||
ip6 = NULL; /* Make the compiler happy. */
|
||||
#endif
|
||||
|
||||
MD5Init(&ctx);
|
||||
/*
|
||||
* Step 1: Update MD5 hash with IP(v6) pseudo-header.
|
||||
@ -2077,7 +2094,7 @@ tcp_signature_compute(struct mbuf *m, int _unused, int len, int optlen,
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return (EINVAL);
|
||||
return (-1);
|
||||
/* NOTREACHED */
|
||||
break;
|
||||
}
|
||||
@ -2110,6 +2127,23 @@ tcp_signature_compute(struct mbuf *m, int _unused, int len, int optlen,
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute TCP-MD5 hash of a TCP segment. (RFC2385)
|
||||
*
|
||||
* Return 0 if successful, otherwise return -1.
|
||||
*/
|
||||
int
|
||||
tcp_signature_compute(struct mbuf *m, int _unused, int len, int optlen,
|
||||
u_char *buf, u_int direction)
|
||||
{
|
||||
struct secasvar *sav;
|
||||
|
||||
if ((sav = tcp_get_sav(m, direction)) == NULL)
|
||||
return (-1);
|
||||
|
||||
return (tcp_signature_do_compute(m, len, optlen, buf, sav));
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify the TCP-MD5 hash of a TCP segment. (RFC2385)
|
||||
*
|
||||
|
@ -122,7 +122,7 @@ SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, syncookies_only, CTLFLAG_RW,
|
||||
static void syncache_drop(struct syncache *, struct syncache_head *);
|
||||
static void syncache_free(struct syncache *);
|
||||
static void syncache_insert(struct syncache *, struct syncache_head *);
|
||||
static int syncache_respond(struct syncache *);
|
||||
static int syncache_respond(struct syncache *, struct syncache_head *, int);
|
||||
static struct socket *syncache_socket(struct syncache *, struct socket *,
|
||||
struct mbuf *m);
|
||||
static void syncache_timeout(struct syncache *sc, struct syncache_head *sch,
|
||||
@ -467,7 +467,7 @@ syncache_timer(void *xsch)
|
||||
free(s, M_TCPLOG);
|
||||
}
|
||||
|
||||
(void) syncache_respond(sc);
|
||||
syncache_respond(sc, sch, 1);
|
||||
TCPSTAT_INC(tcps_sc_retransmitted);
|
||||
syncache_timeout(sc, sch, 0);
|
||||
}
|
||||
@ -1213,7 +1213,7 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
|
||||
s, __func__);
|
||||
free(s, M_TCPLOG);
|
||||
}
|
||||
if (syncache_respond(sc) == 0) {
|
||||
if (syncache_respond(sc, sch, 1) == 0) {
|
||||
sc->sc_rxmits = 0;
|
||||
syncache_timeout(sc, sch, 1);
|
||||
TCPSTAT_INC(tcps_sndacks);
|
||||
@ -1325,11 +1325,9 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
|
||||
}
|
||||
#ifdef TCP_SIGNATURE
|
||||
/*
|
||||
* If listening socket requested TCP digests, and received SYN
|
||||
* If listening socket requested TCP digests, OR received SYN
|
||||
* contains the option, flag this in the syncache so that
|
||||
* syncache_respond() will do the right thing with the SYN+ACK.
|
||||
* XXX: Currently we always record the option by default and will
|
||||
* attempt to use it in syncache_respond().
|
||||
*/
|
||||
if (to->to_flags & TOF_SIGNATURE || ltflags & TF_SIGNATURE)
|
||||
sc->sc_flags |= SCF_SIGNATURE;
|
||||
@ -1359,7 +1357,7 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
|
||||
/*
|
||||
* Do a standard 3-way handshake.
|
||||
*/
|
||||
if (syncache_respond(sc) == 0) {
|
||||
if (syncache_respond(sc, sch, 0) == 0) {
|
||||
if (V_tcp_syncookies && V_tcp_syncookiesonly && sc != &scs)
|
||||
syncache_free(sc);
|
||||
else if (sc != &scs)
|
||||
@ -1387,7 +1385,7 @@ done:
|
||||
}
|
||||
|
||||
static int
|
||||
syncache_respond(struct syncache *sc)
|
||||
syncache_respond(struct syncache *sc, struct syncache_head *sch, int locked)
|
||||
{
|
||||
struct ip *ip = NULL;
|
||||
struct mbuf *m;
|
||||
@ -1398,6 +1396,9 @@ syncache_respond(struct syncache *sc)
|
||||
#ifdef INET6
|
||||
struct ip6_hdr *ip6 = NULL;
|
||||
#endif
|
||||
#ifdef TCP_SIGNATURE
|
||||
struct secasvar *sav;
|
||||
#endif
|
||||
|
||||
hlen =
|
||||
#ifdef INET6
|
||||
@ -1508,8 +1509,29 @@ syncache_respond(struct syncache *sc)
|
||||
if (sc->sc_flags & SCF_SACK)
|
||||
to.to_flags |= TOF_SACKPERM;
|
||||
#ifdef TCP_SIGNATURE
|
||||
if (sc->sc_flags & SCF_SIGNATURE)
|
||||
to.to_flags |= TOF_SIGNATURE;
|
||||
sav = NULL;
|
||||
if (sc->sc_flags & SCF_SIGNATURE) {
|
||||
sav = tcp_get_sav(m, IPSEC_DIR_OUTBOUND);
|
||||
if (sav != NULL)
|
||||
to.to_flags |= TOF_SIGNATURE;
|
||||
else {
|
||||
|
||||
/*
|
||||
* We've got SCF_SIGNATURE flag
|
||||
* inherited from listening socket,
|
||||
* but to SADB key for given source
|
||||
* address. Assume signature is not
|
||||
* required and remove signature flag
|
||||
* instead of silently dropping
|
||||
* connection.
|
||||
*/
|
||||
if (locked == 0)
|
||||
SCH_LOCK(sch);
|
||||
sc->sc_flags &= ~SCF_SIGNATURE;
|
||||
if (locked == 0)
|
||||
SCH_UNLOCK(sch);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
optlen = tcp_addoptions(&to, (u_char *)(th + 1));
|
||||
|
||||
@ -1520,8 +1542,8 @@ syncache_respond(struct syncache *sc)
|
||||
|
||||
#ifdef TCP_SIGNATURE
|
||||
if (sc->sc_flags & SCF_SIGNATURE)
|
||||
tcp_signature_compute(m, 0, 0, optlen,
|
||||
to.to_signature, IPSEC_DIR_OUTBOUND);
|
||||
tcp_signature_do_compute(m, 0, optlen,
|
||||
to.to_signature, sav);
|
||||
#endif
|
||||
#ifdef INET6
|
||||
if (sc->sc_inc.inc_flags & INC_ISIPV6)
|
||||
|
@ -685,9 +685,15 @@ int tcp_twcheck(struct inpcb *, struct tcpopt *, struct tcphdr *,
|
||||
struct mbuf *, int);
|
||||
void tcp_setpersist(struct tcpcb *);
|
||||
#ifdef TCP_SIGNATURE
|
||||
struct secasvar;
|
||||
struct secasvar *tcp_get_sav(struct mbuf *, u_int);
|
||||
int tcp_signature_do_compute(struct mbuf *, int, int, u_char *,
|
||||
struct secasvar *);
|
||||
int tcp_signature_compute(struct mbuf *, int, int, int, u_char *, u_int);
|
||||
int tcp_signature_verify(struct mbuf *, int, int, int, struct tcpopt *,
|
||||
struct tcphdr *, u_int);
|
||||
int tcp_signature_check(struct mbuf *m, int off0, int tlen, int optlen,
|
||||
struct tcpopt *to, struct tcphdr *th, u_int tcpbflag);
|
||||
#endif
|
||||
void tcp_slowtimo(void);
|
||||
struct tcptemp *
|
||||
|
Loading…
x
Reference in New Issue
Block a user