summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcmetz <cmetz@cvs.openbsd.org>1999-07-06 20:17:54 +0000
committercmetz <cmetz@cvs.openbsd.org>1999-07-06 20:17:54 +0000
commitb572bd87e759146844b72e7a327306a471ae69c7 (patch)
tree3e21a6f1fca265ba2767f46b76bfd8d2182243b9
parent1b325370253fe0a5d55ea7f66f9477a75800daaf (diff)
Added support for TCP MD5 option (RFC 2385).
-rw-r--r--sys/conf/files10
-rw-r--r--sys/net/pfkeyv2.c25
-rw-r--r--sys/net/pfkeyv2.h23
-rw-r--r--sys/netinet/ip.h15
-rw-r--r--sys/netinet/ip_ipsp.c8
-rw-r--r--sys/netinet/ip_ipsp.h13
-rw-r--r--sys/netinet/tcp.h5
-rw-r--r--sys/netinet/tcp_input.c166
-rw-r--r--sys/netinet/tcp_output.c128
-rw-r--r--sys/netinet/tcp_subr.c95
-rw-r--r--sys/netinet/tcp_usrreq.c30
-rw-r--r--sys/netinet/tcp_var.h13
12 files changed, 494 insertions, 37 deletions
diff --git a/sys/conf/files b/sys/conf/files
index 5afdf8b393c..7b994ae2f62 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1,4 +1,4 @@
-# $OpenBSD: files,v 1.119 1999/07/01 23:10:39 deraadt Exp $
+# $OpenBSD: files,v 1.120 1999/07/06 20:17:52 cmetz Exp $
# $NetBSD: files,v 1.87 1996/05/19 17:17:50 jonathan Exp $
# @(#)files.newconf 7.5 (Berkeley) 5/10/93
@@ -455,7 +455,7 @@ file netinet/ip_state.c ipfilter
file netinet/ip_proxy.c ipfilter
file netinet/ip_auth.c ipfilter
file netinet/ip_log.c ipfilter
-file netinet/ip_ipsp.c inet & ipsec
+file netinet/ip_ipsp.c inet & (ipsec | tcp_signature)
file netinet/ip_ip4.c inet & (ipsec | mrouting)
file netinet/ip_ah.c inet & ipsec
file netinet/ip_esp.c inet & ipsec
@@ -650,6 +650,6 @@ file netinet6/in6_proto.c inet6
file netinet6/ipv6_trans.c inet6
# ... PF_KEY
-file net/pfkey.c key | ipsec
-file net/pfkeyv2.c key | ipsec
-file net/pfkeyv2_parsemessage.c key | ipsec
+file net/pfkey.c key | ipsec | tcp_signature
+file net/pfkeyv2.c key | ipsec | tcp_signature
+file net/pfkeyv2_parsemessage.c key | ipsec | tcp_signature
diff --git a/sys/net/pfkeyv2.c b/sys/net/pfkeyv2.c
index f9aed42b41c..46b84dc1b5e 100644
--- a/sys/net/pfkeyv2.c
+++ b/sys/net/pfkeyv2.c
@@ -774,6 +774,12 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
sa.tdb_sproto = IPPROTO_IPIP;
break;
+#ifdef TCP_SIGNATURE
+ case SADB_X_SATYPE_TCPSIGNATURE:
+ sa.tdb_sproto = IPPROTO_TCP;
+ break;
+#endif /* TCP_SIGNATURE */
+
default: /* Nothing else supported */
rval = EOPNOTSUPP;
goto ret;
@@ -861,6 +867,13 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
newsa->tdb_sproto = IPPROTO_IPIP;
alg = XF_IP4;
break;
+
+#ifdef TCP_SIGNATURE
+ case SADB_X_SATYPE_TCPSIGNATURE:
+ newsa->tdb_sproto = IPPROTO_TCP;
+ alg = XF_TCPSIGNATURE;
+ break;
+#endif /* TCP_SIGNATURE */
default: /* Nothing else supported */
rval = EOPNOTSUPP;
@@ -988,6 +1001,13 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
alg = XF_IP4;
break;
+#ifdef TCP_SIGNATURE
+ case SADB_X_SATYPE_TCPSIGNATURE:
+ newsa->tdb_sproto = IPPROTO_TCP;
+ alg = XF_TCPSIGNATURE;
+ break;
+#endif /* TCP_SIGNATURE */
+
default: /* Nothing else supported */
rval = EOPNOTSUPP;
goto splxret;
@@ -1757,6 +1777,11 @@ pfkeyv2_expire(struct tdb *sa, u_int16_t type)
case IPPROTO_IPIP:
satype = SADB_X_SATYPE_IPIP;
break;
+#ifdef TCP_SIGNATURE
+ case IPPROTO_TCP:
+ satype = SADB_X_SATYPE_TCPSIGNATURE;
+ break;
+#endif /* TCP_SIGNATURE */
default:
rval = EOPNOTSUPP;
goto ret;
diff --git a/sys/net/pfkeyv2.h b/sys/net/pfkeyv2.h
index 36f22763df6..1a7f52d0d5b 100644
--- a/sys/net/pfkeyv2.h
+++ b/sys/net/pfkeyv2.h
@@ -191,17 +191,18 @@ struct sadb_protocol {
#define SADB_EXT_MAX 22
/* Fix pfkeyv2.c struct pfkeyv2_socket if SATYPE_MAX > 31 */
-#define SADB_SATYPE_UNSPEC 0
-#define SADB_SATYPE_AH 1
-#define SADB_SATYPE_ESP 2
-#define SADB_SATYPE_RSVP 3
-#define SADB_SATYPE_OSPFV2 4
-#define SADB_SATYPE_RIPV2 5
-#define SADB_SATYPE_MIP 6
-#define SADB_X_SATYPE_AH_OLD 7
-#define SADB_X_SATYPE_ESP_OLD 8
-#define SADB_X_SATYPE_IPIP 9
-#define SADB_SATYPE_MAX 9
+#define SADB_SATYPE_UNSPEC 0
+#define SADB_SATYPE_AH 1
+#define SADB_SATYPE_ESP 2
+#define SADB_SATYPE_RSVP 3
+#define SADB_SATYPE_OSPFV2 4
+#define SADB_SATYPE_RIPV2 5
+#define SADB_SATYPE_MIP 6
+#define SADB_X_SATYPE_AH_OLD 7
+#define SADB_X_SATYPE_ESP_OLD 8
+#define SADB_X_SATYPE_IPIP 9
+#define SADB_X_SATYPE_TCPSIGNATURE 10
+#define SADB_SATYPE_MAX 10
#define SADB_SASTATE_LARVAL 0
#define SADB_SASTATE_MATURE 1
diff --git a/sys/netinet/ip.h b/sys/netinet/ip.h
index b3326f17066..524938bb9c7 100644
--- a/sys/netinet/ip.h
+++ b/sys/netinet/ip.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip.h,v 1.4 1997/02/24 14:06:36 niklas Exp $ */
+/* $OpenBSD: ip.h,v 1.5 1999/07/06 20:17:52 cmetz Exp $ */
/* $NetBSD: ip.h,v 1.9 1995/05/15 01:22:44 cgd Exp $ */
/*
@@ -167,3 +167,16 @@ struct ip_timestamp {
#define IPTTLDEC 1 /* subtracted when forwarding */
#define IP_MSS 576 /* default maximum segment size */
+
+/*
+ * This is the real IPv4 psuedo header, used for computing the TCP and UDP
+ * checksums. For the Internet checksum, struct ipovly can be used instead.
+ * For stronger checksums, the real thing must be used.
+ */
+struct ippseudo {
+ struct in_addr ippseudo_src; /* source internet address */
+ struct in_addr ippseudo_dst; /* destination internet address */
+ u_int8_t ippseudo_pad; /* pad, must be zero */
+ u_int8_t ippseudo_p; /* protocol */
+ u_int16_t ippseudo_len; /* protocol length */
+};
diff --git a/sys/netinet/ip_ipsp.c b/sys/netinet/ip_ipsp.c
index 17aee8d995a..749c747c347 100644
--- a/sys/netinet/ip_ipsp.c
+++ b/sys/netinet/ip_ipsp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ipsp.c,v 1.46 1999/06/07 07:20:38 angelos Exp $ */
+/* $OpenBSD: ip_ipsp.c,v 1.47 1999/07/06 20:17:52 cmetz Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -139,6 +139,12 @@ struct xformsw xformsw[] = {
"Encryption + Authentication + Replay Protection",
esp_new_attach, esp_new_init, esp_new_zeroize,
esp_new_input, esp_new_output, },
+#ifdef TCP_SIGNATURE
+ { XF_TCPSIGNATURE, XFT_AUTH, "TCP MD5 Signature Option, RFC 2385",
+ tcp_signature_tdb_attach, tcp_signature_tdb_init,
+ tcp_signature_tdb_zeroize, tcp_signature_tdb_input,
+ tcp_signature_tdb_output, }
+#endif /* TCP_SIGNATURE */
};
struct xformsw *xformswNXFORMSW = &xformsw[sizeof(xformsw)/sizeof(xformsw[0])];
diff --git a/sys/netinet/ip_ipsp.h b/sys/netinet/ip_ipsp.h
index 02e861e3594..7c256a5767c 100644
--- a/sys/netinet/ip_ipsp.h
+++ b/sys/netinet/ip_ipsp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ipsp.h,v 1.37 1999/06/30 17:23:59 deraadt Exp $ */
+/* $OpenBSD: ip_ipsp.h,v 1.38 1999/07/06 20:17:52 cmetz Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -356,6 +356,7 @@ struct xformsw
#define XF_OLD_ESP 3 /* RFCs 1829 & 1851 */
#define XF_NEW_AH 4 /* AH HMAC 96bits */
#define XF_NEW_ESP 5 /* ESP + auth 96bits + replay counter */
+#define XF_TCPSIGNATURE 6 /* TCP MD5 Signature option, RFC 2358 */
/* xform attributes */
#define XFT_AUTH 0x0001
@@ -494,6 +495,16 @@ extern int esp_new_output(struct mbuf *, struct sockaddr_encap *, struct tdb *,
struct mbuf **);
extern struct mbuf *esp_new_input(struct mbuf *, struct tdb *);
+/* XF_TCPSIGNATURE */
+extern int tcp_signature_tdb_attach __P((void));
+extern int tcp_signature_tdb_init __P((struct tdb *, struct xformsw *,
+ struct ipsecinit *));
+extern int tcp_signature_tdb_zeroize __P((struct tdb *));
+extern struct mbuf *tcp_signature_tdb_input __P((struct mbuf *, struct tdb *));
+extern int tcp_signature_tdb_output __P((struct mbuf *,
+ struct sockaddr_encap *, struct tdb *,
+ struct mbuf **));
+
/* Padding */
extern caddr_t m_pad(struct mbuf *, int, int);
diff --git a/sys/netinet/tcp.h b/sys/netinet/tcp.h
index b32970f4f4a..0bd98882b2b 100644
--- a/sys/netinet/tcp.h
+++ b/sys/netinet/tcp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp.h,v 1.7 1999/07/02 21:22:13 cmetz Exp $ */
+/* $OpenBSD: tcp.h,v 1.8 1999/07/06 20:17:52 cmetz Exp $ */
/* $NetBSD: tcp.h,v 1.8 1995/04/17 05:32:58 cgd Exp $ */
/*
@@ -85,6 +85,8 @@ struct tcphdr {
#define TCPOPT_TIMESTAMP 8
#define TCPOLEN_TIMESTAMP 10
#define TCPOLEN_TSTAMP_APPA (TCPOLEN_TIMESTAMP+2) /* appendix A */
+#define TCPOPT_SIGNATURE 19
+#define TCPOLEN_SIGNATURE 18
#define MAX_TCPOPTLEN 40 /* Absolute maximum TCP options len */
@@ -118,6 +120,7 @@ struct tcphdr {
*/
#define TCP_NODELAY 0x01 /* don't delay send to coalesce pkts */
#define TCP_MAXSEG 0x02 /* set maximum segment size */
+#define TCP_SIGNATURE_ENABLE 0x04 /* enable TCP MD5 signature option */
#define TCP_SACK_DISABLE 0x300 /* disable SACKs (if enabled by def.) */
#endif /* !_NETINET_TCP_H_ */
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index 4bc691e5928..9674066c544 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_input.c,v 1.39 1999/07/06 20:14:06 cmetz Exp $ */
+/* $OpenBSD: tcp_input.c,v 1.40 1999/07/06 20:17:52 cmetz Exp $ */
/* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */
/*
@@ -758,9 +758,15 @@ findpcb:
* Process options if not in LISTEN state,
* else do it below (after getting remote address).
*/
- if (optp && tp->t_state != TCPS_LISTEN)
- tcp_dooptions(tp, optp, optlen, th,
- &ts_present, &ts_val, &ts_ecr);
+ if (tp->t_state != TCPS_LISTEN)
+#ifdef TCP_SIGNATURE
+ if (optp || (tp->t_flags & TF_SIGNATURE))
+#else /* TCP_SIGNATURE */
+ if (optp)
+#endif /* TCP_SIGNATURE */
+ if (tcp_dooptions(tp, optp, optlen, th, m, iphlen,
+ &ts_present, &ts_val, &ts_ecr))
+ goto drop;
#ifdef TCP_SACK
if (!tp->sack_disable) {
@@ -1068,7 +1074,7 @@ findpcb:
case PF_INET6:
{
struct sockaddr_in6 *sin6;
- struct laddr6;
+ struct in6_addr laddr6;
/*
* This is probably the place to set the tp->pf
@@ -1113,9 +1119,19 @@ findpcb:
goto drop;
}
- if (optp)
- tcp_dooptions(tp, optp, optlen, th,
- &ts_present, &ts_val, &ts_ecr);
+#ifdef TCP_SIGNATURE
+ if (optp || (tp->t_flags & TF_SIGNATURE)) {
+#else /* TCP_SIGNATURE */
+ if (optp) {
+#endif /* TCP_SIGNATURE */
+ m->m_data -= iphlen + off;
+ m->m_len += iphlen + off;
+ if (tcp_dooptions(tp, optp, optlen, th, m, iphlen,
+ &ts_present, &ts_val, &ts_ecr))
+ goto drop;
+ m->m_data += iphlen + off;
+ m->m_len -= iphlen + off;
+ }
#ifdef TCP_SACK
/*
@@ -2137,17 +2153,22 @@ drop:
#ifndef TUBA_INCLUDE
}
-void
-tcp_dooptions(tp, cp, cnt, th, ts_present, ts_val, ts_ecr)
+int
+tcp_dooptions(tp, cp, cnt, th, m, iphlen, ts_present, ts_val, ts_ecr)
struct tcpcb *tp;
u_char *cp;
int cnt;
struct tcphdr *th;
+ struct mbuf *m;
+ int iphlen;
int *ts_present;
u_int32_t *ts_val, *ts_ecr;
{
u_int16_t mss = 0;
int opt, optlen;
+#ifdef TCP_SIGNATURE
+ caddr_t sigp = NULL;
+#endif /* TCP_SIGNATURE */
for (; cnt > 0; cnt -= optlen, cp += optlen) {
opt = cp[0];
@@ -2216,12 +2237,137 @@ tcp_dooptions(tp, cp, cnt, th, ts_present, ts_val, ts_ecr)
continue;
break;
#endif
+#ifdef TCP_SIGNATURE
+ case TCPOPT_SIGNATURE:
+ if (optlen != TCPOLEN_SIGNATURE)
+ continue;
+
+ if (sigp && bcmp(sigp, cp + 2, 16))
+ return -1;
+
+ sigp = cp + 2;
+ break;
+#endif /* TCP_SIGNATURE */
}
}
+#ifdef TCP_SIGNATURE
+ if ((sigp ? TF_SIGNATURE : 0) ^ (tp->t_flags & TF_SIGNATURE)) {
+ tcpstat.tcps_rcvbadsig++;
+ return -1;
+ }
+
+ if (sigp) {
+ MD5_CTX ctx;
+ union sockaddr_union sa;
+ struct tdb *tdb;
+ char sig[16];
+
+ memset(&sa, 0, sizeof(union sockaddr_union));
+
+ switch (tp->pf) {
+ case 0:
+ case AF_INET:
+ sa.sa.sa_len = sizeof(struct sockaddr_in);
+ sa.sa.sa_family = AF_INET;
+ sa.sin.sin_addr = tp->t_inpcb->inp_laddr;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ sa.sa.sa_len = sizeof(struct sockaddr_in6);
+ sa.sa.sa_family = AF_INET6;
+ sa.sin6.sin6_addr = tp->t_inpcb->inp_laddr6;
+ break;
+#endif /* INET6 */
+ }
+
+ tdb = gettdb(0, &sa, IPPROTO_TCP);
+ if (tdb == NULL) {
+ printf("tdb miss\n");
+ tcpstat.tcps_rcvbadsig++;
+ return -1;
+ }
+
+ MD5Init(&ctx);
+
+ switch(tp->pf) {
+ case 0:
+#ifdef INET
+ case AF_INET:
+ {
+ struct ippseudo ippseudo;
+
+ ippseudo.ippseudo_src =
+ tp->t_inpcb->inp_faddr;
+ ippseudo.ippseudo_dst =
+ tp->t_inpcb->inp_laddr;
+ ippseudo.ippseudo_pad = 0;
+ ippseudo.ippseudo_p = IPPROTO_TCP;
+ ippseudo.ippseudo_len = htons(
+ m->m_pkthdr.len - iphlen);
+
+ MD5Update(&ctx, (char *)&ippseudo,
+ sizeof(struct ippseudo));
+ }
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ {
+ static int printed = 0;
+
+ if (!printed) {
+ printf("error: TCP MD5 support"
+ " for IPv6 not yet"
+ " implemented.\n");
+ printed = 1;
+ }
+ }
+ break
+#endif /* INET6 */
+ }
+
+ {
+ struct tcphdr tcphdr;
+
+ tcphdr.th_sport = th->th_sport;
+ tcphdr.th_dport = th->th_dport;
+ tcphdr.th_seq = htonl(th->th_seq);
+ tcphdr.th_ack = htonl(th->th_ack);
+ tcphdr.th_off = th->th_off;
+ tcphdr.th_x2 = th->th_x2;
+ tcphdr.th_flags = th->th_flags;
+ tcphdr.th_win = htons(th->th_win);
+ tcphdr.th_sum = 0;
+ tcphdr.th_urp = htons(th->th_urp);
+
+ MD5Update(&ctx, (char *)&tcphdr,
+ sizeof(struct tcphdr));
+ }
+
+ if (m_apply(m, iphlen + th->th_off * sizeof(uint32_t),
+ m->m_pkthdr.len - (iphlen + th->th_off *
+ sizeof(uint32_t)), tcp_signature_apply,
+ (caddr_t)&ctx))
+ return (-1);
+
+ MD5Update(&ctx, tdb->tdb_amxkey, tdb->tdb_amxkeylen);
+ MD5Final(sig, &ctx);
+
+ if (bcmp(sig, sigp, 16)) {
+ tcpstat.tcps_rcvbadsig++;
+ return (-1);
+ }
+
+ tcpstat.tcps_rcvgoodsig++;
+ };
+#endif /* TCP_SIGNATURE */
+
/* Update t_maxopd and t_maxseg after all options are processed */
if (th->th_flags & TH_SYN)
(void) tcp_mss(tp, mss); /* sets t_maxseg */
+
+ return (0);
}
#if defined(TCP_SACK) || defined(TCP_NEWRENO)
diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c
index 8c6eecfb9c7..7f79d2067a7 100644
--- a/sys/netinet/tcp_output.c
+++ b/sys/netinet/tcp_output.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_output.c,v 1.20 1999/07/06 20:14:06 cmetz Exp $ */
+/* $OpenBSD: tcp_output.c,v 1.21 1999/07/06 20:17:53 cmetz Exp $ */
/* $NetBSD: tcp_output.c,v 1.16 1997/06/03 16:17:09 kml Exp $ */
/*
@@ -83,6 +83,10 @@ didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
#include <netinet6/tcpipv6.h>
#endif /* INET6 */
+#ifdef TCP_SIGNATURE
+#include <sys/md5k.h>
+#endif /* TCP_SIGNATURE */
+
#ifdef notyet
extern struct mbuf *m_copypack();
#endif
@@ -186,6 +190,14 @@ tcp_output(tp)
#if defined(TCP_SACK) || defined(TCP_NEWRENO)
int maxburst = TCP_MAXBURST;
#endif
+#ifdef TCP_SIGNATURE
+ unsigned int sigoff;
+#endif /* TCP_SIGNATURE */
+
+#if defined(TCP_SACK) && defined(TCP_SIGNATURE) && defined(DIAGNOSTIC)
+ if (!tp->sack_disable && (tp->t_flags & TF_SIGNATURE))
+ return (EINVAL);
+#endif /* defined(TCP_SACK) && defined(TCP_SIGNATURE) && defined(DIAGNOSTIC) */
/*
* Determine length of data that should be transmitted,
@@ -509,6 +521,33 @@ send:
optlen += TCPOLEN_TSTAMP_APPA;
}
+#ifdef TCP_SIGNATURE
+ if (tp->t_flags & TF_SIGNATURE) {
+ u_int8_t *bp = (u_int8_t *)(opt + optlen);
+
+ /* Send signature option */
+ *(bp++) = TCPOPT_SIGNATURE;
+ *(bp++) = TCPOLEN_SIGNATURE;
+ sigoff = optlen + 2;
+
+ {
+ unsigned int i;
+
+ for (i = 0; i < 16; i++)
+ *(bp++) = 0;
+ }
+
+ optlen += TCPOLEN_SIGNATURE;
+
+ /* Pad options list to the next 32 bit boundary and
+ * terminate it.
+ */
+ *bp++ = TCPOPT_NOP;
+ *bp++ = TCPOPT_EOL;
+ optlen += 2;
+ }
+#endif /* TCP_SIGNATURE */
+
#ifdef TCP_SACK
/*
* Send SACKs if necessary. This should be the last option processed.
@@ -743,6 +782,93 @@ send:
#endif /* INET6 */
}
+#ifdef TCP_SIGNATURE
+ if (tp->t_flags & TF_SIGNATURE) {
+ MD5_CTX ctx;
+ union sockaddr_union sa;
+ struct tdb *tdb;
+
+ memset(&sa, 0, sizeof(union sockaddr_union));
+
+#if defined(INET) && defined(INET6)
+ switch(tp->pf) {
+#else /* defined(INET) && defined(INET6) */
+ switch (0) {
+#endif /* defined(INET) && defined(INET6) */
+ case 0:
+#ifdef INET
+ case AF_INET:
+ sa.sa.sa_len = sizeof(struct sockaddr_in);
+ sa.sa.sa_family = AF_INET;
+ sa.sin.sin_addr = mtod(m, struct ip *)->ip_dst;
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ sa.sa.sa_len = sizeof(struct sockaddr_in6);
+ sa.sa.sa_family = AF_INET6;
+ sa.sin6.sin6_addr = mtod(m, struct ipv6 *)->ipv6_dst;
+ break;
+#endif /* INET6 */
+ }
+
+ tdb = gettdb(0, &sa, IPPROTO_TCP);
+ if (tdb == NULL)
+ return (EPERM);
+
+ MD5Init(&ctx);
+
+#if defined(INET) && defined(INET6)
+ switch(tp->pf) {
+#else /* defined(INET) && defined(INET6) */
+ switch (0) {
+#endif /* defined(INET) && defined(INET6) */
+ case 0:
+#ifdef INET
+ case AF_INET:
+ {
+ struct ippseudo ippseudo;
+ struct ipovly *ipovly;
+
+ ipovly = mtod(m, struct ipovly *);
+
+ ippseudo.ippseudo_src = ipovly->ih_src;
+ ippseudo.ippseudo_dst = ipovly->ih_dst;
+ ippseudo.ippseudo_pad = 0;
+ ippseudo.ippseudo_p = IPPROTO_TCP;
+ ippseudo.ippseudo_len = ipovly->ih_len;
+ MD5Update(&ctx, (char *)&ippseudo,
+ sizeof(struct ippseudo));
+ MD5Update(&ctx, mtod(m, caddr_t) +
+ sizeof(struct ip),
+ sizeof(struct tcphdr));
+ }
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ {
+ static int printed = 0;
+
+ if (!printed) {
+ printf("error: TCP MD5 support for "
+ "IPv6 not yet implemented.\n");
+ printed = 1;
+ }
+ }
+ break;
+#endif /* INET6 */
+ }
+
+ if (len && m_apply(m, hdrlen, len, tcp_signature_apply,
+ (caddr_t)&ctx))
+ return (EINVAL);
+
+ MD5Update(&ctx, tdb->tdb_amxkey, tdb->tdb_amxkeylen);
+ MD5Final(mtod(m, caddr_t) + hdrlen - optlen + sigoff, &ctx);
+ }
+#endif /* TCP_SIGNATURE */
+
/*
* Put TCP length in extended header, and then
* checksum extended header and data.
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index 5c733a877ad..b0f498d808c 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_subr.c,v 1.17 1999/07/06 18:01:55 cmetz Exp $ */
+/* $OpenBSD: tcp_subr.c,v 1.18 1999/07/06 20:17:53 cmetz Exp $ */
/* $NetBSD: tcp_subr.c,v 1.22 1996/02/13 23:44:00 christos Exp $ */
/*
@@ -81,6 +81,10 @@ didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
#include <sys/domain.h>
#endif /* INET6 */
+#ifdef TCP_SIGNATURE
+#include <sys/md5k.h>
+#endif /* TCP_SIGNATURE */
+
/* patchable/settable parameters for tcp */
int tcp_mssdflt = TCP_MSS;
int tcp_rttdflt = TCPTV_SRTTDFLT / PR_SLOWHZ;
@@ -756,3 +760,92 @@ tcp_quench(inp, errno)
if (tp)
tp->snd_cwnd = tp->t_maxseg;
}
+
+#ifdef TCP_SIGNATURE
+int
+tcp_signature_tdb_attach()
+{
+ return (0);
+}
+
+int
+tcp_signature_tdb_init(tdbp, xsp, ii)
+ struct tdb *tdbp;
+ struct xformsw *xsp;
+ struct ipsecinit *ii;
+{
+ char *c;
+#define isdigit(c) (((c) >= '0') && ((c) <= '9'))
+#define isalpha(c) ( (((c) >= 'A') && ((c) <= 'Z')) || \
+ (((c) >= 'a') && ((c) <= 'z')) )
+
+ if ((ii->ii_authkeylen < 1) || (ii->ii_authkeylen > 80))
+ return (EINVAL);
+
+ c = (char *)ii->ii_authkey;
+
+ while (c < (char *)ii->ii_authkey + ii->ii_authkeylen - 1) {
+ if (isdigit(*c)) {
+ if (*(c + 1) == ' ')
+ return (EINVAL);
+ } else {
+ if (!isalpha(*c))
+ return (EINVAL);
+ }
+
+ c++;
+ }
+
+ if (!isdigit(*c) && !isalpha(*c))
+ return (EINVAL);
+
+ tdbp->tdb_amxkey = malloc(ii->ii_authkeylen, M_XDATA, M_DONTWAIT);
+ if (tdbp->tdb_amxkey == NULL)
+ return (ENOMEM);
+ bcopy(ii->ii_authkey, tdbp->tdb_amxkey, ii->ii_authkeylen);
+ tdbp->tdb_amxkeylen = ii->ii_authkeylen;
+
+ return (0);
+}
+
+int
+tcp_signature_tdb_zeroize(tdbp)
+ struct tdb *tdbp;
+{
+ if (tdbp->tdb_amxkey) {
+ bzero(tdbp->tdb_amxkey, tdbp->tdb_amxkeylen);
+ free(tdbp->tdb_amxkey, M_XDATA);
+ tdbp->tdb_amxkey = NULL;
+ }
+
+ return (0);
+}
+
+struct mbuf *
+tcp_signature_tdb_input(m, tdbp)
+ struct mbuf *m;
+ struct tdb *tdbp;
+{
+ return (0);
+}
+
+int
+tcp_signature_tdb_output(m, gw, tdbp, mp)
+ struct mbuf *m;
+ struct sockaddr_encap *gw;
+ struct tdb *tdbp;
+ struct mbuf **mp;
+{
+ return (EINVAL);
+}
+
+int
+tcp_signature_apply(fstate, data, len)
+ caddr_t fstate;
+ caddr_t data;
+ unsigned int len;
+{
+ MD5Update((MD5_CTX *)fstate, (char *)data, len);
+ return 0;
+}
+#endif /* TCP_SIGNATURE */
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index de6ee75474f..d9ca963cc58 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_usrreq.c,v 1.34 1999/07/02 20:39:08 cmetz Exp $ */
+/* $OpenBSD: tcp_usrreq.c,v 1.35 1999/07/06 20:17:53 cmetz Exp $ */
/* $NetBSD: tcp_usrreq.c,v 1.20 1996/02/13 23:44:16 christos Exp $ */
/*
@@ -555,13 +555,39 @@ tcp_ctloutput(op, so, level, optname, mp)
break;
}
+ if (tp->t_flags & TF_SIGNATURE) {
+ error = EPERM;
+ break;
+ }
+
if (*mtod(m, int *))
tp->sack_disable = 1;
else
tp->sack_disable = 0;
break;
#endif
- default:
+#ifdef TCP_SIGNATURE
+ case TCP_SIGNATURE_ENABLE:
+ if (m == NULL || m->m_len < sizeof (int)) {
+ error = EINVAL;
+ break;
+ }
+
+ if (TCPS_HAVEESTABLISHED(tp->t_state)) {
+ error = EPERM;
+ break;
+ }
+
+ if (*mtod(m, int *)) {
+ tp->t_flags |= TF_SIGNATURE;
+#ifdef TCP_SACK
+ tp->sack_disable = 1;
+#endif /* TCP_SACK */
+ } else
+ tp->t_flags &= ~TF_SIGNATURE;
+ break;
+#endif /* TCP_SIGNATURE */
+ default:
error = ENOPROTOOPT;
break;
}
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index 3dfc0277860..7b583c5fae5 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_var.h,v 1.20 1999/07/02 21:22:14 cmetz Exp $ */
+/* $OpenBSD: tcp_var.h,v 1.21 1999/07/06 20:17:53 cmetz Exp $ */
/* $NetBSD: tcp_var.h,v 1.17 1996/02/13 23:44:24 christos Exp $ */
/*
@@ -76,6 +76,7 @@ struct tcpcb {
#define TF_REQ_TSTMP 0x0080 /* have/will request timestamps */
#define TF_RCVD_TSTMP 0x0100 /* a timestamp was received in SYN */
#define TF_SACK_PERMIT 0x0200 /* other side said I could SACK */
+#define TF_SIGNATURE 0x0400 /* require TCP MD5 signature */
struct mbuf *t_template; /* skeletal packet for transmit */
struct inpcb *t_inpcb; /* back pointer to internet pcb */
@@ -267,6 +268,9 @@ struct tcpstat {
u_int32_t tcps_pcbhashmiss; /* input packets missing pcb hash */
u_int32_t tcps_noport; /* no socket on port */
u_int32_t tcps_badsyn; /* SYN packet with src==dst rcv'ed */
+
+ u_int32_t tcps_rcvbadsig; /* rcvd bad/missing TCP signatures */
+ u_int64_t tcps_rcvgoodsig; /* rcvd good TCP signatures */
};
/*
@@ -326,8 +330,8 @@ struct tcpcb *
tcp_disconnect __P((struct tcpcb *));
struct tcpcb *
tcp_drop __P((struct tcpcb *, int));
-void tcp_dooptions __P((struct tcpcb *,
- u_char *, int, struct tcphdr *, int *, u_int32_t *, u_int32_t *));
+int tcp_dooptions __P((struct tcpcb *, u_char *, int, struct tcphdr *,
+ struct mbuf *, int, int *, u_int32_t *, u_int32_t *));
void tcp_drain __P((void));
void tcp_fasttimo __P((void));
void tcp_init __P((void));
@@ -373,5 +377,8 @@ void tcp_print_holes __P((struct tcpcb *tp));
int tcp_newreno __P((struct tcpcb *, struct tcphdr *));
u_long tcp_seq_subtract __P((u_long, u_long ));
#endif /* TCP_NEWRENO || TCP_SACK */
+#ifdef TCP_SIGNATURE
+int tcp_signature_apply __P((caddr_t, caddr_t, unsigned int));
+#endif /* TCP_SIGNATURE */
#endif /* _KERNEL */