diff options
Diffstat (limited to 'src/charon/control/interfaces')
-rwxr-xr-x | src/charon/control/interfaces/stroke_interface.c | 61 | ||||
-rw-r--r-- | src/charon/control/interfaces/xml_interface.c | 273 |
2 files changed, 300 insertions, 34 deletions
diff --git a/src/charon/control/interfaces/stroke_interface.c b/src/charon/control/interfaces/stroke_interface.c index 66ed423ae..b51d53ebd 100755 --- a/src/charon/control/interfaces/stroke_interface.c +++ b/src/charon/control/interfaces/stroke_interface.c @@ -239,13 +239,13 @@ static void stroke_add_conn(stroke_msg_t *msg, FILE *out) bool other_ca_same =FALSE; host_t *my_host, *other_host, *my_subnet, *other_subnet; host_t *my_vip = NULL, *other_vip = NULL; - linked_list_t *my_groups = linked_list_create(); linked_list_t *other_groups = linked_list_create(); proposal_t *proposal; traffic_selector_t *my_ts, *other_ts; char *interface; bool use_existing = FALSE; iterator_t *iterator; + u_int32_t vendor; pop_string(msg, &msg->add_conn.name); DBG1(DBG_CFG, "received stroke: add connection '%s'", msg->add_conn.name); @@ -262,7 +262,7 @@ static void stroke_add_conn(stroke_msg_t *msg, FILE *out) DBG2(DBG_CFG, " p2p_mediated_by=%s", msg->add_conn.p2p.mediated_by); DBG2(DBG_CFG, " p2p_peerid=%s", msg->add_conn.p2p.peerid); - my_host = msg->add_conn.me.address? + my_host = msg->add_conn.me.address ? host_create_from_string(msg->add_conn.me.address, IKE_PORT) : NULL; if (my_host == NULL) { @@ -365,11 +365,11 @@ static void stroke_add_conn(stroke_msg_t *msg, FILE *out) } } else -#endif /* P2P */ { - // no peer ID supplied, assume right ID + /* no peer ID supplied, assume right ID */ peer_id = other_id->clone(other_id); } +#endif /* P2P */ my_subnet = host_create_from_string(msg->add_conn.me.subnet ? msg->add_conn.me.subnet : msg->add_conn.me.address, IKE_PORT); @@ -544,7 +544,8 @@ static void stroke_add_conn(stroke_msg_t *msg, FILE *out) && ietfAttr_list_equals(other_groups, peer_cfg->get_groups(peer_cfg)) && peer_cfg->get_ike_version(peer_cfg) == (msg->add_conn.ikev2 ? 2 : 1) && peer_cfg->get_auth_method(peer_cfg) == msg->add_conn.auth_method - && peer_cfg->get_eap_type(peer_cfg) == msg->add_conn.eap_type) + && peer_cfg->get_eap_type(peer_cfg, &vendor) == msg->add_conn.eap_type + && vendor == msg->add_conn.eap_vendor) { DBG1(DBG_CFG, "reusing existing configuration '%s'", peer_cfg->get_name(peer_cfg)); @@ -564,9 +565,8 @@ static void stroke_add_conn(stroke_msg_t *msg, FILE *out) other_host->destroy(other_host); other_id->destroy(other_id); other_ca->destroy(other_ca); - peer_id->destroy(peer_id); + DESTROY_IF(peer_id); DESTROY_IF(mediated_by_cfg); - ietfAttr_list_destroy(my_groups); ietfAttr_list_destroy(other_groups); } else @@ -613,15 +613,25 @@ static void stroke_add_conn(stroke_msg_t *msg, FILE *out) ike_cfg->add_proposal(ike_cfg, proposal); } + u_int32_t rekey = 0, reauth = 0, over, jitter; + + jitter = msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100; + over = msg->add_conn.rekey.margin; + if (msg->add_conn.rekey.reauth) + { + reauth = msg->add_conn.rekey.ike_lifetime - over; + } + else + { + rekey = msg->add_conn.rekey.ike_lifetime - over; + } peer_cfg = peer_cfg_create(msg->add_conn.name, msg->add_conn.ikev2 ? 2 : 1, ike_cfg, my_id, other_id, my_ca, other_ca, other_groups, - msg->add_conn.me.sendcert, - msg->add_conn.auth_method, msg->add_conn.eap_type, - msg->add_conn.rekey.tries, msg->add_conn.rekey.ike_lifetime, - msg->add_conn.rekey.ike_lifetime - msg->add_conn.rekey.margin, - msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100, - msg->add_conn.rekey.reauth, msg->add_conn.mobike, + msg->add_conn.me.sendcert, msg->add_conn.auth_method, + msg->add_conn.eap_type, msg->add_conn.eap_vendor, + msg->add_conn.rekey.tries, rekey, reauth, jitter, over, + msg->add_conn.mobike, msg->add_conn.dpd.delay, msg->add_conn.dpd.action, my_vip, other_vip, msg->add_conn.p2p.mediation, mediated_by_cfg, peer_id); } @@ -1104,9 +1114,8 @@ static void stroke_del_ca(stroke_msg_t *msg, FILE *out) */ static void log_ike_sa(FILE *out, ike_sa_t *ike_sa, bool all) { - peer_cfg_t *cfg = ike_sa->get_peer_cfg(ike_sa); ike_sa_id_t *id = ike_sa->get_id(ike_sa); - u_int32_t next, now = time(NULL); + u_int32_t rekey, reauth; fprintf(out, "%12s[%d]: %N, %H[%D]...%H[%D]\n", ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa), @@ -1116,21 +1125,26 @@ static void log_ike_sa(FILE *out, ike_sa_t *ike_sa, bool all) if (all) { - fprintf(out, "%12s[%d]: IKE SPIs: %.16llx_i%s %.16llx_r%s, ", + fprintf(out, "%12s[%d]: IKE SPIs: %.16llx_i%s %.16llx_r%s", ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa), id->get_initiator_spi(id), id->is_initiator(id) ? "*" : "", id->get_responder_spi(id), id->is_initiator(id) ? "" : "*"); - ike_sa->get_stats(ike_sa, &next); - if (next) + rekey = ike_sa->get_statistic(ike_sa, STAT_REKEY_TIME); + reauth = ike_sa->get_statistic(ike_sa, STAT_REAUTH_TIME); + if (rekey) { - fprintf(out, "%s in %V\n", cfg->use_reauth(cfg) ? - "reauthentication" : "rekeying", &now, &next); + fprintf(out, ", rekeying in %V", &rekey); } - else + if (reauth) { - fprintf(out, "rekeying disabled\n"); + fprintf(out, ", reauthentication in %V", &reauth); } + if (!rekey && !reauth) + { + fprintf(out, ", rekeying disabled"); + } + fprintf(out, "\n"); } } @@ -1188,7 +1202,7 @@ static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all) if (rekey) { - fprintf(out, "in %V", &now, &rekey); + fprintf(out, "in %#V", &now, &rekey); } else { @@ -1692,7 +1706,6 @@ static job_requeue_t stroke_process(int *fdp) return JOB_REQUEUE_NONE; } - /** * Implementation of private_stroke_interface_t.stroke_receive. */ diff --git a/src/charon/control/interfaces/xml_interface.c b/src/charon/control/interfaces/xml_interface.c index 02da1064d..aa2a554a0 100644 --- a/src/charon/control/interfaces/xml_interface.c +++ b/src/charon/control/interfaces/xml_interface.c @@ -91,6 +91,9 @@ static void write_id(xmlTextWriterPtr writer, char *element, identification_t *i char *type = ""; while (TRUE) { + case ID_ANY: + type = "any"; + break; case ID_IPV4_ADDR: type = "ipv4"; break; @@ -114,9 +117,6 @@ static void write_id(xmlTextWriterPtr writer, char *element, identification_t *i xmlTextWriterWriteFormatString(writer, "%D", id); break; } - case ID_ANY: - xmlTextWriterWriteAttribute(writer, "type", "any"); - break; default: /* TODO: base64 keyid */ xmlTextWriterWriteAttribute(writer, "type", "keyid"); @@ -146,17 +146,15 @@ static void write_address(xmlTextWriterPtr writer, char *element, host_t *host) } /** - * write a childEnd + * write networks element */ -static void write_childend(xmlTextWriterPtr writer, child_sa_t *child, bool local) +static void write_networks(xmlTextWriterPtr writer, char *element, + linked_list_t *list) { iterator_t *iterator; - linked_list_t *list; traffic_selector_t *ts; - xmlTextWriterWriteFormatElement(writer, "spi", "%lx", - htonl(child->get_spi(child, local))); - xmlTextWriterStartElement(writer, "networks"); - list = child->get_traffic_selectors(child, local); + + xmlTextWriterStartElement(writer, element); iterator = list->create_iterator(list, TRUE); while (iterator->iterate(iterator, (void**)&ts)) { @@ -171,6 +169,19 @@ static void write_childend(xmlTextWriterPtr writer, child_sa_t *child, bool loca } /** + * write a childEnd + */ +static void write_childend(xmlTextWriterPtr writer, child_sa_t *child, bool local) +{ + linked_list_t *list; + + xmlTextWriterWriteFormatElement(writer, "spi", "%lx", + htonl(child->get_spi(child, local))); + list = child->get_traffic_selectors(child, local); + write_networks(writer, "networks", list); +} + +/** * write a child_sa_t */ static void write_child(xmlTextWriterPtr writer, child_sa_t *child) @@ -284,6 +295,201 @@ static void request_query_ikesa(xmlTextReaderPtr reader, xmlTextWriterPtr writer } /** + * process a configlist query request message + */ +static void request_query_config(xmlTextReaderPtr reader, xmlTextWriterPtr writer) +{ + iterator_t *iterator; + peer_cfg_t *peer_cfg; + + /* <configlist> */ + xmlTextWriterStartElement(writer, "configlist"); + + iterator = charon->backends->create_iterator(charon->backends); + while (iterator->iterate(iterator, (void**)&peer_cfg)) + { + iterator_t *children; + child_cfg_t *child_cfg; + ike_cfg_t *ike_cfg; + linked_list_t *list; + + if (peer_cfg->get_ike_version(peer_cfg) != 2) + { /* only IKEv2 connections yet */ + continue; + } + + /* <peerconfig> */ + xmlTextWriterStartElement(writer, "peerconfig"); + xmlTextWriterWriteElement(writer, "name", peer_cfg->get_name(peer_cfg)); + write_id(writer, "local", peer_cfg->get_my_id(peer_cfg)); + write_id(writer, "remote", peer_cfg->get_other_id(peer_cfg)); + + /* <ikeconfig> */ + ike_cfg = peer_cfg->get_ike_cfg(peer_cfg); + xmlTextWriterStartElement(writer, "ikeconfig"); + write_address(writer, "local", ike_cfg->get_my_host(ike_cfg)); + write_address(writer, "remote", ike_cfg->get_other_host(ike_cfg)); + xmlTextWriterEndElement(writer); + /* </ikeconfig> */ + + /* <childconfiglist> */ + xmlTextWriterStartElement(writer, "childconfiglist"); + children = peer_cfg->create_child_cfg_iterator(peer_cfg); + while (children->iterate(children, (void**)&child_cfg)) + { + /* <childconfig> */ + xmlTextWriterStartElement(writer, "childconfig"); + xmlTextWriterWriteElement(writer, "name", + child_cfg->get_name(child_cfg)); + list = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL); + write_networks(writer, "local", list); + list->destroy_offset(list, offsetof(traffic_selector_t, destroy)); + list = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL, NULL); + write_networks(writer, "remote", list); + list->destroy_offset(list, offsetof(traffic_selector_t, destroy)); + xmlTextWriterEndElement(writer); + /* </childconfig> */ + } + children->destroy(children); + /* </childconfiglist> */ + xmlTextWriterEndElement(writer); + /* </peerconfig> */ + xmlTextWriterEndElement(writer); + } + iterator->destroy(iterator); + /* </configlist> */ + xmlTextWriterEndElement(writer); +} + +/** + * callback which logs to a XML writer + */ +static bool xml_callback(xmlTextWriterPtr writer, signal_t signal, level_t level, + ike_sa_t* ike_sa, char* format, va_list args) +{ + if (level <= 1) + { + /* <item> */ + xmlTextWriterStartElement(writer, "item"); + xmlTextWriterWriteFormatAttribute(writer, "level", "%d", level); + xmlTextWriterWriteFormatAttribute(writer, "source", "%N", signal_names, signal); + xmlTextWriterWriteFormatAttribute(writer, "thread", "%u", pthread_self()); + xmlTextWriterWriteVFormatString(writer, format, args); + xmlTextWriterEndElement(writer); + /* </item> */ + } + return TRUE; +} + +/** + * process a *terminate control request message + */ +static void request_control_terminate(xmlTextReaderPtr reader, + xmlTextWriterPtr writer, bool ike) +{ + if (xmlTextReaderRead(reader) && + xmlTextReaderNodeType(reader) == XML_READER_TYPE_TEXT) + { + const char *str; + u_int32_t id; + status_t status; + + str = xmlTextReaderConstValue(reader); + if (str == NULL || !(id = atoi(str))) + { + DBG1(DBG_CFG, "error parsing XML id string"); + return; + } + DBG1(DBG_CFG, "terminating %s_SA %d", ike ? "IKE" : "CHILD", id); + + /* <log> */ + xmlTextWriterStartElement(writer, "log"); + if (ike) + { + status = charon->interfaces->terminate_ike( + charon->interfaces, id, + (interface_manager_cb_t)xml_callback, writer); + } + else + { + status = charon->interfaces->terminate_child( + charon->interfaces, id, + (interface_manager_cb_t)xml_callback, writer); + } + /* </log> */ + xmlTextWriterEndElement(writer); + xmlTextWriterWriteFormatElement(writer, "status", "%d", status); + } +} + +/** + * process a *initiate control request message + */ +static void request_control_initiate(xmlTextReaderPtr reader, + xmlTextWriterPtr writer, bool ike) +{ + if (xmlTextReaderRead(reader) && + xmlTextReaderNodeType(reader) == XML_READER_TYPE_TEXT) + { + const char *str; + status_t status = FAILED; + peer_cfg_t *peer; + child_cfg_t *child = NULL; + iterator_t *iterator; + + str = xmlTextReaderConstValue(reader); + if (str == NULL) + { + DBG1(DBG_CFG, "error parsing XML config name string"); + return; + } + DBG1(DBG_CFG, "initiating %s_SA %s", ike ? "IKE" : "CHILD", str); + + /* <log> */ + xmlTextWriterStartElement(writer, "log"); + peer = charon->backends->get_peer_cfg_by_name(charon->backends, (char*)str); + if (peer) + { + iterator = peer->create_child_cfg_iterator(peer); + if (ike) + { + if (!iterator->iterate(iterator, (void**)&child)) + { + child = NULL; + } + child->get_ref(child); + } + else + { + while (iterator->iterate(iterator, (void**)&child)) + { + if (streq(child->get_name(child), str)) + { + child->get_ref(child); + break; + } + child = NULL; + } + } + iterator->destroy(iterator); + if (child) + { + status = charon->interfaces->initiate(charon->interfaces, + peer, child, (interface_manager_cb_t)xml_callback, + writer); + } + else + { + peer->destroy(peer); + } + } + /* </log> */ + xmlTextWriterEndElement(writer); + xmlTextWriterWriteFormatElement(writer, "status", "%d", status); + } +} + +/** * process a query request */ static void request_query(xmlTextReaderPtr reader, xmlTextWriterPtr writer) @@ -299,6 +505,11 @@ static void request_query(xmlTextReaderPtr reader, xmlTextWriterPtr writer) request_query_ikesa(reader, writer); break; } + if (streq(xmlTextReaderConstName(reader), "configlist")) + { + request_query_config(reader, writer); + break; + } } } /* </query> */ @@ -306,6 +517,43 @@ static void request_query(xmlTextReaderPtr reader, xmlTextWriterPtr writer) } /** + * process a control request + */ +static void request_control(xmlTextReaderPtr reader, xmlTextWriterPtr writer) +{ + /* <control> */ + xmlTextWriterStartElement(writer, "control"); + while (xmlTextReaderRead(reader)) + { + if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) + { + if (streq(xmlTextReaderConstName(reader), "ikesaterminate")) + { + request_control_terminate(reader, writer, TRUE); + break; + } + if (streq(xmlTextReaderConstName(reader), "childsaterminate")) + { + request_control_terminate(reader, writer, FALSE); + break; + } + if (streq(xmlTextReaderConstName(reader), "ikesainitiate")) + { + request_control_initiate(reader, writer, TRUE); + break; + } + if (streq(xmlTextReaderConstName(reader), "childsainitiate")) + { + request_control_initiate(reader, writer, FALSE); + break; + } + } + } + /* </control> */ + xmlTextWriterEndElement(writer); +} + +/** * process a request message */ static void request(xmlTextReaderPtr reader, char *id, int fd) @@ -337,6 +585,11 @@ static void request(xmlTextReaderPtr reader, char *id, int fd) request_query(reader, writer); break; } + if (streq(xmlTextReaderConstName(reader), "control")) + { + request_control(reader, writer); + break; + } } } /* </message> and close document */ |