Hi,

I'm working on supporting receiving and sending multiple proposals.
While doing that I realized that our proposal matching algorithm might
accept a proposal we can't fully accept.

The RFC specifies that to accept a proposal, we must select a transform
for each transform type.  We do some sanity checks, for instance we do
require an encryption transform for ESP, but that's not enough.  We need
to check that for every proposed transform type we have found a matching
transform in our own proposal.

ok?

Patrick

diff --git a/sbin/iked/ikev2.c b/sbin/iked/ikev2.c
index fbc487695a9..062b6a50b40 100644
--- a/sbin/iked/ikev2.c
+++ b/sbin/iked/ikev2.c
@@ -4079,9 +4079,22 @@ ikev2_match_proposals(struct iked_proposal *local, 
struct iked_proposal *peer,
        struct iked_transform   *tpeer, *tlocal;
        unsigned int             i, j, type, score, requiredh = 0;
        uint8_t                  protoid = peer->prop_protoid;
+       uint8_t                  peerxfs[IKEV2_XFORMTYPE_MAX];
+
+       bzero(peerxfs, sizeof(peerxfs));
 
        for (i = 0; i < peer->prop_nxforms; i++) {
                tpeer = peer->prop_xforms + i;
+               if (tpeer->xform_type > IKEV2_XFORMTYPE_MAX)
+                       continue;
+
+               /*
+                * Record all transform types from the peer's proposal,
+                * because if we want this proposal we have to select
+                * a transform for each proposed transform type.
+                */
+               peerxfs[tpeer->xform_type] = 1;
+
                for (j = 0; j < local->prop_nxforms; j++) {
                        tlocal = local->prop_xforms + j;
 
@@ -4099,8 +4112,6 @@ ikev2_match_proposals(struct iked_proposal *local, struct 
iked_proposal *peer,
                            tpeer->xform_id != tlocal->xform_id ||
                            tpeer->xform_length != tlocal->xform_length)
                                continue;
-                       if (tpeer->xform_type > IKEV2_XFORMTYPE_MAX)
-                               continue;
                        type = tpeer->xform_type;
 
                        if (xforms[type] == NULL || tlocal->xform_score <
@@ -4136,6 +4147,9 @@ ikev2_match_proposals(struct iked_proposal *local, struct 
iked_proposal *peer,
                    (requiredh && i == IKEV2_XFORMTYPE_DH))) {
                        score = 0;
                        break;
+               } else if (peerxfs[i] && xforms[i] == NULL) {
+                       score = 0;
+                       break;
                } else if (xforms[i] == NULL)
                        continue;
 

Reply via email to