]> git.saurik.com Git - apple/ipsec.git/blob - ipsec-tools/racoon/fsm.c
8ff862cc96d57267ffaef12257a5f292643cf6a5
[apple/ipsec.git] / ipsec-tools / racoon / fsm.c
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
46 void
47 fsm_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 //================================
57 void
58 fsm_api_handle_connect (struct sockaddr_storage *remote, const int connect_mode)
59 {
60
61
62 }
63
64 void
65 fsm_api_handle_disconnect (struct sockaddr_storage *remote, const char *reason)
66 {
67
68
69 }
70
71 void
72 fsm_pfkey_handle_acquire (phase2_handle_t *iph2)
73 {
74
75
76 }
77
78 void
79 fsm_pfkey_getspi_complete (phase2_handle_t *iph2)
80 {
81
82 }
83
84 void
85 fsm_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
95 int
96 fsm_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
184 fail:
185 plog(ASL_LEVEL_ERR, "Phase 1 negotiation failed.\n");
186 ike_session_unlink_phase1(iph1);
187 return error;
188
189 }
190
191
192 int
193 fsm_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 vpncontrol_notify_ike_failed(error, FROM_LOCAL, iph1_get_remote_v4_address(iph1), 0, NULL);
251 }
252
253 return error;
254 }
255
256 int
257 fsm_ikev1_phase2_process_payloads (phase2_handle_t *iph2, vchar_t *msg)
258 {
259
260 int error = 0;
261 #ifdef ENABLE_STATS
262 struct timeval start, end;
263
264 gettimeofday(&start, NULL);
265 #endif
266
267 switch (iph2->status) {
268 /* ignore a packet */
269 case IKEV1_STATE_PHASE2_ESTABLISHED:
270 case IKEV1_STATE_QUICK_I_GETSPISENT:
271 case IKEV1_STATE_QUICK_R_GETSPISENT:
272 return 0;
273
274 case IKEV1_STATE_QUICK_I_MSG1SENT:
275 error = quick_i2recv(iph2, msg);
276 break;
277
278 case IKEV1_STATE_QUICK_I_MSG3SENT:
279 error = quick_i4recv(iph2, msg);
280 break;
281
282 case IKEV1_STATE_QUICK_R_START:
283 error = quick_r1recv(iph2, msg);
284 break;
285
286 case IKEV1_STATE_QUICK_R_MSG2SENT:
287 error = quick_r3recv(iph2, msg);
288 break;
289
290 default:
291 // log invalid state
292 error = -1;
293 break;
294 }
295
296 if (error) {
297 plog(ASL_LEVEL_ERR, "failed to pre-process packet.\n");
298 if (error == ISAKMP_INTERNAL_ERROR)
299 fatal_error(-1);
300 isakmp_info_send_n1(iph2->ph1, error, NULL);
301 goto fail;
302 }
303
304 /* when using commit bit, status will be reached here. */
305 //if (iph2->status == PHASE2ST_ADDSA) //%%% BUG FIX - wrong place
306 // return 0;
307
308 /* free resend buffer */
309 if (iph2->sendbuf == NULL && iph2->status != IKEV1_STATE_QUICK_R_MSG1RCVD) {
310 plog(ASL_LEVEL_ERR,
311 "no buffer found as sendbuf\n");
312 error = -1;
313 goto fail;
314 }
315 VPTRINIT(iph2->sendbuf);
316
317 /* turn off schedule */
318 SCHED_KILL(iph2->scr);
319
320 /* when using commit bit, will be finished here - no more packets to send */
321 if (iph2->status == IKEV1_STATE_QUICK_I_ADDSA)
322 return 0;
323
324 error = fsm_ikev1_phase2_send_response(iph2, msg);
325 if (error) {
326 plog(ASL_LEVEL_ERR, "failed to process packet.\n");
327 goto fail;
328 }
329
330 #ifdef ENABLE_STATS
331 gettimeofday(&end, NULL);
332 syslog(LOG_NOTICE, "%s(%s): %8.6f",
333 "Phase 2",
334 s_isakmp_state(ISAKMP_ETYPE_QUICK, iph2->side, iph2->status),
335 timedelta(&start, &end));
336 #endif
337
338 return 0;
339
340 fail:
341 plog(ASL_LEVEL_ERR, "Phase 2 negotiation failed.\n");
342 ike_session_unlink_phase2(iph2);
343 return error;
344
345 }
346
347 int
348 fsm_ikev1_phase2_send_response(phase2_handle_t *iph2, vchar_t *msg)
349 {
350
351 int error = 0;
352
353 switch (iph2->status) {
354 case IKEV1_STATE_QUICK_R_MSG1RCVD:
355 error = quick_rprep(iph2, msg);
356 break;
357
358 case IKEV1_STATE_QUICK_I_GETSPIDONE:
359 error = quick_i1send(iph2, msg);
360 break;
361
362 case IKEV1_STATE_QUICK_I_MSG2RCVD:
363 error = quick_i3send(iph2, msg);
364 break;
365
366 case IKEV1_STATE_QUICK_R_GETSPIDONE:
367 error = quick_r2send(iph2, msg);
368 break;
369
370 case IKEV1_STATE_QUICK_R_MSG3RCVD:
371 error = quick_r4send(iph2, msg);
372 break;
373
374 case IKEV1_STATE_QUICK_R_COMMIT:
375 error = quick_rfinalize(iph2, msg);
376 break;
377
378 default:
379 // log invalid state
380 error = -1;
381 break;;
382 }
383 return error;
384
385 }