summaryrefslogtreecommitdiff
path: root/sbin/isakmpd
diff options
context:
space:
mode:
authorHakan Olsson <ho@cvs.openbsd.org>2003-11-06 15:55:55 +0000
committerHakan Olsson <ho@cvs.openbsd.org>2003-11-06 15:55:55 +0000
commit19ab6f203585d2248f3829418d72906d79d633f4 (patch)
tree1e2f591e7b36fdc18315a750846073579d2724d0 /sbin/isakmpd
parentba4efe5356f0caf0c07313ee2fd57257495c1514 (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.c8
-rw-r--r--sbin/isakmpd/message.c99
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;
}