summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/net/pfkeyv2.c215
1 files changed, 115 insertions, 100 deletions
diff --git a/sys/net/pfkeyv2.c b/sys/net/pfkeyv2.c
index db6be5819b8..44d73be335d 100644
--- a/sys/net/pfkeyv2.c
+++ b/sys/net/pfkeyv2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfkeyv2.c,v 1.81 2002/03/03 21:47:00 angelos Exp $ */
+/* $OpenBSD: pfkeyv2.c,v 1.82 2002/05/31 01:42:17 angelos Exp $ */
/*
* @(#)COPYRIGHT 1.1 (NRL) 17 January 1995
@@ -791,7 +791,7 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
{
int i, j, rval = 0, mode = PFKEYV2_SENDMESSAGE_BROADCAST, delflag = 0, s;
struct sockaddr_encap encapdst, encapnetmask, encapgw;
- struct ipsec_policy *ipo;
+ struct ipsec_policy *ipo, *tmpipo;
struct ipsec_acquire *ipa;
struct pfkeyv2_socket *pfkeyv2_socket, *so = NULL;
@@ -917,6 +917,23 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
ssa = (struct sadb_sa *) headers[SADB_EXT_SA];
sunionp = (union sockaddr_union *) (headers[SADB_EXT_ADDRESS_DST] +
sizeof(struct sadb_address));
+
+ /* Either all or none of the flow must be included */
+ if ((headers[SADB_X_EXT_SRC_FLOW] ||
+ headers[SADB_X_EXT_PROTOCOL] ||
+ headers[SADB_X_EXT_DST_FLOW] ||
+ headers[SADB_X_EXT_SRC_MASK] ||
+ headers[SADB_X_EXT_DST_MASK]) &&
+ !(headers[SADB_X_EXT_SRC_FLOW] &&
+ headers[SADB_X_EXT_PROTOCOL] &&
+ headers[SADB_X_EXT_DST_FLOW] &&
+ headers[SADB_X_EXT_SRC_MASK] &&
+ headers[SADB_X_EXT_DST_MASK]))
+ {
+ rval = EINVAL;
+ goto ret;
+ }
+
s = spltdb();
/* Find TDB */
@@ -980,6 +997,11 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
PFKEYV2_AUTH_LOCAL);
import_auth(newsa, headers[SADB_X_EXT_REMOTE_AUTH],
PFKEYV2_AUTH_REMOTE);
+ import_flow(&newsa->tdb_filter, &newsa->tdb_filtermask,
+ headers[SADB_X_EXT_SRC_FLOW], headers[SADB_X_EXT_SRC_MASK],
+ headers[SADB_X_EXT_DST_FLOW], headers[SADB_X_EXT_DST_MASK],
+ headers[SADB_X_EXT_PROTOCOL]);
+
headers[SADB_EXT_KEY_AUTH] = NULL;
headers[SADB_EXT_KEY_ENCRYPT] = NULL;
headers[SADB_X_EXT_LOCAL_AUTH] = NULL;
@@ -1031,12 +1053,27 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
splx(s);
break;
-
case SADB_ADD:
ssa = (struct sadb_sa *) headers[SADB_EXT_SA];
sunionp = (union sockaddr_union *) (headers[SADB_EXT_ADDRESS_DST] +
sizeof(struct sadb_address));
+ /* Either all or none of the flow must be included */
+ if ((headers[SADB_X_EXT_SRC_FLOW] ||
+ headers[SADB_X_EXT_PROTOCOL] ||
+ headers[SADB_X_EXT_DST_FLOW] ||
+ headers[SADB_X_EXT_SRC_MASK] ||
+ headers[SADB_X_EXT_DST_MASK]) &&
+ !(headers[SADB_X_EXT_SRC_FLOW] &&
+ headers[SADB_X_EXT_PROTOCOL] &&
+ headers[SADB_X_EXT_DST_FLOW] &&
+ headers[SADB_X_EXT_SRC_MASK] &&
+ headers[SADB_X_EXT_DST_MASK]))
+ {
+ rval = EINVAL;
+ goto ret;
+ }
+
s = spltdb();
sa2 = gettdb(ssa->sadb_sa_spi, sunionp,
@@ -1106,6 +1143,11 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
PFKEYV2_AUTH_LOCAL);
import_auth(newsa, headers[SADB_X_EXT_REMOTE_AUTH],
PFKEYV2_AUTH_REMOTE);
+ import_flow(&newsa->tdb_filter, &newsa->tdb_filtermask,
+ headers[SADB_X_EXT_SRC_FLOW], headers[SADB_X_EXT_SRC_MASK],
+ headers[SADB_X_EXT_DST_FLOW], headers[SADB_X_EXT_DST_MASK],
+ headers[SADB_X_EXT_PROTOCOL]);
+
headers[SADB_EXT_KEY_AUTH] = NULL;
headers[SADB_EXT_KEY_ENCRYPT] = NULL;
headers[SADB_X_EXT_LOCAL_AUTH] = NULL;
@@ -1273,8 +1315,19 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
{
case SADB_SATYPE_UNSPEC:
s = spltdb();
- while ((ipo = TAILQ_FIRST(&ipsec_policy_head)) != NULL)
- ipsec_delete_policy(ipo);
+
+ /*
+ * Go through the list of policies, delete those that
+ * are not socket-attached.
+ */
+ for (ipo = TAILQ_FIRST(&ipsec_policy_head);
+ ipo != NULL;
+ ipo = tmpipo)
+ {
+ tmpipo = TAILQ_NEXT(ipo, ipo_list);
+ if (!(ipo->ipo_flags & IPSP_POLICY_SOCKET))
+ ipsec_delete_policy(ipo);
+ }
splx(s);
/* Fall through */
case SADB_SATYPE_AH:
@@ -1375,10 +1428,9 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
case SADB_X_ADDFLOW:
{
- union sockaddr_union *src, *dst, *srcmask, *dstmask, *ssrc;
struct sadb_protocol *sab;
+ union sockaddr_union *ssrc;
struct route_enc re;
- u_int8_t transproto = 0;
int exists = 0;
sab = (struct sadb_protocol *) headers[SADB_X_EXT_FLOW_TYPE];
@@ -1408,89 +1460,13 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
else
ssrc = NULL;
- src = (union sockaddr_union *) (headers[SADB_X_EXT_SRC_FLOW] +
- sizeof(struct sadb_address));
- dst = (union sockaddr_union *) (headers[SADB_X_EXT_DST_FLOW] +
- sizeof(struct sadb_address));
- srcmask = (union sockaddr_union *) (headers[SADB_X_EXT_SRC_MASK] +
- sizeof(struct sadb_address));
- dstmask = (union sockaddr_union *) (headers[SADB_X_EXT_DST_MASK] +
- sizeof(struct sadb_address));
-
- /*
- * Check that all the address families match. We know they are
- * valid and supported because pfkeyv2_parsemessage() checked that.
- */
- if ((src->sa.sa_family != dst->sa.sa_family) ||
- (src->sa.sa_family != srcmask->sa.sa_family) ||
- (src->sa.sa_family != dstmask->sa.sa_family))
- {
- rval = EINVAL;
- goto ret;
- }
-
- bzero(&encapdst, sizeof(struct sockaddr_encap));
- bzero(&encapnetmask, sizeof(struct sockaddr_encap));
- bzero(&encapgw, sizeof(struct sockaddr_encap));
-
- /* Transport protocol specified ? */
- if (headers[SADB_X_EXT_PROTOCOL])
- transproto = ((struct sadb_protocol *) headers[SADB_X_EXT_PROTOCOL])->sadb_protocol_proto;
-
- /* Generic netmask handling, works for IPv4 and IPv6 */
- rt_maskedcopy(&src->sa, &src->sa, &srcmask->sa);
- rt_maskedcopy(&dst->sa, &dst->sa, &dstmask->sa);
-
- /* Setup the encap fields */
- encapdst.sen_family = encapnetmask.sen_family = PF_KEY;
- encapdst.sen_len = encapnetmask.sen_len = SENT_LEN;
-
- switch (src->sa.sa_family)
- {
-#ifdef INET
- case AF_INET:
- encapdst.sen_type = SENT_IP4;
- encapdst.sen_direction = sab->sadb_protocol_direction;
- encapdst.sen_ip_src = src->sin.sin_addr;
- encapdst.sen_ip_dst = dst->sin.sin_addr;
- encapdst.sen_proto = transproto;
- encapdst.sen_sport = src->sin.sin_port;
- encapdst.sen_dport = dst->sin.sin_port;
-
- encapnetmask.sen_type = SENT_IP4;
- encapnetmask.sen_direction = 0xff;
- encapnetmask.sen_ip_src = srcmask->sin.sin_addr;
- encapnetmask.sen_ip_dst = dstmask->sin.sin_addr;
- encapnetmask.sen_sport = srcmask->sin.sin_port;
- encapnetmask.sen_dport = dstmask->sin.sin_port;
- if (transproto)
- encapnetmask.sen_proto = 0xff;
- break;
-#endif /* INET */
-
-#ifdef INET6
- case AF_INET6:
- encapdst.sen_type = SENT_IP6;
- encapdst.sen_ip6_direction = sab->sadb_protocol_direction;
- encapdst.sen_ip6_src = src->sin6.sin6_addr;
- encapdst.sen_ip6_dst = dst->sin6.sin6_addr;
- encapdst.sen_ip6_proto = transproto;
- encapdst.sen_ip6_sport = src->sin6.sin6_port;
- encapdst.sen_ip6_dport = dst->sin6.sin6_port;
-
- encapnetmask.sen_type = SENT_IP6;
- encapnetmask.sen_ip6_direction = 0xff;
- encapnetmask.sen_ip6_src = srcmask->sin6.sin6_addr;
- encapnetmask.sen_ip6_dst = dstmask->sin6.sin6_addr;
- encapnetmask.sen_ip6_sport = srcmask->sin6.sin6_port;
- encapnetmask.sen_ip6_dport = dstmask->sin6.sin6_port;
- if (transproto)
- encapnetmask.sen_ip6_proto = 0xff;
- break;
-#endif /* INET6 */
- }
+ import_flow(&encapdst, &encapnetmask,
+ headers[SADB_X_EXT_SRC_FLOW], headers[SADB_X_EXT_SRC_MASK],
+ headers[SADB_X_EXT_DST_FLOW], headers[SADB_X_EXT_DST_MASK],
+ headers[SADB_X_EXT_PROTOCOL]);
/* Determine whether the exact same SPD entry already exists. */
+ bzero(&encapgw, sizeof(struct sockaddr_encap));
bzero(&re, sizeof(struct route_enc));
bcopy(&encapdst, &re.re_dst, sizeof(struct sockaddr_encap));
@@ -1537,7 +1513,7 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
goto ret;
}
- /* If we were asked to delete something non-existant, error */
+ /* If we were asked to delete something non-existant, error. */
splx(s);
rval = ESRCH;
break;
@@ -1562,6 +1538,7 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
}
bzero(ipo, sizeof(struct ipsec_policy));
+ ipo->ipo_ref_count = 1;
TAILQ_INIT(&ipo->ipo_acquires);
/* Finish initialization of SPD entry */
@@ -1605,7 +1582,7 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
default:
if (!exists)
- pool_put(&ipsec_policy_pool, ipo);
+ pool_put(&ipsec_policy_pool, ipo);
else
ipsec_delete_policy(ipo);
@@ -1620,22 +1597,15 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
if (sunionp)
bcopy(sunionp, &ipo->ipo_dst, sizeof(union sockaddr_union));
else
- {
- bzero(&ipo->ipo_dst, sizeof(union sockaddr_union));
- ipo->ipo_dst.sa.sa_family = src->sa.sa_family;
- ipo->ipo_dst.sa.sa_len = src->sa.sa_len;
- }
+ bzero(&ipo->ipo_dst, sizeof(union sockaddr_union));
if (ssrc)
bcopy(ssrc, &ipo->ipo_src, sizeof(union sockaddr_union));
else
- {
- bzero(&ipo->ipo_src, sizeof(union sockaddr_union));
- ipo->ipo_src.sa.sa_family = src->sa.sa_family;
- ipo->ipo_src.sa.sa_len = src->sa.sa_len;
- }
+ bzero(&ipo->ipo_src, sizeof(union sockaddr_union));
ipo->ipo_sproto = SADB_X_GETSPROTO(smsg->sadb_msg_satype);
+
if (ipo->ipo_srcid)
{
ipsp_reffree(ipo->ipo_srcid);
@@ -1844,6 +1814,7 @@ pfkeyv2_acquire(struct ipsec_policy *ipo, union sockaddr_union *gw,
{
void *p, *headers[SADB_EXT_MAX + 1], *buffer = NULL;
struct sadb_ident *srcid, *dstid;
+ struct sadb_x_cred *lcred, *lauth;
struct sadb_comb *sadb_comb;
struct sadb_address *sadd;
struct sadb_prop *sa_prop;
@@ -1872,6 +1843,7 @@ pfkeyv2_acquire(struct ipsec_policy *ipo, union sockaddr_union *gw,
if (ipo->ipo_dstid)
i += sizeof(struct sadb_ident) + PADUP(ipo->ipo_dstid->ref_len);
+
/* Allocate */
if (!(p = malloc(i, M_PFKEY, M_DONTWAIT)))
{
@@ -1948,6 +1920,49 @@ pfkeyv2_acquire(struct ipsec_policy *ipo, union sockaddr_union *gw,
sizeof(struct sadb_ident), ipo->ipo_dstid->ref_len);
}
+ if (ipo->ipo_local_cred)
+ {
+ headers[SADB_X_EXT_LOCAL_CREDENTIALS] = p;
+ p += sizeof(struct sadb_x_cred) + PADUP(ipo->ipo_local_cred->ref_len);
+ lcred = (struct sadb_x_cred *) headers[SADB_X_EXT_LOCAL_CREDENTIALS];
+ lcred->sadb_x_cred_len = (sizeof(struct sadb_x_cred) +
+ PADUP(ipo->ipo_local_cred->ref_len)) /
+ sizeof(u_int64_t);
+ switch (ipo->ipo_local_cred->ref_type)
+ {
+ case IPSP_CRED_KEYNOTE:
+ lcred->sadb_x_cred_type = SADB_X_CREDTYPE_KEYNOTE;
+ break;
+ case IPSP_CRED_X509:
+ lcred->sadb_x_cred_type = SADB_X_CREDTYPE_X509;
+ break;
+ }
+ bcopy(ipo->ipo_local_cred + 1, headers[SADB_X_EXT_LOCAL_CREDENTIALS] +
+ sizeof(struct sadb_x_cred), ipo->ipo_local_cred->ref_len);
+ }
+
+ if (ipo->ipo_local_auth)
+ {
+ headers[SADB_X_EXT_LOCAL_AUTH] = p;
+ p += sizeof(struct sadb_x_cred) + PADUP(ipo->ipo_local_auth->ref_len);
+ lauth = (struct sadb_x_cred *) headers[SADB_X_EXT_LOCAL_AUTH];
+ lauth->sadb_x_cred_len = (sizeof(struct sadb_x_cred) +
+ PADUP(ipo->ipo_local_auth->ref_len)) /
+ sizeof(u_int64_t);
+ switch (ipo->ipo_local_auth->ref_type)
+ {
+ case IPSP_AUTH_PASSPHRASE:
+ lauth->sadb_x_cred_type = SADB_X_AUTHTYPE_PASSPHRASE;
+ break;
+ case IPSP_AUTH_RSA:
+ lauth->sadb_x_cred_type = SADB_X_AUTHTYPE_RSA;
+ break;
+ }
+
+ bcopy(ipo->ipo_local_auth + 1, headers[SADB_X_EXT_LOCAL_AUTH] +
+ sizeof(struct sadb_x_cred), ipo->ipo_local_auth->ref_len);
+ }
+
headers[SADB_EXT_PROPOSAL] = p;
p += sizeof(struct sadb_prop);
sa_prop = (struct sadb_prop *) headers[SADB_EXT_PROPOSAL];