1 /* $OpenBSD: nat_traversal.c,v 1.25 2017/12/05 20:31:45 jca Exp $ */ 2 3 /* 4 * Copyright (c) 2004 H�kan Olsson. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include <sys/types.h> 28 #include <stdlib.h> 29 #include <string.h> 30 31 #include "conf.h" 32 #include "exchange.h" 33 #include "hash.h" 34 #include "ipsec.h" 35 #include "isakmp_fld.h" 36 #include "isakmp_num.h" 37 #include "ipsec_num.h" 38 #include "log.h" 39 #include "message.h" 40 #include "nat_traversal.h" 41 #include "prf.h" 42 #include "sa.h" 43 #include "timer.h" 44 #include "transport.h" 45 #include "util.h" 46 #include "virtual.h" 47 48 int disable_nat_t = 0; 49 50 /* 51 * NAT-T capability of the other peer is determined by a particular vendor 52 * ID sent in the first message. This vendor ID string is supposed to be a 53 * MD5 hash of "RFC 3947". 54 * 55 * These seem to be the "well" known variants of this string in use by 56 * products today. 57 * 58 * Note that the VID specified in draft 2 is ambiguous: It was 59 * accidentally calculated from the string "draft-ietf-ipsec-nat-t-ike-02\n" 60 * although the string was documented without the trailing '\n'. The authors 61 * suggested afterwards to use the string with the trailing '\n'. 62 */ 63 64 static struct nat_t_cap isakmp_nat_t_cap[] = { 65 { VID_DRAFT_V2_N, EXCHANGE_FLAG_NAT_T_DRAFT, 66 "draft-ietf-ipsec-nat-t-ike-02\n", NULL, 0 }, 67 { VID_DRAFT_V3, EXCHANGE_FLAG_NAT_T_DRAFT, 68 "draft-ietf-ipsec-nat-t-ike-03", NULL, 0 }, 69 { VID_RFC3947, EXCHANGE_FLAG_NAT_T_RFC, 70 "RFC 3947", NULL, 0 }, 71 }; 72 73 #define NUMNATTCAP (sizeof isakmp_nat_t_cap / sizeof isakmp_nat_t_cap[0]) 74 75 /* In seconds. Recommended in draft-ietf-ipsec-udp-encaps-09. */ 76 #define NAT_T_KEEPALIVE_INTERVAL 20 77 78 static int nat_t_setup_hashes(void); 79 static int nat_t_add_vendor_payload(struct message *, struct nat_t_cap *); 80 static int nat_t_add_nat_d(struct message *, struct sockaddr *); 81 static int nat_t_match_nat_d_payload(struct message *, struct sockaddr *); 82 83 void 84 nat_t_init(void) 85 { 86 nat_t_setup_hashes(); 87 } 88 89 /* Generate the NAT-T capability marker hashes. Executed only once. */ 90 static int 91 nat_t_setup_hashes(void) 92 { 93 struct hash *hash; 94 int n = NUMNATTCAP; 95 int i; 96 97 /* The draft says to use MD5. */ 98 hash = hash_get(HASH_MD5); 99 if (!hash) { 100 /* Should never happen. */ 101 log_print("nat_t_setup_hashes: " 102 "could not find MD5 hash structure!"); 103 return -1; 104 } 105 106 /* Populate isakmp_nat_t_cap with hashes. */ 107 for (i = 0; i < n; i++) { 108 isakmp_nat_t_cap[i].hashsize = hash->hashsize; 109 isakmp_nat_t_cap[i].hash = malloc(hash->hashsize); 110 if (!isakmp_nat_t_cap[i].hash) { 111 log_error("nat_t_setup_hashes: malloc (%lu) failed", 112 (unsigned long)hash->hashsize); 113 goto errout; 114 } 115 116 hash->Init(hash->ctx); 117 hash->Update(hash->ctx, 118 (unsigned char *)isakmp_nat_t_cap[i].text, 119 strlen(isakmp_nat_t_cap[i].text)); 120 hash->Final(isakmp_nat_t_cap[i].hash, hash->ctx); 121 122 LOG_DBG((LOG_EXCHANGE, 50, "nat_t_setup_hashes: " 123 "MD5(\"%s\") (%lu bytes)", isakmp_nat_t_cap[i].text, 124 (unsigned long)hash->hashsize)); 125 LOG_DBG_BUF((LOG_EXCHANGE, 50, "nat_t_setup_hashes", 126 isakmp_nat_t_cap[i].hash, hash->hashsize)); 127 } 128 129 return 0; 130 131 errout: 132 for (i = 0; i < n; i++) 133 free(isakmp_nat_t_cap[i].hash); 134 return -1; 135 } 136 137 /* Add one NAT-T VENDOR payload. */ 138 static int 139 nat_t_add_vendor_payload(struct message *msg, struct nat_t_cap *cap) 140 { 141 size_t buflen = cap->hashsize + ISAKMP_GEN_SZ; 142 u_int8_t *buf; 143 144 if (disable_nat_t) 145 return 0; 146 147 buf = malloc(buflen); 148 if (!buf) { 149 log_error("nat_t_add_vendor_payload: malloc (%lu) failed", 150 (unsigned long)buflen); 151 return -1; 152 } 153 154 SET_ISAKMP_GEN_LENGTH(buf, buflen); 155 memcpy(buf + ISAKMP_VENDOR_ID_OFF, cap->hash, cap->hashsize); 156 if (message_add_payload(msg, ISAKMP_PAYLOAD_VENDOR, buf, buflen, 1)) { 157 free(buf); 158 return -1; 159 } 160 return 0; 161 } 162 163 /* Add the NAT-T capability markers (VENDOR payloads). */ 164 int 165 nat_t_add_vendor_payloads(struct message *msg) 166 { 167 int i; 168 169 if (disable_nat_t) 170 return 0; 171 172 for (i = 0; i < NUMNATTCAP; i++) 173 if (nat_t_add_vendor_payload(msg, &isakmp_nat_t_cap[i])) 174 return -1; 175 return 0; 176 } 177 178 /* 179 * Check an incoming message for NAT-T capability markers. 180 */ 181 void 182 nat_t_check_vendor_payload(struct message *msg, struct payload *p) 183 { 184 u_int8_t *pbuf = p->p; 185 size_t vlen; 186 int i; 187 188 if (disable_nat_t) 189 return; 190 191 vlen = GET_ISAKMP_GEN_LENGTH(pbuf) - ISAKMP_GEN_SZ; 192 193 for (i = 0; i < NUMNATTCAP; i++) { 194 if (vlen != isakmp_nat_t_cap[i].hashsize) { 195 continue; 196 } 197 if (memcmp(isakmp_nat_t_cap[i].hash, pbuf + ISAKMP_GEN_SZ, 198 vlen) == 0) { 199 /* This peer is NAT-T capable. */ 200 msg->exchange->flags |= EXCHANGE_FLAG_NAT_T_CAP_PEER; 201 msg->exchange->flags |= isakmp_nat_t_cap[i].flags; 202 LOG_DBG((LOG_EXCHANGE, 10, 203 "nat_t_check_vendor_payload: " 204 "NAT-T capable peer detected")); 205 p->flags |= PL_MARK; 206 } 207 } 208 209 return; 210 } 211 212 /* Generate the NAT-D payload hash : HASH(CKY-I | CKY-R | IP | Port). */ 213 static u_int8_t * 214 nat_t_generate_nat_d_hash(struct message *msg, struct sockaddr *sa, 215 size_t *hashlen) 216 { 217 struct ipsec_exch *ie = (struct ipsec_exch *)msg->exchange->data; 218 struct hash *hash; 219 u_int8_t *res; 220 in_port_t port; 221 222 hash = hash_get(ie->hash->type); 223 if (hash == NULL) { 224 log_print ("nat_t_generate_nat_d_hash: no hash"); 225 return NULL; 226 } 227 228 *hashlen = hash->hashsize; 229 230 res = malloc(*hashlen); 231 if (!res) { 232 log_print("nat_t_generate_nat_d_hash: malloc (%lu) failed", 233 (unsigned long)*hashlen); 234 *hashlen = 0; 235 return NULL; 236 } 237 238 port = sockaddr_port(sa); 239 bzero(res, *hashlen); 240 241 hash->Init(hash->ctx); 242 hash->Update(hash->ctx, msg->exchange->cookies, 243 sizeof msg->exchange->cookies); 244 hash->Update(hash->ctx, sockaddr_addrdata(sa), sockaddr_addrlen(sa)); 245 hash->Update(hash->ctx, (unsigned char *)&port, sizeof port); 246 hash->Final(res, hash->ctx); 247 return res; 248 } 249 250 /* Add a NAT-D payload to our message. */ 251 static int 252 nat_t_add_nat_d(struct message *msg, struct sockaddr *sa) 253 { 254 int ret; 255 u_int8_t *hbuf, *buf; 256 size_t hbuflen, buflen; 257 258 hbuf = nat_t_generate_nat_d_hash(msg, sa, &hbuflen); 259 if (!hbuf) { 260 log_print("nat_t_add_nat_d: NAT-D hash gen failed"); 261 return -1; 262 } 263 264 buflen = ISAKMP_NAT_D_DATA_OFF + hbuflen; 265 buf = malloc(buflen); 266 if (!buf) { 267 log_error("nat_t_add_nat_d: malloc (%lu) failed", 268 (unsigned long)buflen); 269 free(hbuf); 270 return -1; 271 } 272 273 SET_ISAKMP_GEN_LENGTH(buf, buflen); 274 memcpy(buf + ISAKMP_NAT_D_DATA_OFF, hbuf, hbuflen); 275 free(hbuf); 276 277 if (msg->exchange->flags & EXCHANGE_FLAG_NAT_T_RFC) 278 ret = message_add_payload(msg, ISAKMP_PAYLOAD_NAT_D, buf, 279 buflen, 1); 280 else if (msg->exchange->flags & EXCHANGE_FLAG_NAT_T_DRAFT) 281 ret = message_add_payload(msg, ISAKMP_PAYLOAD_NAT_D_DRAFT, 282 buf, buflen, 1); 283 else 284 ret = -1; 285 286 if (ret) { 287 free(buf); 288 return -1; 289 } 290 return 0; 291 } 292 293 /* We add two NAT-D payloads, one each for src and dst. */ 294 int 295 nat_t_exchange_add_nat_d(struct message *msg) 296 { 297 struct sockaddr *sa; 298 299 /* Remote address first. */ 300 msg->transport->vtbl->get_dst(msg->transport, &sa); 301 if (nat_t_add_nat_d(msg, sa)) 302 return -1; 303 304 msg->transport->vtbl->get_src(msg->transport, &sa); 305 if (nat_t_add_nat_d(msg, sa)) 306 return -1; 307 return 0; 308 } 309 310 /* Generate and match a NAT-D hash against the NAT-D payload (pl.) data. */ 311 static int 312 nat_t_match_nat_d_payload(struct message *msg, struct sockaddr *sa) 313 { 314 struct payload *p; 315 u_int8_t *hbuf; 316 size_t hbuflen; 317 int found = 0; 318 319 /* 320 * If there are no NAT-D payloads in the message, return "found" 321 * as this will avoid NAT-T (see nat_t_exchange_check_nat_d()). 322 */ 323 if ((p = payload_first(msg, ISAKMP_PAYLOAD_NAT_D_DRAFT)) == NULL && 324 (p = payload_first(msg, ISAKMP_PAYLOAD_NAT_D)) == NULL) 325 return 1; 326 327 hbuf = nat_t_generate_nat_d_hash(msg, sa, &hbuflen); 328 if (!hbuf) 329 return 0; 330 331 for (; p; p = TAILQ_NEXT(p, link)) { 332 if (GET_ISAKMP_GEN_LENGTH (p->p) != 333 hbuflen + ISAKMP_NAT_D_DATA_OFF) 334 continue; 335 336 if (memcmp(p->p + ISAKMP_NAT_D_DATA_OFF, hbuf, hbuflen) == 0) { 337 found++; 338 break; 339 } 340 } 341 free(hbuf); 342 return found; 343 } 344 345 /* 346 * Check if we need to activate NAT-T, and if we need to send keepalive 347 * messages to the other side, i.e if we are a nat:ed peer. 348 */ 349 int 350 nat_t_exchange_check_nat_d(struct message *msg) 351 { 352 struct sockaddr *sa; 353 int outgoing_path_is_clear, incoming_path_is_clear; 354 355 /* Assume trouble, i.e NAT-boxes in our path. */ 356 outgoing_path_is_clear = incoming_path_is_clear = 0; 357 358 msg->transport->vtbl->get_src(msg->transport, &sa); 359 if (nat_t_match_nat_d_payload(msg, sa)) 360 outgoing_path_is_clear = 1; 361 362 msg->transport->vtbl->get_dst(msg->transport, &sa); 363 if (nat_t_match_nat_d_payload(msg, sa)) 364 incoming_path_is_clear = 1; 365 366 if (outgoing_path_is_clear && incoming_path_is_clear) { 367 LOG_DBG((LOG_EXCHANGE, 40, "nat_t_exchange_check_nat_d: " 368 "no NAT")); 369 return 0; /* No NAT-T required. */ 370 } 371 372 /* NAT-T handling required. */ 373 msg->exchange->flags |= EXCHANGE_FLAG_NAT_T_ENABLE; 374 375 if (!outgoing_path_is_clear) { 376 msg->exchange->flags |= EXCHANGE_FLAG_NAT_T_KEEPALIVE; 377 LOG_DBG((LOG_EXCHANGE, 10, "nat_t_exchange_check_nat_d: " 378 "NAT detected, we're behind it")); 379 } else 380 LOG_DBG ((LOG_EXCHANGE, 10, 381 "nat_t_exchange_check_nat_d: NAT detected")); 382 return 1; 383 } 384 385 static void 386 nat_t_send_keepalive(void *v_arg) 387 { 388 struct sa *sa = (struct sa *)v_arg; 389 struct transport *t; 390 struct timespec now; 391 int interval; 392 393 /* Send the keepalive message. */ 394 t = ((struct virtual_transport *)sa->transport)->encap; 395 t->vtbl->send_message(NULL, t); 396 397 /* Set new timer. */ 398 interval = conf_get_num("General", "NAT-T-Keepalive", 0); 399 if (interval < 1) 400 interval = NAT_T_KEEPALIVE_INTERVAL; 401 clock_gettime(CLOCK_MONOTONIC, &now); 402 now.tv_sec += interval; 403 404 sa->nat_t_keepalive = timer_add_event("nat_t_send_keepalive", 405 nat_t_send_keepalive, v_arg, &now); 406 if (!sa->nat_t_keepalive) 407 log_print("nat_t_send_keepalive: " 408 "timer_add_event() failed, will send no more keepalives"); 409 } 410 411 void 412 nat_t_setup_keepalive(struct sa *sa) 413 { 414 struct sockaddr *src; 415 struct timespec now; 416 417 if (sa->initiator) 418 sa->transport->vtbl->get_src(sa->transport, &src); 419 else 420 sa->transport->vtbl->get_dst(sa->transport, &src); 421 422 if (!virtual_listen_lookup(src)) 423 return; 424 425 clock_gettime(CLOCK_MONOTONIC, &now); 426 now.tv_sec += NAT_T_KEEPALIVE_INTERVAL; 427 428 sa->nat_t_keepalive = timer_add_event("nat_t_send_keepalive", 429 nat_t_send_keepalive, sa, &now); 430 if (!sa->nat_t_keepalive) 431 log_print("nat_t_setup_keepalive: " 432 "timer_add_event() failed, will not send keepalives"); 433 434 LOG_DBG((LOG_TRANSPORT, 50, "nat_t_setup_keepalive: " 435 "added event for phase 1 SA %p", sa)); 436 } 437