implemented updown script to handle firewalling

This commit is contained in:
Martin Willi
2006-09-12 13:50:14 +00:00
parent a095243f60
commit d7934d0cfc
9 changed files with 208 additions and 33 deletions
+2 -8
View File
@@ -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 */
+7 -2
View File
@@ -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;
+5 -1
View File
@@ -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
View File
@@ -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;
+6 -2
View File
@@ -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_*/
+2 -3
View File
@@ -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);
+12 -2
View File
@@ -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)
+6 -2
View File
@@ -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)
+2 -2
View File
@@ -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");