xref: /openbsd-src/sbin/isakmpd/isakmp_doi.c (revision 8713c8b000830eef160a0366b99357d5428d0a62)
1*8713c8b0Stodd /* $OpenBSD: isakmp_doi.c,v 1.26 2010/10/18 21:38:58 todd Exp $	 */
23724e3b9Sniklas /* $EOM: isakmp_doi.c,v 1.42 2000/09/12 16:29:41 ho Exp $	 */
32040585eSniklas 
42040585eSniklas /*
53635a927Sniklas  * Copyright (c) 1998, 1999, 2001 Niklas Hallqvist.  All rights reserved.
62040585eSniklas  *
72040585eSniklas  * Redistribution and use in source and binary forms, with or without
82040585eSniklas  * modification, are permitted provided that the following conditions
92040585eSniklas  * are met:
102040585eSniklas  * 1. Redistributions of source code must retain the above copyright
112040585eSniklas  *    notice, this list of conditions and the following disclaimer.
122040585eSniklas  * 2. Redistributions in binary form must reproduce the above copyright
132040585eSniklas  *    notice, this list of conditions and the following disclaimer in the
142040585eSniklas  *    documentation and/or other materials provided with the distribution.
152040585eSniklas  *
162040585eSniklas  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
172040585eSniklas  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
182040585eSniklas  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
192040585eSniklas  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
202040585eSniklas  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
212040585eSniklas  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
222040585eSniklas  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
232040585eSniklas  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
242040585eSniklas  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
252040585eSniklas  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
262040585eSniklas  */
272040585eSniklas 
282040585eSniklas /*
292040585eSniklas  * This code was written under funding by Ericsson Radio Systems.
302040585eSniklas  */
312040585eSniklas 
322040585eSniklas /*
332040585eSniklas  * XXX This DOI is very fuzzily defined, and should perhaps be short-circuited
3461d575f0Sangelos  * to the IPsec DOI instead.  At the moment I will have it as its own DOI,
352040585eSniklas  * as the ISAKMP architecture seems to imply it should be done like this.
362040585eSniklas  */
372040585eSniklas 
382040585eSniklas #include <sys/types.h>
392040585eSniklas 
402040585eSniklas #include "doi.h"
41*8713c8b0Stodd #include "dpd.h"
422040585eSniklas #include "exchange.h"
432040585eSniklas #include "isakmp.h"
444c8c122bSho #include "isakmp_doi.h"
459796240cSniklas #include "ipsec.h"
462040585eSniklas #include "log.h"
472040585eSniklas #include "message.h"
482040585eSniklas #include "sa.h"
492040585eSniklas #include "util.h"
502040585eSniklas 
5150eea14cSho static int      isakmp_debug_attribute(u_int16_t, u_int8_t *, u_int16_t,
5250eea14cSho     void *);
532040585eSniklas static void     isakmp_finalize_exchange(struct message *);
542040585eSniklas static struct keystate *isakmp_get_keystate(struct message *);
552040585eSniklas static int      isakmp_initiator(struct message *);
562040585eSniklas static int      isakmp_responder(struct message *);
572040585eSniklas static void     isakmp_setup_situation(u_int8_t *);
582040585eSniklas static size_t   isakmp_situation_size(void);
592040585eSniklas static u_int8_t isakmp_spi_size(u_int8_t);
6012f43dabShshoexer static int	isakmp_validate_attribute(u_int16_t, u_int8_t *, u_int16_t,
612040585eSniklas     void *);
622040585eSniklas static int      isakmp_validate_exchange(u_int8_t);
6350eea14cSho static int	isakmp_validate_id_information(u_int8_t, u_int8_t *,
6450eea14cSho     u_int8_t *, size_t, struct exchange *);
652040585eSniklas static int      isakmp_validate_key_information(u_int8_t *, size_t);
662040585eSniklas static int      isakmp_validate_notification(u_int16_t);
672040585eSniklas static int      isakmp_validate_proto(u_int8_t);
686153a28bShshoexer static int      isakmp_validate_situation(u_int8_t *, size_t *, size_t);
692040585eSniklas static int      isakmp_validate_transform_id(u_int8_t, u_int8_t);
702040585eSniklas 
712040585eSniklas static struct doi isakmp_doi = {
722040585eSniklas 	{0}, ISAKMP_DOI_ISAKMP, 0, 0, 0,
732040585eSniklas 	isakmp_debug_attribute,
742040585eSniklas 	0,			/* delete_spi not needed.  */
752040585eSniklas 	0,			/* exchange_script not needed.  */
762040585eSniklas 	isakmp_finalize_exchange,
772040585eSniklas 	0,			/* free_exchange_data not needed.  */
782040585eSniklas 	0,			/* free_proto_data not needed.  */
792040585eSniklas 	0,			/* free_sa_data not needed.  */
802040585eSniklas 	isakmp_get_keystate,
812040585eSniklas 	0,			/* get_spi not needed.  */
824013cc22Sniklas 	0,			/* handle_leftover_payload not needed.  */
83ad336730Sniklas 	0,			/* informational_post_hook not needed.  */
84ad336730Sniklas 	0,			/* informational_pre_hook not needed.  */
852040585eSniklas 	0,			/* XXX need maybe be filled-in.  */
86e87c48deSniklas 	0,			/* proto_init not needed.  */
872040585eSniklas 	isakmp_setup_situation,
882040585eSniklas 	isakmp_situation_size,
892040585eSniklas 	isakmp_spi_size,
902040585eSniklas 	isakmp_validate_attribute,
912040585eSniklas 	isakmp_validate_exchange,
922040585eSniklas 	isakmp_validate_id_information,
932040585eSniklas 	isakmp_validate_key_information,
942040585eSniklas 	isakmp_validate_notification,
952040585eSniklas 	isakmp_validate_proto,
962040585eSniklas 	isakmp_validate_situation,
972040585eSniklas 	isakmp_validate_transform_id,
982040585eSniklas 	isakmp_initiator,
999796240cSniklas 	isakmp_responder,
1009796240cSniklas 	ipsec_decode_ids
1012040585eSniklas };
1022040585eSniklas 
1032040585eSniklas /* Requires doi_init to already have been called.  */
1042040585eSniklas void
isakmp_doi_init(void)1054c8c122bSho isakmp_doi_init(void)
1062040585eSniklas {
1072040585eSniklas 	doi_register(&isakmp_doi);
1082040585eSniklas }
1092040585eSniklas 
1102040585eSniklas int
isakmp_debug_attribute(u_int16_t type,u_int8_t * value,u_int16_t len,void * vmsg)1112040585eSniklas isakmp_debug_attribute(u_int16_t type, u_int8_t *value, u_int16_t len,
1122040585eSniklas     void *vmsg)
1132040585eSniklas {
1142040585eSniklas 	/* XXX Not implemented yet.  */
1152040585eSniklas 	return 0;
1162040585eSniklas }
1172040585eSniklas 
1182040585eSniklas static void
isakmp_finalize_exchange(struct message * msg)1192040585eSniklas isakmp_finalize_exchange(struct message *msg)
1202040585eSniklas {
1212040585eSniklas }
1222040585eSniklas 
1232040585eSniklas static struct keystate *
isakmp_get_keystate(struct message * msg)1242040585eSniklas isakmp_get_keystate(struct message *msg)
1252040585eSniklas {
1262040585eSniklas 	return 0;
1272040585eSniklas }
1282040585eSniklas 
1292040585eSniklas static void
isakmp_setup_situation(u_int8_t * buf)1302040585eSniklas isakmp_setup_situation(u_int8_t *buf)
1312040585eSniklas {
1322040585eSniklas 	/* Nothing to do.  */
1332040585eSniklas }
1342040585eSniklas 
1352040585eSniklas static size_t
isakmp_situation_size(void)1362040585eSniklas isakmp_situation_size(void)
1372040585eSniklas {
1382040585eSniklas 	return 0;
1392040585eSniklas }
1402040585eSniklas 
1412040585eSniklas static u_int8_t
isakmp_spi_size(u_int8_t proto)1422040585eSniklas isakmp_spi_size(u_int8_t proto)
1432040585eSniklas {
1442040585eSniklas 	/* One way to specify ISAKMP SPIs is to say they're zero-sized.  */
1452040585eSniklas 	return 0;
1462040585eSniklas }
1472040585eSniklas 
1482040585eSniklas static int
isakmp_validate_attribute(u_int16_t type,u_int8_t * value,u_int16_t len,void * vmsg)1492040585eSniklas isakmp_validate_attribute(u_int16_t type, u_int8_t *value, u_int16_t len,
1502040585eSniklas     void *vmsg)
1512040585eSniklas {
1522040585eSniklas 	/* XXX Not implemented yet.  */
1532040585eSniklas 	return -1;
1542040585eSniklas }
1552040585eSniklas 
1562040585eSniklas static int
isakmp_validate_exchange(u_int8_t exch)1572040585eSniklas isakmp_validate_exchange(u_int8_t exch)
1582040585eSniklas {
1592040585eSniklas 	/* If we get here the exchange is invalid.  */
1602040585eSniklas 	return -1;
1612040585eSniklas }
1622040585eSniklas 
1632040585eSniklas static int
isakmp_validate_id_information(u_int8_t type,u_int8_t * extra,u_int8_t * buf,size_t sz,struct exchange * exchange)1642040585eSniklas isakmp_validate_id_information(u_int8_t type, u_int8_t *extra, u_int8_t *buf,
1652040585eSniklas     size_t sz, struct exchange *exchange)
1662040585eSniklas {
1672040585eSniklas 	return zero_test(extra, ISAKMP_ID_DOI_DATA_LEN);
1682040585eSniklas }
1692040585eSniklas 
1702040585eSniklas static int
isakmp_validate_key_information(u_int8_t * buf,size_t sz)1712040585eSniklas isakmp_validate_key_information(u_int8_t *buf, size_t sz)
1722040585eSniklas {
1732040585eSniklas 	/* Nothing to do.  */
1742040585eSniklas 	return 0;
1752040585eSniklas }
1762040585eSniklas 
1772040585eSniklas static int
isakmp_validate_notification(u_int16_t type)1782040585eSniklas isakmp_validate_notification(u_int16_t type)
1792040585eSniklas {
1802040585eSniklas 	/* If we get here the message type is invalid.  */
1812040585eSniklas 	return -1;
1822040585eSniklas }
1832040585eSniklas 
1842040585eSniklas static int
isakmp_validate_proto(u_int8_t proto)1852040585eSniklas isakmp_validate_proto(u_int8_t proto)
1862040585eSniklas {
1872040585eSniklas 	/* If we get here the protocol is invalid.  */
1882040585eSniklas 	return -1;
1892040585eSniklas }
1902040585eSniklas 
1912040585eSniklas static int
isakmp_validate_situation(u_int8_t * buf,size_t * sz,size_t len)1926153a28bShshoexer isakmp_validate_situation(u_int8_t *buf, size_t *sz, size_t len)
1932040585eSniklas {
1942040585eSniklas 	/* There are no situations in the ISAKMP DOI.  */
1952040585eSniklas 	*sz = 0;
1962040585eSniklas 	return 0;
1972040585eSniklas }
1982040585eSniklas 
1992040585eSniklas static int
isakmp_validate_transform_id(u_int8_t proto,u_int8_t transform_id)2002040585eSniklas isakmp_validate_transform_id(u_int8_t proto, u_int8_t transform_id)
2012040585eSniklas {
2022040585eSniklas 	/* XXX Not yet implemented.  */
2032040585eSniklas 	return -1;
2042040585eSniklas }
2052040585eSniklas 
2062040585eSniklas static int
isakmp_initiator(struct message * msg)2072040585eSniklas isakmp_initiator(struct message *msg)
2082040585eSniklas {
209fb9475d6Sderaadt 	if (msg->exchange->type != ISAKMP_EXCH_INFO) {
21012f43dabShshoexer 		log_print("isakmp_initiator: unsupported exchange type %d "
21112f43dabShshoexer 		    "in phase %d", msg->exchange->type, msg->exchange->phase);
212d48a8669Sniklas 		return -1;
213d48a8669Sniklas 	}
214d48a8669Sniklas 	return message_send_info(msg);
2152040585eSniklas }
2162040585eSniklas 
2172040585eSniklas static int
isakmp_responder(struct message * msg)2182040585eSniklas isakmp_responder(struct message *msg)
2192040585eSniklas {
220d48a8669Sniklas 	struct payload *p;
221*8713c8b0Stodd 	u_int16_t	type;
222d48a8669Sniklas 
223fb9475d6Sderaadt 	switch (msg->exchange->type) {
224d48a8669Sniklas 	case ISAKMP_EXCH_INFO:
22577fa3de5Sho 		for (p = payload_first(msg, ISAKMP_PAYLOAD_NOTIFY); p;
226fb9475d6Sderaadt 		    p = TAILQ_NEXT(p, link)) {
227*8713c8b0Stodd 			type = GET_ISAKMP_NOTIFY_MSG_TYPE(p->p);
228*8713c8b0Stodd 
22950eea14cSho 			LOG_DBG((LOG_EXCHANGE, 10, "isakmp_responder: "
230*8713c8b0Stodd 			    "got NOTIFY of type %s",
231107c5904Sho 			    constant_name(isakmp_notify_cst,
232*8713c8b0Stodd 			    type)));
233*8713c8b0Stodd 
234*8713c8b0Stodd 			switch (type) {
235*8713c8b0Stodd 			case ISAKMP_NOTIFY_STATUS_DPD_R_U_THERE:
236*8713c8b0Stodd 			case ISAKMP_NOTIFY_STATUS_DPD_R_U_THERE_ACK:
237*8713c8b0Stodd 				dpd_handle_notify(msg, p);
238*8713c8b0Stodd 				break;
239*8713c8b0Stodd 
240*8713c8b0Stodd 			default:
241d48a8669Sniklas 				p->flags |= PL_MARK;
242*8713c8b0Stodd 				break;
243*8713c8b0Stodd 			}
244d48a8669Sniklas 		}
245d48a8669Sniklas 
24677fa3de5Sho 		for (p = payload_first(msg, ISAKMP_PAYLOAD_DELETE); p;
247fb9475d6Sderaadt 		    p = TAILQ_NEXT(p, link)) {
24851ca15aeSniklas 			LOG_DBG((LOG_EXCHANGE, 10,
24951ca15aeSniklas 			    "isakmp_responder: got DELETE, ignoring"));
250d48a8669Sniklas 			p->flags |= PL_MARK;
251d48a8669Sniklas 		}
252d48a8669Sniklas 		return 0;
253d48a8669Sniklas 
2543635a927Sniklas 	case ISAKMP_EXCH_TRANSACTION:
2553635a927Sniklas 		/* return 0 isakmp_cfg_responder (msg); */
2563635a927Sniklas 
257d48a8669Sniklas 	default:
2582040585eSniklas 		/* XXX So far we don't accept any proposals.  */
25977fa3de5Sho 		if (payload_first(msg, ISAKMP_PAYLOAD_SA)) {
26012f43dabShshoexer 			message_drop(msg, ISAKMP_NOTIFY_NO_PROPOSAL_CHOSEN,
26112f43dabShshoexer 			    0, 1, 0);
2622040585eSniklas 			return -1;
2632040585eSniklas 		}
264d48a8669Sniklas 	}
2652040585eSniklas 	return 0;
2662040585eSniklas }
267