implemented updown script to handle firewalling
This commit is contained in:
@@ -177,10 +177,7 @@ static void update_string(private_traffic_selector_t *this)
|
||||
|
||||
/* build network mask string */
|
||||
mask = calc_netbits(this);
|
||||
if (mask != 32)
|
||||
{
|
||||
snprintf(mask_str, sizeof(mask_str), "/%d", mask);
|
||||
}
|
||||
snprintf(mask_str, sizeof(mask_str), "/%d", mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -191,10 +188,7 @@ static void update_string(private_traffic_selector_t *this)
|
||||
|
||||
/* build network mask string */
|
||||
mask = calc_netbits(this);
|
||||
if (mask != 128)
|
||||
{
|
||||
snprintf(mask_str, sizeof(mask_str), "/%d", mask);
|
||||
}
|
||||
snprintf(mask_str, sizeof(mask_str), "/%d", mask);
|
||||
}
|
||||
|
||||
/* build protocol string */
|
||||
|
||||
@@ -398,7 +398,7 @@ status_t sender(private_socket_t *this, packet_t *packet)
|
||||
/**
|
||||
* implements socket_t.is_local_address
|
||||
*/
|
||||
static bool is_local_address(private_socket_t *this, host_t *host)
|
||||
static bool is_local_address(private_socket_t *this, host_t *host, char **dev)
|
||||
{
|
||||
struct ifaddrs *list;
|
||||
struct ifaddrs *cur;
|
||||
@@ -455,6 +455,11 @@ static bool is_local_address(private_socket_t *this, host_t *host)
|
||||
|
||||
if (found)
|
||||
{
|
||||
if (dev && cur->ifa_name)
|
||||
{
|
||||
/* return interface name, if requested */
|
||||
*dev = strdup(cur->ifa_name);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -768,7 +773,7 @@ socket_t *socket_create(u_int16_t port, u_int16_t natt_port)
|
||||
/* public functions */
|
||||
this->public.send = (status_t(*)(socket_t*, packet_t*))sender;
|
||||
this->public.receive = (status_t(*)(socket_t*, packet_t**))receiver;
|
||||
this->public.is_local_address = (bool(*)(socket_t*, host_t*))is_local_address;
|
||||
this->public.is_local_address = (bool(*)(socket_t*, host_t*,char**))is_local_address;
|
||||
this->public.create_local_address_list = (linked_list_t*(*)(socket_t*))create_local_address_list;
|
||||
this->public.destroy = (void(*)(socket_t*)) destroy;
|
||||
|
||||
|
||||
@@ -93,11 +93,15 @@ struct socket_t {
|
||||
/**
|
||||
* @brief Check if an address is an address of this host.
|
||||
*
|
||||
* If the name parameter is not NULL, a string is allocated which
|
||||
* holds the interfaces name.
|
||||
*
|
||||
* @param this socket_t object to work on
|
||||
* @param host address to check
|
||||
* @param name[out] interface name on which address is used
|
||||
* @return TRUE if local address, FALSE otherwise
|
||||
*/
|
||||
bool (*is_local_address) (socket_t *this, host_t *host);
|
||||
bool (*is_local_address) (socket_t *this, host_t *host, char **name);
|
||||
|
||||
/**
|
||||
* @brief Create a list of hosts with all local addresses.
|
||||
|
||||
+166
-11
@@ -80,6 +80,8 @@ struct private_child_sa_t {
|
||||
struct {
|
||||
/** address of peer */
|
||||
host_t *addr;
|
||||
/** id of peer */
|
||||
identification_t *id;
|
||||
/** actual used SPI, 0 if unused */
|
||||
u_int32_t spi;
|
||||
} me, other;
|
||||
@@ -154,15 +156,15 @@ struct private_child_sa_t {
|
||||
*/
|
||||
void *rekeying_transaction;
|
||||
|
||||
/**
|
||||
* Updown script
|
||||
*/
|
||||
char *script;
|
||||
|
||||
/**
|
||||
* Specifies if NAT traversal is used
|
||||
*/
|
||||
bool use_natt;
|
||||
|
||||
/**
|
||||
* Specifies if CHILD_SA goes to ROUTED state if DPD detected
|
||||
*/
|
||||
bool stays_routed;
|
||||
|
||||
/**
|
||||
* CHILD_SAs own logger
|
||||
@@ -229,12 +231,157 @@ static child_sa_state_t get_state(private_child_sa_t *this)
|
||||
return this->state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the up/down script
|
||||
*/
|
||||
static void updown(private_child_sa_t *this, bool up)
|
||||
{
|
||||
iterator_t *iterator;
|
||||
|
||||
if (this->script == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
iterator = this->policies->create_iterator(this->policies, TRUE);
|
||||
while (iterator->has_next(iterator))
|
||||
{
|
||||
sa_policy_t *policy;
|
||||
char command[1024];
|
||||
char *ifname = NULL;
|
||||
char *my_str, *other_str;
|
||||
char *my_client, *other_client, *my_client_mask, *other_client_mask;
|
||||
char *pos;
|
||||
FILE *shell;
|
||||
|
||||
/* get ts strings */
|
||||
iterator->current(iterator, (void**)&policy);
|
||||
my_str = policy->my_ts->get_string(policy->my_ts);
|
||||
other_str = policy->other_ts->get_string(policy->other_ts);
|
||||
|
||||
/* get subnet/bits from string */
|
||||
my_client = strdup(my_str);
|
||||
pos = strchr(my_client, '/');
|
||||
*pos = '\0';
|
||||
my_client_mask = pos + 1;
|
||||
pos = strchr(my_client_mask, '[');
|
||||
if (pos)
|
||||
{
|
||||
*pos = '\0';
|
||||
}
|
||||
other_client = strdup(other_str);
|
||||
pos = strchr(other_client, '/');
|
||||
*pos = '\0';
|
||||
other_client_mask = pos + 1;
|
||||
pos = strchr(other_client_mask, '[');
|
||||
if (pos)
|
||||
{
|
||||
*pos = '\0';
|
||||
}
|
||||
|
||||
charon->socket->is_local_address(charon->socket, this->me.addr, &ifname);
|
||||
|
||||
/* build the command with all env variables.
|
||||
* TODO: PLUTO_MY_SRCIP, PLUTO_PEER_CA and PLUTO_NEXT_HOP
|
||||
* are currently missing */
|
||||
snprintf(command, sizeof(command),
|
||||
"2>&1 "
|
||||
"PLUTO_VERSION='1.1' "
|
||||
"PLUTO_VERB='%s%s%s' "
|
||||
"PLUTO_CONNECTION='%s' "
|
||||
"PLUTO_INTERFACE='%s' "
|
||||
"PLUTO_REQID='%u' "
|
||||
"PLUTO_ME='%s' "
|
||||
"PLUTO_MY_ID='%s' "
|
||||
"PLUTO_MY_CLIENT='%s/%s' "
|
||||
"PLUTO_MY_CLIENT_NET='%s' "
|
||||
"PLUTO_MY_CLIENT_MASK='%s' "
|
||||
"PLUTO_MY_PORT='%u' "
|
||||
"PLUTO_MY_PROTOCOL='%u' "
|
||||
"PLUTO_PEER='%s' "
|
||||
"PLUTO_PEER_ID='%s' "
|
||||
"PLUTO_PEER_CLIENT='%s/%s' "
|
||||
"PLUTO_PEER_CLIENT_NET='%s' "
|
||||
"PLUTO_PEER_CLIENT_MASK='%s' "
|
||||
"PLUTO_PEER_PORT='%u' "
|
||||
"PLUTO_PEER_PROTOCOL='%u' "
|
||||
"%s",
|
||||
up ? "up" : "down",
|
||||
streq(this->me.addr->get_string(this->me.addr),
|
||||
my_client) ? "-host" : "-client",
|
||||
this->me.addr->get_family(this->me.addr) == AF_INET ? "" : "-ipv6",
|
||||
this->name,
|
||||
ifname,
|
||||
this->reqid,
|
||||
this->me.addr->get_string(this->me.addr),
|
||||
this->me.id->get_string(this->me.id),
|
||||
my_client, my_client_mask,
|
||||
my_client, my_client_mask,
|
||||
policy->my_ts->get_from_port(policy->my_ts),
|
||||
policy->my_ts->get_protocol(policy->my_ts),
|
||||
this->other.addr->get_string(this->other.addr),
|
||||
this->other.id->get_string(this->other.id),
|
||||
other_client, other_client_mask,
|
||||
other_client, other_client_mask,
|
||||
policy->other_ts->get_from_port(policy->other_ts),
|
||||
policy->other_ts->get_protocol(policy->other_ts),
|
||||
this->script);
|
||||
free(ifname);
|
||||
free(my_client);
|
||||
free(other_client);
|
||||
|
||||
shell = popen(command, "r");
|
||||
|
||||
if (shell == NULL)
|
||||
{
|
||||
this->logger->log(this->logger, ERROR,
|
||||
"could not execute updown script '%s'",
|
||||
this->script);
|
||||
return;
|
||||
}
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
char resp[128];
|
||||
|
||||
if (fgets(resp, sizeof(resp), shell) == NULL)
|
||||
{
|
||||
if (ferror(shell))
|
||||
{
|
||||
this->logger->log(this->logger, ERROR,
|
||||
"error reading output from updown script");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char *e = resp + strlen(resp);
|
||||
if (e > resp && e[-1] == '\n')
|
||||
{ /* trim trailing '\n' */
|
||||
e[-1] = '\0';
|
||||
}
|
||||
this->logger->log(this->logger, ERROR, "updown: %s", resp);
|
||||
}
|
||||
}
|
||||
pclose(shell);
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements child_sa_t.set_state
|
||||
*/
|
||||
static void set_state(private_child_sa_t *this, child_sa_state_t state)
|
||||
{
|
||||
this->state = state;
|
||||
if (state == CHILD_INSTALLED)
|
||||
{
|
||||
updown(this, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -440,8 +587,6 @@ static status_t add(private_child_sa_t *this, proposal_t *proposal, prf_plus_t *
|
||||
}
|
||||
proposal->set_spi(proposal, inbound_spi);
|
||||
|
||||
this->state = CHILD_INSTALLED;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@@ -466,8 +611,6 @@ static status_t update(private_child_sa_t *this, proposal_t *proposal, prf_plus_
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
this->state = CHILD_INSTALLED;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@@ -903,6 +1046,11 @@ static void destroy(private_child_sa_t *this)
|
||||
{
|
||||
sa_policy_t *policy;
|
||||
|
||||
if (this->state == CHILD_DELETING || this->state == CHILD_INSTALLED)
|
||||
{
|
||||
updown(this, FALSE);
|
||||
}
|
||||
|
||||
/* delete SAs in the kernel, if they are set up */
|
||||
if (this->me.spi)
|
||||
{
|
||||
@@ -950,16 +1098,20 @@ static void destroy(private_child_sa_t *this)
|
||||
this->other_ts->destroy(this->other_ts);
|
||||
this->me.addr->destroy(this->me.addr);
|
||||
this->other.addr->destroy(this->other.addr);
|
||||
this->me.id->destroy(this->me.id);
|
||||
this->other.id->destroy(this->other.id);
|
||||
free(this->name);
|
||||
free(this->script);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
child_sa_t * child_sa_create(u_int32_t rekey, host_t *me, host_t* other,
|
||||
child_sa_t * child_sa_create(u_int32_t rekey, host_t *me, host_t* other,
|
||||
identification_t *my_id, identification_t *other_id,
|
||||
u_int32_t soft_lifetime, u_int32_t hard_lifetime,
|
||||
bool use_natt)
|
||||
char *script, bool use_natt)
|
||||
{
|
||||
static u_int32_t reqid = REQID_START;
|
||||
private_child_sa_t *this = malloc_thing(private_child_sa_t);
|
||||
@@ -990,10 +1142,13 @@ child_sa_t * child_sa_create(u_int32_t rekey, host_t *me, host_t* other,
|
||||
this->name = strdup("(uninitialized)");
|
||||
this->me.addr = me->clone(me);
|
||||
this->other.addr = other->clone(other);
|
||||
this->me.id = my_id->clone(my_id);
|
||||
this->other.id = other_id->clone(other_id);
|
||||
this->me.spi = 0;
|
||||
this->other.spi = 0;
|
||||
this->alloc_ah_spi = 0;
|
||||
this->alloc_esp_spi = 0;
|
||||
this->script = script ? strdup(script) : NULL;
|
||||
this->use_natt = use_natt;
|
||||
this->soft_lifetime = soft_lifetime;
|
||||
this->hard_lifetime = hard_lifetime;
|
||||
|
||||
@@ -306,15 +306,19 @@ struct child_sa_t {
|
||||
* @param rekey_reqid reqid of old CHILD_SA when rekeying, 0 otherwise
|
||||
* @param me own address
|
||||
* @param other remote address
|
||||
* @param my_id id of own peer
|
||||
* @param other_id id of remote peer
|
||||
* @param soft_lifetime time before rekeying
|
||||
* @param hard_lifteime time before delete
|
||||
* @param script updown script to use when calling child_sa_t.script()
|
||||
* @param use_natt TRUE if NAT traversal is used
|
||||
* @return child_sa_t object
|
||||
*
|
||||
* @ingroup sa
|
||||
*/
|
||||
child_sa_t * child_sa_create(u_int32_t rekey_reqid, host_t *me, host_t *other,
|
||||
child_sa_t * child_sa_create(u_int32_t rekey_reqid, host_t *me, host_t *other,
|
||||
identification_t *my_id, identification_t* other_id,
|
||||
u_int32_t soft_lifetime, u_int32_t hard_lifetime,
|
||||
bool use_natt);
|
||||
char *script, bool use_natt);
|
||||
|
||||
#endif /*CHILD_SA_H_*/
|
||||
|
||||
@@ -993,7 +993,6 @@ static status_t acquire(private_ike_sa_t *this, u_int32_t reqid)
|
||||
{
|
||||
if (current->get_reqid(current) == reqid)
|
||||
{
|
||||
//iterator->remove(iterator);
|
||||
child_sa = current;
|
||||
break;
|
||||
}
|
||||
@@ -1013,7 +1012,6 @@ static status_t acquire(private_ike_sa_t *this, u_int32_t reqid)
|
||||
this->my_id, this->other_id,
|
||||
my_ts, other_ts,
|
||||
this->my_host, this->other_host);
|
||||
//child_sa->destroy(child_sa);
|
||||
if (policy == NULL)
|
||||
{
|
||||
this->logger->log(this->logger, ERROR,
|
||||
@@ -1200,7 +1198,8 @@ static status_t route(private_ike_sa_t *this, connection_t *connection, policy_t
|
||||
}
|
||||
|
||||
child_sa = child_sa_create(0, this->my_host, this->other_host,
|
||||
0, 0, FALSE);
|
||||
this->my_id, this->other_id,
|
||||
0, 0, NULL, FALSE);
|
||||
child_sa->set_name(child_sa, policy->get_name(policy));
|
||||
my_ts = policy->get_my_traffic_selectors(policy, this->my_host);
|
||||
other_ts = policy->get_other_traffic_selectors(policy, this->other_host);
|
||||
|
||||
@@ -221,6 +221,7 @@ static status_t get_request(private_create_child_sa_t *this, message_t **result)
|
||||
{
|
||||
message_t *request;
|
||||
host_t *me, *other;
|
||||
identification_t *my_id, *other_id;
|
||||
|
||||
/* check if we already have built a message (retransmission) */
|
||||
if (this->message)
|
||||
@@ -250,6 +251,8 @@ static status_t get_request(private_create_child_sa_t *this, message_t **result)
|
||||
|
||||
me = this->ike_sa->get_my_host(this->ike_sa);
|
||||
other = this->ike_sa->get_other_host(this->ike_sa);
|
||||
my_id = this->ike_sa->get_my_id(this->ike_sa);
|
||||
other_id = this->ike_sa->get_other_id(this->ike_sa);
|
||||
|
||||
/* build the request */
|
||||
request = message_create();
|
||||
@@ -295,9 +298,10 @@ static status_t get_request(private_create_child_sa_t *this, message_t **result)
|
||||
|
||||
proposals = this->policy->get_proposals(this->policy);
|
||||
use_natt = this->ike_sa->is_natt_enabled(this->ike_sa);
|
||||
this->child_sa = child_sa_create(this->reqid, me, other,
|
||||
this->child_sa = child_sa_create(this->reqid, me, other, my_id, other_id,
|
||||
this->policy->get_soft_lifetime(this->policy),
|
||||
this->policy->get_hard_lifetime(this->policy),
|
||||
this->policy->get_updown(this->policy),
|
||||
use_natt);
|
||||
this->child_sa->set_name(this->child_sa, this->policy->get_name(this->policy));
|
||||
if (this->child_sa->alloc(this->child_sa, proposals) != SUCCESS)
|
||||
@@ -501,7 +505,9 @@ static status_t install_child_sa(private_create_child_sa_t *this, bool initiator
|
||||
{
|
||||
return DESTROY_ME;
|
||||
}
|
||||
|
||||
/* add to IKE_SA, and remove from transaction */
|
||||
this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
|
||||
this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
|
||||
this->child_sa = NULL;
|
||||
return SUCCESS;
|
||||
@@ -514,6 +520,7 @@ static status_t get_response(private_create_child_sa_t *this, message_t *request
|
||||
message_t **result, transaction_t **next)
|
||||
{
|
||||
host_t *me, *other;
|
||||
identification_t *my_id, *other_id;
|
||||
message_t *response;
|
||||
status_t status;
|
||||
iterator_t *payloads;
|
||||
@@ -532,6 +539,8 @@ static status_t get_response(private_create_child_sa_t *this, message_t *request
|
||||
|
||||
me = this->ike_sa->get_my_host(this->ike_sa);
|
||||
other = this->ike_sa->get_other_host(this->ike_sa);
|
||||
my_id = this->ike_sa->get_my_id(this->ike_sa);
|
||||
other_id = this->ike_sa->get_other_id(this->ike_sa);
|
||||
this->message_id = request->get_message_id(request);
|
||||
|
||||
/* set up response */
|
||||
@@ -705,8 +714,9 @@ static status_t get_response(private_create_child_sa_t *this, message_t *request
|
||||
soft_lifetime = this->policy->get_soft_lifetime(this->policy);
|
||||
hard_lifetime = this->policy->get_hard_lifetime(this->policy);
|
||||
use_natt = this->ike_sa->is_natt_enabled(this->ike_sa);
|
||||
this->child_sa = child_sa_create(this->reqid, me, other,
|
||||
this->child_sa = child_sa_create(this->reqid, me, other, my_id, other_id,
|
||||
soft_lifetime, hard_lifetime,
|
||||
this->policy->get_updown(this->policy),
|
||||
use_natt);
|
||||
this->child_sa->set_name(this->child_sa, this->policy->get_name(this->policy));
|
||||
if (install_child_sa(this, FALSE) != SUCCESS)
|
||||
|
||||
@@ -318,8 +318,9 @@ static status_t get_request(private_ike_auth_t *this, message_t **result)
|
||||
soft_lifetime = this->policy->get_soft_lifetime(this->policy);
|
||||
hard_lifetime = this->policy->get_hard_lifetime(this->policy);
|
||||
enable_natt = this->ike_sa->is_natt_enabled(this->ike_sa);
|
||||
this->child_sa = child_sa_create(this->reqid, me, other,
|
||||
this->child_sa = child_sa_create(this->reqid, me, other, my_id, other_id,
|
||||
soft_lifetime, hard_lifetime,
|
||||
this->policy->get_updown(this->policy),
|
||||
enable_natt);
|
||||
this->child_sa->set_name(this->child_sa, this->policy->get_name(this->policy));
|
||||
if (this->child_sa->alloc(this->child_sa, proposal_list) != SUCCESS)
|
||||
@@ -519,7 +520,9 @@ static status_t install_child_sa(private_ike_auth_t *this, bool initiator)
|
||||
{
|
||||
return DESTROY_ME;
|
||||
}
|
||||
|
||||
/* add to IKE_SA, and remove from transaction */
|
||||
this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
|
||||
this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
|
||||
this->child_sa = NULL;
|
||||
return SUCCESS;
|
||||
@@ -784,8 +787,9 @@ static status_t get_response(private_ike_auth_t *this, message_t *request,
|
||||
soft_lifetime = this->policy->get_soft_lifetime(this->policy);
|
||||
hard_lifetime = this->policy->get_hard_lifetime(this->policy);
|
||||
use_natt = this->ike_sa->is_natt_enabled(this->ike_sa);
|
||||
this->child_sa = child_sa_create(this->reqid, me, other,
|
||||
this->child_sa = child_sa_create(this->reqid, me, other, my_id, other_id,
|
||||
soft_lifetime, hard_lifetime,
|
||||
this->policy->get_updown(this->policy),
|
||||
use_natt);
|
||||
this->child_sa->set_name(this->child_sa, this->policy->get_name(this->policy));
|
||||
if (install_child_sa(this, FALSE) != SUCCESS)
|
||||
|
||||
@@ -222,7 +222,7 @@ static void stroke_add_conn(private_stroke_t *this, stroke_msg_t *msg)
|
||||
return;
|
||||
}
|
||||
|
||||
if (charon->socket->is_local_address(charon->socket, other_host))
|
||||
if (charon->socket->is_local_address(charon->socket, other_host, NULL))
|
||||
{
|
||||
stroke_end_t tmp_end;
|
||||
host_t *tmp_host;
|
||||
@@ -238,7 +238,7 @@ static void stroke_add_conn(private_stroke_t *this, stroke_msg_t *msg)
|
||||
msg->add_conn.me = msg->add_conn.other;
|
||||
msg->add_conn.other = tmp_end;
|
||||
}
|
||||
else if (!charon->socket->is_local_address(charon->socket, my_host))
|
||||
else if (!charon->socket->is_local_address(charon->socket, my_host, NULL))
|
||||
{
|
||||
this->stroke_logger->log(this->stroke_logger, ERROR,
|
||||
"left nor right host is our side, aborting");
|
||||
|
||||
Reference in New Issue
Block a user