pluto now supports SQL-based virtual IP pools

This commit is contained in:
Andreas Steffen
2009-10-14 14:30:14 +02:00
parent 601bc1df20
commit 270bb348e3
16 changed files with 441 additions and 244 deletions
+53 -9
View File
@@ -320,7 +320,9 @@ void delete_connection(connection_t *c, bool relations)
release_connection(c, relations); /* won't delete c */
if (c->kind == CK_GROUP)
{
delete_group(c);
}
/* free up any logging resources */
perpeer_logfree(c);
@@ -333,7 +335,9 @@ void delete_connection(connection_t *c, bool relations)
if (c->host_pair == NULL)
{
if (c->ikev1)
{
list_rm(connection_t, hp_next, c, unoriented_connections);
}
}
else
{
@@ -358,6 +362,20 @@ void delete_connection(connection_t *c, bool relations)
{
free(c->spd.that.virt);
}
/* release virtual IP address lease if any */
if (c->spd.that.modecfg && c->spd.that.pool &&
!isanyaddr(&c->spd.that.host_srcip))
{
host_t *vip;
vip = host_create_from_sockaddr((sockaddr_t*)&c->spd.that.host_srcip);
lib->attributes->release_address(lib->attributes, c->spd.that.pool,
vip, c->spd.that.id);
vip->destroy(vip);
}
/* free internal data */
#ifdef DEBUG
cur_debugging = old_cur_debugging;
#endif
@@ -366,10 +384,12 @@ void delete_connection(connection_t *c, bool relations)
DESTROY_IF(c->spd.this.ca);
DESTROY_IF(c->spd.this.groups);
free(c->spd.this.updown);
free(c->spd.this.pool);
DESTROY_IF(c->spd.that.id);
DESTROY_IF(c->spd.that.ca);
DESTROY_IF(c->spd.that.groups);
free(c->spd.that.updown);
free(c->spd.that.pool);
if (c->requested_ca)
{
c->requested_ca->destroy_offset(c->requested_ca,
@@ -562,7 +582,7 @@ static err_t default_end(struct end *e, ip_address *dflt_nexthop)
size_t format_end(char *buf, size_t buf_len, const struct end *this,
const struct end *that, bool is_left, lset_t policy)
{
char client[SUBNETTOT_BUF];
char client[BUF_LEN];
const char *client_sep = "";
char protoport[sizeof(":255/65535")];
const char *host = NULL;
@@ -618,17 +638,24 @@ size_t format_end(char *buf, size_t buf_len, const struct end *this,
if (isanyaddr(&client_net) && isanyaddr(&client_mask)
&& (policy & (POLICY_GROUP | POLICY_OPPO)))
{
client_sep = ""; /* boring case */
}
else if (subnetisnone(&this->client))
{
strcpy(client, "?");
}
else
{
subnettot(&this->client, 0, client, sizeof(client));
}
}
else if (this->modecfg && isanyaddr(&this->host_srcip))
{
/* we are mode config client */
/* we are mode config client, or a server with a pool */
client_sep = "===";
strcpy(client, "%modecfg");
client[0] = '%';
strcpy(client+1, this->pool ? this->pool : "modecfg");
}
/* host */
@@ -640,16 +667,21 @@ size_t format_end(char *buf, size_t buf_len, const struct end *this,
host_port[0] = '\0';
if (this->host_port != IKE_UDP_PORT)
snprintf(host_port, sizeof(host_port), ":%u"
, this->host_port);
{
snprintf(host_port, sizeof(host_port), ":%u", this->host_port);
}
/* payload portocol and port */
protoport[0] = '\0';
if (this->has_port_wildcard)
{
snprintf(protoport, sizeof(protoport), ":%u/%%any", this->protocol);
}
else if (this->port || this->protocol)
{
snprintf(protoport, sizeof(protoport), ":%u/%u", this->protocol
, this->port);
}
/* id */
snprintf(host_id, sizeof(host_id), "[%Y]", this->id);
@@ -664,17 +696,21 @@ size_t format_end(char *buf, size_t buf_len, const struct end *this,
}
if (is_left)
{
snprintf(buf, buf_len, "%s%s%s%s%s%s%s%s%s%s%s"
, open_brackets, client, close_brackets, client_sep
, this->allow_any? "%":""
, host, host_port, host_id, protoport
, hop_sep, hop);
}
else
{
snprintf(buf, buf_len, "%s%s%s%s%s%s%s%s%s%s%s"
, hop, hop_sep
, this->allow_any? "%":""
, host, host_port, host_id, protoport, client_sep
, open_brackets, client, close_brackets);
}
return strlen(buf);
}
@@ -697,6 +733,7 @@ static void unshare_connection_strings(connection_t *c)
{
c->name = clone_str(c->name);
c->spd.this.id = c->spd.this.id->clone(c->spd.this.id);
c->spd.this.pool = clone_str(c->spd.this.pool);
c->spd.this.updown = clone_str(c->spd.this.updown);
scx_share(c->spd.this.sc);
share_cert(c->spd.this.cert);
@@ -709,6 +746,7 @@ static void unshare_connection_strings(connection_t *c)
c->spd.this.groups = c->spd.this.groups->get_ref(c->spd.this.groups);
}
c->spd.that.id = c->spd.that.id->clone(c->spd.that.id);
c->spd.that.pool = clone_str(c->spd.that.pool);
c->spd.that.updown = clone_str(c->spd.that.updown);
scx_share(c->spd.that.sc);
share_cert(c->spd.that.cert);
@@ -886,13 +924,17 @@ static bool extract_end(struct end *dst, const whack_end_t *src,
dst->updown = clone_str(src->updown);
dst->host_port = src->host_port;
/* if the sourceip netmask is zero a named pool exists */
if (src->sourceip_mask == 0)
{
dst->pool = clone_str(src->sourceip);
}
/* if host sourceip is defined but no client is present
* behind the host then set client to sourceip/32
*/
if (addrbytesptr(&dst->host_srcip, NULL)
&& !isanyaddr(&dst->host_srcip)
&& !dst->has_natip
&& !dst->has_client)
if (addrbytesptr(&dst->host_srcip, NULL) &&
!isanyaddr(&dst->host_srcip) && !dst->has_natip && !dst->has_client)
{
err_t ugh = addrtosubnet(&dst->host_srcip, &dst->client);
@@ -2987,7 +3029,9 @@ void ISAKMP_SA_established(connection_t *c, so_serial_t serial)
* whether we are a mode config server with a virtual IP to send.
*/
if (!isanyaddr(&c->spd.that.host_srcip) && !c->spd.that.has_natip)
{
c->spd.that.modecfg = TRUE;
}
if (uniqueIDs)
{
+4 -3
View File
@@ -154,6 +154,7 @@ struct end {
struct virtual_t *virt;
bool modecfg; /* this end: request local address from server */
/* that end: give local addresses to clients */
char *pool; /* name of an associated virtual IP address pool */
bool hostaccess; /* allow access to host via iptables INPUT/OUTPUT */
/* rules if client behind host is a subnet */
bool allow_any; /* IP address is subject to change */
@@ -187,10 +188,10 @@ struct connection {
time_t dpd_timeout;
dpd_action_t dpd_action;
char *log_file_name; /* name of log file */
FILE *log_file; /* possibly open FILE */
char *log_file_name; /* name of log file */
FILE *log_file; /* possibly open FILE */
TAILQ_ENTRY(connection) log_link; /* linked list of open conns */
bool log_file_err; /* only bitch once */
bool log_file_err; /* only bitch once */
struct spd_route spd;
+77 -56
View File
@@ -82,11 +82,10 @@ struct internal_addr
bool xauth_status;
};
/*
/**
* Initialize an internal_addr struct
*/
static void
init_internal_addr(internal_addr_t *ia)
static void init_internal_addr(internal_addr_t *ia)
{
int i;
@@ -114,17 +113,36 @@ init_internal_addr(internal_addr_t *ia)
}
}
/*
* get internal IP address for a connection
/**
* Get internal IP address for a connection
*/
static void
get_internal_addr(connection_t *c, internal_addr_t *ia)
static void get_internal_addr(connection_t *c, host_t *requested_vip,
internal_addr_t *ia)
{
int i, dns_idx = 0, nbns_idx = 0;
if (isanyaddr(&c->spd.that.host_srcip))
{
/* not defined in connection - fetch it from LDAP */
if (c->spd.that.pool)
{
host_t *vip;
vip = lib->attributes->acquire_address(lib->attributes,
c->spd.that.pool, c->spd.that.id,
requested_vip);
if (vip)
{
chunk_t addr = vip->get_address(vip);
plog("assigning virtual IP %H to peer", vip);
initaddr(addr.ptr, addr.len, vip->get_family(vip), &ia->ipaddr);
vip->destroy(vip);
}
}
else
{
plog("no virtual IP found");
}
}
else
{
@@ -133,11 +151,12 @@ get_internal_addr(connection_t *c, internal_addr_t *ia)
ia->ipaddr = c->spd.that.host_srcip;
addrtot(&ia->ipaddr, 0, srcip, sizeof(srcip));
plog("assigning virtual IP source address %s", srcip);
plog("assigning virtual IP %s to peer", srcip);
}
if (!isanyaddr(&ia->ipaddr)) /* We got an IP address, send it */
{
c->spd.that.host_srcip = ia->ipaddr;
c->spd.that.client.addr = ia->ipaddr;
c->spd.that.client.maskbits = 32;
c->spd.that.has_client = TRUE;
@@ -200,11 +219,10 @@ get_internal_addr(connection_t *c, internal_addr_t *ia)
}
/*
/**
* Set srcip and client subnet to internal IP address
*/
static bool
set_internal_addr(connection_t *c, internal_addr_t *ia)
static bool set_internal_addr(connection_t *c, internal_addr_t *ia)
{
if (ia->attr_set & LELEM(INTERNAL_IP4_ADDRESS)
&& !isanyaddr(&ia->ipaddr))
@@ -241,7 +259,7 @@ set_internal_addr(connection_t *c, internal_addr_t *ia)
return FALSE;
}
/*
/**
* Compute HASH of Mode Config.
*/
static size_t modecfg_hash(u_char *dest, u_char *start, u_char *roof,
@@ -269,14 +287,13 @@ static size_t modecfg_hash(u_char *dest, u_char *start, u_char *roof,
}
/*
/**
* Generate an IKE message containing ModeCfg information (eg: IP, DNS, WINS)
*/
static stf_status
modecfg_build_msg(struct state *st, pb_stream *rbody
, u_int16_t msg_type
, internal_addr_t *ia
, u_int16_t ap_id)
static stf_status modecfg_build_msg(struct state *st, pb_stream *rbody,
u_int16_t msg_type,
internal_addr_t *ia,
u_int16_t ap_id)
{
u_char *r_hash_start, *r_hashval;
@@ -492,11 +509,11 @@ modecfg_build_msg(struct state *st, pb_stream *rbody
return STF_OK;
}
/*
/**
* Send ModeCfg message
*/
static stf_status
modecfg_send_msg(struct state *st, int isama_type, internal_addr_t *ia)
static stf_status modecfg_send_msg(struct state *st, int isama_type,
internal_addr_t *ia)
{
pb_stream msg;
pb_stream rbody;
@@ -550,11 +567,10 @@ modecfg_send_msg(struct state *st, int isama_type, internal_addr_t *ia)
return STF_OK;
}
/*
/**
* Parse a ModeCfg attribute payload
*/
static stf_status
modecfg_parse_attributes(pb_stream *attrs, internal_addr_t *ia)
static stf_status modecfg_parse_attributes(pb_stream *attrs, internal_addr_t *ia)
{
struct isakmp_attribute attr;
pb_stream strattr;
@@ -736,12 +752,11 @@ modecfg_parse_attributes(pb_stream *attrs, internal_addr_t *ia)
return STF_OK;
}
/*
/**
* Parse a ModeCfg message
*/
static stf_status
modecfg_parse_msg(struct msg_digest *md, int isama_type, u_int16_t *isama_id
, internal_addr_t *ia)
static stf_status modecfg_parse_msg(struct msg_digest *md, int isama_type,
u_int16_t *isama_id, internal_addr_t *ia)
{
struct state *const st = md->st;
struct payload_digest *p;
@@ -789,12 +804,12 @@ modecfg_parse_msg(struct msg_digest *md, int isama_type, u_int16_t *isama_id
return STF_IGNORE;
}
/*
/**
* Send ModeCfg request message from client to server in pull mode
*/
stf_status
modecfg_send_request(struct state *st)
stf_status modecfg_send_request(struct state *st)
{
connection_t *c = st->st_connection;
stf_status stat;
internal_addr_t ia;
@@ -802,6 +817,7 @@ modecfg_send_request(struct state *st)
ia.attr_set = LELEM(INTERNAL_IP4_ADDRESS)
| LELEM(INTERNAL_IP4_NETMASK);
ia.ipaddr = c->spd.this.host_srcip;
plog("sending ModeCfg request");
st->st_state = STATE_MODE_CFG_I1;
@@ -818,14 +834,14 @@ modecfg_send_request(struct state *st)
*
* used in ModeCfg pull mode, on the server (responder)
*/
stf_status
modecfg_inR0(struct msg_digest *md)
stf_status modecfg_inR0(struct msg_digest *md)
{
struct state *const st = md->st;
u_int16_t isama_id;
internal_addr_t ia;
bool want_unity_banner;
stf_status stat, stat_build;
host_t *requested_vip;
stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, &ia);
if (stat != STF_OK)
@@ -833,9 +849,20 @@ modecfg_inR0(struct msg_digest *md)
return stat;
}
if (ia.attr_set & LELEM(INTERNAL_IP4_ADDRESS))
{
requested_vip = host_create_from_sockaddr((sockaddr_t*)&ia.ipaddr);
}
else
{
requested_vip = host_create_any(AF_INET);
}
plog("peer requested virtual IP %H", requested_vip);
want_unity_banner = (ia.unity_attr_set & LELEM(UNITY_BANNER - UNITY_BASE)) != LEMPTY;
init_internal_addr(&ia);
get_internal_addr(st->st_connection, &ia);
get_internal_addr(st->st_connection, requested_vip, &ia);
requested_vip->destroy(requested_vip);
if (want_unity_banner)
{
@@ -862,8 +889,7 @@ modecfg_inR0(struct msg_digest *md)
*
* used in ModeCfg pull mode, on the client (initiator)
*/
stf_status
modecfg_inI1(struct msg_digest *md)
stf_status modecfg_inI1(struct msg_digest *md)
{
struct state *const st = md->st;
u_int16_t isama_id;
@@ -883,17 +909,19 @@ modecfg_inI1(struct msg_digest *md)
}
/*
/**
* Send ModeCfg set message from server to client in push mode
*/
stf_status
modecfg_send_set(struct state *st)
stf_status modecfg_send_set(struct state *st)
{
stf_status stat;
internal_addr_t ia;
host_t *vip;
init_internal_addr(&ia);
get_internal_addr(st->st_connection, &ia);
vip = host_create_any(AF_INET);
get_internal_addr(st->st_connection, vip, &ia);
vip->destroy(vip);
#ifdef CISCO_QUIRKS
ia.unity_banner = UNITY_BANNER_STR;
@@ -915,8 +943,7 @@ modecfg_send_set(struct state *st)
*
* used in ModeCfg push mode, on the client (initiator).
*/
stf_status
modecfg_inI0(struct msg_digest *md)
stf_status modecfg_inI0(struct msg_digest *md)
{
struct state *const st = md->st;
u_int16_t isama_id;
@@ -959,8 +986,7 @@ modecfg_inI0(struct msg_digest *md)
*
* used in ModeCfg push mode, on the server (responder)
*/
stf_status
modecfg_inR3(struct msg_digest *md)
stf_status modecfg_inR3(struct msg_digest *md)
{
struct state *const st = md->st;
u_int16_t isama_id;
@@ -978,11 +1004,10 @@ modecfg_inR3(struct msg_digest *md)
return STF_OK;
}
/*
/**
* Send XAUTH credentials request (username + password)
*/
stf_status
xauth_send_request(struct state *st)
stf_status xauth_send_request(struct state *st)
{
stf_status stat;
internal_addr_t ia;
@@ -1006,8 +1031,7 @@ xauth_send_request(struct state *st)
*
* used on the XAUTH client (initiator)
*/
stf_status
xauth_inI0(struct msg_digest *md)
stf_status xauth_inI0(struct msg_digest *md)
{
struct state *const st = md->st;
u_int16_t isama_id;
@@ -1112,8 +1136,7 @@ xauth_inI0(struct msg_digest *md)
*
* used on the XAUTH server (responder)
*/
stf_status
xauth_inR1(struct msg_digest *md)
stf_status xauth_inR1(struct msg_digest *md)
{
struct state *const st = md->st;
u_int16_t isama_id;
@@ -1193,8 +1216,7 @@ xauth_inR1(struct msg_digest *md)
*
* used on the XAUTH client (initiator)
*/
stf_status
xauth_inI1(struct msg_digest *md)
stf_status xauth_inI1(struct msg_digest *md)
{
struct state *const st = md->st;
u_int16_t isama_id;
@@ -1245,8 +1267,7 @@ xauth_inI1(struct msg_digest *md)
*
* used on the XAUTH server (responder)
*/
stf_status
xauth_inR2(struct msg_digest *md)
stf_status xauth_inR2(struct msg_digest *md)
{
struct state *const st = md->st;
u_int16_t isama_id;
+20 -18
View File
@@ -306,24 +306,26 @@ void whack_handle(int whackctlfd)
|| !unpack_str(&msg.left.ca) /* string 4 */
|| !unpack_str(&msg.left.groups) /* string 5 */
|| !unpack_str(&msg.left.updown) /* string 6 */
|| !unpack_str(&msg.left.virt) /* string 7 */
|| !unpack_str(&msg.right.id) /* string 8 */
|| !unpack_str(&msg.right.cert) /* string 9 */
|| !unpack_str(&msg.right.ca) /* string 10 */
|| !unpack_str(&msg.right.groups) /* string 11 */
|| !unpack_str(&msg.right.updown) /* string 12 */
|| !unpack_str(&msg.right.virt) /* string 13 */
|| !unpack_str(&msg.keyid) /* string 14 */
|| !unpack_str(&msg.myid) /* string 15 */
|| !unpack_str(&msg.cacert) /* string 16 */
|| !unpack_str(&msg.ldaphost) /* string 17 */
|| !unpack_str(&msg.ldapbase) /* string 18 */
|| !unpack_str(&msg.crluri) /* string 19 */
|| !unpack_str(&msg.crluri2) /* string 20 */
|| !unpack_str(&msg.ocspuri) /* string 21 */
|| !unpack_str(&msg.ike) /* string 22 */
|| !unpack_str(&msg.esp) /* string 23 */
|| !unpack_str(&msg.sc_data) /* string 24 */
|| !unpack_str(&msg.left.sourceip) /* string 7 */
|| !unpack_str(&msg.left.virt) /* string 8 */
|| !unpack_str(&msg.right.id) /* string 9 */
|| !unpack_str(&msg.right.cert) /* string 10 */
|| !unpack_str(&msg.right.ca) /* string 11 */
|| !unpack_str(&msg.right.groups) /* string 12 */
|| !unpack_str(&msg.right.updown) /* string 13 */
|| !unpack_str(&msg.right.sourceip) /* string 14 */
|| !unpack_str(&msg.right.virt) /* string 15 */
|| !unpack_str(&msg.keyid) /* string 16 */
|| !unpack_str(&msg.myid) /* string 17 */
|| !unpack_str(&msg.cacert) /* string 18 */
|| !unpack_str(&msg.ldaphost) /* string 19 */
|| !unpack_str(&msg.ldapbase) /* string 20 */
|| !unpack_str(&msg.crluri) /* string 21 */
|| !unpack_str(&msg.crluri2) /* string 22 */
|| !unpack_str(&msg.ocspuri) /* string 23 */
|| !unpack_str(&msg.ike) /* string 24 */
|| !unpack_str(&msg.esp) /* string 25 */
|| !unpack_str(&msg.sc_data) /* string 26 */
|| str_roof - next_str != (ptrdiff_t)msg.keyval.len) /* check chunk */
{
ugh = "message from whack contains bad string";