summaryrefslogtreecommitdiff
path: root/sys/netinet/ip_ipsp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet/ip_ipsp.c')
-rw-r--r--sys/netinet/ip_ipsp.c143
1 files changed, 73 insertions, 70 deletions
diff --git a/sys/netinet/ip_ipsp.c b/sys/netinet/ip_ipsp.c
index e1f61e406d0..ffb957b376e 100644
--- a/sys/netinet/ip_ipsp.c
+++ b/sys/netinet/ip_ipsp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ipsp.c,v 1.146 2002/03/14 01:27:11 millert Exp $ */
+/* $OpenBSD: ip_ipsp.c,v 1.147 2002/05/31 02:41:08 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr),
@@ -300,12 +300,62 @@ gettdb(u_int32_t spi, union sockaddr_union *dst, u_int8_t proto)
}
/*
+ * Check that credentials and IDs match. Return true if so. The t*
+ * range of arguments contains information from TDBs; the p*
+ * range of arguments contains information from policies or
+ * already established TDBs.
+ */
+int
+ipsp_aux_match(struct ipsec_ref *tsrcid, struct ipsec_ref *psrcid,
+ struct ipsec_ref *tdstid, struct ipsec_ref *pdstid,
+ struct ipsec_ref *tlcred, struct ipsec_ref *plcred,
+ struct ipsec_ref *trcred, struct ipsec_ref *prcred,
+ struct sockaddr_encap *tfilter, struct sockaddr_encap *pfilter,
+ struct sockaddr_encap *tfiltermask, struct sockaddr_encap *pfiltermask)
+{
+ if (psrcid != NULL)
+ if (tsrcid == NULL || !ipsp_ref_match(tsrcid, psrcid))
+ return 0;
+
+ if (pdstid != NULL)
+ if (tdstid == NULL || !ipsp_ref_match(tdstid, pdstid))
+ return 0;
+
+ if (plcred != NULL)
+ if (tlcred == NULL || !ipsp_ref_match(tlcred, plcred))
+ return 0;
+
+ if (prcred != NULL)
+ if (trcred == NULL || !ipsp_ref_match(trcred, prcred))
+ return 0;
+
+ /* Check for filter matches. */
+ if (tfilter->sen_type) {
+ /*
+ * XXX We should really be doing a subnet-check (see
+ * whether the TDB-associated filter is a subset
+ * of the policy's. For now, an exact match will solve
+ * most problems (all this will do is make every
+ * policy get its own SAs).
+ */
+ if (bcmp(tfilter, pfilter, sizeof(struct sockaddr_encap)) ||
+ bcmp(tfiltermask, pfiltermask,
+ sizeof(struct sockaddr_encap)))
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
* Get an SA given the remote address, the security protocol type, and
* the desired IDs.
*/
struct tdb *
-gettdbbyaddr(union sockaddr_union *dst, struct ipsec_policy *ipo,
- struct mbuf *m, int af)
+gettdbbyaddr(union sockaddr_union *dst, u_int8_t sproto,
+ struct ipsec_ref *srcid, struct ipsec_ref *dstid,
+ struct ipsec_ref *local_cred, struct mbuf *m, int af,
+ struct sockaddr_encap *filter, struct sockaddr_encap *filtermask)
{
u_int32_t hashval;
struct tdb *tdbp;
@@ -313,51 +363,18 @@ gettdbbyaddr(union sockaddr_union *dst, struct ipsec_policy *ipo,
if (tdbaddr == NULL)
return (struct tdb *) NULL;
- hashval = tdb_hash(0, dst, ipo->ipo_sproto);
+ hashval = tdb_hash(0, dst, sproto);
for (tdbp = tdbaddr[hashval]; tdbp != NULL; tdbp = tdbp->tdb_anext)
- if ((tdbp->tdb_sproto == ipo->ipo_sproto) &&
+ if ((tdbp->tdb_sproto == sproto) &&
((tdbp->tdb_flags & TDBF_INVALID) == 0) &&
(!bcmp(&tdbp->tdb_dst, dst, SA_LEN(&dst->sa)))) {
- /*
- * If the IDs are not set, this was probably a
- * manually-keyed SA, so it can be used for
- * any type of traffic.
- */
- if (tdbp->tdb_srcid != NULL) {
- if (ipo->ipo_srcid != NULL &&
- !ipsp_ref_match(ipo->ipo_srcid,
- tdbp->tdb_srcid))
- continue;
- /* Otherwise, this is fine. */
- }
-
- if (tdbp->tdb_dstid != NULL) {
- if (ipo->ipo_dstid != NULL &&
- !ipsp_ref_match(ipo->ipo_dstid,
- tdbp->tdb_dstid))
- continue;
- /* Otherwise, this is fine. */
- }
-
- /* Check for credential matches. */
- if (tdbp->tdb_local_cred != NULL) {
- if (ipo->ipo_local_cred != NULL &&
- !ipsp_ref_match(ipo->ipo_local_cred,
- tdbp->tdb_local_cred))
- continue;
- } else if (ipo->ipo_local_cred != NULL)
- continue; /* If no credential was used
- * in the TDB, try to
- * establish a new SA with
- * the given credential,
- * since some type of access
- * control may be done on
- * the other side based on
- * that credential.
- */
-
- /* XXX Check for filter matches. */
+ /* Do IDs and local credentials match ? */
+ if (!ipsp_aux_match(tdbp->tdb_srcid, srcid,
+ tdbp->tdb_dstid, dstid, tdbp->tdb_local_cred,
+ local_cred, NULL, NULL, &tdbp->tdb_filter, filter,
+ &tdbp->tdb_filtermask, filtermask))
+ continue;
break;
}
@@ -369,8 +386,10 @@ gettdbbyaddr(union sockaddr_union *dst, struct ipsec_policy *ipo,
* the desired IDs.
*/
struct tdb *
-gettdbbysrc(union sockaddr_union *src, struct ipsec_policy *ipo,
- struct mbuf *m, int af)
+gettdbbysrc(union sockaddr_union *src, u_int8_t sproto,
+ struct ipsec_ref *srcid, struct ipsec_ref *dstid,
+ struct mbuf *m, int af, struct sockaddr_encap *filter,
+ struct sockaddr_encap *filtermask)
{
u_int32_t hashval;
struct tdb *tdbp;
@@ -378,34 +397,18 @@ gettdbbysrc(union sockaddr_union *src, struct ipsec_policy *ipo,
if (tdbsrc == NULL)
return (struct tdb *) NULL;
- hashval = tdb_hash(0, src, ipo->ipo_sproto);
+ hashval = tdb_hash(0, src, sproto);
for (tdbp = tdbsrc[hashval]; tdbp != NULL; tdbp = tdbp->tdb_snext)
- if ((tdbp->tdb_sproto == ipo->ipo_sproto) &&
+ if ((tdbp->tdb_sproto == sproto) &&
((tdbp->tdb_flags & TDBF_INVALID) == 0) &&
(!bcmp(&tdbp->tdb_src, src, SA_LEN(&src->sa)))) {
- /*
- * If the IDs are not set, this was probably a
- * manually-keyed SA, so it can be used for
- * any type of traffic.
- */
- if (tdbp->tdb_srcid != NULL) {
- if (ipo->ipo_dstid != NULL &&
- !ipsp_ref_match(ipo->ipo_dstid,
- tdbp->tdb_srcid))
- continue;
- /* Otherwise, this is fine. */
- }
-
- if (tdbp->tdb_dstid != NULL) {
- if (ipo->ipo_srcid != NULL &&
- !ipsp_ref_match(ipo->ipo_srcid,
- tdbp->tdb_dstid))
- continue;
- /* Otherwise, this is fine. */
- }
-
- /* XXX Check for filter matches. */
+ /* Check whether IDs match */
+ if (!ipsp_aux_match(tdbp->tdb_srcid, dstid,
+ tdbp->tdb_dstid, srcid, NULL, NULL, NULL, NULL,
+ &tdbp->tdb_filter, filter, &tdbp->tdb_filtermask,
+ filtermask))
+ continue;
break;
}