xref: /openbsd/sbin/isakmpd/isakmp_doi.c (revision 8713c8b0)
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 
51 static int      isakmp_debug_attribute(u_int16_t, u_int8_t *, u_int16_t,
52     void *);
53 static void     isakmp_finalize_exchange(struct message *);
54 static struct keystate *isakmp_get_keystate(struct message *);
55 static int      isakmp_initiator(struct message *);
56 static int      isakmp_responder(struct message *);
57 static void     isakmp_setup_situation(u_int8_t *);
58 static size_t   isakmp_situation_size(void);
59 static u_int8_t isakmp_spi_size(u_int8_t);
60 static int	isakmp_validate_attribute(u_int16_t, u_int8_t *, u_int16_t,
61     void *);
62 static int      isakmp_validate_exchange(u_int8_t);
63 static int	isakmp_validate_id_information(u_int8_t, u_int8_t *,
64     u_int8_t *, size_t, struct exchange *);
65 static int      isakmp_validate_key_information(u_int8_t *, size_t);
66 static int      isakmp_validate_notification(u_int16_t);
67 static int      isakmp_validate_proto(u_int8_t);
68 static int      isakmp_validate_situation(u_int8_t *, size_t *, size_t);
69 static int      isakmp_validate_transform_id(u_int8_t, u_int8_t);
70 
71 static 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.  */
104 void
isakmp_doi_init(void)105 isakmp_doi_init(void)
106 {
107 	doi_register(&isakmp_doi);
108 }
109 
110 int
isakmp_debug_attribute(u_int16_t type,u_int8_t * value,u_int16_t len,void * vmsg)111 isakmp_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 
118 static void
isakmp_finalize_exchange(struct message * msg)119 isakmp_finalize_exchange(struct message *msg)
120 {
121 }
122 
123 static struct keystate *
isakmp_get_keystate(struct message * msg)124 isakmp_get_keystate(struct message *msg)
125 {
126 	return 0;
127 }
128 
129 static void
isakmp_setup_situation(u_int8_t * buf)130 isakmp_setup_situation(u_int8_t *buf)
131 {
132 	/* Nothing to do.  */
133 }
134 
135 static size_t
isakmp_situation_size(void)136 isakmp_situation_size(void)
137 {
138 	return 0;
139 }
140 
141 static u_int8_t
isakmp_spi_size(u_int8_t proto)142 isakmp_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 
148 static int
isakmp_validate_attribute(u_int16_t type,u_int8_t * value,u_int16_t len,void * vmsg)149 isakmp_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 
156 static int
isakmp_validate_exchange(u_int8_t exch)157 isakmp_validate_exchange(u_int8_t exch)
158 {
159 	/* If we get here the exchange is invalid.  */
160 	return -1;
161 }
162 
163 static int
isakmp_validate_id_information(u_int8_t type,u_int8_t * extra,u_int8_t * buf,size_t sz,struct exchange * exchange)164 isakmp_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 
170 static int
isakmp_validate_key_information(u_int8_t * buf,size_t sz)171 isakmp_validate_key_information(u_int8_t *buf, size_t sz)
172 {
173 	/* Nothing to do.  */
174 	return 0;
175 }
176 
177 static int
isakmp_validate_notification(u_int16_t type)178 isakmp_validate_notification(u_int16_t type)
179 {
180 	/* If we get here the message type is invalid.  */
181 	return -1;
182 }
183 
184 static int
isakmp_validate_proto(u_int8_t proto)185 isakmp_validate_proto(u_int8_t proto)
186 {
187 	/* If we get here the protocol is invalid.  */
188 	return -1;
189 }
190 
191 static int
isakmp_validate_situation(u_int8_t * buf,size_t * sz,size_t len)192 isakmp_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 
199 static int
isakmp_validate_transform_id(u_int8_t proto,u_int8_t transform_id)200 isakmp_validate_transform_id(u_int8_t proto, u_int8_t transform_id)
201 {
202 	/* XXX Not yet implemented.  */
203 	return -1;
204 }
205 
206 static int
isakmp_initiator(struct message * msg)207 isakmp_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 
217 static int
isakmp_responder(struct message * msg)218 isakmp_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