From: Martin Willi Date: Tue, 18 Nov 2008 15:21:10 +0000 (+0000) Subject: pushing basic CHILD_SA sync data to backup node X-Git-Tag: 4.4.0~105 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7999be5b0edebe8fc3b194f34be5ea43b8bb13b6;p=thirdparty%2Fstrongswan.git pushing basic CHILD_SA sync data to backup node --- diff --git a/src/charon/plugins/ha_sync/ha_sync_child.c b/src/charon/plugins/ha_sync/ha_sync_child.c index ab6908eb45..260d33e271 100644 --- a/src/charon/plugins/ha_sync/ha_sync_child.c +++ b/src/charon/plugins/ha_sync/ha_sync_child.c @@ -42,6 +42,85 @@ static bool child_keys(private_ha_sync_child_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r) { + ha_sync_message_t *m; + chunk_t secret; + proposal_t *proposal; + u_int16_t alg, len; + linked_list_t *list; + enumerator_t *enumerator; + traffic_selector_t *ts; + + m = ha_sync_message_create(HA_SYNC_CHILD_ADD); + + m->add_attribute(m, HA_SYNC_IKE_ID, ike_sa->get_id(ike_sa)); + m->add_attribute(m, HA_SYNC_INBOUND_SPI, child_sa->get_spi(child_sa, TRUE)); + m->add_attribute(m, HA_SYNC_OUTBOUND_SPI, child_sa->get_spi(child_sa, FALSE)); + m->add_attribute(m, HA_SYNC_INBOUND_CPI, child_sa->get_cpi(child_sa, TRUE)); + m->add_attribute(m, HA_SYNC_OUTBOUND_CPI, child_sa->get_cpi(child_sa, FALSE)); + m->add_attribute(m, HA_SYNC_IPSEC_MODE, child_sa->get_mode(child_sa)); + m->add_attribute(m, HA_SYNC_IPCOMP, child_sa->get_ipcomp(child_sa)); + m->add_attribute(m, HA_SYNC_CONFIG_NAME, child_sa->get_name(child_sa)); + + proposal = child_sa->get_proposal(child_sa); + if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &alg, &len)) + { + m->add_attribute(m, HA_SYNC_ALG_ENCR, alg); + if (len) + { + m->add_attribute(m, HA_SYNC_ALG_ENCR_LEN, len); + } + } + if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &alg, NULL)) + { + m->add_attribute(m, HA_SYNC_ALG_INTEG, alg); + } + m->add_attribute(m, HA_SYNC_NONCE_I, nonce_i); + m->add_attribute(m, HA_SYNC_NONCE_R, nonce_r); + if (dh && dh->get_shared_secret(dh, &secret) == SUCCESS) + { + m->add_attribute(m, HA_SYNC_SECRET, secret); + chunk_clear(&secret); + } + + list = child_sa->get_traffic_selectors(child_sa, TRUE); + enumerator = list->create_enumerator(list); + while (enumerator->enumerate(enumerator, &ts)) + { + m->add_attribute(m, HA_SYNC_LOCAL_TS, ts); + } + enumerator->destroy(enumerator); + list = child_sa->get_traffic_selectors(child_sa, FALSE); + enumerator = list->create_enumerator(list); + while (enumerator->enumerate(enumerator, &ts)) + { + m->add_attribute(m, HA_SYNC_REMOTE_TS, ts); + } + enumerator->destroy(enumerator); + + this->socket->push(this->socket, m); + m->destroy(m); + + return TRUE; +} + +/** + * Implementation of listener_t.child_state_change + */ +static bool child_state_change(private_ha_sync_child_t *this, ike_sa_t *ike_sa, + child_sa_t *child_sa, child_sa_state_t state) +{ + if (state == CHILD_DESTROYING) + { + ha_sync_message_t *m; + + m = ha_sync_message_create(HA_SYNC_CHILD_DELETE); + + m->add_attribute(m, HA_SYNC_IKE_ID, ike_sa->get_id(ike_sa)); + m->add_attribute(m, HA_SYNC_INBOUND_SPI, + child_sa->get_spi(child_sa, TRUE)); + this->socket->push(this->socket, m); + m->destroy(m); + } return TRUE; } @@ -62,6 +141,7 @@ ha_sync_child_t *ha_sync_child_create(ha_sync_socket_t *socket) memset(&this->public.listener, 0, sizeof(listener_t)); this->public.listener.child_keys = (bool(*)(listener_t*, ike_sa_t *ike_sa, child_sa_t *child_sa, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r))child_keys; + this->public.listener.child_state_change = (bool(*)(listener_t*,ike_sa_t *ike_sa, child_sa_t *child_sa, child_sa_state_t state))child_state_change; this->public.destroy = (void(*)(ha_sync_child_t*))destroy; this->socket = socket; diff --git a/src/charon/plugins/ha_sync/ha_sync_dispatcher.c b/src/charon/plugins/ha_sync/ha_sync_dispatcher.c index b42ca51489..dc404a50ed 100644 --- a/src/charon/plugins/ha_sync/ha_sync_dispatcher.c +++ b/src/charon/plugins/ha_sync/ha_sync_dispatcher.c @@ -270,6 +270,28 @@ static void process_ike_delete(private_ha_sync_dispatcher_t *this, enumerator->destroy(enumerator); } +/** + * Process messages of type CHILD_ADD + */ +static void process_child_add(private_ha_sync_dispatcher_t *this, + ha_sync_message_t *message) +{ + chunk_t chunk = message->get_encoding(message); + + DBG1(DBG_CHD, "CHILD_ADD: %B", &chunk); +} + +/** + * Process messages of type CHILD_DELETE + */ +static void process_child_delete(private_ha_sync_dispatcher_t *this, + ha_sync_message_t *message) +{ + chunk_t chunk = message->get_encoding(message); + + DBG1(DBG_CHD, "CHILD_DELETE: %B", &chunk); +} + /** * Dispatcher job function */ @@ -292,8 +314,10 @@ static job_requeue_t dispatch(private_ha_sync_dispatcher_t *this) case HA_SYNC_IKE_REKEY: break; case HA_SYNC_CHILD_ADD: + process_child_add(this, message); break; case HA_SYNC_CHILD_DELETE: + process_child_delete(this, message); break; default: DBG1(DBG_CFG, "received unknown HA sync message type %d", diff --git a/src/charon/plugins/ha_sync/ha_sync_message.c b/src/charon/plugins/ha_sync/ha_sync_message.c index 7a1fc71343..ad949287c6 100644 --- a/src/charon/plugins/ha_sync/ha_sync_message.c +++ b/src/charon/plugins/ha_sync/ha_sync_message.c @@ -81,6 +81,20 @@ struct host_encoding_t { char encoding[]; } __attribute__((packed)); +typedef struct ts_encoding_t ts_encoding_t; + +/** + * encoding of a traffic_selector_t + */ +struct ts_encoding_t { + u_int8_t type; + u_int8_t protocol; + u_int16_t from_port; + u_int16_t to_port; + u_int8_t dynamic; + char encoding[]; +} __attribute__((packed)); + /** * Implementation of ha_sync_message_t.get_type */ @@ -191,11 +205,25 @@ static void add_attribute(private_ha_sync_message_t *this, this->buf.len += len; break; } + /* u_int8_t */ + case HA_SYNC_IPSEC_MODE: + case HA_SYNC_IPCOMP: + { + u_int8_t val; + + val = (u_int8_t)va_arg(args, u_int32_t); + check_buf(this, sizeof(val)); + this->buf.ptr[this->buf.len] = val; + this->buf.len += sizeof(val); + break; + } /* u_int16_t */ case HA_SYNC_ALG_PRF: case HA_SYNC_ALG_ENCR: case HA_SYNC_ALG_ENCR_LEN: case HA_SYNC_ALG_INTEG: + case HA_SYNC_INBOUND_CPI: + case HA_SYNC_OUTBOUND_CPI: { u_int16_t val; @@ -208,6 +236,8 @@ static void add_attribute(private_ha_sync_message_t *this, /** u_int32_t */ case HA_SYNC_CONDITIONS: case HA_SYNC_EXTENSIONS: + case HA_SYNC_INBOUND_SPI: + case HA_SYNC_OUTBOUND_SPI: { u_int32_t val; @@ -232,6 +262,28 @@ static void add_attribute(private_ha_sync_message_t *this, this->buf.len += chunk.len + sizeof(u_int16_t);; break; } + /** traffic_selector_t */ + case HA_SYNC_LOCAL_TS: + case HA_SYNC_REMOTE_TS: + { + ts_encoding_t *enc; + traffic_selector_t *ts; + chunk_t data; + + ts = va_arg(args, traffic_selector_t*); + data = chunk_cata("cc", ts->get_from_address(ts), + ts->get_to_address(ts)); + check_buf(this, sizeof(ts_encoding_t) + data.len); + enc = (ts_encoding_t*)(this->buf.ptr + this->buf.len); + this->buf.len += sizeof(ts_encoding_t) + data.len; + enc->type = ts->get_type(ts); + enc->protocol = ts->get_protocol(ts); + enc->from_port = htons(ts->get_from_port(ts)); + enc->to_port = htons(ts->get_to_port(ts)); + enc->dynamic = ts->is_dynamic(ts); + memcpy(enc->encoding, data.ptr, data.len); + break; + } default: { DBG1(DBG_CFG, "unable to encode, attribute %d unknown", attribute); @@ -363,11 +415,26 @@ static bool attribute_enumerate(attribute_enumerator_t *this, this->buf = chunk_skip(this->buf, len + 1); return TRUE; } + /* u_int8_t */ + case HA_SYNC_IPSEC_MODE: + case HA_SYNC_IPCOMP: + { + if (this->buf.len < sizeof(u_int8_t)) + { + return FALSE; + } + value->u8 = *(u_int8_t*)this->buf.ptr; + *attr_out = attr; + this->buf = chunk_skip(this->buf, sizeof(u_int8_t)); + return TRUE; + } /** u_int16_t */ case HA_SYNC_ALG_PRF: case HA_SYNC_ALG_ENCR: case HA_SYNC_ALG_ENCR_LEN: case HA_SYNC_ALG_INTEG: + case HA_SYNC_INBOUND_CPI: + case HA_SYNC_OUTBOUND_CPI: { if (this->buf.len < sizeof(u_int16_t)) { @@ -381,6 +448,8 @@ static bool attribute_enumerate(attribute_enumerator_t *this, /** u_int32_t */ case HA_SYNC_CONDITIONS: case HA_SYNC_EXTENSIONS: + case HA_SYNC_INBOUND_SPI: + case HA_SYNC_OUTBOUND_SPI: { if (this->buf.len < sizeof(u_int32_t)) { @@ -414,6 +483,69 @@ static bool attribute_enumerate(attribute_enumerator_t *this, this->buf = chunk_skip(this->buf, len); return TRUE; } + case HA_SYNC_LOCAL_TS: + case HA_SYNC_REMOTE_TS: + { + ts_encoding_t *enc; + host_t *host; + int addr_len; + + enc = (ts_encoding_t*)(this->buf.ptr); + if (this->buf.len < sizeof(ts_encoding_t)) + { + return FALSE; + } + switch (enc->type) + { + case TS_IPV4_ADDR_RANGE: + addr_len = 4; + if (this->buf.len < sizeof(ts_encoding_t) + 2 * addr_len) + { + return FALSE; + } + break; + case TS_IPV6_ADDR_RANGE: + addr_len = 16; + if (this->buf.len < sizeof(ts_encoding_t) + 2 * addr_len) + { + return FALSE; + } + break; + default: + return FALSE; + } + if (enc->dynamic) + { + host = host_create_from_chunk(0, + chunk_create(enc->encoding, addr_len), 0); + if (!host) + { + return FALSE; + } + value->ts = traffic_selector_create_dynamic(enc->protocol, + ntohs(enc->from_port), ntohs(enc->to_port)); + value->ts->set_address(value->ts, host); + host->destroy(host); + } + else + { + value->ts = traffic_selector_create_from_bytes(enc->protocol, + enc->type, chunk_create(enc->encoding, addr_len), + ntohs(enc->from_port), + chunk_create(enc->encoding + addr_len, addr_len), + ntohs(enc->to_port)); + if (!value->ts) + { + return FALSE; + } + } + *attr_out = attr; + this->cleanup = (void*)value->ts->destroy; + this->cleanup_data = value->ts; + this->buf = chunk_skip(this->buf, sizeof(ts_encoding_t) + + addr_len * 2); + return TRUE; + } default: { return FALSE; diff --git a/src/charon/plugins/ha_sync/ha_sync_message.h b/src/charon/plugins/ha_sync/ha_sync_message.h index e7d358ccc1..c28b8424b6 100644 --- a/src/charon/plugins/ha_sync/ha_sync_message.h +++ b/src/charon/plugins/ha_sync/ha_sync_message.h @@ -27,6 +27,7 @@ #include #include #include +#include /** * Protocol version of this implementation @@ -100,19 +101,37 @@ enum ha_sync_message_attribute_t { HA_SYNC_ALG_ENCR_LEN, /** u_int16_t, integrity protection algorithm */ HA_SYNC_ALG_INTEG, + /** u_int8_t, IPsec mode, TUNNEL|TRANSPORT|... */ + HA_SYNC_IPSEC_MODE, + /** u_int8_t, IPComp protocol */ + HA_SYNC_IPCOMP, + /** u_int32_t, inbound security parameter index */ + HA_SYNC_INBOUND_SPI, + /** u_int32_t, outbound security parameter index */ + HA_SYNC_OUTBOUND_SPI, + /** u_int16_t, inbound security parameter index */ + HA_SYNC_INBOUND_CPI, + /** u_int16_t, outbound security parameter index */ + HA_SYNC_OUTBOUND_CPI, + /** traffic_selector_t*, local traffic selector */ + HA_SYNC_LOCAL_TS, + /** traffic_selector_t*, remote traffic selector */ + HA_SYNC_REMOTE_TS, }; /** * Union to enumerate typed attributes in a message */ union ha_sync_message_value_t { - u_int32_t u32; + u_int8_t u8; u_int16_t u16; + u_int32_t u32; char *str; chunk_t chunk; ike_sa_id_t *ike_sa_id; identification_t *id; host_t *host; + traffic_selector_t *ts; }; /**