diff options
author | Niklas Hallqvist <niklas@cvs.openbsd.org> | 2001-07-01 20:43:41 +0000 |
---|---|---|
committer | Niklas Hallqvist <niklas@cvs.openbsd.org> | 2001-07-01 20:43:41 +0000 |
commit | 984a723c9274fa719d9d436a914d3899d5c626f8 (patch) | |
tree | 7f8ad17ac8c2a4e47e19e0105a96cd13d300550f | |
parent | 1b1cf9310c1ee499d272e783c7ed479e12387ddd (diff) |
ISAKMP configuration, a.k.a IKECFG or "mode-config", protocol implementation.
Disabled, has no configuration mechanism yet. This will be used for roaming
users, who are going to get parameters like IP-address and nameserver from its
peer, very much like DHCP, but securily inside an ISAKMP connection and still
in time before negotiation of IPsec connections. You may see stylistic fixes
in this commit too. Add some not yet used Makefile magic to deal with DNSSEC-
enabled OpenSSL too. The IKECFG code work was sponsered by Gatespace Inc.
Thank you! Configuration will come very soon, btw.
-rw-r--r-- | sbin/isakmpd/Makefile | 14 | ||||
-rw-r--r-- | sbin/isakmpd/TO-DO | 10 | ||||
-rw-r--r-- | sbin/isakmpd/features/isakmp_cfg | 33 | ||||
-rw-r--r-- | sbin/isakmpd/ipsec.c | 60 | ||||
-rw-r--r-- | sbin/isakmpd/ipsec.h | 24 | ||||
-rw-r--r-- | sbin/isakmpd/isakmp_cfg.c | 515 | ||||
-rw-r--r-- | sbin/isakmpd/isakmp_cfg.h | 57 | ||||
-rw-r--r-- | sbin/isakmpd/isakmp_doi.c | 9 | ||||
-rw-r--r-- | sbin/isakmpd/isakmp_fld.fld | 12 | ||||
-rw-r--r-- | sbin/isakmpd/isakmp_num.cst | 47 | ||||
-rw-r--r-- | sbin/isakmpd/message.c | 34 | ||||
-rw-r--r-- | sbin/isakmpd/regress/x509/Makefile | 7 |
12 files changed, 783 insertions, 39 deletions
diff --git a/sbin/isakmpd/Makefile b/sbin/isakmpd/Makefile index 9a7d49d9921..ce5d06b8d6a 100644 --- a/sbin/isakmpd/Makefile +++ b/sbin/isakmpd/Makefile @@ -1,8 +1,8 @@ -# $OpenBSD: Makefile,v 1.38 2001/05/31 20:21:37 angelos Exp $ +# $OpenBSD: Makefile,v 1.39 2001/07/01 20:43:39 niklas Exp $ # $EOM: Makefile,v 1.78 2000/10/15 21:33:42 niklas Exp $ # -# Copyright (c) 1998, 1999, 2000 Niklas Hallqvist. All rights reserved. +# Copyright (c) 1998, 1999, 2000, 2001 Niklas Hallqvist. All rights reserved. # Copyright (c) 2000, 2001 Håkan Olsson. All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -53,9 +53,9 @@ OS= openbsd # Compile-time configuration of otherwise optional features #FEATURES= tripledes des blowfish cast policy x509 ec aggressive debug gmp -#FEATURES+= dnssec +#FEATURES+= isakmp_cfg dnssec FEATURES= tripledes des blowfish cast policy x509 ec aggressive debug -#FEATURES+= +#FEATURES= .PATH: ${.CURDIR}/sysdep/${OS} @@ -124,6 +124,9 @@ CFLAGS+= -Wall -DNEED_SYSDEP_APP \ # strcpy (_y_, _x_); \ # })' +# Enable this if you have a DNSSEC enabled OpenSSL +#LWRESLIB= /usr/local/lib/liblwres.a + SUBDIR= apps .include "sysdep/${OS}/Makefile.sysdep" @@ -173,7 +176,8 @@ LDADD+= -lcrypto DPADD+= ${LIBCRYPTO} .endif -SRCS+= ${IPSEC_SRCS} ${X509} ${POLICY} ${EC} ${AGGRESSIVE} ${DNSSEC} +SRCS+= ${IPSEC_SRCS} ${X509} ${POLICY} ${EC} ${AGGRESSIVE} ${DNSSEC} \ + ${ISAKMP_CFG} CFLAGS+= ${IPSEC_CFLAGS} ${DNSSEC_CFLAGS} LDADD+= ${DESLIB} ${LWRESLIB} diff --git a/sbin/isakmpd/TO-DO b/sbin/isakmpd/TO-DO index 4325f49ae16..f6929ab3153 100644 --- a/sbin/isakmpd/TO-DO +++ b/sbin/isakmpd/TO-DO @@ -1,4 +1,4 @@ -$OpenBSD: TO-DO,v 1.22 2001/06/27 03:31:40 angelos Exp $ +$OpenBSD: TO-DO,v 1.23 2001/07/01 20:43:39 niklas Exp $ $EOM: TO-DO,v 1.45 2000/04/07 22:47:38 niklas Exp $ This file mixes small nitpicks with large projects to be done. @@ -118,7 +118,7 @@ This file mixes small nitpicks with large projects to be done. * Base mode. -* IKECFG +* IKECFG [protocol done, configuration controls remain] * XAUTH framework. @@ -134,10 +134,12 @@ This file mixes small nitpicks with large projects to be done. * Replace ui's fifo with a slightly more versatile interface. -* Report current configuration. +* Report current configuration. [done] -* IPv6 +* IPv6 [done] * AES in phase 1 * x509_certreq_validate needs implementing. + +* Smartcard support. diff --git a/sbin/isakmpd/features/isakmp_cfg b/sbin/isakmpd/features/isakmp_cfg new file mode 100644 index 00000000000..4849d42a5cd --- /dev/null +++ b/sbin/isakmpd/features/isakmp_cfg @@ -0,0 +1,33 @@ +# $OpenBSD: isakmp_cfg,v 1.1 2001/07/01 20:43:40 niklas Exp $ + +# +# Copyright (c) 2001 Niklas Hallqvist. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# This code was written under funding by Gatespace (http://www.gatespace.com/). +# + +ISAKMP_CFG= isakmp_cfg.c diff --git a/sbin/isakmpd/ipsec.c b/sbin/isakmpd/ipsec.c index fc98b78eaae..68bb1eebded 100644 --- a/sbin/isakmpd/ipsec.c +++ b/sbin/isakmpd/ipsec.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ipsec.c,v 1.51 2001/07/01 14:17:06 ho Exp $ */ +/* $OpenBSD: ipsec.c,v 1.52 2001/07/01 20:43:39 niklas Exp $ */ /* $EOM: ipsec.c,v 1.143 2000/12/11 23:57:42 niklas Exp $ */ /* @@ -61,6 +61,9 @@ #include "ipsec.h" #include "ipsec_doi.h" #include "isakmp.h" +#include "isakmp_cfg.h" +#include "isakmp_fld.h" +#include "isakmp_num.h" #include "log.h" #include "math_group.h" #include "message.h" @@ -541,6 +544,9 @@ static void ipsec_free_exchange_data (void *vie) { struct ipsec_exch *ie = vie; +#ifdef USE_ISAKMP_CFG + struct isakmp_cfg_attr *attr; +#endif if (ie->sa_i_b) free (ie->sa_i_b); @@ -568,6 +574,15 @@ ipsec_free_exchange_data (void *vie) free (ie->hash_r); if (ie->group) group_free (ie->group); +#ifdef USE_ISAKMP_CFG + for (attr = LIST_FIRST (&ie->attrs); attr; attr = LIST_FIRST (&ie->attrs)) + { + LIST_REMOVE (attr, link); + if (attr->length) + free (attr->value); + free (attr); + } +#endif } /* Free the DOI-specific SA data pointed to by VISA. */ @@ -608,6 +623,10 @@ ipsec_exchange_script (u_int8_t type) { switch (type) { +#ifdef USE_ISAKMP_CFG + case ISAKMP_EXCH_TRANSACTION: + return script_transaction; +#endif case IKE_EXCH_QUICK_MODE: return script_quick_mode; case IKE_EXCH_NEW_GROUP_MODE: @@ -860,11 +879,12 @@ ipsec_initiator (struct message *msg) int (**script) (struct message *msg) = 0; /* Check that the SA is coherent with the IKE rules. */ - if ((exchange->phase == 1 && exchange->type != ISAKMP_EXCH_ID_PROT - && exchange->type != ISAKMP_EXCH_AGGRESSIVE - && exchange->type != ISAKMP_EXCH_INFO) - || (exchange->phase == 2 && exchange->type != IKE_EXCH_QUICK_MODE - && exchange->type != ISAKMP_EXCH_INFO)) + if (exchange->type != ISAKMP_EXCH_TRANSACTION + && ((exchange->phase == 1 && exchange->type != ISAKMP_EXCH_ID_PROT + && exchange->type != ISAKMP_EXCH_AGGRESSIVE + && exchange->type != ISAKMP_EXCH_INFO) + || (exchange->phase == 2 && exchange->type != IKE_EXCH_QUICK_MODE + && exchange->type != ISAKMP_EXCH_INFO))) { log_print ("ipsec_initiator: unsupported exchange type %d in phase %d", exchange->type, exchange->phase); @@ -881,6 +901,11 @@ ipsec_initiator (struct message *msg) script = ike_aggressive_initiator; break; #endif +#ifdef USE_ISAKMP_CFG + case ISAKMP_EXCH_TRANSACTION: + script = isakmp_cfg_initiator; + break; +#endif case ISAKMP_EXCH_INFO: return message_send_info (msg); case IKE_EXCH_QUICK_MODE: @@ -995,7 +1020,7 @@ ipsec_responder (struct message *msg) u_int16_t type; /* Check that a new exchange is coherent with the IKE rules. */ - if (exchange->step == 0 + if (exchange->step == 0 && exchange->type != ISAKMP_EXCH_TRANSACTION && ((exchange->phase == 1 && exchange->type != ISAKMP_EXCH_ID_PROT && exchange->type != ISAKMP_EXCH_AGGRESSIVE && exchange->type != ISAKMP_EXCH_INFO) @@ -1020,6 +1045,12 @@ ipsec_responder (struct message *msg) break; #endif +#ifdef USE_ISAKMP_CFG + case ISAKMP_EXCH_TRANSACTION: + script = isakmp_cfg_responder; + break; +#endif + case ISAKMP_EXCH_INFO: for (p = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_NOTIFY]); p; p = TAILQ_NEXT (p, link)) @@ -1943,22 +1974,21 @@ ipsec_build_id (char *section, size_t *sz) /* * copy an ISAKMPD id */ - int ipsec_clone_id (u_int8_t **did, size_t *did_len, u_int8_t *id, size_t id_len) { if (*did) free (*did); - if (!id_len || id == NULL) + if (!id_len || !id) { - *did = NULL; + *did = 0; *did_len = 0; return 0; } *did = malloc (id_len); - if (*did == NULL) + if (!*did) { *did_len = 0; log_error ("ipsec_clone_id: malloc(%d) failed", id_len); @@ -2233,6 +2263,14 @@ ipsec_id_size (char *section, u_int8_t *id) return -1; } return strlen (data); + case IPSEC_ID_DER_ASN1_DN: + data = conf_get_str (section, "Name"); + if (!data) + { + log_print ("ipsec_id_size: section %s has no \"Name\" tag", section); + return -1; + } + break; } log_print ("ipsec_id_size: unrecognized ID-type %d (%s)", *id, type); return -1; diff --git a/sbin/isakmpd/ipsec.h b/sbin/isakmpd/ipsec.h index 3b60305b8b3..76571f0a20e 100644 --- a/sbin/isakmpd/ipsec.h +++ b/sbin/isakmpd/ipsec.h @@ -1,8 +1,8 @@ -/* $OpenBSD: ipsec.h,v 1.17 2001/06/29 04:12:00 ho Exp $ */ +/* $OpenBSD: ipsec.h,v 1.18 2001/07/01 20:43:39 niklas Exp $ */ /* $EOM: ipsec.h,v 1.42 2000/12/03 07:58:20 angelos Exp $ */ /* - * Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved. + * Copyright (c) 1998, 1999, 2001 Niklas Hallqvist. All rights reserved. * Copyright (c) 1999 Angelos D. Keromytis. All rights reserved. * Copyright (c) 2001 Håkan Olsson. All rights reserved. * @@ -39,9 +39,14 @@ #ifndef _IPSEC_H_ #define _IPSEC_H_ +#include <sys/queue.h> +#include <sys/types.h> #include <netinet/in.h> #include "ipsec_doi.h" +#ifdef USE_ISAKMP_CFG +#include "isakmp_cfg.h" +#endif struct group; struct hash; @@ -52,8 +57,9 @@ struct sa; /* * IPsec-specific data to be linked into the exchange struct. - * XXX Should probably be two different structs, one for phase 1 and one - * for phase 2 parameters. + * XXX Should probably be several different structs, one for each kind + * of exchange, i.e. phase 1, phase 2 and ISAKMP configuration parameters + * separated. */ struct ipsec_exch { u_int flags; @@ -61,7 +67,9 @@ struct ipsec_exch { struct ike_auth *ike_auth; struct group *group; u_int16_t prf_type; - u_int8_t pfs; /* 0 if no KEY_EXCH was proposed, 1 otherwise */ + + /* 0 if no KEY_EXCH was proposed, 1 otherwise */ + u_int8_t pfs; /* * A copy of the initiator SA payload body for later computation of hashes. @@ -95,6 +103,12 @@ struct ipsec_exch { size_t id_ci_sz; u_int8_t *id_cr; size_t id_cr_sz; + +#ifdef USE_ISAKMP_CFG + /* ISAKMP configuration mode parameters */ + u_int16_t cfg_id; + LIST_HEAD (, isakmp_cfg_attr) attrs; +#endif }; #define IPSEC_EXCH_FLAG_NO_ID 1 diff --git a/sbin/isakmpd/isakmp_cfg.c b/sbin/isakmpd/isakmp_cfg.c new file mode 100644 index 00000000000..a5ef6c3677a --- /dev/null +++ b/sbin/isakmpd/isakmp_cfg.c @@ -0,0 +1,515 @@ +/* $OpenBSD: isakmp_cfg.c,v 1.1 2001/07/01 20:43:39 niklas Exp $ */ + +/* + * Copyright (c) 2001 Niklas Hallqvist. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Ericsson Radio Systems. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This code was written under funding by Gatespace + * (http://www.gatespace.com/). + */ + +#include <stdlib.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include "sysdep.h" + +#include "attribute.h" +#include "conf.h" +#include "exchange.h" +#include "hash.h" +#include "ipsec.h" +#include "isakmp_fld.h" +#include "isakmp_num.h" +#include "log.h" +#include "message.h" +#include "prf.h" +#include "sa.h" +#include "util.h" + +/* + * Validation script used to test messages for correct content of + * payloads depending on the exchange type. + */ +int16_t script_transaction[] = { + ISAKMP_PAYLOAD_ATTRIBUTE, /* Initiator -> responder. */ + EXCHANGE_SCRIPT_SWITCH, + ISAKMP_PAYLOAD_ATTRIBUTE, /* Responder -> initiator. */ + EXCHANGE_SCRIPT_END +}; + +static int decode_attribute (u_int16_t, u_int8_t *, u_int16_t, void *); +static int initiator_send_ATTR (struct message *); +static int initiator_recv_ATTR (struct message *); +static int responder_recv_ATTR (struct message *); +static int responder_send_ATTR (struct message *); + +int (*isakmp_cfg_initiator[]) (struct message *) = { + initiator_send_ATTR, + initiator_recv_ATTR +}; + +int (*isakmp_cfg_responder[]) (struct message *) = { + responder_recv_ATTR, + responder_send_ATTR +}; + +/* XXX A lot can be shared with responder_send_ATTR. */ +static int +initiator_send_ATTR (struct message *msg) +{ + struct exchange *exchange = msg->exchange; + struct sa *isakmp_sa = msg->isakmp_sa; + struct ipsec_sa *isa = isakmp_sa->data; + struct hash *hash = hash_get (isa->hash); + struct prf *prf; + size_t hashsize = hash->hashsize; + u_int8_t *hashp = 0, *attrp; + size_t attrlen; + + if (exchange->phase == 2) + { + /* We want a HASH payload to start with. XXX Share with others? */ + hashp = malloc (ISAKMP_HASH_SZ + hashsize); + if (!hashp) + { + log_error ("responder_send_ATTR: malloc (%d) failed", + ISAKMP_HASH_SZ + hashsize); + return -1; + } + if (message_add_payload (msg, ISAKMP_PAYLOAD_HASH, hashp, + ISAKMP_HASH_SZ + hashsize, 1)) + { + free (hashp); + return -1; + } + } + +#ifndef to_be_removed + attrp = 0; + attrlen = 0; +#endif + + if (exchange->phase == 2) + { + prf = prf_alloc (isa->prf_type, isa->hash, isa->skeyid_a, + isa->skeyid_len); + if (!prf) + return -1; + prf->Init (prf->prfctx); + prf->Update (prf->prfctx, exchange->message_id, + ISAKMP_HDR_MESSAGE_ID_LEN); + prf->Update (prf->prfctx, attrp, attrlen); + prf->Final (hashp + ISAKMP_GEN_SZ, prf->prfctx); + prf_free (prf); + } + return 0; +} + +static int +initiator_recv_ATTR (struct message *msg) +{ + struct exchange *exchange = msg->exchange; +#if 0 + struct payload *p = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_ATTRIBUTE]); +#endif + struct payload *hashp = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_HASH]); + + if (exchange->phase == 2) + { + if (!hashp) + { + /* XXX Should another NOTIFY type be used? */ + message_drop (msg, ISAKMP_NOTIFY_INVALID_HASH_INFORMATION, 0, 1, 0); + log_print ("initiator_recv_ATTR: phase 2 message missing HASH"); + return -1; + } + + /* XXX Verify hash! */ + + /* Mark the HASH as handled. */ + hashp->flags |= PL_MARK; + } + + return 0; +} + +static int +responder_recv_ATTR (struct message *msg) +{ + struct exchange *exchange = msg->exchange; + struct payload *attrp + = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_ATTRIBUTE]); + struct payload *hashp = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_HASH]); + struct ipsec_exch *ie = exchange->data; + struct sa *isakmp_sa = msg->isakmp_sa; + struct ipsec_sa *isa = isakmp_sa->data; + struct prf *prf; + u_int8_t *hash, *comp_hash; + size_t hash_len; + + if (exchange->phase == 2) + { + if (!hashp) + { + /* XXX Should another NOTIFY type be used? */ + message_drop (msg, ISAKMP_NOTIFY_INVALID_HASH_INFORMATION, 0, 1, 0); + log_print ("responder_recv_ATTR: phase 2 message missing HASH"); + return -1; + } + + hash = hashp->p; + hash_len = GET_ISAKMP_GEN_LENGTH (hash); + comp_hash = malloc (hash_len - ISAKMP_GEN_SZ); + if (!comp_hash) + { + log_error ("responder_recv_ATTR: malloc (%d) failed", + hash_len - ISAKMP_GEN_SZ); + return -1; + } + + /* Verify hash! */ + prf = prf_alloc (isa->prf_type, isa->hash, isa->skeyid_a, + isa->skeyid_len); + if (!prf) + { + free (comp_hash); + return -1; + } + prf->Init (prf->prfctx); + prf->Update (prf->prfctx, exchange->message_id, + ISAKMP_HDR_MESSAGE_ID_LEN); + prf->Update (prf->prfctx, hash + hash_len, + msg->iov[0].iov_len - ISAKMP_HDR_SZ - hash_len); + prf->Final (comp_hash, prf->prfctx); + prf_free (prf); + if (memcmp (hash + ISAKMP_GEN_SZ, comp_hash, hash_len - ISAKMP_GEN_SZ) + != 0) + { + 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; + } + + ie->cfg_id = GET_ISAKMP_ATTRIBUTE_ID (attrp->p); + + switch (attrp->p[ISAKMP_ATTRIBUTE_TYPE_OFF]) + { + case ISAKMP_CFG_REQUEST: + attribute_map (attrp->p + ISAKMP_ATTRIBUTE_ATTRS_OFF, + GET_ISAKMP_GEN_LENGTH (attrp->p) + - ISAKMP_TRANSFORM_SA_ATTRS_OFF, decode_attribute, ie); + break; + +#ifdef notyet + case ISAKMP_CFG_SET: + break; +#endif + + default: + message_drop (msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0); + log_print ("responder_recv_ATTR: " + "unexpected configuration message type %d", + attrp->p[ISAKMP_ATTRIBUTE_TYPE_OFF]); + return -1; + } + + return 0; +} + +/* XXX A lot can be shared with initiator_send_ATTR. */ +static int +responder_send_ATTR (struct message *msg) +{ + struct exchange *exchange = msg->exchange; + struct ipsec_exch *ie = exchange->data; + struct sa *isakmp_sa = msg->isakmp_sa; + struct ipsec_sa *isa = isakmp_sa->data; + struct hash *hash = hash_get (isa->hash); + struct prf *prf; + size_t hashsize = hash->hashsize; + u_int8_t *hashp = 0, *attrp; + size_t attrlen, off; + struct isakmp_cfg_attr *attr; + struct sockaddr *sa; + u_int32_t value; + + if (exchange->phase == 2) + { + /* We want a HASH payload to start with. XXX Share with others? */ + hashp = malloc (ISAKMP_HASH_SZ + hashsize); + if (!hashp) + { + log_error ("responder_send_ATTR: malloc (%d) failed", + ISAKMP_HASH_SZ + hashsize); + return -1; + } + if (message_add_payload (msg, ISAKMP_PAYLOAD_HASH, hashp, + ISAKMP_HASH_SZ + hashsize, 1)) + { + free (hashp); + return -1; + } + } + + /* Compute reply attribute payload length. */ + attrlen = ISAKMP_ATTRIBUTE_SZ; + for (attr = LIST_FIRST (&ie->attrs); attr; attr = LIST_NEXT (attr, link)) + { + switch (attr->type) + { + case ISAKMP_CFG_ATTR_INTERNAL_IP4_ADDRESS: + case ISAKMP_CFG_ATTR_INTERNAL_IP4_NETMASK: + case ISAKMP_CFG_ATTR_INTERNAL_IP4_DHCP: + case ISAKMP_CFG_ATTR_INTERNAL_IP4_DNS: + case ISAKMP_CFG_ATTR_INTERNAL_IP4_NBNS: + case ISAKMP_CFG_ATTR_INTERNAL_ADDRESS_EXPIRY: + attr->length = 4; + break; + + case ISAKMP_CFG_ATTR_INTERNAL_IP4_SUBNET: + attr->length = 8; + break; + + case ISAKMP_CFG_ATTR_APPLICATION_VERSION: + /* XXX So far no version identifier of isakmpd here. */ + attr->length = 0; + break; + + case ISAKMP_CFG_ATTR_SUPPORTED_ATTRIBUTES: + /* XXX 2 * 6 more when IPv6 is supported. */ + attr->length = 2 * 9; + break; + +#if 0 + case ISAKMP_CFG_ATTR_INTERNAL_IP6_ADDRESS: + case ISAKMP_CFG_ATTR_INTERNAL_IP6_NETMASK: + case ISAKMP_CFG_ATTR_INTERNAL_IP6_DHCP: + case ISAKMP_CFG_ATTR_INTERNAL_IP6_DNS: + case ISAKMP_CFG_ATTR_INTERNAL_IP6_NBNS: + attr->length = 16; + break; + + case ISAKMP_CFG_ATTR_INTERNAL_IP6_SUBNET: + attr->length = 17; + break; +#endif + + default: + attr->ignore++; + /* XXX Log! */ + } + attrlen += ISAKMP_ATTR_SZ + attr->length; + } + + attrp = malloc (attrlen); + if (!attrp) + { + log_error ("responder_send_ATTR: malloc (%d) failed", attrlen); + return -1; + } + + if (message_add_payload (msg, ISAKMP_PAYLOAD_ATTRIBUTE, attrp, attrlen, 1)) + { + free (attrp); + return -1; + } + + SET_ISAKMP_ATTRIBUTE_TYPE (attrp, ISAKMP_CFG_REPLY); + SET_ISAKMP_ATTRIBUTE_ID (attrp, ie->cfg_id); + + off = ISAKMP_ATTRIBUTE_SZ; + for (attr = LIST_FIRST (&ie->attrs); attr; + off += ISAKMP_ATTR_SZ + attr->length, attr = LIST_NEXT (attr, link)) + { + SET_ISAKMP_ATTR_TYPE (attrp + off, attr->type); + SET_ISAKMP_ATTR_LENGTH_VALUE (attrp + off, attr->length); + switch (attr->type) + { + case ISAKMP_CFG_ATTR_INTERNAL_IP4_ADDRESS: + /* XXX The section should be tagged off the peer somehow. */ + sa = conf_get_address ("ISAKMP-cfg", "Address"); + if (!sa) + /* XXX What to do? */ + continue; + if (sa->sa_family != AF_INET) + /* XXX What to do? */ + free (sa); + continue; + + memcpy (attrp + off + ISAKMP_ATTR_VALUE_OFF, + &((struct sockaddr_in *)sa)->sin_addr, attr->length); + free (sa); + break; + + case ISAKMP_CFG_ATTR_INTERNAL_IP4_NETMASK: + break; + + case ISAKMP_CFG_ATTR_INTERNAL_IP4_SUBNET: + break; + + case ISAKMP_CFG_ATTR_INTERNAL_IP4_DHCP: + break; + + case ISAKMP_CFG_ATTR_INTERNAL_IP4_DNS: + /* XXX The section should be tagged off the peer somehow. */ + sa = conf_get_address ("ISAKMP-cfg", "Nameserver"); + if (!sa) + /* XXX What to do? */ + continue; + if (sa->sa_family != AF_INET) + /* XXX What to do? */ + free (sa); + continue; + + memcpy (attrp + off + ISAKMP_ATTR_VALUE_OFF, + &((struct sockaddr_in *)sa)->sin_addr, attr->length); + free (sa); + break; + + case ISAKMP_CFG_ATTR_INTERNAL_IP4_NBNS: + /* XXX The section should be tagged off the peer somehow. */ + sa = conf_get_address ("ISAKMP-cfg", "WINS-server"); + if (!sa) + /* XXX What to do? */ + continue; + if (sa->sa_family != AF_INET) + /* XXX What to do? */ + free (sa); + continue; + + memcpy (attrp + off + ISAKMP_ATTR_VALUE_OFF, + &((struct sockaddr_in *)sa)->sin_addr, attr->length); + free (sa); + break; + + case ISAKMP_CFG_ATTR_INTERNAL_ADDRESS_EXPIRY: + /* XXX The section should be tagged off the peer somehow. */ + value = conf_get_num ("ISAKMP-cfg", "Lifetime", 1200); + encode_32 (attrp + off + ISAKMP_ATTR_VALUE_OFF, value); + break; + + case ISAKMP_CFG_ATTR_APPLICATION_VERSION: + /* XXX So far no version identifier of isakmpd here. */ + break; + + case ISAKMP_CFG_ATTR_SUPPORTED_ATTRIBUTES: + break; + +#if 0 + case ISAKMP_CFG_ATTR_INTERNAL_IP6_ADDRESS: + break; + + case ISAKMP_CFG_ATTR_INTERNAL_IP6_NETMASK: + break; + + case ISAKMP_CFG_ATTR_INTERNAL_IP6_SUBNET: + break; + + case ISAKMP_CFG_ATTR_INTERNAL_IP6_DHCP: + break; + + case ISAKMP_CFG_ATTR_INTERNAL_IP6_DNS: + break; + + case ISAKMP_CFG_ATTR_INTERNAL_IP6_NBNS: + break; +#endif + + default: + } + } + + if (exchange->phase == 2) + { + prf = prf_alloc (isa->prf_type, isa->hash, isa->skeyid_a, + isa->skeyid_len); + if (!prf) + { + /* XXX Log? */ + return -1; + } + prf->Init (prf->prfctx); + prf->Update (prf->prfctx, exchange->message_id, + ISAKMP_HDR_MESSAGE_ID_LEN); + prf->Update (prf->prfctx, attrp, attrlen); + prf->Final (hashp + ISAKMP_GEN_SZ, prf->prfctx); + prf_free (prf); + } + + return 0; +} + +/* + * Decode the attribute of type TYPE with a LEN length value pointed to by + * VALUE. VIE is a pointer to the IPsec exchange context holding the + * attributes indexed by type for easy retrieval. + */ +static int +decode_attribute (u_int16_t type, u_int8_t *value, u_int16_t len, void *vie) +{ + struct ipsec_exch *ie = vie; + struct isakmp_cfg_attr *attr; + + if (type >= ISAKMP_CFG_ATTR_PRIVATE_MIN + && type <= ISAKMP_CFG_ATTR_PRIVATE_MAX) + return 0; + if (type == 0 || type >= ISAKMP_CFG_ATTR_FUTURE_MIN) + /* XXX Log! */ + return -1; + + attr = calloc (1, sizeof *attr); + if (!attr) + { + log_error ("decode_attribute: calloc (1, %d) failed", sizeof *attr); + return -1; + } + attr->type = type; + attr->length = len; + if (len) + { + attr->value = malloc (len); + if (!attr->value) + { + log_error ("decode_attribute: malloc (%d) failed", len); + free (attr); + /* Should we also deallocate all other values? */ + return -1; + } + memcpy (attr->value, value, len); + } + LIST_INSERT_HEAD (&ie->attrs, attr, link); + return 0; +} diff --git a/sbin/isakmpd/isakmp_cfg.h b/sbin/isakmpd/isakmp_cfg.h new file mode 100644 index 00000000000..a73f461fee5 --- /dev/null +++ b/sbin/isakmpd/isakmp_cfg.h @@ -0,0 +1,57 @@ +/* $OpenBSD: isakmp_cfg.h,v 1.1 2001/07/01 20:43:39 niklas Exp $ */ + +/* + * Copyright (c) 2001 Niklas Hallqvist. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Ericsson Radio Systems. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This code was written under funding by Gatespace + * (http://www.gatespace.com/). + */ + +#ifndef _ISAKMP_CFG_H_ +#define _ISAKMP_CFG_H_ + +#include <sys/queue.h> + +struct isakmp_cfg_attr { + LIST_ENTRY (isakmp_cfg_attr) link; + u_int16_t type; + /* 16 bits just to be well-aligned. */ + u_int16_t ignore; + size_t length; + void *value; +}; + +struct message; + +extern int (*isakmp_cfg_initiator[]) (struct message *); +extern int (*isakmp_cfg_responder[]) (struct message *); +extern int16_t script_transaction[]; + +#endif /* _ISAKMP_CFG_H_ */ diff --git a/sbin/isakmpd/isakmp_doi.c b/sbin/isakmpd/isakmp_doi.c index 7af52bc43b2..77e936f2b17 100644 --- a/sbin/isakmpd/isakmp_doi.c +++ b/sbin/isakmpd/isakmp_doi.c @@ -1,8 +1,8 @@ -/* $OpenBSD: isakmp_doi.c,v 1.12 2001/06/27 03:31:41 angelos Exp $ */ +/* $OpenBSD: isakmp_doi.c,v 1.13 2001/07/01 20:43:39 niklas Exp $ */ /* $EOM: isakmp_doi.c,v 1.42 2000/09/12 16:29:41 ho Exp $ */ /* - * Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved. + * Copyright (c) 1998, 1999, 2001 Niklas Hallqvist. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -255,6 +255,11 @@ isakmp_responder (struct message *msg) } return 0; +#ifdef USE_ISAKMP_CFG + case ISAKMP_EXCH_TRANSACTION: + /* return 0 isakmp_cfg_responder (msg); */ +#endif /* USE_ISAKMP_CFG */ + default: /* XXX So far we don't accept any proposals. */ if (TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_SA])) diff --git a/sbin/isakmpd/isakmp_fld.fld b/sbin/isakmpd/isakmp_fld.fld index a9d5809df05..4576a644d3a 100644 --- a/sbin/isakmpd/isakmp_fld.fld +++ b/sbin/isakmpd/isakmp_fld.fld @@ -1,8 +1,8 @@ -# $OpenBSD: isakmp_fld.fld,v 1.5 1999/04/27 21:14:30 niklas Exp $ +# $OpenBSD: isakmp_fld.fld,v 1.6 2001/07/01 20:43:39 niklas Exp $ # $EOM: isakmp_fld.fld,v 1.5 1999/04/25 13:38:22 niklas Exp $ # -# Copyright (c) 1998 Niklas Hallqvist. All rights reserved. +# Copyright (c) 1998, 2001 Niklas Hallqvist. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -147,3 +147,11 @@ ISAKMP_DELETE : ISAKMP_GEN ISAKMP_VENDOR : ISAKMP_GEN ID raw . + +# Attribute payload. +ISAKMP_ATTRIBUTE : ISAKMP_GEN + TYPE num 1 isakmp_cfg_cst + RESERVED ign 1 + ID num 2 + ATTRS raw +. diff --git a/sbin/isakmpd/isakmp_num.cst b/sbin/isakmpd/isakmp_num.cst index 721284bcf0c..80ea9015f77 100644 --- a/sbin/isakmpd/isakmp_num.cst +++ b/sbin/isakmpd/isakmp_num.cst @@ -1,8 +1,8 @@ -# $OpenBSD: isakmp_num.cst,v 1.4 2000/06/08 20:49:37 niklas Exp $ +# $OpenBSD: isakmp_num.cst,v 1.5 2001/07/01 20:43:39 niklas Exp $ # $EOM: isakmp_num.cst,v 1.3 2000/05/17 03:09:50 angelos Exp $ # -# Copyright (c) 1998 Niklas Hallqvist. All rights reserved. +# Copyright (c) 1998, 2001 Niklas Hallqvist. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -55,7 +55,9 @@ ISAKMP_PAYLOAD NOTIFY 11 DELETE 12 VENDOR 13 - RESERVED_MIN 14 +# XXX the following is not quite legitimate according to the IETF process + ATTRIBUTE 14 + RESERVED_MIN 15 RESERVED_MAX 127 PRIVATE_MIN 128 PRIVATE_MAX 255 @@ -69,7 +71,9 @@ ISAKMP_EXCH AUTH_ONLY 3 AGGRESSIVE 4 INFO 5 - FUTURE_MIN 6 +# XXX the following is not quite legitimate according to the IETF process + TRANSACTION 6 + FUTURE_MIN 7 FUTURE_MAX 31 DOI_MIN 32 DOI_MAX 255 @@ -156,3 +160,38 @@ ISAKMP_DOI ISAKMP_PROTO ISAKMP 1 . + +# ISAKMP transaction message type. +ISAKMP_CFG + REQUEST 1 + REPLY 2 + SET 3 + ACK 4 + FUTURE_MIN 5 + FUTURE_MAX 127 + PRIVATE_MIN 128 + PRIVATE_MAX 255 +. + +# ISAKMP configuration attributes. +ISAKMP_CFG_ATTR + INTERNAL_IP4_ADDRESS 1 + INTERNAL_IP4_NETMASK 2 + INTERNAL_IP4_DNS 3 + INTERNAL_IP4_NBNS 4 + INTERNAL_ADDRESS_EXPIRY 5 + INTERNAL_IP4_DHCP 6 + APPLICATION_VERSION 7 + INTERNAL_IP6_ADDRESS 8 + INTERNAL_IP6_NETMASK 9 + INTERNAL_IP6_DNS 10 + INTERNAL_IP6_NBNS 11 + INTERNAL_IP6_DHCP 12 + INTERNAL_IP4_SUBNET 13 + SUPPORTED_ATTRIBUTES 14 + INTERNAL_IP6_SUBNET 15 + FUTURE_MIN 16 + FUTURE_MAX 16383 + PRIVATE_MIN 16384 + PRIVATE_MAX 32767 +. diff --git a/sbin/isakmpd/message.c b/sbin/isakmpd/message.c index a418ff54096..c42ca672626 100644 --- a/sbin/isakmpd/message.c +++ b/sbin/isakmpd/message.c @@ -1,4 +1,4 @@ -/* $OpenBSD: message.c,v 1.44 2001/07/01 06:10:34 angelos Exp $ */ +/* $OpenBSD: message.c,v 1.45 2001/07/01 20:43:39 niklas Exp $ */ /* $EOM: message.c,v 1.156 2000/10/10 12:36:39 provos Exp $ */ /* @@ -52,6 +52,7 @@ #include "doi.h" #include "exchange.h" #include "field.h" +#include "ipsec_num.h" #include "isakmp.h" #include "log.h" #include "message.h" @@ -78,6 +79,7 @@ static int message_index_payload (struct message *, struct payload *, u_int8_t, u_int8_t *); static int message_parse_transform (struct message *, struct payload *, u_int8_t, u_int8_t *); +static int message_validate_attribute (struct message *, struct payload *); static int message_validate_cert (struct message *, struct payload *); static int message_validate_cert_req (struct message *, struct payload *); static int message_validate_delete (struct message *, struct payload *); @@ -100,14 +102,14 @@ static int (*message_validate_payload[]) (struct message *, struct payload *) = message_validate_key_exch, message_validate_id, message_validate_cert, message_validate_cert_req, message_validate_hash, message_validate_sig, message_validate_nonce, message_validate_notify, message_validate_delete, - message_validate_vendor + message_validate_vendor, message_validate_attribute }; static struct field *fields[] = { isakmp_sa_fld, isakmp_prop_fld, isakmp_transform_fld, isakmp_ke_fld, isakmp_id_fld, isakmp_cert_fld, isakmp_certreq_fld, isakmp_hash_fld, isakmp_sig_fld, isakmp_nonce_fld, isakmp_notify_fld, isakmp_delete_fld, - isakmp_vendor_fld + isakmp_vendor_fld, isakmp_attribute_fld }; /* @@ -364,6 +366,30 @@ message_parse_transform (struct message *msg, struct payload *p, return 0; } +/* Validate the attribute payload P in message MSG. */ +static int +message_validate_attribute (struct message *msg, struct payload *p) +{ +#ifdef USE_ISAKMP_CFG + /* If we don't have an exchange yet, create one. */ + if (!msg->exchange) + { + if (zero_test (msg->iov[0].iov_base + ISAKMP_HDR_MESSAGE_ID_OFF, + ISAKMP_HDR_MESSAGE_ID_LEN)) + msg->exchange = exchange_setup_p1 (msg, IPSEC_DOI_IPSEC); + else + msg->exchange = exchange_setup_p2 (msg, IPSEC_DOI_IPSEC); + if (!msg->exchange) + { + log_print ("message_validate_attribute: can not create exchange"); + message_free (msg); + return -1; + } + } +#endif + return 0; +} + /* Validate the certificate payload P in message MSG. */ static int message_validate_cert (struct message *msg, struct payload *p) @@ -1033,7 +1059,7 @@ message_recv (struct message *msg) if (flags & ISAKMP_FLAGS_ENC) { - if (msg->isakmp_sa == NULL) + if (!msg->isakmp_sa) { LOG_DBG ((LOG_MISC, 10, "message_recv: no isakmp_sa for encrypted message")); diff --git a/sbin/isakmpd/regress/x509/Makefile b/sbin/isakmpd/regress/x509/Makefile index fef2e7cadd2..345f8c78825 100644 --- a/sbin/isakmpd/regress/x509/Makefile +++ b/sbin/isakmpd/regress/x509/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.12 2001/01/27 12:03:38 niklas Exp $ +# $OpenBSD: Makefile,v 1.13 2001/07/01 20:43:40 niklas Exp $ # $EOM: Makefile,v 1.16 2000/09/28 12:53:27 niklas Exp $ # @@ -37,6 +37,9 @@ # Test X509 +# Enable this if you have a DNSSEC enabled OpenSSL +#LIBLWRES= /usr/local/lib/liblwres.a + PROG= x509test SRCS= x509test.c conf.c log.c libcrypto.c sysdep.c field.c util.c \ isakmp_fld.c ipsec_fld.c ipsec_num.c isakmp_num.c constants.c \ @@ -79,7 +82,7 @@ CFLAGS+= -DUSE_KEYNOTE .ifdef USE_LIBCRYPTO X509= x509.c CFLAGS+= -DUSE_LIBCRYPTO -LDADD+= -lcrypto +LDADD+= -lcrypto ${LIBLWRES} DPADD+= ${LIBCRYPTO} .endif |