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 105 isakmp_doi_init(void) 106 { 107 doi_register(&isakmp_doi); 108 } 109 110 int 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 119 isakmp_finalize_exchange(struct message *msg) 120 { 121 } 122 123 static struct keystate * 124 isakmp_get_keystate(struct message *msg) 125 { 126 return 0; 127 } 128 129 static void 130 isakmp_setup_situation(u_int8_t *buf) 131 { 132 /* Nothing to do. */ 133 } 134 135 static size_t 136 isakmp_situation_size(void) 137 { 138 return 0; 139 } 140 141 static u_int8_t 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 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 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 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 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 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 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 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 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 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 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