1/* 2 * Copyright (c) 2008, 2012, 2013 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * The contents of this file constitute Original Code as defined in and 7 * are subject to the Apple Public Source License Version 1.1 (the 8 * "License"). You may not use this file except in compliance with the 9 * License. Please obtain a copy of the License at 10 * http://www.apple.com/publicsource and read it before using this file. 11 * 12 * This Original Code and all software distributed under the License are 13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 * License for the specific language governing rights and limitations 18 * under the License. 19 * 20 * @APPLE_LICENSE_HEADER_END@ 21 */ 22 23 24#include "fsm.h" 25 26#include <stdlib.h> 27#include <sys/types.h> 28#include <sys/param.h> 29#include <sys/queue.h> 30 31#include "var.h" 32#include "misc.h" 33#include "session.h" 34#include "isakmp.h" 35#include "ike_session.h" 36#include "isakmp_var.h" 37#include "isakmp_ident.h" 38#include "isakmp_agg.h" 39#include "isakmp_quick.h" 40#include "isakmp_inf.h" 41#include "vpn_control_var.h" 42 43#include "plog.h" 44#include "schedule.h" 45 46void 47fsm_set_state(int *var, int state) 48{ 49 *var = state; 50 plog(ASL_LEVEL_DEBUG, "****** state changed to: %s\n", s_isakmp_state(0, 0, state)); 51} 52 53 54//================================ 55// Version Agnostic Events 56//================================ 57void 58fsm_api_handle_connect (struct sockaddr_storage *remote, const int connect_mode) 59{ 60 61 62} 63 64void 65fsm_api_handle_disconnect (struct sockaddr_storage *remote, const char *reason) 66{ 67 68 69} 70 71void 72fsm_pfkey_handle_acquire (phase2_handle_t *iph2) 73{ 74 75 76} 77 78void 79fsm_pfkey_getspi_complete (phase2_handle_t *iph2) 80{ 81 82} 83 84void 85fsm_isakmp_initial_pkt (vchar_t *pkt, struct sockaddr_storage *local, struct sockaddr_storage *remote) 86{ 87 88 89} 90 91//================================ 92// IKEv1 Events 93//================================ 94 95int 96fsm_ikev1_phase1_process_payloads (phase1_handle_t *iph1, vchar_t *msg) 97{ 98 99 int error = 0; 100#ifdef ENABLE_STATS 101 struct timeval start, end; 102 103 gettimeofday(&start, NULL); 104#endif 105 106 switch (iph1->status) { 107 case IKEV1_STATE_PHASE1_ESTABLISHED: 108 return 0; // ignore - already established 109 110 case IKEV1_STATE_IDENT_I_MSG1SENT: 111 error = ident_i2recv(iph1, msg); 112 break; 113 114 case IKEV1_STATE_IDENT_I_MSG3SENT: 115 error = ident_i4recv(iph1, msg); 116 break; 117 118 case IKEV1_STATE_IDENT_I_MSG5SENT: 119 error = ident_i6recv(iph1, msg); 120 break; 121 122 case IKEV1_STATE_IDENT_R_START: 123 error = ident_r1recv(iph1, msg); 124 if (error) { 125 plog(ASL_LEVEL_ERR, "failed to pre-process packet.\n"); 126 goto fail; 127 } 128 break; 129 130 case IKEV1_STATE_IDENT_R_MSG2SENT: 131 error = ident_r3recv(iph1, msg); 132 break; 133 134 case IKEV1_STATE_IDENT_R_MSG4SENT: 135 error = ident_r5recv(iph1, msg); 136 break; 137 138 case IKEV1_STATE_AGG_R_START: 139 error = agg_r1recv(iph1, msg); 140 if (error) { 141 plog(ASL_LEVEL_ERR, "failed to pre-process packet.\n"); 142 goto fail; 143 } 144 break; 145 146 case IKEV1_STATE_AGG_I_MSG1SENT: 147 error = agg_i2recv(iph1, msg); 148 break; 149 150 case IKEV1_STATE_AGG_R_MSG2SENT: 151 error = agg_r3recv(iph1, msg); 152 break; 153 154 default: 155 // log invalid state 156 error = -1; 157 break; 158 } 159 if (error) 160 return 0; // ignore error and keep phase 1 handle 161 162 VPTRINIT(iph1->sendbuf); 163 /* turn off schedule */ 164 SCHED_KILL(iph1->scr); 165 166 /* send */ 167 plog(ASL_LEVEL_DEBUG, "===\n"); 168 if ((error = fsm_ikev1_phase1_send_response(iph1, msg))) { 169 plog(ASL_LEVEL_ERR, "failed to process packet.\n"); 170 goto fail; 171 } 172 173#ifdef ENABLE_STATS 174 gettimeofday(&end, NULL); 175 syslog(LOG_NOTICE, "%s(%s): %8.6f", 176 "Phase 1", s_isakmp_state(iph1->etype, iph1->side, iph1->status), 177 timedelta(&start, &end)); 178#endif 179 if (FSM_STATE_IS_ESTABLISHED(iph1->status)) 180 ikev1_phase1_established(iph1); 181 182 return 0; 183 184fail: 185 plog(ASL_LEVEL_ERR, "Phase 1 negotiation failed.\n"); 186 ike_session_unlink_phase1(iph1); 187 return error; 188 189} 190 191 192int 193fsm_ikev1_phase1_send_response(phase1_handle_t *iph1, vchar_t *msg) 194{ 195 196 int error = 0; 197 198 switch (iph1->status) { 199 case IKEV1_STATE_IDENT_I_START: 200 error = ident_i1send(iph1, msg); 201 break; 202 203 case IKEV1_STATE_IDENT_I_MSG2RCVD: 204 error = ident_i3send(iph1, msg); 205 break; 206 207 case IKEV1_STATE_IDENT_I_MSG4RCVD: 208 error = ident_i5send(iph1, msg); 209 break; 210 211 case IKEV1_STATE_IDENT_I_MSG6RCVD: 212 error = ident_ifinalize(iph1, msg); 213 break; 214 215 case IKEV1_STATE_IDENT_R_MSG1RCVD: 216 error = ident_r2send(iph1, msg); 217 break; 218 219 case IKEV1_STATE_IDENT_R_MSG3RCVD: 220 error = ident_r4send(iph1, msg); 221 break; 222 223 case IKEV1_STATE_IDENT_R_MSG5RCVD: 224 error = ident_r6send(iph1, msg); 225 break; 226 227 case IKEV1_STATE_AGG_I_START: 228 error = agg_i1send(iph1, msg); 229 break; 230 231 case IKEV1_STATE_AGG_I_MSG2RCVD: 232 error = agg_i3send(iph1, msg); 233 break; 234 235 case IKEV1_STATE_AGG_R_MSG1RCVD: 236 error = agg_r2send(iph1, msg); 237 break; 238 239 case IKEV1_STATE_AGG_R_MSG3RCVD: 240 error = agg_rfinalize(iph1, msg); 241 break; 242 243 default: 244 // log invalid state 245 error = -1; 246 break;; 247 } 248 249 if (error) { 250 u_int32_t address; 251 if (iph1->remote->ss_family == AF_INET) 252 address = ((struct sockaddr_in *)iph1->remote)->sin_addr.s_addr; 253 else { 254 address = 0; 255 } 256 vpncontrol_notify_ike_failed(error, FROM_LOCAL, address, 0, NULL); 257 } 258 259 return error; 260} 261 262int 263fsm_ikev1_phase2_process_payloads (phase2_handle_t *iph2, vchar_t *msg) 264{ 265 266 int error = 0; 267#ifdef ENABLE_STATS 268 struct timeval start, end; 269 270 gettimeofday(&start, NULL); 271#endif 272 273 switch (iph2->status) { 274 /* ignore a packet */ 275 case IKEV1_STATE_PHASE2_ESTABLISHED: 276 case IKEV1_STATE_QUICK_I_GETSPISENT: 277 case IKEV1_STATE_QUICK_R_GETSPISENT: 278 return 0; 279 280 case IKEV1_STATE_QUICK_I_MSG1SENT: 281 error = quick_i2recv(iph2, msg); 282 break; 283 284 case IKEV1_STATE_QUICK_I_MSG3SENT: 285 error = quick_i4recv(iph2, msg); 286 break; 287 288 case IKEV1_STATE_QUICK_R_START: 289 error = quick_r1recv(iph2, msg); 290 break; 291 292 case IKEV1_STATE_QUICK_R_MSG2SENT: 293 error = quick_r3recv(iph2, msg); 294 break; 295 296 default: 297 // log invalid state 298 error = -1; 299 break; 300 } 301 302 if (error) { 303 plog(ASL_LEVEL_ERR, "failed to pre-process packet.\n"); 304 if (error == ISAKMP_INTERNAL_ERROR) 305 fatal_error(-1); 306 isakmp_info_send_n1(iph2->ph1, error, NULL); 307 goto fail; 308 } 309 310 /* when using commit bit, status will be reached here. */ 311 //if (iph2->status == PHASE2ST_ADDSA) //%%% BUG FIX - wrong place 312 // return 0; 313 314 /* free resend buffer */ 315 if (iph2->sendbuf == NULL && iph2->status != IKEV1_STATE_QUICK_R_MSG1RCVD) { 316 plog(ASL_LEVEL_ERR, 317 "no buffer found as sendbuf\n"); 318 error = -1; 319 goto fail; 320 } 321 VPTRINIT(iph2->sendbuf); 322 323 /* turn off schedule */ 324 SCHED_KILL(iph2->scr); 325 326 /* when using commit bit, will be finished here - no more packets to send */ 327 if (iph2->status == IKEV1_STATE_QUICK_I_ADDSA) 328 return 0; 329 330 error = fsm_ikev1_phase2_send_response(iph2, msg); 331 if (error) { 332 plog(ASL_LEVEL_ERR, "failed to process packet.\n"); 333 goto fail; 334 } 335 336#ifdef ENABLE_STATS 337 gettimeofday(&end, NULL); 338 syslog(LOG_NOTICE, "%s(%s): %8.6f", 339 "Phase 2", 340 s_isakmp_state(ISAKMP_ETYPE_QUICK, iph2->side, iph2->status), 341 timedelta(&start, &end)); 342#endif 343 344 return 0; 345 346fail: 347 plog(ASL_LEVEL_ERR, "Phase 2 negotiation failed.\n"); 348 ike_session_unlink_phase2(iph2); 349 return error; 350 351} 352 353int 354fsm_ikev1_phase2_send_response(phase2_handle_t *iph2, vchar_t *msg) 355{ 356 357 int error = 0; 358 359 switch (iph2->status) { 360 case IKEV1_STATE_QUICK_R_MSG1RCVD: 361 error = quick_rprep(iph2, msg); 362 break; 363 364 case IKEV1_STATE_QUICK_I_GETSPIDONE: 365 error = quick_i1send(iph2, msg); 366 break; 367 368 case IKEV1_STATE_QUICK_I_MSG2RCVD: 369 error = quick_i3send(iph2, msg); 370 break; 371 372 case IKEV1_STATE_QUICK_R_GETSPIDONE: 373 error = quick_r2send(iph2, msg); 374 break; 375 376 case IKEV1_STATE_QUICK_R_MSG3RCVD: 377 error = quick_r4send(iph2, msg); 378 break; 379 380 case IKEV1_STATE_QUICK_R_COMMIT: 381 error = quick_rfinalize(iph2, msg); 382 break; 383 384 default: 385 // log invalid state 386 error = -1; 387 break;; 388 } 389 return error; 390 391} 392 393