aboutsummaryrefslogtreecommitdiffstats
path: root/src/pluto/modecfg.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pluto/modecfg.c')
-rw-r--r--src/pluto/modecfg.c179
1 files changed, 144 insertions, 35 deletions
diff --git a/src/pluto/modecfg.c b/src/pluto/modecfg.c
index 967a0b2a5..45c7230bc 100644
--- a/src/pluto/modecfg.c
+++ b/src/pluto/modecfg.c
@@ -26,6 +26,7 @@
#include <string.h>
#include <freeswan.h>
+#include <settings.h>
#include "constants.h"
#include "defs.h"
@@ -42,6 +43,8 @@
#include "xauth.h"
#define MAX_XAUTH_TRIES 3
+#define DNS_SERVER_MAX 2
+#define NBNS_SERVER_MAX 2
#define SUPPORTED_ATTR_SET ( LELEM(INTERNAL_IP4_ADDRESS) \
| LELEM(INTERNAL_IP4_NETMASK) \
@@ -54,6 +57,8 @@
#define UNITY_BANNER_STR "Welcome to strongSwan - the Linux VPN Solution!\n"
+extern settings_t *settings;
+
/*
* Addresses assigned (usually via ModeCfg) to the Initiator
*/
@@ -67,8 +72,8 @@ struct internal_addr
/* ModeCfg variables */
ip_address ipaddr;
- ip_address dns[2];
- ip_address wins[2];
+ ip_address dns[DNS_SERVER_MAX];
+ ip_address nbns[NBNS_SERVER_MAX];
char *unity_banner;
@@ -84,6 +89,8 @@ struct internal_addr
static void
init_internal_addr(internal_addr_t *ia)
{
+ int i;
+
ia->attr_set = LEMPTY;
ia->xauth_attr_set = LEMPTY;
ia->xauth_secret.user_name = empty_chunk;
@@ -94,10 +101,18 @@ init_internal_addr(internal_addr_t *ia)
ia->unity_banner = NULL;
anyaddr(AF_INET, &ia->ipaddr);
- anyaddr(AF_INET, &ia->dns[0]);
- anyaddr(AF_INET, &ia->dns[1]);
- anyaddr(AF_INET, &ia->wins[0]);
- anyaddr(AF_INET, &ia->wins[1]);
+
+ /* initialize DNS server information */
+ for (i = 0; i < DNS_SERVER_MAX; i++)
+ {
+ anyaddr(AF_INET, &ia->dns[i]);
+ }
+
+ /* initialize WINS server information */
+ for (i = 0; i < NBNS_SERVER_MAX; i++)
+ {
+ anyaddr(AF_INET, &ia->nbns[i]);
+ }
}
/*
@@ -106,6 +121,8 @@ init_internal_addr(internal_addr_t *ia)
static void
get_internal_addr(struct connection *c, 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 */
@@ -130,13 +147,60 @@ get_internal_addr(struct connection *c, internal_addr_t *ia)
| LELEM(INTERNAL_IP4_NETMASK);
}
- if (!isanyaddr(&ia->dns[0])) /* We got DNS addresses, send them */
- ia->attr_set |= LELEM(INTERNAL_IP4_DNS);
+ /* assign DNS servers */
+ for (i = 1; i <= DNS_SERVER_MAX; i++)
+ {
+ char dns_key[16], *dns_str;
+
+ snprintf(dns_key, sizeof(dns_key), "pluto.dns%d", i);
+ dns_str = settings->get_str(settings, dns_key, NULL);
+ if (dns_str)
+ {
+ err_t ugh;
+ sa_family_t family = strchr(dns_str, ':') ? AF_INET6 : AF_INET;
- if (!isanyaddr(&ia->wins[0])) /* We got WINS addresses, send them */
- ia->attr_set |= LELEM(INTERNAL_IP4_NBNS);
+ ugh = ttoaddr(dns_str, 0, family, &ia->dns[dns_idx]);
+ if (ugh != NULL)
+ {
+ plog("error in DNS server address: %s", ugh);
+ continue;
+ }
+ plog("assigning DNS server %s to peer", dns_str);
+
+ /* differentiate between IP4 and IP6 in modecfg_build_msg() */
+ ia->attr_set |= LELEM(INTERNAL_IP4_DNS);
+ dns_idx++;
+ }
+ }
+
+ /* assign WINS servers */
+ for (i = 1; i <= NBNS_SERVER_MAX; i++)
+ {
+ char nbns_key[16], *nbns_str;
+
+ snprintf(nbns_key, sizeof(nbns_key), "pluto.nbns%d", i);
+ nbns_str = settings->get_str(settings, nbns_key, NULL);
+ if (nbns_str)
+ {
+ err_t ugh;
+ sa_family_t family = strchr(nbns_str, ':') ? AF_INET6 : AF_INET;
+
+ ugh = ttoaddr(nbns_str, 0, family, &ia->nbns[nbns_idx]);
+ if (ugh != NULL)
+ {
+ plog("error in WINS server address: %s", ugh);
+ continue;
+ }
+ plog("assigning NBNS server %s to peer", nbns_str);
+
+ /* differentiate between IP4 and IP6 in modecfg_build_msg() */
+ ia->attr_set |= LELEM(INTERNAL_IP4_NBNS);
+ nbns_idx++;
+ }
+ }
}
+
/*
* Set srcip and client subnet to internal IP address
*/
@@ -218,8 +282,8 @@ modecfg_build_msg(struct state *st, pb_stream *rbody
struct isakmp_mode_attr attrh;
struct isakmp_attribute attr;
pb_stream strattr,attrval;
- int attr_type;
- int dns_idx, wins_idx;
+ int attr_type, dns_attr_type, nbns_attr_type;
+ int dns_idx, nbns_idx;
bool dont_advance;
bool is_xauth_attr_set = ia->xauth_attr_set != LEMPTY;
bool is_unity_attr_set = ia->unity_attr_set != LEMPTY;
@@ -230,11 +294,12 @@ modecfg_build_msg(struct state *st, pb_stream *rbody
attrh.isama_identifier = ap_id;
if (!out_struct(&attrh, &isakmp_attr_desc, rbody, &strattr))
+ {
return STF_INTERNAL_ERROR;
-
+ }
attr_type = 0;
dns_idx = 0;
- wins_idx = 0;
+ nbns_idx = 0;
while (attr_set != LEMPTY || is_xauth_attr_set || is_unity_attr_set)
{
@@ -272,6 +337,20 @@ modecfg_build_msg(struct state *st, pb_stream *rbody
attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TV;
attr.isaat_lv = ia->xauth_status;
}
+ else if (attr_type == INTERNAL_IP4_DNS && !isanyaddr(&ia->dns[dns_idx]))
+ {
+ dns_attr_type = (addrtypeof(&ia->dns[dns_idx]) == AF_INET) ?
+ INTERNAL_IP4_DNS : INTERNAL_IP6_DNS;
+ attr.isaat_af_type = dns_attr_type | ISAKMP_ATTR_AF_TLV;
+
+ }
+ else if (attr_type == INTERNAL_IP4_NBNS && !isanyaddr(&ia->nbns[nbns_idx]))
+ {
+ nbns_attr_type = (addrtypeof(&ia->nbns[nbns_idx]) == AF_INET) ?
+ INTERNAL_IP4_NBNS : INTERNAL_IP6_NBNS;
+ attr.isaat_af_type = nbns_attr_type | ISAKMP_ATTR_AF_TLV;
+
+ }
else
{
attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TLV;
@@ -303,10 +382,14 @@ modecfg_build_msg(struct state *st, pb_stream *rbody
}
#endif
if (st->st_connection->spd.this.client.maskbits == 0)
+ {
mask = 0;
+ }
else
+ {
mask = 0xffffffff * 1;
out_raw(&mask, 4, &attrval, "IP4_mask");
+ }
}
break;
case INTERNAL_IP4_SUBNET:
@@ -318,13 +401,12 @@ modecfg_build_msg(struct state *st, pb_stream *rbody
for (t = 0; t < 4; t++)
{
- if (m < 8)
- mask[t] = bits[m];
- else
- mask[t] = 0xff;
+ mask[t] = (m < 8) ? bits[m] : 0xff;
m -= 8;
if (m < 0)
+ {
m = 0;
+ }
}
len = addrbytesptr(&st->st_connection->spd.this.client.addr, &byte_ptr);
out_raw(byte_ptr, len, &attrval, "IP4_subnet");
@@ -332,23 +414,25 @@ modecfg_build_msg(struct state *st, pb_stream *rbody
}
break;
case INTERNAL_IP4_DNS:
+ case INTERNAL_IP6_DNS:
if (!isanyaddr(&ia->dns[dns_idx]))
{
len = addrbytesptr(&ia->dns[dns_idx++], &byte_ptr);
- out_raw(byte_ptr, len, &attrval, "IP4_dns");
+ out_raw(byte_ptr, len, &attrval, "IP_dns");
}
- if (dns_idx < 2 && !isanyaddr(&ia->dns[dns_idx]))
+ if (dns_idx < DNS_SERVER_MAX && !isanyaddr(&ia->dns[dns_idx]))
{
dont_advance = TRUE;
}
break;
case INTERNAL_IP4_NBNS:
- if (!isanyaddr(&ia->wins[wins_idx]))
+ case INTERNAL_IP6_NBNS:
+ if (!isanyaddr(&ia->nbns[nbns_idx]))
{
- len = addrbytesptr(&ia->wins[wins_idx++], &byte_ptr);
- out_raw(byte_ptr, len, &attrval, "IP4_wins");
+ len = addrbytesptr(&ia->nbns[nbns_idx++], &byte_ptr);
+ out_raw(byte_ptr, len, &attrval, "IP_nbns");
}
- if (wins_idx < 2 && !isanyaddr(&ia->wins[wins_idx]))
+ if (nbns_idx < NBNS_SERVER_MAX && !isanyaddr(&ia->nbns[nbns_idx]))
{
dont_advance = TRUE;
}
@@ -619,7 +703,9 @@ modecfg_parse_msg(struct msg_digest *md, int isama_type, u_int16_t *isama_id
stat = modecfg_parse_attributes(&p->pbs, &ia_candidate);
}
if (stat != STF_OK)
+ {
return stat;
+ }
}
return STF_IGNORE;
}
@@ -642,7 +728,9 @@ modecfg_send_request(struct state *st)
st->st_state = STATE_MODE_CFG_I1;
stat = modecfg_send_msg(st, ISAKMP_CFG_REQUEST, &ia);
if (stat == STF_OK)
+ {
st->st_modecfg.started = TRUE;
+ }
return stat;
}
@@ -662,10 +750,11 @@ modecfg_inR0(struct msg_digest *md)
stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, &ia);
if (stat != STF_OK)
+ {
return stat;
+ }
want_unity_banner = (ia.unity_attr_set & LELEM(UNITY_BANNER - UNITY_BASE)) != LEMPTY;
-
init_internal_addr(&ia);
get_internal_addr(st->st_connection, &ia);
@@ -682,8 +771,9 @@ modecfg_inR0(struct msg_digest *md)
, &ia
, isama_id);
if (stat_build != STF_OK)
+ {
return stat_build;
-
+ }
st->st_msgid = 0;
return STF_OK;
}
@@ -705,8 +795,9 @@ modecfg_inI1(struct msg_digest *md)
stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, &ia);
if (stat != STF_OK)
+ {
return stat;
-
+ }
st->st_modecfg.vars_set = set_internal_addr(st->st_connection, &ia);
st->st_msgid = 0;
return STF_OK;
@@ -734,7 +825,9 @@ modecfg_send_set(struct state *st)
st->st_state = STATE_MODE_CFG_R3;
stat = modecfg_send_msg(st, ISAKMP_CFG_SET, &ia);
if (stat == STF_OK)
+ {
st->st_modecfg.started = TRUE;
+ }
return stat;
}
@@ -756,8 +849,9 @@ modecfg_inI0(struct msg_digest *md)
stat = modecfg_parse_msg(md, ISAKMP_CFG_SET, &isama_id, &ia);
if (stat != STF_OK)
+ {
return stat;
-
+ }
st->st_modecfg.vars_set = set_internal_addr(st->st_connection, &ia);
/* prepare ModeCfg ack which sends zero length attributes */
@@ -774,8 +868,9 @@ modecfg_inI0(struct msg_digest *md)
, &ia
, isama_id);
if (stat_build != STF_OK)
+ {
return stat_build;
-
+ }
st->st_msgid = 0;
return STF_OK;
}
@@ -797,8 +892,9 @@ modecfg_inR3(struct msg_digest *md)
stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, &ia);
if (stat != STF_OK)
+ {
return stat;
-
+ }
st->st_msgid = 0;
return STF_OK;
}
@@ -820,7 +916,9 @@ xauth_send_request(struct state *st)
st->st_state = STATE_XAUTH_R1;
stat = modecfg_send_msg(st, ISAKMP_CFG_REQUEST, &ia);
if (stat == STF_OK)
+ {
st->st_xauth.started = TRUE;
+ }
return stat;
}
@@ -842,8 +940,10 @@ xauth_inI0(struct msg_digest *md)
stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, &ia);
if (stat != STF_OK)
+ {
return stat;
-
+ }
+
/* check XAUTH attributes */
xauth_type_present = (ia.xauth_attr_set & LELEM(XAUTH_TYPE - XAUTH_BASE)) != LEMPTY;
@@ -890,7 +990,9 @@ xauth_inI0(struct msg_digest *md)
ia.xauth_attr_set = LELEM(XAUTH_USER_NAME - XAUTH_BASE)
| LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE);
if (xauth_type_present)
+ {
ia.xauth_attr_set |= LELEM(XAUTH_TYPE - XAUTH_BASE);
+ }
}
else
{
@@ -905,8 +1007,9 @@ xauth_inI0(struct msg_digest *md)
, &ia
, isama_id);
if (stat_build != STF_OK)
+ {
return stat_build;
-
+ }
if (stat == STF_OK)
{
st->st_xauth.started = TRUE;
@@ -942,8 +1045,10 @@ xauth_inR1(struct msg_digest *md)
stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, &ia);
if (stat != STF_OK)
+ {
return stat;
-
+ }
+
/* did the client return an XAUTH FAIL status? */
if ((ia.xauth_attr_set & LELEM(XAUTH_STATUS - XAUTH_BASE)) != LEMPTY)
{
@@ -997,7 +1102,9 @@ xauth_inR1(struct msg_digest *md)
stat_build = modecfg_send_msg(st, ISAKMP_CFG_SET, &ia);
if (stat_build != STF_OK)
+ {
return stat_build;
+ }
return STF_OK;
}
@@ -1033,8 +1140,9 @@ xauth_inI1(struct msg_digest *md)
, &ia
, isama_id);
if (stat_build != STF_OK)
+ {
return stat_build;
-
+ }
if (st->st_xauth.status)
{
st->st_msgid = 0;
@@ -1069,8 +1177,9 @@ xauth_inR2(struct msg_digest *md)
stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, &ia);
if (stat != STF_OK)
+ {
return stat;
-
+ }
st->st_msgid = 0;
if (st->st_xauth.status)
{