2 * Copyright (C) 2008 Tobias Brunner
3 * Copyright (C) 2005-2006 Martin Willi
4 * Copyright (C) 2005 Jan Hutter
5 * Hochschule fuer Technik Rapperswil
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 #include <network/socket.h>
25 #include <network/packet.h>
26 #include <processing/jobs/job.h>
27 #include <processing/jobs/process_message_job.h>
28 #include <processing/jobs/callback_job.h>
29 #include <crypto/hashers/hasher.h>
31 /** lifetime of a cookie, in seconds */
32 #define COOKIE_LIFETIME 10
33 /** how many times to reuse the secret */
34 #define COOKIE_REUSE 10000
35 /** default value for private_receiver_t.cookie_threshold */
36 #define COOKIE_THRESHOLD_DEFAULT 10
37 /** default value for private_receiver_t.block_threshold */
38 #define BLOCK_THRESHOLD_DEFAULT 5
39 /** length of the secret to use for cookie calculation */
40 #define SECRET_LENGTH 16
42 typedef struct private_receiver_t private_receiver_t
;
45 * Private data of a receiver_t object.
47 struct private_receiver_t
{
49 * Public part of a receiver_t object.
54 * Threads job receiving packets
59 * current secret to use for cookie calculation
61 char secret
[SECRET_LENGTH
];
64 * previous secret used to verify older cookies
66 char secret_old
[SECRET_LENGTH
];
69 * how many times we have used "secret" so far
71 u_int32_t secret_used
;
74 * time we did the cookie switch
76 u_int32_t secret_switch
;
79 * time offset to use, hides our system time
81 u_int32_t secret_offset
;
84 * the RNG to use for secret generation
89 * hasher to use for cookie calculation
94 * require cookies after this many half open IKE_SAs
96 u_int32_t cookie_threshold
;
99 * how many half open IKE_SAs per peer before blocking
101 u_int32_t block_threshold
;
104 * Drop IKE_SA_INIT requests if processor job load exceeds this limit
106 u_int init_limit_job_load
;
109 * Drop IKE_SA_INIT requests if half open IKE_SA count exceeds this limit
111 u_int init_limit_half_open
;
114 * Delay for receiving incoming packets, to simulate larger RTT
119 * Specific message type to delay, 0 for any
121 int receive_delay_type
;
124 * Delay request messages?
126 bool receive_delay_request
;
129 * Delay response messages?
131 bool receive_delay_response
;
135 * send a notify back to the sender
137 static void send_notify(message_t
*request
, notify_type_t type
, chunk_t data
)
139 if (request
->get_request(request
) &&
140 request
->get_exchange_type(request
) == IKE_SA_INIT
)
145 ike_sa_id_t
*ike_sa_id
;
147 response
= message_create();
148 dst
= request
->get_source(request
);
149 src
= request
->get_destination(request
);
150 response
->set_source(response
, src
->clone(src
));
151 response
->set_destination(response
, dst
->clone(dst
));
152 response
->set_exchange_type(response
, request
->get_exchange_type(request
));
153 response
->set_request(response
, FALSE
);
154 response
->set_message_id(response
, 0);
155 ike_sa_id
= request
->get_ike_sa_id(request
);
156 ike_sa_id
->switch_initiator(ike_sa_id
);
157 response
->set_ike_sa_id(response
, ike_sa_id
);
158 response
->add_notify(response
, FALSE
, type
, data
);
159 if (response
->generate(response
, NULL
, &packet
) == SUCCESS
)
161 charon
->sender
->send(charon
->sender
, packet
);
162 response
->destroy(response
);
170 static chunk_t
cookie_build(private_receiver_t
*this, message_t
*message
,
171 u_int32_t t
, chunk_t secret
)
173 u_int64_t spi
= message
->get_initiator_spi(message
);
174 host_t
*ip
= message
->get_source(message
);
177 /* COOKIE = t | sha1( IPi | SPIi | t | secret ) */
178 input
= chunk_cata("cccc", ip
->get_address(ip
), chunk_from_thing(spi
),
179 chunk_from_thing(t
), secret
);
180 hash
= chunk_alloca(this->hasher
->get_hash_size(this->hasher
));
181 this->hasher
->get_hash(this->hasher
, input
, hash
.ptr
);
182 return chunk_cat("cc", chunk_from_thing(t
), hash
);
186 * verify a received cookie
188 static bool cookie_verify(private_receiver_t
*this, message_t
*message
,
195 now
= time_monotonic(NULL
);
196 t
= *(u_int32_t
*)cookie
.ptr
;
198 if (cookie
.len
!= sizeof(u_int32_t
) +
199 this->hasher
->get_hash_size(this->hasher
) ||
200 t
< now
- this->secret_offset
- COOKIE_LIFETIME
)
202 DBG2(DBG_NET
, "received cookie lifetime expired, rejecting");
206 /* check if cookie is derived from old_secret */
207 if (t
+ this->secret_offset
> this->secret_switch
)
209 secret
= chunk_from_thing(this->secret
);
213 secret
= chunk_from_thing(this->secret_old
);
216 /* compare own calculation against received */
217 reference
= cookie_build(this, message
, t
, secret
);
218 if (chunk_equals(reference
, cookie
))
220 chunk_free(&reference
);
223 chunk_free(&reference
);
228 * Check if a valid cookie found
230 static bool check_cookie(private_receiver_t
*this, message_t
*message
)
235 /* check for a cookie. We don't use our parser here and do it
236 * quick and dirty for performance reasons.
237 * we assume the cookie is the first payload (which is a MUST), and
238 * the cookie's SPI length is zero. */
239 packet
= message
->get_packet(message
);
240 data
= packet
->get_data(packet
);
242 IKE_HEADER_LENGTH
+ NOTIFY_PAYLOAD_HEADER_LENGTH
+
243 sizeof(u_int32_t
) + this->hasher
->get_hash_size(this->hasher
) ||
244 *(data
.ptr
+ 16) != NOTIFY
||
245 *(u_int16_t
*)(data
.ptr
+ IKE_HEADER_LENGTH
+ 6) != htons(COOKIE
))
247 /* no cookie found */
248 packet
->destroy(packet
);
251 data
.ptr
+= IKE_HEADER_LENGTH
+ NOTIFY_PAYLOAD_HEADER_LENGTH
;
252 data
.len
= sizeof(u_int32_t
) + this->hasher
->get_hash_size(this->hasher
);
253 if (!cookie_verify(this, message
, data
))
255 DBG2(DBG_NET
, "found cookie, but content invalid");
256 packet
->destroy(packet
);
263 * Check if we should drop IKE_SA_INIT because of cookie/overload checking
265 static bool drop_ike_sa_init(private_receiver_t
*this, message_t
*message
)
269 half_open
= charon
->ike_sa_manager
->get_half_open_count(
270 charon
->ike_sa_manager
, NULL
);
272 /* check for cookies */
273 if (this->cookie_threshold
&& half_open
>= this->cookie_threshold
&&
274 !check_cookie(this, message
))
276 u_int32_t now
= time_monotonic(NULL
);
277 chunk_t cookie
= cookie_build(this, message
, now
- this->secret_offset
,
278 chunk_from_thing(this->secret
));
280 DBG2(DBG_NET
, "received packet from: %#H to %#H",
281 message
->get_source(message
),
282 message
->get_destination(message
));
283 DBG2(DBG_NET
, "sending COOKIE notify to %H",
284 message
->get_source(message
));
285 send_notify(message
, COOKIE
, cookie
);
287 if (++this->secret_used
> COOKIE_REUSE
)
289 /* create new cookie */
290 DBG1(DBG_NET
, "generating new cookie secret after %d uses",
292 memcpy(this->secret_old
, this->secret
, SECRET_LENGTH
);
293 this->rng
->get_bytes(this->rng
, SECRET_LENGTH
, this->secret
);
294 this->secret_switch
= now
;
295 this->secret_used
= 0;
300 /* check if peer has too many IKE_SAs half open */
301 if (this->block_threshold
&&
302 charon
->ike_sa_manager
->get_half_open_count(charon
->ike_sa_manager
,
303 message
->get_source(message
)) >= this->block_threshold
)
305 DBG1(DBG_NET
, "ignoring IKE_SA setup from %H, "
306 "peer too aggressive", message
->get_source(message
));
310 /* check if global half open IKE_SA limit reached */
311 if (this->init_limit_half_open
&&
312 half_open
>= this->init_limit_half_open
)
314 DBG1(DBG_NET
, "ignoring IKE_SA setup from %H, half open IKE_SA "
315 "count of %d exceeds limit of %d", message
->get_source(message
),
316 half_open
, this->init_limit_half_open
);
320 /* check if job load acceptable */
321 if (this->init_limit_job_load
)
325 for (i
= 0; i
< JOB_PRIO_MAX
; i
++)
327 jobs
+= lib
->processor
->get_job_load(lib
->processor
, i
);
329 if (jobs
> this->init_limit_job_load
)
331 DBG1(DBG_NET
, "ignoring IKE_SA setup from %H, job load of %d "
332 "exceeds limit of %d", message
->get_source(message
),
333 jobs
, this->init_limit_job_load
);
341 * Job callback to receive packets
343 static job_requeue_t
receive_packets(private_receiver_t
*this)
349 /* read in a packet */
350 status
= charon
->socket
->receive(charon
->socket
, &packet
);
351 if (status
== NOT_SUPPORTED
)
353 /* the processor destroys this job */
355 return JOB_REQUEUE_NONE
;
357 else if (status
!= SUCCESS
)
359 DBG2(DBG_NET
, "receiving from socket failed!");
360 return JOB_REQUEUE_FAIR
;
363 /* parse message header */
364 message
= message_create_from_packet(packet
);
365 if (message
->parse_header(message
) != SUCCESS
)
367 DBG1(DBG_NET
, "received invalid IKE header from %H - ignored",
368 packet
->get_source(packet
));
369 message
->destroy(message
);
370 return JOB_REQUEUE_DIRECT
;
373 /* check IKE major version */
374 if (message
->get_major_version(message
) != IKEV2_MAJOR_VERSION
)
376 DBG1(DBG_NET
, "received unsupported IKE version %d.%d from %H, "
377 "sending INVALID_MAJOR_VERSION", message
->get_major_version(message
),
378 message
->get_minor_version(message
), packet
->get_source(packet
));
379 send_notify(message
, INVALID_MAJOR_VERSION
, chunk_empty
);
380 message
->destroy(message
);
381 return JOB_REQUEUE_DIRECT
;
384 if (message
->get_request(message
) &&
385 message
->get_exchange_type(message
) == IKE_SA_INIT
)
387 if (drop_ike_sa_init(this, message
))
389 message
->destroy(message
);
390 return JOB_REQUEUE_DIRECT
;
393 if (this->receive_delay
)
395 if (this->receive_delay_type
== 0 ||
396 this->receive_delay_type
== message
->get_exchange_type(message
))
398 if ((message
->get_request(message
) && this->receive_delay_request
) ||
399 (!message
->get_request(message
) && this->receive_delay_response
))
401 DBG1(DBG_NET
, "using receive delay: %dms",
402 this->receive_delay
);
403 lib
->scheduler
->schedule_job_ms(lib
->scheduler
,
404 (job_t
*)process_message_job_create(message
),
405 this->receive_delay
);
406 return JOB_REQUEUE_DIRECT
;
410 lib
->processor
->queue_job(lib
->processor
,
411 (job_t
*)process_message_job_create(message
));
412 return JOB_REQUEUE_DIRECT
;
415 METHOD(receiver_t
, destroy
, void,
416 private_receiver_t
*this)
420 this->job
->cancel(this->job
);
422 this->rng
->destroy(this->rng
);
423 this->hasher
->destroy(this->hasher
);
428 * Described in header.
430 receiver_t
*receiver_create()
432 private_receiver_t
*this;
433 u_int32_t now
= time_monotonic(NULL
);
439 .secret_switch
= now
,
440 .secret_offset
= random() % now
,
443 if (lib
->settings
->get_bool(lib
->settings
, "charon.dos_protection", TRUE
))
445 this->cookie_threshold
= lib
->settings
->get_int(lib
->settings
,
446 "charon.cookie_threshold", COOKIE_THRESHOLD_DEFAULT
);
447 this->block_threshold
= lib
->settings
->get_int(lib
->settings
,
448 "charon.block_threshold", BLOCK_THRESHOLD_DEFAULT
);
450 this->init_limit_job_load
= lib
->settings
->get_int(lib
->settings
,
451 "charon.init_limit_job_load", 0);
452 this->init_limit_half_open
= lib
->settings
->get_int(lib
->settings
,
453 "charon.init_limit_half_open", 0);
454 this->receive_delay
= lib
->settings
->get_int(lib
->settings
,
455 "charon.receive_delay", 0);
456 this->receive_delay_type
= lib
->settings
->get_int(lib
->settings
,
457 "charon.receive_delay_type", 0),
458 this->receive_delay_request
= lib
->settings
->get_bool(lib
->settings
,
459 "charon.receive_delay_request", TRUE
),
460 this->receive_delay_response
= lib
->settings
->get_int(lib
->settings
,
461 "charon.receive_delay_response", TRUE
),
463 this->hasher
= lib
->crypto
->create_hasher(lib
->crypto
, HASH_PREFERRED
);
464 if (this->hasher
== NULL
)
466 DBG1(DBG_NET
, "creating cookie hasher failed, no hashers supported");
470 this->rng
= lib
->crypto
->create_rng(lib
->crypto
, RNG_STRONG
);
471 if (this->rng
== NULL
)
473 DBG1(DBG_NET
, "creating cookie RNG failed, no RNG supported");
474 this->hasher
->destroy(this->hasher
);
478 this->rng
->get_bytes(this->rng
, SECRET_LENGTH
, this->secret
);
479 memcpy(this->secret_old
, this->secret
, SECRET_LENGTH
);
481 this->job
= callback_job_create_with_prio((callback_job_cb_t
)receive_packets
,
482 this, NULL
, NULL
, JOB_PRIO_CRITICAL
);
483 lib
->processor
->queue_job(lib
->processor
, (job_t
*)this->job
);
485 return &this->public;