From 1df1430146ac80db8966a57254b70c32b0b85f3f Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Tue, 4 Feb 2014 11:14:27 +0100 Subject: [PATCH 1/5] charon-cmd: Block SIGUSR1 on worker threads To properly shut down charon-cmd with leak reports, only the main thread should catch SIGUSR1 to shut down the application. Work threads should ignore SIGUSR1 to avoid any hard application termination. --- src/charon-cmd/charon-cmd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/charon-cmd/charon-cmd.c b/src/charon-cmd/charon-cmd.c index 5f4787b58..0c24fd146 100644 --- a/src/charon-cmd/charon-cmd.c +++ b/src/charon-cmd/charon-cmd.c @@ -389,6 +389,7 @@ int main(int argc, char *argv[]) sigaddset(&action.sa_mask, SIGINT); sigaddset(&action.sa_mask, SIGTERM); sigaddset(&action.sa_mask, SIGHUP); + sigaddset(&action.sa_mask, SIGUSR1); sigaction(SIGSEGV, &action, NULL); sigaction(SIGILL, &action, NULL); sigaction(SIGBUS, &action, NULL); From 2796cf59bc11a59d4ae9bb67e07d75d2dafb3798 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Tue, 4 Feb 2014 11:17:37 +0100 Subject: [PATCH 2/5] charon-cmd: Add an --ike-proposal option to specify non-default IKE proposals --- src/charon-cmd/cmd/cmd_connection.c | 32 ++++++++++++++++++++++++++++- src/charon-cmd/cmd/cmd_options.c | 2 ++ src/charon-cmd/cmd/cmd_options.h | 1 + 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/charon-cmd/cmd/cmd_connection.c b/src/charon-cmd/cmd/cmd_connection.c index 180e8da98..e015d01dc 100644 --- a/src/charon-cmd/cmd/cmd_connection.c +++ b/src/charon-cmd/cmd/cmd_connection.c @@ -86,6 +86,11 @@ struct private_cmd_connection_t { */ linked_list_t *remote_ts; + /** + * List of IKE proposals + */ + linked_list_t *ike_proposals; + /** * Hostname to connect to */ @@ -135,6 +140,7 @@ static peer_cfg_t* create_peer_cfg(private_cmd_connection_t *this) u_int16_t local_port, remote_port = IKEV2_UDP_PORT; ike_version_t version = IKE_ANY; bool aggressive = FALSE; + proposal_t *proposal; switch (this->profile) { @@ -165,7 +171,18 @@ static peer_cfg_t* create_peer_cfg(private_cmd_connection_t *this) } ike_cfg = ike_cfg_create(version, TRUE, FALSE, "0.0.0.0", local_port, this->host, remote_port, FRAGMENTATION_NO, 0); - ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); + if (this->ike_proposals->get_count(this->ike_proposals)) + { + while (this->ike_proposals->remove_first(this->ike_proposals, + (void**)&proposal) == SUCCESS) + { + ike_cfg->add_proposal(ike_cfg, proposal); + } + } + else + { + ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); + } peer_cfg = peer_cfg_create("cmd", ike_cfg, CERT_SEND_IF_ASKED, UNIQUE_REPLACE, 1, /* keyingtries */ 36000, 0, /* rekey 10h, reauth none */ @@ -421,6 +438,8 @@ static void set_profile(private_cmd_connection_t *this, char *name) METHOD(cmd_connection_t, handle, bool, private_cmd_connection_t *this, cmd_option_type_t opt, char *arg) { + proposal_t *proposal; + switch (opt) { case CMD_OPT_HOST: @@ -447,6 +466,14 @@ METHOD(cmd_connection_t, handle, bool, case CMD_OPT_REMOTE_TS: add_ts(this, this->remote_ts, arg); break; + case CMD_OPT_IKE_PROPOSAL: + proposal = proposal_create_from_string(PROTO_IKE, arg); + if (!proposal) + { + exit(1); + } + this->ike_proposals->insert_last(this->ike_proposals, proposal); + break; case CMD_OPT_PROFILE: set_profile(this, arg); break; @@ -459,6 +486,8 @@ METHOD(cmd_connection_t, handle, bool, METHOD(cmd_connection_t, destroy, void, private_cmd_connection_t *this) { + this->ike_proposals->destroy_offset(this->ike_proposals, + offsetof(proposal_t, destroy)); this->local_ts->destroy_offset(this->local_ts, offsetof(traffic_selector_t, destroy)); this->remote_ts->destroy_offset(this->remote_ts, @@ -481,6 +510,7 @@ cmd_connection_t *cmd_connection_create() .pid = getpid(), .local_ts = linked_list_create(), .remote_ts = linked_list_create(), + .ike_proposals = linked_list_create(), .profile = PROF_UNDEF, ); diff --git a/src/charon-cmd/cmd/cmd_options.c b/src/charon-cmd/cmd/cmd_options.c index 597ccda1f..562244100 100644 --- a/src/charon-cmd/cmd/cmd_options.c +++ b/src/charon-cmd/cmd/cmd_options.c @@ -56,6 +56,8 @@ cmd_option_t cmd_options[CMD_OPT_COUNT] = { "additional traffic selector to propose for our side", {}}, { CMD_OPT_REMOTE_TS, "remote-ts", required_argument, "subnet", "traffic selector to propose for remote side", {}}, + { CMD_OPT_IKE_PROPOSAL, "ike-proposal", required_argument, "proposal", + "a single IKE proposal to offer instead of the default", {}}, { CMD_OPT_PROFILE, "profile", required_argument, "name", "authentication profile to use, where name is one of:", { " ikev2-pub, ikev2-eap, ikev2-pub-eap", diff --git a/src/charon-cmd/cmd/cmd_options.h b/src/charon-cmd/cmd/cmd_options.h index 6b8b04cdf..ecb5e6ca5 100644 --- a/src/charon-cmd/cmd/cmd_options.h +++ b/src/charon-cmd/cmd/cmd_options.h @@ -45,6 +45,7 @@ enum cmd_option_type_t { CMD_OPT_AGENT, CMD_OPT_LOCAL_TS, CMD_OPT_REMOTE_TS, + CMD_OPT_IKE_PROPOSAL, CMD_OPT_PROFILE, CMD_OPT_COUNT From c9e85424a8cb61580a80b716fc4c846f7f535b69 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Tue, 4 Feb 2014 11:29:28 +0100 Subject: [PATCH 3/5] charon-cmd: Add --esp/--ah-proposal options to specify CHILD_SA proposals --- src/charon-cmd/cmd/cmd_connection.c | 38 ++++++++++++++++++++++++++++- src/charon-cmd/cmd/cmd_options.c | 4 +++ src/charon-cmd/cmd/cmd_options.h | 2 ++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/charon-cmd/cmd/cmd_connection.c b/src/charon-cmd/cmd/cmd_connection.c index e015d01dc..14719384a 100644 --- a/src/charon-cmd/cmd/cmd_connection.c +++ b/src/charon-cmd/cmd/cmd_connection.c @@ -91,6 +91,11 @@ struct private_cmd_connection_t { */ linked_list_t *ike_proposals; + /** + * List of CHILD proposals + */ + linked_list_t *child_proposals; + /** * Hostname to connect to */ @@ -327,6 +332,7 @@ static child_cfg_t* create_child_cfg(private_cmd_connection_t *this) { child_cfg_t *child_cfg; traffic_selector_t *ts; + proposal_t *proposal; lifetime_cfg_t lifetime = { .time = { .life = 10800 /* 3h */, @@ -339,7 +345,18 @@ static child_cfg_t* create_child_cfg(private_cmd_connection_t *this) NULL, FALSE, MODE_TUNNEL, /* updown, hostaccess */ ACTION_NONE, ACTION_NONE, ACTION_NONE, FALSE, 0, 0, NULL, NULL, 0); - child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP)); + if (this->child_proposals->get_count(this->child_proposals)) + { + while (this->child_proposals->remove_first(this->child_proposals, + (void**)&proposal) == SUCCESS) + { + child_cfg->add_proposal(child_cfg, proposal); + } + } + else + { + child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP)); + } while (this->local_ts->remove_first(this->local_ts, (void**)&ts) == SUCCESS) { child_cfg->add_traffic_selector(child_cfg, TRUE, ts); @@ -474,6 +491,22 @@ METHOD(cmd_connection_t, handle, bool, } this->ike_proposals->insert_last(this->ike_proposals, proposal); break; + case CMD_OPT_ESP_PROPOSAL: + proposal = proposal_create_from_string(PROTO_ESP, arg); + if (!proposal) + { + exit(1); + } + this->child_proposals->insert_last(this->child_proposals, proposal); + break; + case CMD_OPT_AH_PROPOSAL: + proposal = proposal_create_from_string(PROTO_AH, arg); + if (!proposal) + { + exit(1); + } + this->child_proposals->insert_last(this->child_proposals, proposal); + break; case CMD_OPT_PROFILE: set_profile(this, arg); break; @@ -488,6 +521,8 @@ METHOD(cmd_connection_t, destroy, void, { this->ike_proposals->destroy_offset(this->ike_proposals, offsetof(proposal_t, destroy)); + this->child_proposals->destroy_offset(this->child_proposals, + offsetof(proposal_t, destroy)); this->local_ts->destroy_offset(this->local_ts, offsetof(traffic_selector_t, destroy)); this->remote_ts->destroy_offset(this->remote_ts, @@ -511,6 +546,7 @@ cmd_connection_t *cmd_connection_create() .local_ts = linked_list_create(), .remote_ts = linked_list_create(), .ike_proposals = linked_list_create(), + .child_proposals = linked_list_create(), .profile = PROF_UNDEF, ); diff --git a/src/charon-cmd/cmd/cmd_options.c b/src/charon-cmd/cmd/cmd_options.c index 562244100..5428941ff 100644 --- a/src/charon-cmd/cmd/cmd_options.c +++ b/src/charon-cmd/cmd/cmd_options.c @@ -58,6 +58,10 @@ cmd_option_t cmd_options[CMD_OPT_COUNT] = { "traffic selector to propose for remote side", {}}, { CMD_OPT_IKE_PROPOSAL, "ike-proposal", required_argument, "proposal", "a single IKE proposal to offer instead of the default", {}}, + { CMD_OPT_ESP_PROPOSAL, "esp-proposal", required_argument, "proposal", + "a single ESP proposal to offer instead of the default", {}}, + { CMD_OPT_AH_PROPOSAL, "ah-proposal", required_argument, "proposal", + "a single AH proposal to offer instead of the default", {}}, { CMD_OPT_PROFILE, "profile", required_argument, "name", "authentication profile to use, where name is one of:", { " ikev2-pub, ikev2-eap, ikev2-pub-eap", diff --git a/src/charon-cmd/cmd/cmd_options.h b/src/charon-cmd/cmd/cmd_options.h index ecb5e6ca5..c7441e795 100644 --- a/src/charon-cmd/cmd/cmd_options.h +++ b/src/charon-cmd/cmd/cmd_options.h @@ -46,6 +46,8 @@ enum cmd_option_type_t { CMD_OPT_LOCAL_TS, CMD_OPT_REMOTE_TS, CMD_OPT_IKE_PROPOSAL, + CMD_OPT_AH_PROPOSAL, + CMD_OPT_ESP_PROPOSAL, CMD_OPT_PROFILE, CMD_OPT_COUNT From fe7269c089ddb18d4d2778002a7f249148966f19 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Tue, 4 Feb 2014 11:37:52 +0100 Subject: [PATCH 4/5] charon-cmd: Document new proposal options in manpage --- src/charon-cmd/charon-cmd.8.in | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/charon-cmd/charon-cmd.8.in b/src/charon-cmd/charon-cmd.8.in index 25d706995..a2d424e9a 100644 --- a/src/charon-cmd/charon-cmd.8.in +++ b/src/charon-cmd/charon-cmd.8.in @@ -116,6 +116,24 @@ address will always be proposed. .BI "\-\-remote\-ts " subnet Traffic selector to propose for remote side, defaults to 0.0.0.0/0. .TP +.BI "\-\-ike\-proposal " proposal +IKE proposal to offer instead of default. For IKEv1, a single proposal consists +of one encryption algorithm, an integrity/PRF algorithm and a DH group. IKEv2 +can propose multiple algorithms of the same kind. To specify multiple proposals, +repeat the option. +.TP +.BI "\-\-esp\-proposal " proposal +ESP proposal to offer instead of default. For IKEv1, a single proposal consists +of one encryption algorithm, an integrity algorithm and an optional DH group for +Perfect Forward Secrecy rekeying. IKEv2 can propose multiple algorithms of the +same kind. To specify multiple proposals, repeat the option. +.TP +.BI "\-\-ah\-proposal " proposal +AH proposal to offer instead of ESP. For IKEv1, a single proposal consists +of an integrity algorithm and an optional DH group for Perfect Forward Secrecy +rekeying. IKEv2 can propose multiple algorithms of the same kind. To specify +multiple proposals, repeat the option. +.TP .BI "\-\-profile " name Authentication profile to use, the list of supported profiles can be found in the From e2de972c55c882274a826926aac414ae432740ae Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Tue, 4 Feb 2014 16:40:25 +0100 Subject: [PATCH 5/5] charon-cmd: Request an IPv6 virtual IP if an IPv6 remote subnet given --- src/charon-cmd/cmd/cmd_connection.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/charon-cmd/cmd/cmd_connection.c b/src/charon-cmd/cmd/cmd_connection.c index 14719384a..ac085e131 100644 --- a/src/charon-cmd/cmd/cmd_connection.c +++ b/src/charon-cmd/cmd/cmd_connection.c @@ -195,7 +195,6 @@ static peer_cfg_t* create_peer_cfg(private_cmd_connection_t *this) TRUE, aggressive, TRUE, /* mobike, aggressive, pull */ 30, 0, /* DPD delay, timeout */ FALSE, NULL, NULL); /* mediation */ - peer_cfg->add_virtual_ip(peer_cfg, host_create_from_string("0.0.0.0", 0)); return peer_cfg; } @@ -328,11 +327,13 @@ static bool add_auth_cfgs(private_cmd_connection_t *this, peer_cfg_t *peer_cfg) /** * Attach child config to peer config */ -static child_cfg_t* create_child_cfg(private_cmd_connection_t *this) +static child_cfg_t* create_child_cfg(private_cmd_connection_t *this, + peer_cfg_t *peer_cfg) { child_cfg_t *child_cfg; traffic_selector_t *ts; proposal_t *proposal; + bool has_v4 = FALSE, has_v6 = FALSE; lifetime_cfg_t lifetime = { .time = { .life = 10800 /* 3h */, @@ -367,12 +368,31 @@ static child_cfg_t* create_child_cfg(private_cmd_connection_t *this) ts = traffic_selector_create_from_string(0, TS_IPV4_ADDR_RANGE, "0.0.0.0", 0, "255.255.255.255", 65535); this->remote_ts->insert_last(this->remote_ts, ts); + has_v4 = TRUE; } while (this->remote_ts->remove_first(this->remote_ts, (void**)&ts) == SUCCESS) { + switch (ts->get_type(ts)) + { + case TS_IPV4_ADDR_RANGE: + has_v4 = TRUE; + break; + case TS_IPV6_ADDR_RANGE: + has_v6 = TRUE; + break; + } child_cfg->add_traffic_selector(child_cfg, FALSE, ts); } + if (has_v4) + { + peer_cfg->add_virtual_ip(peer_cfg, host_create_from_string("0.0.0.0", 0)); + } + if (has_v6) + { + peer_cfg->add_virtual_ip(peer_cfg, host_create_from_string("::", 0)); + } + peer_cfg->add_child_cfg(peer_cfg, child_cfg->get_ref(child_cfg)); return child_cfg; } @@ -408,8 +428,7 @@ static job_requeue_t initiate(private_cmd_connection_t *this) return JOB_REQUEUE_NONE; } - child_cfg = create_child_cfg(this); - peer_cfg->add_child_cfg(peer_cfg, child_cfg->get_ref(child_cfg)); + child_cfg = create_child_cfg(this, peer_cfg); if (charon->controller->initiate(charon->controller, peer_cfg, child_cfg, controller_cb_empty, NULL, 0) != SUCCESS)