1/* $OpenBSD: isakmp_doi.c,v 1.26 2010/10/18 21:38:58 todd Exp $	 */
2/* $EOM: isakmp_doi.c,v 1.42 2000/09/12 16:29:41 ho Exp $	 */
3
4/*
5 * Copyright (c) 1998, 1999, 2001 Niklas Hallqvist.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28/*
29 * This code was written under funding by Ericsson Radio Systems.
30 */
31
32/*
33 * XXX This DOI is very fuzzily defined, and should perhaps be short-circuited
34 * to the IPsec DOI instead.  At the moment I will have it as its own DOI,
35 * as the ISAKMP architecture seems to imply it should be done like this.
36 */
37
38#include <sys/types.h>
39
40#include "doi.h"
41#include "dpd.h"
42#include "exchange.h"
43#include "isakmp.h"
44#include "isakmp_doi.h"
45#include "ipsec.h"
46#include "log.h"
47#include "message.h"
48#include "sa.h"
49#include "util.h"
50
51static int      isakmp_debug_attribute(u_int16_t, u_int8_t *, u_int16_t,
52    void *);
53static void     isakmp_finalize_exchange(struct message *);
54static struct keystate *isakmp_get_keystate(struct message *);
55static int      isakmp_initiator(struct message *);
56static int      isakmp_responder(struct message *);
57static void     isakmp_setup_situation(u_int8_t *);
58static size_t   isakmp_situation_size(void);
59static u_int8_t isakmp_spi_size(u_int8_t);
60static int	isakmp_validate_attribute(u_int16_t, u_int8_t *, u_int16_t,
61    void *);
62static int      isakmp_validate_exchange(u_int8_t);
63static int	isakmp_validate_id_information(u_int8_t, u_int8_t *,
64    u_int8_t *, size_t, struct exchange *);
65static int      isakmp_validate_key_information(u_int8_t *, size_t);
66static int      isakmp_validate_notification(u_int16_t);
67static int      isakmp_validate_proto(u_int8_t);
68static int      isakmp_validate_situation(u_int8_t *, size_t *, size_t);
69static int      isakmp_validate_transform_id(u_int8_t, u_int8_t);
70
71static struct doi isakmp_doi = {
72	{0}, ISAKMP_DOI_ISAKMP, 0, 0, 0,
73	isakmp_debug_attribute,
74	0,			/* delete_spi not needed.  */
75	0,			/* exchange_script not needed.  */
76	isakmp_finalize_exchange,
77	0,			/* free_exchange_data not needed.  */
78	0,			/* free_proto_data not needed.  */
79	0,			/* free_sa_data not needed.  */
80	isakmp_get_keystate,
81	0,			/* get_spi not needed.  */
82	0,			/* handle_leftover_payload not needed.  */
83	0,			/* informational_post_hook not needed.  */
84	0,			/* informational_pre_hook not needed.  */
85	0,			/* XXX need maybe be filled-in.  */
86	0,			/* proto_init not needed.  */
87	isakmp_setup_situation,
88	isakmp_situation_size,
89	isakmp_spi_size,
90	isakmp_validate_attribute,
91	isakmp_validate_exchange,
92	isakmp_validate_id_information,
93	isakmp_validate_key_information,
94	isakmp_validate_notification,
95	isakmp_validate_proto,
96	isakmp_validate_situation,
97	isakmp_validate_transform_id,
98	isakmp_initiator,
99	isakmp_responder,
100	ipsec_decode_ids
101};
102
103/* Requires doi_init to already have been called.  */
104void
105isakmp_doi_init(void)
106{
107	doi_register(&isakmp_doi);
108}
109
110int
111isakmp_debug_attribute(u_int16_t type, u_int8_t *value, u_int16_t len,
112    void *vmsg)
113{
114	/* XXX Not implemented yet.  */
115	return 0;
116}
117
118static void
119isakmp_finalize_exchange(struct message *msg)
120{
121}
122
123static struct keystate *
124isakmp_get_keystate(struct message *msg)
125{
126	return 0;
127}
128
129static void
130isakmp_setup_situation(u_int8_t *buf)
131{
132	/* Nothing to do.  */
133}
134
135static size_t
136isakmp_situation_size(void)
137{
138	return 0;
139}
140
141static u_int8_t
142isakmp_spi_size(u_int8_t proto)
143{
144	/* One way to specify ISAKMP SPIs is to say they're zero-sized.  */
145	return 0;
146}
147
148static int
149isakmp_validate_attribute(u_int16_t type, u_int8_t *value, u_int16_t len,
150    void *vmsg)
151{
152	/* XXX Not implemented yet.  */
153	return -1;
154}
155
156static int
157isakmp_validate_exchange(u_int8_t exch)
158{
159	/* If we get here the exchange is invalid.  */
160	return -1;
161}
162
163static int
164isakmp_validate_id_information(u_int8_t type, u_int8_t *extra, u_int8_t *buf,
165    size_t sz, struct exchange *exchange)
166{
167	return zero_test(extra, ISAKMP_ID_DOI_DATA_LEN);
168}
169
170static int
171isakmp_validate_key_information(u_int8_t *buf, size_t sz)
172{
173	/* Nothing to do.  */
174	return 0;
175}
176
177static int
178isakmp_validate_notification(u_int16_t type)
179{
180	/* If we get here the message type is invalid.  */
181	return -1;
182}
183
184static int
185isakmp_validate_proto(u_int8_t proto)
186{
187	/* If we get here the protocol is invalid.  */
188	return -1;
189}
190
191static int
192isakmp_validate_situation(u_int8_t *buf, size_t *sz, size_t len)
193{
194	/* There are no situations in the ISAKMP DOI.  */
195	*sz = 0;
196	return 0;
197}
198
199static int
200isakmp_validate_transform_id(u_int8_t proto, u_int8_t transform_id)
201{
202	/* XXX Not yet implemented.  */
203	return -1;
204}
205
206static int
207isakmp_initiator(struct message *msg)
208{
209	if (msg->exchange->type != ISAKMP_EXCH_INFO) {
210		log_print("isakmp_initiator: unsupported exchange type %d "
211		    "in phase %d", msg->exchange->type, msg->exchange->phase);
212		return -1;
213	}
214	return message_send_info(msg);
215}
216
217static int
218isakmp_responder(struct message *msg)
219{
220	struct payload *p;
221	u_int16_t	type;
222
223	switch (msg->exchange->type) {
224	case ISAKMP_EXCH_INFO:
225		for (p = payload_first(msg, ISAKMP_PAYLOAD_NOTIFY); p;
226		    p = TAILQ_NEXT(p, link)) {
227			type = GET_ISAKMP_NOTIFY_MSG_TYPE(p->p);
228
229			LOG_DBG((LOG_EXCHANGE, 10, "isakmp_responder: "
230			    "got NOTIFY of type %s",
231			    constant_name(isakmp_notify_cst,
232			    type)));
233
234			switch (type) {
235			case ISAKMP_NOTIFY_STATUS_DPD_R_U_THERE:
236			case ISAKMP_NOTIFY_STATUS_DPD_R_U_THERE_ACK:
237				dpd_handle_notify(msg, p);
238				break;
239
240			default:
241				p->flags |= PL_MARK;
242				break;
243			}
244		}
245
246		for (p = payload_first(msg, ISAKMP_PAYLOAD_DELETE); p;
247		    p = TAILQ_NEXT(p, link)) {
248			LOG_DBG((LOG_EXCHANGE, 10,
249			    "isakmp_responder: got DELETE, ignoring"));
250			p->flags |= PL_MARK;
251		}
252		return 0;
253
254	case ISAKMP_EXCH_TRANSACTION:
255		/* return 0 isakmp_cfg_responder (msg); */
256
257	default:
258		/* XXX So far we don't accept any proposals.  */
259		if (payload_first(msg, ISAKMP_PAYLOAD_SA)) {
260			message_drop(msg, ISAKMP_NOTIFY_NO_PROPOSAL_CHOSEN,
261			    0, 1, 0);
262			return -1;
263		}
264	}
265	return 0;
266}
267