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