diff options
author | Martin Willi <martin@strongswan.org> | 2006-09-12 13:50:14 +0000 |
---|---|---|
committer | Martin Willi <martin@strongswan.org> | 2006-09-12 13:50:14 +0000 |
commit | d7934d0cfc84805bebc59f866c4af2f6e9687370 (patch) | |
tree | 25d99a2f178383e28996186a1d56de682f5eb503 | |
parent | a095243f604ea0dd3023acbef3622a0d53200dd3 (diff) | |
download | strongswan-d7934d0cfc84805bebc59f866c4af2f6e9687370.tar.bz2 strongswan-d7934d0cfc84805bebc59f866c4af2f6e9687370.tar.xz |
implemented updown script to handle firewalling
-rw-r--r-- | src/charon/config/traffic_selector.c | 10 | ||||
-rw-r--r-- | src/charon/network/socket.c | 9 | ||||
-rw-r--r-- | src/charon/network/socket.h | 6 | ||||
-rw-r--r-- | src/charon/sa/child_sa.c | 175 | ||||
-rw-r--r-- | src/charon/sa/child_sa.h | 8 | ||||
-rw-r--r-- | src/charon/sa/ike_sa.c | 5 | ||||
-rw-r--r-- | src/charon/sa/transactions/create_child_sa.c | 14 | ||||
-rw-r--r-- | src/charon/sa/transactions/ike_auth.c | 8 | ||||
-rwxr-xr-x | src/charon/threads/stroke_interface.c | 4 |
9 files changed, 207 insertions, 32 deletions
diff --git a/src/charon/config/traffic_selector.c b/src/charon/config/traffic_selector.c index e567c6eca..ba6803156 100644 --- a/src/charon/config/traffic_selector.c +++ b/src/charon/config/traffic_selector.c @@ -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 */ diff --git a/src/charon/network/socket.c b/src/charon/network/socket.c index 81d9d63a8..adac63979 100644 --- a/src/charon/network/socket.c +++ b/src/charon/network/socket.c @@ -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; diff --git a/src/charon/network/socket.h b/src/charon/network/socket.h index 34a06c0bb..431d9f2eb 100644 --- a/src/charon/network/socket.h +++ b/src/charon/network/socket.h @@ -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. diff --git a/src/charon/sa/child_sa.c b/src/charon/sa/child_sa.c index 79cff7ae1..b1335fa27 100644 --- a/src/charon/sa/child_sa.c +++ b/src/charon/sa/child_sa.c @@ -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; @@ -155,14 +157,14 @@ struct private_child_sa_t { void *rekeying_transaction; /** - * Specifies if NAT traversal is used + * Updown script */ - bool use_natt; + char *script; /** - * Specifies if CHILD_SA goes to ROUTED state if DPD detected + * Specifies if NAT traversal is used */ - bool stays_routed; + bool use_natt; /** * CHILD_SAs own logger @@ -230,11 +232,156 @@ static child_sa_state_t get_state(private_child_sa_t *this) } /** + * 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; diff --git a/src/charon/sa/child_sa.h b/src/charon/sa/child_sa.h index 5129ffe6a..e8e97c607 100644 --- a/src/charon/sa/child_sa.h +++ b/src/charon/sa/child_sa.h @@ -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_*/ diff --git a/src/charon/sa/ike_sa.c b/src/charon/sa/ike_sa.c index 55c3302ca..f8299863d 100644 --- a/src/charon/sa/ike_sa.c +++ b/src/charon/sa/ike_sa.c @@ -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); diff --git a/src/charon/sa/transactions/create_child_sa.c b/src/charon/sa/transactions/create_child_sa.c index d88c2341b..154a8e800 100644 --- a/src/charon/sa/transactions/create_child_sa.c +++ b/src/charon/sa/transactions/create_child_sa.c @@ -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) diff --git a/src/charon/sa/transactions/ike_auth.c b/src/charon/sa/transactions/ike_auth.c index 0632fe421..c30dde2a4 100644 --- a/src/charon/sa/transactions/ike_auth.c +++ b/src/charon/sa/transactions/ike_auth.c @@ -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) diff --git a/src/charon/threads/stroke_interface.c b/src/charon/threads/stroke_interface.c index 3a39990a9..3c84415f4 100755 --- a/src/charon/threads/stroke_interface.c +++ b/src/charon/threads/stroke_interface.c @@ -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"); |