diff options
author | Tobias Brunner <tobias@strongswan.org> | 2012-07-06 10:46:34 +0200 |
---|---|---|
committer | Martin Willi <martin@revosec.ch> | 2012-07-16 14:53:35 +0200 |
commit | 5d91d8c46937c45824ca2afcb726723527481539 (patch) | |
tree | 377d8c2b7507469a4e9c4bb60f7d3860b3ad763f /src | |
parent | 8a8364f26e45e3c02f704eff320d5d8041a67cba (diff) | |
download | strongswan-5d91d8c46937c45824ca2afcb726723527481539.tar.bz2 strongswan-5d91d8c46937c45824ca2afcb726723527481539.tar.xz |
Check rng return value when generating SPIs in ike_sa_manager_t
Diffstat (limited to 'src')
-rw-r--r-- | src/libcharon/sa/ike_sa_manager.c | 102 |
1 files changed, 67 insertions, 35 deletions
diff --git a/src/libcharon/sa/ike_sa_manager.c b/src/libcharon/sa/ike_sa_manager.c index 702fe52d6..d9375a45f 100644 --- a/src/libcharon/sa/ike_sa_manager.c +++ b/src/libcharon/sa/ike_sa_manager.c @@ -944,13 +944,14 @@ static void remove_connected_peers(private_ike_sa_manager_t *this, entry_t *entr */ static u_int64_t get_spi(private_ike_sa_manager_t *this) { - u_int64_t spi = 0; + u_int64_t spi; - if (this->rng) + if (this->rng && + this->rng->get_bytes(this->rng, sizeof(spi), (u_int8_t*)&spi)) { - this->rng->get_bytes(this->rng, sizeof(spi), (u_int8_t*)&spi); + return spi; } - return spi; + return 0; } /** @@ -962,15 +963,18 @@ static u_int64_t get_spi(private_ike_sa_manager_t *this) * stored together with the hash, otherwise it is newly allocated and should * be used to create the IKE_SA. * - * @returns TRUE if the message with the given hash was seen before + * @returns ALREADY_DONE if the message with the given hash has been seen before + * NOT_FOUND if the message hash was not found + * FAILED if the SPI allocation failed */ -static bool check_and_put_init_hash(private_ike_sa_manager_t *this, - chunk_t init_hash, u_int64_t *our_spi) +static status_t check_and_put_init_hash(private_ike_sa_manager_t *this, + chunk_t init_hash, u_int64_t *our_spi) { table_item_t *item; u_int row, segment; mutex_t *mutex; init_hash_t *init; + u_int64_t spi; row = chunk_hash(init_hash) & this->table_mask; segment = row & this->segment_mask; @@ -985,17 +989,23 @@ static bool check_and_put_init_hash(private_ike_sa_manager_t *this, { *our_spi = current->our_spi; mutex->unlock(mutex); - return TRUE; + return ALREADY_DONE; } item = item->next; } + spi = get_spi(this); + if (!spi) + { + return FAILED; + } + INIT(init, .hash = { .len = init_hash.len, .ptr = init_hash.ptr, }, - .our_spi = get_spi(this), + .our_spi = spi, ); INIT(item, .value = init, @@ -1004,7 +1014,7 @@ static bool check_and_put_init_hash(private_ike_sa_manager_t *this, this->init_hashes_table[row] = item; *our_spi = init->our_spi; mutex->unlock(mutex); - return FALSE; + return NOT_FOUND; } /** @@ -1075,16 +1085,24 @@ METHOD(ike_sa_manager_t, checkout_new, ike_sa_t*, ike_sa_id_t *ike_sa_id; ike_sa_t *ike_sa; u_int8_t ike_version; + u_int64_t spi; ike_version = version == IKEV1 ? IKEV1_MAJOR_VERSION : IKEV2_MAJOR_VERSION; + spi = get_spi(this); + if (!spi) + { + DBG1(DBG_MGR, "failed to allocate SPI for new IKE_SA"); + return NULL; + } + if (initiator) { - ike_sa_id = ike_sa_id_create(ike_version, get_spi(this), 0, TRUE); + ike_sa_id = ike_sa_id_create(ike_version, spi, 0, TRUE); } else { - ike_sa_id = ike_sa_id_create(ike_version, 0, get_spi(this), FALSE); + ike_sa_id = ike_sa_id_create(ike_version, 0, spi, FALSE); } ike_sa = ike_sa_create(ike_sa_id, initiator, version); ike_sa_id->destroy(ike_sa_id); @@ -1150,35 +1168,49 @@ METHOD(ike_sa_manager_t, checkout_by_message, ike_sa_t*, message->get_packet_data(message), &hash); /* ensure this is not a retransmit of an already handled init message */ - if (!check_and_put_init_hash(this, hash, &our_spi)) - { /* we've not seen this packet yet, create a new IKE_SA */ - id->set_responder_spi(id, our_spi); - ike_sa = ike_sa_create(id, FALSE, ike_version); - if (ike_sa) - { - entry = entry_create(); - entry->ike_sa = ike_sa; - entry->ike_sa_id = id->clone(id); + switch (check_and_put_init_hash(this, hash, &our_spi)) + { + case NOT_FOUND: + { /* we've not seen this packet yet, create a new IKE_SA */ + id->set_responder_spi(id, our_spi); + ike_sa = ike_sa_create(id, FALSE, ike_version); + if (ike_sa) + { + entry = entry_create(); + entry->ike_sa = ike_sa; + entry->ike_sa_id = id->clone(id); - segment = put_entry(this, entry); - entry->checked_out = TRUE; - unlock_single_segment(this, segment); + segment = put_entry(this, entry); + entry->checked_out = TRUE; + unlock_single_segment(this, segment); - entry->message_id = message->get_message_id(message); - entry->init_hash = hash; + entry->message_id = message->get_message_id(message); + entry->init_hash = hash; - DBG2(DBG_MGR, "created IKE_SA %s[%u]", - ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa)); + DBG2(DBG_MGR, "created IKE_SA %s[%u]", + ike_sa->get_name(ike_sa), + ike_sa->get_unique_id(ike_sa)); + } + else + { + remove_init_hash(this, hash); + chunk_free(&hash); + DBG1(DBG_MGR, "ignoring message, no such IKE_SA"); + } + id->destroy(id); + charon->bus->set_sa(charon->bus, ike_sa); + return ike_sa; } - else - { - remove_init_hash(this, hash); + case FAILED: + { /* we failed to allocate an SPI */ chunk_free(&hash); - DBG1(DBG_MGR, "ignoring message, no such IKE_SA"); + id->destroy(id); + DBG1(DBG_MGR, "ignoring message, failed to allocate SPI"); + return NULL; } - id->destroy(id); - charon->bus->set_sa(charon->bus, ike_sa); - return ike_sa; + case ALREADY_DONE: + default: + break; } /* it looks like we already handled this init message to some degree */ id->set_responder_spi(id, our_spi); |