diff options
author | Hans-Joerg Hoexer <hshoexer@cvs.openbsd.org> | 2005-07-25 15:03:48 +0000 |
---|---|---|
committer | Hans-Joerg Hoexer <hshoexer@cvs.openbsd.org> | 2005-07-25 15:03:48 +0000 |
commit | 8272b5713745ba8883d2ec7edc49f623a77b2b79 (patch) | |
tree | a6eccb71ae2478723b6c9c3fec1da85bfe95c6bb /sbin/isakmpd | |
parent | ce2cdc01880edacdbb20e3efb83cd3099c90f2db (diff) |
Use payload NAT-D or NAT-D-DRAFT according to NAT-T vendor ID advertised by the
peer.
looks good ho
Diffstat (limited to 'sbin/isakmpd')
-rw-r--r-- | sbin/isakmpd/exchange.h | 18 | ||||
-rw-r--r-- | sbin/isakmpd/nat_traversal.c | 121 | ||||
-rw-r--r-- | sbin/isakmpd/nat_traversal.h | 15 |
3 files changed, 81 insertions, 73 deletions
diff --git a/sbin/isakmpd/exchange.h b/sbin/isakmpd/exchange.h index 35610c284be..84175afdfb3 100644 --- a/sbin/isakmpd/exchange.h +++ b/sbin/isakmpd/exchange.h @@ -1,4 +1,4 @@ -/* $OpenBSD: exchange.h,v 1.29 2005/01/31 10:07:59 hshoexer Exp $ */ +/* $OpenBSD: exchange.h,v 1.30 2005/07/25 15:03:47 hshoexer Exp $ */ /* $EOM: exchange.h,v 1.28 2000/09/28 12:54:28 niklas Exp $ */ /* @@ -210,15 +210,17 @@ struct exchange { }; /* The flag bits. */ -#define EXCHANGE_FLAG_I_COMMITTED 0x01 -#define EXCHANGE_FLAG_HE_COMMITTED 0x02 +#define EXCHANGE_FLAG_I_COMMITTED 0x0001 +#define EXCHANGE_FLAG_HE_COMMITTED 0x0002 #define EXCHANGE_FLAG_COMMITTED (EXCHANGE_FLAG_I_COMMITTED \ | EXCHANGE_FLAG_HE_COMMITTED) -#define EXCHANGE_FLAG_ENCRYPT 0x04 -#define EXCHANGE_FLAG_NAT_T_CAP_PEER 0x08 /* Peer is NAT capable. */ -#define EXCHANGE_FLAG_NAT_T_ENABLE 0x10 /* We are doing NAT-T. */ -#define EXCHANGE_FLAG_NAT_T_KEEPALIVE 0x20 /* We are the NAT:ed peer. */ -#define EXCHANGE_FLAG_DPD_CAP_PEER 0x40 /* Peer is DPD capable. */ +#define EXCHANGE_FLAG_ENCRYPT 0x0004 +#define EXCHANGE_FLAG_NAT_T_CAP_PEER 0x0008 /* Peer is NAT capable. */ +#define EXCHANGE_FLAG_NAT_T_ENABLE 0x0010 /* We are doing NAT-T. */ +#define EXCHANGE_FLAG_NAT_T_KEEPALIVE 0x0020 /* We are the NAT:ed peer. */ +#define EXCHANGE_FLAG_DPD_CAP_PEER 0x0040 /* Peer is DPD capable. */ +#define EXCHANGE_FLAG_NAT_T_RFC 0x0080 /* Peer does RFC NAT-T. */ +#define EXCHANGE_FLAG_NAT_T_DRAFT 0x0100 /* Peer does draft NAT-T.*/ extern int exchange_add_certs(struct message *); extern void exchange_finalize(struct message *); diff --git a/sbin/isakmpd/nat_traversal.c b/sbin/isakmpd/nat_traversal.c index 583e9d890c5..07f46c3291c 100644 --- a/sbin/isakmpd/nat_traversal.c +++ b/sbin/isakmpd/nat_traversal.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nat_traversal.c,v 1.15 2005/06/02 19:49:23 hshoexer Exp $ */ +/* $OpenBSD: nat_traversal.c,v 1.16 2005/07/25 15:03:47 hshoexer Exp $ */ /* * Copyright (c) 2004 Håkan Olsson. All rights reserved. @@ -56,28 +56,30 @@ int disable_nat_t = 0; * These seem to be the "well" known variants of this string in use by * products today. */ -static const char *isakmp_nat_t_cap_text[] = { - "draft-ietf-ipsec-nat-t-ike-02\n", /* draft, V2 */ - "draft-ietf-ipsec-nat-t-ike-03", /* draft, V3 */ - "RFC 3947" + +static struct nat_t_cap isakmp_nat_t_cap[] = { + { VID_DRAFT_V2_N, EXCHANGE_FLAG_NAT_T_DRAFT, + "draft-ietf-ipsec-nat-t-ike-02\n", NULL, 0 }, + { VID_DRAFT_V3, EXCHANGE_FLAG_NAT_T_DRAFT, + "draft-ietf-ipsec-nat-t-ike-03", NULL, 0 }, + { VID_RFC3947, EXCHANGE_FLAG_NAT_T_RFC, + "RFC 3947", NULL, 0 }, }; +#define NUMNATTCAP (sizeof isakmp_nat_t_cap / sizeof isakmp_nat_t_cap[0]) + /* In seconds. Recommended in draft-ietf-ipsec-udp-encaps-09. */ #define NAT_T_KEEPALIVE_INTERVAL 20 -/* The MD5 hashes of the above strings is put in this array. */ -static char **nat_t_hashes; -static size_t nat_t_hashsize; - static int nat_t_setup_hashes(void); -static int nat_t_add_vendor_payload(struct message *, char *); +static int nat_t_add_vendor_payload(struct message *, struct nat_t_cap *); static int nat_t_add_nat_d(struct message *, struct sockaddr *); static int nat_t_match_nat_d_payload(struct message *, struct sockaddr *); void nat_t_init(void) { - nat_t_hashes = (char **)NULL; + nat_t_setup_hashes(); } /* Generate the NAT-T capability marker hashes. Executed only once. */ @@ -85,7 +87,7 @@ static int nat_t_setup_hashes(void) { struct hash *hash; - int n = sizeof isakmp_nat_t_cap_text / sizeof isakmp_nat_t_cap_text[0]; + int n = NUMNATTCAP; int i; /* The draft says to use MD5. */ @@ -96,54 +98,44 @@ nat_t_setup_hashes(void) "could not find MD5 hash structure!"); return -1; } - nat_t_hashsize = hash->hashsize; - /* Allocate one more than is necessary, i.e NULL terminated. */ - nat_t_hashes = (char **)calloc((size_t)(n + 1), sizeof(char *)); - if (!nat_t_hashes) { - log_error("nat_t_setup_hashes: calloc (%lu,%lu) failed", - (unsigned long)n, (unsigned long)sizeof(char *)); - return -1; - } - - /* Populate with hashes. */ + /* Populate isakmp_nat_t_cap with hashes. */ for (i = 0; i < n; i++) { - nat_t_hashes[i] = (char *)malloc(nat_t_hashsize); - if (!nat_t_hashes[i]) { + isakmp_nat_t_cap[i].hashsize = hash->hashsize; + isakmp_nat_t_cap[i].hash = (char *)malloc(hash->hashsize); + if (!isakmp_nat_t_cap[i].hash) { log_error("nat_t_setup_hashes: malloc (%lu) failed", - (unsigned long)nat_t_hashsize); + (unsigned long)hash->hashsize); goto errout; } hash->Init(hash->ctx); hash->Update(hash->ctx, - (unsigned char *)isakmp_nat_t_cap_text[i], - strlen(isakmp_nat_t_cap_text[i])); - hash->Final(nat_t_hashes[i], hash->ctx); + (unsigned char *)isakmp_nat_t_cap[i].text, + strlen(isakmp_nat_t_cap[i].text)); + hash->Final(isakmp_nat_t_cap[i].hash, hash->ctx); LOG_DBG((LOG_EXCHANGE, 50, "nat_t_setup_hashes: " - "MD5(\"%s\") (%lu bytes)", isakmp_nat_t_cap_text[i], - (unsigned long)nat_t_hashsize)); + "MD5(\"%s\") (%lu bytes)", isakmp_nat_t_cap[i].text, + (unsigned long)hash->hashsize)); LOG_DBG_BUF((LOG_EXCHANGE, 50, "nat_t_setup_hashes", - nat_t_hashes[i], nat_t_hashsize)); + isakmp_nat_t_cap[i].hash, hash->hashsize)); } return 0; errout: for (i = 0; i < n; i++) - if (nat_t_hashes[i]) - free(nat_t_hashes[i]); - free(nat_t_hashes); - nat_t_hashes = NULL; + if (isakmp_nat_t_cap[i].hash) + free(isakmp_nat_t_cap[i].hash); return -1; } /* Add one NAT-T VENDOR payload. */ static int -nat_t_add_vendor_payload(struct message *msg, char *hash) +nat_t_add_vendor_payload(struct message *msg, struct nat_t_cap *cap) { - size_t buflen = nat_t_hashsize + ISAKMP_GEN_SZ; + size_t buflen = cap->hashsize + ISAKMP_GEN_SZ; u_int8_t *buf; if (disable_nat_t) @@ -157,7 +149,7 @@ nat_t_add_vendor_payload(struct message *msg, char *hash) } SET_ISAKMP_GEN_LENGTH(buf, buflen); - memcpy(buf + ISAKMP_VENDOR_ID_OFF, hash, nat_t_hashsize); + memcpy(buf + ISAKMP_VENDOR_ID_OFF, cap->hash, cap->hashsize); if (message_add_payload(msg, ISAKMP_PAYLOAD_VENDOR, buf, buflen, 1)) { free(buf); return -1; @@ -169,16 +161,13 @@ nat_t_add_vendor_payload(struct message *msg, char *hash) int nat_t_add_vendor_payloads(struct message *msg) { - int i = 0; + int i; if (disable_nat_t) return 0; - if (!nat_t_hashes) - if (nat_t_setup_hashes()) - return 0; /* XXX should this be an error? */ - while (nat_t_hashes[i]) - if (nat_t_add_vendor_payload(msg, nat_t_hashes[i++])) + for (i = 0; i < NUMNATTCAP; i++) + if (nat_t_add_vendor_payload(msg, &isakmp_nat_t_cap[i])) return -1; return 0; } @@ -191,39 +180,33 @@ nat_t_check_vendor_payload(struct message *msg, struct payload *p) { u_int8_t *pbuf = p->p; size_t vlen; - int i = 0; + int i; if (disable_nat_t) return; - /* Already checked? */ - if (p->flags & PL_MARK || - msg->exchange->flags & EXCHANGE_FLAG_NAT_T_CAP_PEER) - return; - - if (!nat_t_hashes) - if (nat_t_setup_hashes()) - return; - vlen = GET_ISAKMP_GEN_LENGTH(pbuf) - ISAKMP_GEN_SZ; - if (vlen != nat_t_hashsize) { - LOG_DBG((LOG_EXCHANGE, 50, "nat_t_check_vendor_payload: " - "bad size %lu != %lu", (unsigned long)vlen, - (unsigned long)nat_t_hashsize)); - return; - } - while (nat_t_hashes[i]) - if (memcmp(nat_t_hashes[i++], pbuf + ISAKMP_GEN_SZ, + for (i = 0; i < NUMNATTCAP; i++) { + if (vlen != isakmp_nat_t_cap[i].hashsize) { + LOG_DBG((LOG_EXCHANGE, 50, "nat_t_check_vendor_payload: " + "bad size %lu != %lu", (unsigned long)vlen, + (unsigned long)isakmp_nat_t_cap[i].hashsize)); + continue; + } + if (memcmp(isakmp_nat_t_cap[i].hash, pbuf + ISAKMP_GEN_SZ, vlen) == 0) { /* This peer is NAT-T capable. */ msg->exchange->flags |= EXCHANGE_FLAG_NAT_T_CAP_PEER; + msg->exchange->flags |= isakmp_nat_t_cap[i].flags; LOG_DBG((LOG_EXCHANGE, 10, "nat_t_check_vendor_payload: " "NAT-T capable peer detected")); p->flags |= PL_MARK; - return; } + } + + return; } /* Generate the NAT-D payload hash : HASH(CKY-I | CKY-R | IP | Port). */ @@ -268,6 +251,7 @@ nat_t_generate_nat_d_hash(struct message *msg, struct sockaddr *sa, static int nat_t_add_nat_d(struct message *msg, struct sockaddr *sa) { + int ret; u_int8_t *hbuf, *buf; size_t hbuflen, buflen; @@ -290,7 +274,16 @@ nat_t_add_nat_d(struct message *msg, struct sockaddr *sa) memcpy(buf + ISAKMP_NAT_D_DATA_OFF, hbuf, hbuflen); free(hbuf); - if (message_add_payload(msg, ISAKMP_PAYLOAD_NAT_D_DRAFT, buf, buflen, 1)) { + if (msg->exchange->flags & EXCHANGE_FLAG_NAT_T_RFC) + ret = message_add_payload(msg, ISAKMP_PAYLOAD_NAT_D, buf, + buflen, 1); + else if (msg->exchange->flags & EXCHANGE_FLAG_NAT_T_DRAFT) + ret = message_add_payload(msg, ISAKMP_PAYLOAD_NAT_D_DRAFT, + buf, buflen, 1); + else + ret = -1; + + if (ret) { free(buf); return -1; } diff --git a/sbin/isakmpd/nat_traversal.h b/sbin/isakmpd/nat_traversal.h index 984d825603f..843d43bc72c 100644 --- a/sbin/isakmpd/nat_traversal.h +++ b/sbin/isakmpd/nat_traversal.h @@ -1,4 +1,4 @@ -/* $OpenBSD: nat_traversal.h,v 1.3 2005/04/05 18:06:06 cloder Exp $ */ +/* $OpenBSD: nat_traversal.h,v 1.4 2005/07/25 15:03:47 hshoexer Exp $ */ /* * Copyright (c) 2004 Håkan Olsson. All rights reserved. @@ -27,6 +27,19 @@ #ifndef _NAT_TRAVERSAL_H_ #define _NAT_TRAVERSAL_H_ +#define VID_DRAFT_V2 0 +#define VID_DRAFT_V2_N 1 +#define VID_DRAFT_V3 2 +#define VID_RFC3947 3 + +struct nat_t_cap { + int id; + u_int32_t flags; + const char *text; + char *hash; + size_t hashsize; +}; + /* * Set if -T is given on the command line to disable NAT-T support. */ |