diff options
author | Hakan Olsson <ho@cvs.openbsd.org> | 2003-11-06 15:55:55 +0000 |
---|---|---|
committer | Hakan Olsson <ho@cvs.openbsd.org> | 2003-11-06 15:55:55 +0000 |
commit | 19ab6f203585d2248f3829418d72906d79d633f4 (patch) | |
tree | 1e2f591e7b36fdc18315a750846073579d2724d0 /sbin/isakmpd | |
parent | ba4efe5356f0caf0c07313ee2fd57257495c1514 (diff) |
Require encrypted messages are soon as we have the keystate for it.
Require DELETE payloads to be accompanied by HASHes, and add validation
for HASH payloads without active exchanges.
From Hans-Joerg Hoexer with various modifications and suggestions from me
and markus@. Ok markus@.
Diffstat (limited to 'sbin/isakmpd')
-rw-r--r-- | sbin/isakmpd/exchange.c | 8 | ||||
-rw-r--r-- | sbin/isakmpd/message.c | 99 |
2 files changed, 98 insertions, 9 deletions
diff --git a/sbin/isakmpd/exchange.c b/sbin/isakmpd/exchange.c index 52f652380bc..f142c2f4cf7 100644 --- a/sbin/isakmpd/exchange.c +++ b/sbin/isakmpd/exchange.c @@ -1,4 +1,4 @@ -/* $OpenBSD: exchange.c,v 1.86 2003/10/14 14:29:15 ho Exp $ */ +/* $OpenBSD: exchange.c,v 1.87 2003/11/06 15:55:54 ho Exp $ */ /* $EOM: exchange.c,v 1.143 2000/12/04 00:02:25 angelos Exp $ */ /* @@ -220,8 +220,10 @@ exchange_validate (struct message *msg) && !TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_HASH]) && !TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_SIG])) || (*pc == EXCHANGE_SCRIPT_INFO - && !TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_NOTIFY]) - && !TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_DELETE]))) + && ((!TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_NOTIFY]) + && !TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_DELETE])) + || (TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_DELETE]) + && !TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_HASH]))))) { /* Missing payload. */ LOG_DBG ((LOG_MESSAGE, 70, diff --git a/sbin/isakmpd/message.c b/sbin/isakmpd/message.c index e7eee52a07b..030132fb9ff 100644 --- a/sbin/isakmpd/message.c +++ b/sbin/isakmpd/message.c @@ -1,4 +1,4 @@ -/* $OpenBSD: message.c,v 1.61 2003/09/02 18:14:52 ho Exp $ */ +/* $OpenBSD: message.c,v 1.62 2003/11/06 15:55:54 ho Exp $ */ /* $EOM: message.c,v 1.156 2000/10/10 12:36:39 provos Exp $ */ /* @@ -47,10 +47,13 @@ #include "doi.h" #include "exchange.h" #include "field.h" +#include "hash.h" +#include "ipsec.h" #include "ipsec_num.h" #include "isakmp.h" #include "log.h" #include "message.h" +#include "prf.h" #include "sa.h" #include "timer.h" #include "transport.h" @@ -477,11 +480,93 @@ message_validate_delete (struct message *msg, struct payload *p) } /* - * Validate the hash payload P in message MSG. */ + * Validate the hash payload P in message MSG. + * XXX Currently hash payloads are processed by the particular exchanges, + * except INFORMATIONAL. This should be actually done here. + */ static int message_validate_hash (struct message *msg, struct payload *p) { - /* XXX Not implemented yet. */ + struct sa *isakmp_sa = msg->isakmp_sa; + struct ipsec_sa *isa; + struct hash *hash; + struct payload *hashp = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_HASH]); + struct prf *prf; + u_int8_t *comp_hash, *rest; + u_int8_t message_id[ISAKMP_HDR_MESSAGE_ID_LEN]; + size_t rest_len; + + if (msg->exchange) /* active exchange validates hash payload. */ + return 0; + + if (isakmp_sa == NULL) + { + log_print ("message_validate_hash: invalid hash information"); + return -1; + } + + isa = isakmp_sa->data; + hash = hash_get (isa->hash); + + if (hash == NULL) + { + log_print ("message_validate_hash: invalid hash information"); + return -1; + } + + /* If no SKEYID_a, we can not do anything (should not happen). */ + if (!isa->skeyid_a) + { + log_print ("message_validate_hash: invalid hash information"); + return -1; + } + + /* Allocate the prf and start calculating our HASH(1). */ + LOG_DBG_BUF ((LOG_MISC, 90, "message_validate_hash: SKEYID_a", isa->skeyid_a, + isa->skeyid_len)); + prf = prf_alloc (isa->prf_type, hash->type, isa->skeyid_a, isa->skeyid_len); + if (!prf) + return -1; + + comp_hash = (u_int8_t *)malloc (hash->hashsize); + if (!comp_hash) + { + log_error ("message_validate_hash: malloc (%lu) failed", + (unsigned long)hash->hashsize); + prf_free (prf); + return -1; + } + + /* This is not an active exchange. */ + GET_ISAKMP_HDR_MESSAGE_ID (msg->iov[0].iov_base, message_id); + + prf->Init (prf->prfctx); + LOG_DBG_BUF ((LOG_MISC, 90, "message_validate_hash: message_id", + message_id, ISAKMP_HDR_MESSAGE_ID_LEN)); + prf->Update (prf->prfctx, message_id, ISAKMP_HDR_MESSAGE_ID_LEN); + rest = hashp->p + GET_ISAKMP_GEN_LENGTH (hashp->p); + rest_len = (GET_ISAKMP_HDR_LENGTH (msg->iov[0].iov_base) + - (rest - (u_int8_t*)msg->iov[0].iov_base)); + LOG_DBG_BUF ((LOG_MISC, 90, "message_validate_hash: payloads after HASH(1)", + rest, rest_len)); + prf->Update (prf->prfctx, rest, rest_len); + prf->Final (comp_hash, prf->prfctx); + prf_free (prf); + + if (memcmp (hashp->p + ISAKMP_HASH_DATA_OFF, comp_hash, hash->hashsize)) + { + log_print ("message_validate_hash: invalid hash value for %s payload", + TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_DELETE]) + ? "DELETE" : "NOTIFY"); + message_drop (msg, ISAKMP_NOTIFY_INVALID_HASH_INFORMATION, 0, 1, 0); + free (comp_hash); + return -1; + } + free (comp_hash); + + /* Mark the HASH as handled. */ + hashp->flags |= PL_MARK; + return 0; } @@ -1217,10 +1302,12 @@ message_recv (struct message *msg) && (flags & ISAKMP_FLAGS_COMMIT)) msg->exchange->flags |= EXCHANGE_FLAG_HE_COMMITTED; - /* Require encryption for any phase 2 message. XXX Always? */ - if (msg->exchange->phase == 2 && (flags & ISAKMP_FLAGS_ENC) == 0) + /* Require encryption as soon as we have the keystate for it. */ + if ((flags & ISAKMP_FLAGS_ENC) == 0 && + (msg->exchange->phase == 2 || msg->exchange->keystate)) { - log_print ("message_recv: cleartext phase 2 message"); + log_print ("message_recv: cleartext phase %d message", + msg->exchange->phase); message_drop (msg, ISAKMP_NOTIFY_INVALID_FLAGS, 0, 1, 1); return -1; } |