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