merged multi-auth branch back into trunk

This commit is contained in:
Martin Willi
2009-04-14 10:34:24 +00:00
parent 6e5c8d9413
commit a44bb9345f
230 changed files with 6163 additions and 4193 deletions
+50 -22
View File
@@ -17,6 +17,9 @@
#include "eap_mschapv2.h"
#include <ctype.h>
#include <unistd.h>
#include <daemon.h>
#include <library.h>
#include <utils/enumerator.h>
@@ -141,7 +144,7 @@ ENUM_END(mschapv2_error_names, ERROR_CHANGING_PASSWORD);
/* Name we send as authenticator */
#define MSCHAPV2_HOST_NAME "strongSwan"
/* Message sent on success */
#define SUCCESS_MESSAGE " M=Welcome to strongSwan"
#define SUCCESS_MESSAGE " M=Welcome2strongSwan"
/* Message sent on failure */
#define FAILURE_MESSAGE "E=691 R=1 C="
/* Length of the complete failure message */
@@ -366,7 +369,6 @@ static status_t AuthenticatorResponse(chunk_t password_hash_hash,
static const chunk_t magic1 = chunk_from_buf(magic1_data);
static const chunk_t magic2 = chunk_from_buf(magic2_data);
status_t status = FAILED;
chunk_t digest = chunk_empty, concat;
hasher_t *hasher;
@@ -526,6 +528,24 @@ static chunk_t ascii_to_unicode(chunk_t ascii)
return unicode;
}
/**
* sanitize a string for printing
*/
static char* sanitize(char *str)
{
char *pos = str;
while (pos && *pos)
{
if (!isprint(*pos))
{
*pos = '?';
}
pos++;
}
return str;
}
/**
* Returns a chunk of just the username part of the given user identity.
* Note: the chunk points to internal data of the identification.
@@ -535,7 +555,7 @@ static chunk_t extract_username(identification_t* identification)
char *has_domain;
chunk_t id;
id = identification->get_encoding(identification);
has_domain = (char*)memrchr(id.ptr, '\\', id.len);
has_domain = (char*)memchr(id.ptr, '\\', id.len);
if (has_domain)
{
int len;
@@ -625,7 +645,8 @@ static status_t process_peer_challenge(private_eap_mschapv2_t *this,
if (cha->value_size != CHALLENGE_LEN)
{
DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message: invalid challenge size");
DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message: "
"invalid challenge size");
return FAILED;
}
@@ -643,11 +664,11 @@ static status_t process_peer_challenge(private_eap_mschapv2_t *this,
rng->destroy(rng);
shared = charon->credentials->get_shared(charon->credentials,
SHARED_EAP, this->peer, this->server);
SHARED_EAP, this->peer, this->server);
if (shared == NULL)
{
DBG1(DBG_IKE, "no EAP key found for hosts '%D' - '%D'",
this->server, this->peer);
this->server, this->peer);
return NOT_FOUND;
}
@@ -725,7 +746,8 @@ static status_t process_peer_success(private_eap_mschapv2_t *this,
token += 2;
if (strlen(token) != AUTH_RESPONSE_LEN - 2)
{
DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message: invalid auth string");
DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message: "
"invalid auth string");
goto error;
}
hex = chunk_create(token, AUTH_RESPONSE_LEN - 2);
@@ -741,7 +763,8 @@ static status_t process_peer_success(private_eap_mschapv2_t *this,
if (auth_string.ptr == NULL)
{
DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message: auth string missing");
DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message: "
"auth string missing");
goto error;
}
@@ -751,7 +774,7 @@ static status_t process_peer_success(private_eap_mschapv2_t *this,
goto error;
}
DBG1(DBG_IKE, "EAP-MS-CHAPv2 succeeded: '%s'", msg);
DBG1(DBG_IKE, "EAP-MS-CHAPv2 succeeded: '%s'", sanitize(msg));
eap = alloca(len);
eap->code = EAP_RESPONSE;
@@ -780,7 +803,6 @@ static status_t process_peer_failure(private_eap_mschapv2_t *this,
char *message, *token, *msg = NULL;
int message_len, error, retryable;
chunk_t challenge = chunk_empty;
u_int16_t len = SHORT_HEADER_LEN;
data = in->get_data(in);
eap = (eap_mschapv2_header_t*)data.ptr;
@@ -816,7 +838,8 @@ static status_t process_peer_failure(private_eap_mschapv2_t *this,
token += 2;
if (strlen(token) != 2 * CHALLENGE_LEN)
{
DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message: invalid challenge");
DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message:"
"invalid challenge");
goto error;
}
hex = chunk_create(token, 2 * CHALLENGE_LEN);
@@ -836,7 +859,8 @@ static status_t process_peer_failure(private_eap_mschapv2_t *this,
}
enumerator->destroy(enumerator);
DBG1(DBG_IKE, "EAP-MS-CHAPv2 failed with error %N: '%s'", mschapv2_error_names, error, msg);
DBG1(DBG_IKE, "EAP-MS-CHAPv2 failed with error %N: '%s'",
mschapv2_error_names, error, sanitize(msg));
/**
* at this point, if the error is retryable, we MAY retry the authentication
@@ -898,8 +922,8 @@ static status_t process_peer(private_eap_mschapv2_t *this, eap_payload_t *in,
}
default:
{
DBG1(DBG_IKE, "EAP-MS-CHAPv2 received packet with unsupported OpCode (%N)!",
mschapv2_opcode_names, eap->opcode);
DBG1(DBG_IKE, "EAP-MS-CHAPv2 received packet with unsupported "
"OpCode (%N)!", mschapv2_opcode_names, eap->opcode);
break;
}
}
@@ -925,7 +949,8 @@ static status_t process_server_retry(private_eap_mschapv2_t *this,
* so, to clean up our state we just fail with an EAP-Failure.
* this gives an unknown error on the windows side, but is also fine
* with the standard. */
DBG1(DBG_IKE, "EAP-MS-CHAPv2 verification failed: maximum number of retries reached");
DBG1(DBG_IKE, "EAP-MS-CHAPv2 verification failed: "
"maximum number of retries reached");
return FAILED;
}
@@ -977,6 +1002,7 @@ static status_t process_server_response(private_eap_mschapv2_t *this,
identification_t *userid;
shared_key_t *shared;
int name_len;
char buf[256];
data = in->get_data(in);
eap = (eap_mschapv2_header_t*)data.ptr;
@@ -991,10 +1017,10 @@ static status_t process_server_response(private_eap_mschapv2_t *this,
peer_challenge = chunk_create(res->response.peer_challenge, CHALLENGE_LEN);
name_len = min(data.len - RESPONSE_PAYLOAD_LEN, 255);
userid = identification_create_from_encoding(ID_EAP,
chunk_create(res->name, name_len));
snprintf(buf, sizeof(buf), "%.*s", name_len, res->name);
userid = identification_create_from_string(buf);
DBG2(DBG_IKE, "EAP-MS-CHAPv2 username: '%D'", userid);
username = extract_username(userid);
DBG2(DBG_IKE, "EAP-MS-CHAPv2 username: '%.*s'", name_len, res->name);
shared = charon->credentials->get_shared(charon->credentials,
SHARED_EAP, this->server, userid);
@@ -1015,7 +1041,8 @@ static status_t process_server_response(private_eap_mschapv2_t *this,
password = ascii_to_unicode(shared->get_key(shared));
shared->destroy(shared);
if (GenerateStuff(this, this->challenge, peer_challenge, username, password) != SUCCESS)
if (GenerateStuff(this, this->challenge, peer_challenge,
username, password) != SUCCESS)
{
DBG1(DBG_IKE, "EAP-MS-CHAPv2 verification failed");
userid->destroy(userid);
@@ -1063,7 +1090,8 @@ static status_t process_server(private_eap_mschapv2_t *this, eap_payload_t *in,
if (this->identifier != in->get_identifier(in))
{
DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message: unexpected identifier");
DBG1(DBG_IKE, "received invalid EAP-MS-CHAPv2 message: "
"unexpected identifier");
return FAILED;
}
@@ -1092,8 +1120,8 @@ static status_t process_server(private_eap_mschapv2_t *this, eap_payload_t *in,
}
default:
{
DBG1(DBG_IKE, "EAP-MS-CHAPv2 received packet with unsupported OpCode (%N)!",
mschapv2_opcode_names, eap->opcode);
DBG1(DBG_IKE, "EAP-MS-CHAPv2 received packet with unsupported "
"OpCode (%N)!", mschapv2_opcode_names, eap->opcode);
break;
}
}
@@ -52,13 +52,13 @@ static bool get_triplet(private_eap_sim_file_card_t *this,
identification_t *id;
char *c_rand, *c_sres, *c_kc;
DBG1(DBG_CFG, "looking for rand: %b", rand, RAND_LEN);
DBG2(DBG_CFG, "looking for rand: %b", rand, RAND_LEN);
enumerator = this->triplets->create_enumerator(this->triplets);
while (enumerator->enumerate(enumerator, &id, &c_rand, &c_sres, &c_kc))
{
DBG1(DBG_CFG, "found triplet: %b %b %b", c_rand, RAND_LEN, c_sres, SRES_LEN, c_kc, KC_LEN);
DBG2(DBG_CFG, "found triplet: rand %b\nsres %b\n kc %b",
c_rand, RAND_LEN, c_sres, SRES_LEN, c_kc, KC_LEN);
if (memeq(c_rand, rand, RAND_LEN))
{
memcpy(sres, c_sres, SRES_LEN);
@@ -196,8 +196,7 @@ static void read_triplets(private_eap_sim_file_triplets_t *this, char *path)
switch (i++)
{
case 0: /* IMSI */
triplet->imsi = identification_create_from_encoding(ID_EAP,
chunk_create(token, strlen(token)));
triplet->imsi = identification_create_from_string(token);
continue;
case 1: /* rand */
parse_token(triplet->rand, token, RAND_LEN);
@@ -221,7 +220,7 @@ static void read_triplets(private_eap_sim_file_triplets_t *this, char *path)
continue;
}
DBG1(DBG_CFG, "triplet: imsi %D\nrand %b\nsres %b\nkc %b",
DBG2(DBG_CFG, "triplet: imsi %D\nrand %b\nsres %b\nkc %b",
triplet->imsi, triplet->rand, RAND_LEN,
triplet->sres, SRES_LEN, triplet->kc, KC_LEN);
@@ -57,9 +57,14 @@ struct private_load_tester_config_t {
proposal_t *proposal;
/**
* Authentication method to use
* Authentication method(s) to use/expect from initiator
*/
auth_class_t class;
char *initiator_auth;
/**
* Authentication method(s) use/expected from responder
*/
char *responder_auth;
/**
* incremental numbering of generated configs
@@ -67,6 +72,97 @@ struct private_load_tester_config_t {
u_int num;
};
/**
* Generate auth config from string
*/
static void generate_auth_cfg(private_load_tester_config_t *this, char *str,
peer_cfg_t *peer_cfg, bool local, int num)
{
enumerator_t *enumerator;
auth_cfg_t *auth;
identification_t *id;
auth_class_t class;
eap_type_t type;
char buf[128];
int rnd = 0;
enumerator = enumerator_create_token(str, "|", " ");
while (enumerator->enumerate(enumerator, &str))
{
auth = auth_cfg_create();
rnd++;
if (streq(str, "psk"))
{ /* PSK authentication, use FQDNs */
class = AUTH_CLASS_PSK;
if ((local && !num) || (!local && num))
{
id = identification_create_from_string("srv.strongswan.org");
}
else if (local)
{
snprintf(buf, sizeof(buf), "c%d-r%d.strongswan.org", num, rnd);
id = identification_create_from_string(buf);
}
else
{
id = identification_create_from_string("*.strongswan.org");
}
}
else if (strneq(str, "eap", strlen("eap")))
{ /* EAP authentication, use a NAI */
class = AUTH_CLASS_EAP;
if (*(str + strlen("eap")) == '-')
{
type = eap_type_from_string(str + strlen("eap-"));
if (type)
{
auth->add(auth, AUTH_RULE_EAP_TYPE, type);
}
}
if (local && num)
{
snprintf(buf, sizeof(buf), "1%.10d%[email protected]", num, rnd);
id = identification_create_from_string(buf);
}
else
{
id = identification_create_from_encoding(ID_ANY, chunk_empty);
}
}
else
{
if (!streq(str, "pubkey"))
{
DBG1(DBG_CFG, "invalid authentication: '%s', fallback to pubkey",
str);
}
/* certificate authentication, use distinguished names */
class = AUTH_CLASS_PUBKEY;
if ((local && !num) || (!local && num))
{
id = identification_create_from_string(
"CN=srv, OU=load-test, O=strongSwan");
}
else if (local)
{
snprintf(buf, sizeof(buf),
"CN=c%d-r%d, OU=load-test, O=strongSwan", num, rnd);
id = identification_create_from_string(buf);
}
else
{
id = identification_create_from_string(
"CN=*, OU=load-test, O=strongSwan");
}
}
auth->add(auth, AUTH_RULE_AUTH_CLASS, class);
auth->add(auth, AUTH_RULE_IDENTITY, id);
peer_cfg->add_auth_cfg(peer_cfg, auth, local);
}
enumerator->destroy(enumerator);
}
/**
* Generate a new initiator config, num = 0 for responder config
*/
@@ -76,36 +172,26 @@ static peer_cfg_t* generate_config(private_load_tester_config_t *this, uint num)
child_cfg_t *child_cfg;
peer_cfg_t *peer_cfg;
traffic_selector_t *ts;
auth_info_t *auth;
identification_t *local, *remote;
proposal_t *proposal;
char buf[128];
if (num)
{ /* initiator */
snprintf(buf, sizeof(buf), "CN=cli-%d, OU=load-test, O=strongSwan", num);
local = identification_create_from_string(buf);
snprintf(buf, sizeof(buf), "CN=srv, OU=load-test, O=strongSwan", num);
remote = identification_create_from_string(buf);
}
else
{ /* responder */
local = identification_create_from_string(
"CN=srv, OU=load-test, O=strongSwan");
remote = identification_create_from_string(
"CN=*, OU=load-test, O=strongSwan");
}
ike_cfg = ike_cfg_create(FALSE, FALSE, "0.0.0.0", this->remote);
ike_cfg->add_proposal(ike_cfg, this->proposal->clone(this->proposal));
peer_cfg = peer_cfg_create("load-test", 2, ike_cfg, local, remote,
peer_cfg = peer_cfg_create("load-test", 2, ike_cfg,
CERT_SEND_IF_ASKED, UNIQUE_NO, 1, 0, 0, /* keytries, rekey, reauth */
0, 0, FALSE, 0, /* jitter, overtime, mobike, dpddelay */
this->vip ? this->vip->clone(this->vip) : NULL,
this->pool, FALSE, NULL, NULL);
auth = peer_cfg->get_auth(peer_cfg);
auth->add_item(auth, AUTHN_AUTH_CLASS, &this->class);
child_cfg = child_cfg_create("load-test", 600, 400, 100, NULL, TRUE,
if (num)
{ /* initiator */
generate_auth_cfg(this, this->initiator_auth, peer_cfg, TRUE, num);
generate_auth_cfg(this, this->responder_auth, peer_cfg, FALSE, num);
}
else
{ /* responder */
generate_auth_cfg(this, this->responder_auth, peer_cfg, TRUE, num);
generate_auth_cfg(this, this->initiator_auth, peer_cfg, FALSE, num);
}
child_cfg = child_cfg_create("load-test", 1200, 600, 0, NULL, TRUE,
MODE_TUNNEL, ACTION_NONE, ACTION_NONE, FALSE);
proposal = proposal_create_from_string(PROTO_ESP, "aes128-sha1");
child_cfg->add_proposal(child_cfg, proposal);
@@ -169,7 +255,6 @@ static void destroy(private_load_tester_config_t *this)
load_tester_config_t *load_tester_config_create()
{
private_load_tester_config_t *this = malloc_thing(private_load_tester_config_t);
char *authstr;
this->public.backend.create_peer_cfg_enumerator = (enumerator_t*(*)(backend_t*, identification_t *me, identification_t *other))create_peer_cfg_enumerator;
this->public.backend.create_ike_cfg_enumerator = (enumerator_t*(*)(backend_t*, host_t *me, host_t *other))create_ike_cfg_enumerator;
@@ -195,16 +280,10 @@ load_tester_config_t *load_tester_config_create()
this->proposal = proposal_create_from_string(PROTO_IKE,
"aes128-sha1-modp768");
}
authstr = lib->settings->get_str(lib->settings,
"charon.plugins.load_tester.auth", "pubkey");
if (streq(authstr, "psk"))
{
this->class = AUTH_CLASS_PSK;
}
else
{
this->class = AUTH_CLASS_PUBKEY;
}
this->initiator_auth = lib->settings->get_str(lib->settings,
"charon.plugins.load_tester.initiator_auth", "pubkey");
this->responder_auth = lib->settings->get_str(lib->settings,
"charon.plugins.load_tester.responder_auth", "pubkey");
this->num = 1;
this->peer_cfg = generate_config(this, 0);
+1 -3
View File
@@ -259,9 +259,7 @@ static void set_username_password(private_nm_creds_t *this, identification_t *id
{
this->lock->write_lock(this->lock);
DESTROY_IF(this->user);
/* for EAP authentication, we use always use ID_EAP type */
this->user = identification_create_from_encoding(ID_EAP,
id->get_encoding(id));
this->user = id->clone(id);
free(this->pass);
this->pass = password ? strdup(password) : NULL;
this->lock->unlock(this->lock);
+11 -6
View File
@@ -151,7 +151,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
child_cfg_t *child_cfg;
traffic_selector_t *ts;
ike_sa_t *ike_sa;
auth_info_t *auth;
auth_cfg_t *auth;
auth_class_t auth_class = AUTH_CLASS_EAP;
certificate_t *cert = NULL;
bool agent = FALSE;
@@ -223,8 +223,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
str = nm_setting_vpn_get_data_item(settings, "user");
if (str)
{
user = identification_create_from_encoding(ID_KEY_ID,
chunk_create(str, strlen(str)));
user = identification_create_from_string(str);
str = nm_setting_vpn_get_secret(settings, "password");
creds->set_username_password(creds, user, (char*)str);
}
@@ -322,15 +321,21 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
ike_cfg = ike_cfg_create(TRUE, encap, "0.0.0.0", (char*)address);
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
peer_cfg = peer_cfg_create(CONFIG_NAME, 2, ike_cfg,
user, gateway->clone(gateway),
CERT_SEND_IF_ASKED, UNIQUE_REPLACE, 1, /* keyingtries */
36000, 0, /* rekey 10h, reauth none */
600, 600, /* jitter, over 10min */
TRUE, 0, /* mobike, DPD */
virtual ? host_create_from_string("0.0.0.0", 0) : NULL,
NULL, FALSE, NULL, NULL); /* pool, mediation */
auth = peer_cfg->get_auth(peer_cfg);
auth->add_item(auth, AUTHN_AUTH_CLASS, &auth_class);
auth = auth_cfg_create();
auth->add(auth, AUTH_RULE_AUTH_CLASS, auth_class);
auth->add(auth, AUTH_RULE_IDENTITY, user);
peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE);
auth = auth_cfg_create();
auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
auth->add(auth, AUTH_RULE_IDENTITY, gateway->clone(gateway));
peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
child_cfg = child_cfg_create(CONFIG_NAME,
10800, 10200, /* lifetime 3h, rekey 2h50min */
300, /* jitter 5min */
+5 -4
View File
@@ -294,8 +294,9 @@ static void request_query_config(xmlTextReaderPtr reader, xmlTextWriterPtr write
/* <configlist> */
xmlTextWriterStartElement(writer, "configlist");
enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends);
while (enumerator->enumerate(enumerator, (void**)&peer_cfg))
enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends,
NULL, NULL, NULL, NULL);
while (enumerator->enumerate(enumerator, &peer_cfg))
{
enumerator_t *children;
child_cfg_t *child_cfg;
@@ -310,8 +311,8 @@ static void request_query_config(xmlTextReaderPtr reader, xmlTextWriterPtr write
/* <peerconfig> */
xmlTextWriterStartElement(writer, "peerconfig");
xmlTextWriterWriteElement(writer, "name", peer_cfg->get_name(peer_cfg));
write_id(writer, "local", peer_cfg->get_my_id(peer_cfg));
write_id(writer, "remote", peer_cfg->get_other_id(peer_cfg));
/* TODO: write auth_cfgs */
/* <ikeconfig> */
ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
-5
View File
@@ -401,11 +401,6 @@ static enumerator_t *create_lease_query(char *filter)
{
id = identification_create_from_string(value);
}
if (!id)
{
fprintf(stderr, "invalid 'id' in filter string.\n");
exit(-1);
}
break;
case FIL_ADDR:
if (value)
+2 -2
View File
@@ -179,7 +179,7 @@ static host_t *get_address(private_sql_attribute_t *this, char *name,
*/
static host_t* acquire_address(private_sql_attribute_t *this,
char *name, identification_t *id,
auth_info_t *auth, host_t *requested)
host_t *requested)
{
enumerator_t *enumerator;
u_int pool, timeout, identity;
@@ -263,7 +263,7 @@ sql_attribute_t *sql_attribute_create(database_t *db)
private_sql_attribute_t *this = malloc_thing(private_sql_attribute_t);
time_t now = time(NULL);
this->public.provider.acquire_address = (host_t*(*)(attribute_provider_t *this, char*, identification_t *,auth_info_t *, host_t *))acquire_address;
this->public.provider.acquire_address = (host_t*(*)(attribute_provider_t *this, char*, identification_t *, host_t *))acquire_address;
this->public.provider.release_address = (bool(*)(attribute_provider_t *this, char*,host_t *, identification_t*))release_address;
this->public.destroy = (void(*)(sql_attribute_t*))destroy;
+12 -6
View File
@@ -267,7 +267,7 @@ static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e,
peer_cfg_t *peer_cfg, *mediated_cfg;
ike_cfg_t *ike;
host_t *vip = NULL;
auth_info_t *auth;
auth_cfg_t *auth;
local_id = identification_create_from_encoding(l_type, l_data);
remote_id = identification_create_from_encoding(r_type, r_data);
@@ -291,20 +291,26 @@ static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e,
if (ike)
{
peer_cfg = peer_cfg_create(
name, 2, ike, local_id, remote_id, cert_policy, uniqueid,
name, 2, ike, cert_policy, uniqueid,
keyingtries, rekeytime, reauthtime, jitter, overtime,
mobike, dpd_delay, vip, pool,
mediation, mediated_cfg, peer_id);
auth = peer_cfg->get_auth(peer_cfg);
auth->add_item(auth, AUTHN_AUTH_CLASS, &auth_method);
auth = auth_cfg_create();
auth->add(auth, AUTH_RULE_AUTH_CLASS, auth_method);
auth->add(auth, AUTH_RULE_IDENTITY, local_id->clone(local_id));
peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE);
auth = auth_cfg_create();
auth->add(auth, AUTH_RULE_IDENTITY, remote_id->clone(remote_id));
if (eap_type)
{
auth->add_item(auth, AUTHN_EAP_TYPE, &eap_type);
auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
auth->add(auth, AUTH_RULE_EAP_TYPE, eap_type);
if (eap_vendor)
{
auth->add_item(auth, AUTHN_EAP_VENDOR, &eap_vendor);
auth->add(auth, AUTH_RULE_EAP_VENDOR, eap_vendor);
}
}
peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
add_child_cfgs(this, peer_cfg, id);
return peer_cfg;
}
+2 -2
View File
@@ -191,7 +191,7 @@ int host2offset(pool_t *pool, host_t *addr)
*/
static host_t* acquire_address(private_stroke_attribute_t *this,
char *name, identification_t *id,
auth_info_t *auth, host_t *requested)
host_t *requested)
{
pool_t *pool;
uintptr_t offset = 0;
@@ -530,7 +530,7 @@ stroke_attribute_t *stroke_attribute_create()
{
private_stroke_attribute_t *this = malloc_thing(private_stroke_attribute_t);
this->public.provider.acquire_address = (host_t*(*)(attribute_provider_t *this, char*, identification_t *,auth_info_t *, host_t *))acquire_address;
this->public.provider.acquire_address = (host_t*(*)(attribute_provider_t *this, char*, identification_t *,host_t *))acquire_address;
this->public.provider.release_address = (bool(*)(attribute_provider_t *this, char*,host_t *, identification_t*))release_address;
this->public.add_pool = (void(*)(stroke_attribute_t*, stroke_msg_t *msg))add_pool;
this->public.del_pool = (void(*)(stroke_attribute_t*, stroke_msg_t *msg))del_pool;
+343 -355
View File
@@ -54,49 +54,6 @@ struct private_stroke_config_t {
stroke_cred_t *cred;
};
/**
* data to pass peer_filter
*/
typedef struct {
private_stroke_config_t *this;
identification_t *me;
identification_t *other;
} peer_data_t;
/**
* destroy id enumerator data and unlock list
*/
static void peer_data_destroy(peer_data_t *data)
{
data->this->mutex->unlock(data->this->mutex);
free(data);
}
/**
* filter function for peer configs
*/
static bool peer_filter(peer_data_t *data, peer_cfg_t **in, peer_cfg_t **out)
{
bool match_me = FALSE, match_other = FALSE;
identification_t *me, *other;
me = (*in)->get_my_id(*in);
other = (*in)->get_other_id(*in);
/* own ID may have wildcards in data (no IDr payload) or in config */
match_me = (!data->me || data->me->matches(data->me, me) ||
me->matches(me, data->me));
/* others ID has wildcards in config only */
match_other = (!data->other || data->other->matches(data->other, other));
if (match_me && match_other)
{
*out = *in;
return TRUE;
}
return FALSE;
}
/**
* Implementation of backend_t.create_peer_cfg_enumerator.
*/
@@ -104,41 +61,15 @@ static enumerator_t* create_peer_cfg_enumerator(private_stroke_config_t *this,
identification_t *me,
identification_t *other)
{
peer_data_t *data;
data = malloc_thing(peer_data_t);
data->this = this;
data->me = me;
data->other = other;
this->mutex->lock(this->mutex);
return enumerator_create_filter(this->list->create_enumerator(this->list),
(void*)peer_filter, data,
(void*)peer_data_destroy);
}
/**
* data to pass ike_filter
*/
typedef struct {
private_stroke_config_t *this;
host_t *me;
host_t *other;
} ike_data_t;
/**
* destroy id enumerator data and unlock list
*/
static void ike_data_destroy(ike_data_t *data)
{
data->this->mutex->unlock(data->this->mutex);
free(data);
return enumerator_create_cleaner(this->list->create_enumerator(this->list),
(void*)this->mutex->unlock, this->mutex);
}
/**
* filter function for ike configs
*/
static bool ike_filter(ike_data_t *data, peer_cfg_t **in, ike_cfg_t **out)
static bool ike_filter(void *data, peer_cfg_t **in, ike_cfg_t **out)
{
*out = (*in)->get_ike_cfg(*in);
return TRUE;
@@ -150,17 +81,10 @@ static bool ike_filter(ike_data_t *data, peer_cfg_t **in, ike_cfg_t **out)
static enumerator_t* create_ike_cfg_enumerator(private_stroke_config_t *this,
host_t *me, host_t *other)
{
ike_data_t *data;
data = malloc_thing(ike_data_t);
data->this = this;
data->me = me;
data->other = other;
this->mutex->lock(this->mutex);
return enumerator_create_filter(this->list->create_enumerator(this->list),
(void*)ike_filter, data,
(void*)ike_data_destroy);
(void*)ike_filter, this->mutex,
(void*)this->mutex->unlock);
}
/**
@@ -171,56 +95,40 @@ static peer_cfg_t *get_peer_cfg_by_name(private_stroke_config_t *this, char *nam
enumerator_t *e1, *e2;
peer_cfg_t *current, *found = NULL;
child_cfg_t *child;
this->mutex->lock(this->mutex);
e1 = this->list->create_enumerator(this->list);
while (e1->enumerate(e1, &current))
{
/* compare peer_cfgs name first */
if (streq(current->get_name(current), name))
{
found = current;
found->get_ref(found);
break;
}
/* compare all child_cfg names otherwise */
e2 = current->create_child_cfg_enumerator(current);
while (e2->enumerate(e2, &child))
{
if (streq(child->get_name(child), name))
{
found = current;
found->get_ref(found);
break;
}
}
e2->destroy(e2);
if (found)
{
break;
}
/* compare peer_cfgs name first */
if (streq(current->get_name(current), name))
{
found = current;
found->get_ref(found);
break;
}
/* compare all child_cfg names otherwise */
e2 = current->create_child_cfg_enumerator(current);
while (e2->enumerate(e2, &child))
{
if (streq(child->get_name(child), name))
{
found = current;
found->get_ref(found);
break;
}
}
e2->destroy(e2);
if (found)
{
break;
}
}
e1->destroy(e1);
this->mutex->unlock(this->mutex);
return found;
}
/**
* check if a certificate has an ID
*/
static identification_t *update_peerid(certificate_t *cert, identification_t *id)
{
if (id->get_type(id) == ID_ANY || !cert->has_subject(cert, id))
{
DBG1(DBG_CFG, " peerid %D not confirmed by certificate, "
"defaulting to subject DN", id);
id->destroy(id);
id = cert->get_subject(cert);
return id->clone(id);
}
return id;
}
/**
* parse a proposal string, either into ike_cfg or child_cfg
*/
@@ -332,45 +240,303 @@ static ike_cfg_t *build_ike_cfg(private_stroke_config_t *this, stroke_msg_t *msg
add_proposals(this, msg->add_conn.algorithms.ike, ike_cfg, NULL);
return ike_cfg;
}
/**
* Add CRL constraint to config
*/
static void build_crl_policy(auth_cfg_t *cfg, bool local, int policy)
{
/* CRL/OCSP policy, for remote config only */
if (!local)
{
switch (policy)
{
case CRL_STRICT_YES:
/* if yes, we require a GOOD validation */
cfg->add(cfg, AUTH_RULE_CRL_VALIDATION, VALIDATION_GOOD);
break;
case CRL_STRICT_IFURI:
/* for ifuri, a SKIPPED validation is sufficient */
cfg->add(cfg, AUTH_RULE_CRL_VALIDATION, VALIDATION_SKIPPED);
break;
default:
break;
}
}
}
/**
* build authentication config
*/
static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this,
stroke_msg_t *msg, bool local, bool primary)
{
identification_t *identity;
certificate_t *certificate;
char *auth, *id, *cert, *ca;
stroke_end_t *end, *other_end;
auth_cfg_t *cfg;
char eap_buf[32];
/* select strings */
if (local)
{
end = &msg->add_conn.me;
other_end = &msg->add_conn.other;
}
else
{
end = &msg->add_conn.other;
other_end = &msg->add_conn.me;
}
if (primary)
{
auth = end->auth;
id = end->id;
if (!id)
{ /* leftid/rightid fallback to address */
id = end->address;
}
cert = end->cert;
ca = end->ca;
if (ca && streq(ca, "%same"))
{
ca = other_end->ca;
}
}
else
{
auth = end->auth2;
id = end->id2;
if (local && !id)
{ /* leftid2 falls back to leftid */
id = end->id;
}
cert = end->cert2;
ca = end->ca2;
if (ca && streq(ca, "%same"))
{
ca = other_end->ca2;
}
}
if (!auth)
{
if (primary)
{
if (local)
{ /* "leftauth" not defined, fall back to deprecated "authby" */
switch (msg->add_conn.auth_method)
{
default:
case AUTH_CLASS_PUBKEY:
auth = "pubkey";
break;
case AUTH_CLASS_PSK:
auth = "psk";
break;
case AUTH_CLASS_EAP:
auth = "eap";
break;
}
}
else
{ /* "rightauth" not defined, fall back to deprecated "eap" */
if (msg->add_conn.eap_type)
{
if (msg->add_conn.eap_vendor)
{
snprintf(eap_buf, sizeof(eap_buf), "eap-%d-%d",
msg->add_conn.eap_type,
msg->add_conn.eap_vendor);
}
else
{
snprintf(eap_buf, sizeof(eap_buf), "eap-%d",
msg->add_conn.eap_type);
}
auth = eap_buf;
}
else
{ /* not EAP => no constraints for this peer */
auth = "any";
}
}
}
else
{ /* no second authentication round, fine */
return NULL;
}
}
cfg = auth_cfg_create();
/* add identity and peer certifcate */
identity = identification_create_from_string(id);
if (cert)
{
certificate = this->cred->load_peer(this->cred, cert);
if (certificate)
{
if (local)
{
this->ca->check_for_hash_and_url(this->ca, certificate);
}
cfg->add(cfg, AUTH_RULE_SUBJECT_CERT, certificate);
if (identity->get_type(identity) == ID_ANY ||
!certificate->has_subject(certificate, identity))
{
DBG1(DBG_CFG, " peerid %D not confirmed by certificate, "
"defaulting to subject DN: %D", identity,
certificate->get_subject(certificate));
identity->destroy(identity);
identity = certificate->get_subject(certificate);
identity = identity->clone(identity);
}
}
}
cfg->add(cfg, AUTH_RULE_IDENTITY, identity);
/* CA constraint */
if (ca)
{
identity = identification_create_from_string(ca);
certificate = charon->credentials->get_cert(charon->credentials,
CERT_X509, KEY_ANY, identity, TRUE);
identity->destroy(identity);
if (certificate)
{
cfg->add(cfg, AUTH_RULE_CA_CERT, certificate);
}
else
{
DBG1(DBG_CFG, "CA certificate %s not found, discarding CA "
"constraint", ca);
}
}
/* AC groups */
if (end->groups)
{
enumerator_t *enumerator;
char *group;
enumerator = enumerator_create_token(end->groups, ",", " ");
while (enumerator->enumerate(enumerator, &group))
{
identity = identification_create_from_encoding(ID_IETF_ATTR_STRING,
chunk_create(group, strlen(group)));
cfg->add(cfg, AUTH_RULE_AC_GROUP, identity);
}
enumerator->destroy(enumerator);
}
/* authentication metod (class, actually) */
if (streq(auth, "pubkey") ||
streq(auth, "rsasig") || streq(auth, "rsa") ||
streq(auth, "ecdsasig") || streq(auth, "ecdsa"))
{
cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
build_crl_policy(cfg, local, msg->add_conn.crl_policy);
}
else if (streq(auth, "psk") || streq(auth, "secret"))
{
cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
}
else if (strneq(auth, "eap", 3))
{
enumerator_t *enumerator;
char *str;
int i = 0, type = 0, vendor;
cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
/* parse EAP string, format: eap[-type[-vendor]] */
enumerator = enumerator_create_token(auth, "-", " ");
while (enumerator->enumerate(enumerator, &str))
{
switch (i)
{
case 1:
type = eap_type_from_string(str);
if (!type)
{
type = atoi(str);
if (!type)
{
DBG1(DBG_CFG, "unknown EAP method: %s", str);
break;
}
}
cfg->add(cfg, AUTH_RULE_EAP_TYPE, type);
break;
case 2:
if (type)
{
vendor = atoi(str);
if (vendor)
{
cfg->add(cfg, AUTH_RULE_EAP_VENDOR, vendor);
}
else
{
DBG1(DBG_CFG, "unknown EAP vendor: %s", str);
}
}
break;
default:
break;
}
i++;
}
enumerator->destroy(enumerator);
if (msg->add_conn.eap_identity)
{
if (streq(msg->add_conn.eap_identity, "%identity"))
{
identity = identification_create_from_encoding(ID_ANY,
chunk_empty);
}
else
{
identity = identification_create_from_string(
msg->add_conn.eap_identity);
}
cfg->add(cfg, AUTH_RULE_EAP_IDENTITY, identity);
}
}
else
{
if (!streq(auth, "any"))
{
DBG1(DBG_CFG, "authentication method %s unknown, fallback to any",
auth);
}
build_crl_policy(cfg, local, msg->add_conn.crl_policy);
}
return cfg;
}
/**
* build a peer_cfg from a stroke msg
*/
static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
stroke_msg_t *msg, ike_cfg_t *ike_cfg,
identification_t **my_issuer,
identification_t **other_issuer)
stroke_msg_t *msg, ike_cfg_t *ike_cfg)
{
identification_t *me, *other, *peer_id = NULL;
identification_t *peer_id = NULL;
peer_cfg_t *mediated_by = NULL;
host_t *vip = NULL;
certificate_t *cert;
unique_policy_t unique;
u_int32_t rekey = 0, reauth = 0, over, jitter;
me = identification_create_from_string(msg->add_conn.me.id ?
msg->add_conn.me.id : msg->add_conn.me.address);
if (!me)
{
DBG1(DBG_CFG, "invalid ID: %s\n", msg->add_conn.me.id);
return NULL;
}
other = identification_create_from_string(msg->add_conn.other.id ?
msg->add_conn.other.id : msg->add_conn.other.address);
if (!other)
{
DBG1(DBG_CFG, "invalid ID: %s\n", msg->add_conn.other.id);
me->destroy(me);
return NULL;
}
peer_cfg_t *peer_cfg;
auth_cfg_t *auth_cfg;
#ifdef ME
if (msg->add_conn.ikeme.mediation && msg->add_conn.ikeme.mediated_by)
{
DBG1(DBG_CFG, "a mediation connection cannot be a"
" mediated connection at the same time, aborting");
me->destroy(me);
other->destroy(other);
return NULL;
}
@@ -388,8 +554,6 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
{
DBG1(DBG_CFG, "mediation connection '%s' not found, aborting",
msg->add_conn.ikeme.mediated_by);
me->destroy(me);
other->destroy(other);
return NULL;
}
@@ -399,56 +563,19 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
"no mediation connection, aborting",
msg->add_conn.ikeme.mediated_by, msg->add_conn.name);
mediated_by->destroy(mediated_by);
me->destroy(me);
other->destroy(other);
return NULL;
}
}
if (msg->add_conn.ikeme.peerid)
{
peer_id = identification_create_from_string(msg->add_conn.ikeme.peerid);
if (!peer_id)
if (msg->add_conn.ikeme.peerid)
{
DBG1(DBG_CFG, "invalid peer ID: %s\n", msg->add_conn.ikeme.peerid);
mediated_by->destroy(mediated_by);
me->destroy(me);
other->destroy(other);
return NULL;
peer_id = identification_create_from_string(msg->add_conn.ikeme.peerid);
}
else if (msg->add_conn.other.id)
{
peer_id = identification_create_from_string(msg->add_conn.other.id);
}
}
else
{
/* no peer ID supplied, assume right ID */
peer_id = other->clone(other);
}
#endif /* ME */
if (msg->add_conn.me.cert)
{
cert = this->cred->load_peer(this->cred, msg->add_conn.me.cert);
if (cert)
{
identification_t *issuer = cert->get_issuer(cert);
*my_issuer = issuer->clone(issuer);
this->ca->check_for_hash_and_url(this->ca, cert);
me = update_peerid(cert, me);
cert->destroy(cert);
}
}
if (msg->add_conn.other.cert)
{
cert = this->cred->load_peer(this->cred, msg->add_conn.other.cert);
if (cert)
{
identification_t *issuer = cert->get_issuer(cert);
*other_issuer = issuer->clone(issuer);
other = update_peerid(cert, other);
cert->destroy(cert);
}
}
jitter = msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100;
over = msg->add_conn.rekey.margin;
if (msg->add_conn.rekey.reauth)
@@ -512,179 +639,45 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
/* other.sourceip is managed in stroke_attributes. If it is set, we define
* the pool name as the connection name, which the attribute provider
* uses to serve pool addresses. */
return peer_cfg_create(msg->add_conn.name,
msg->add_conn.ikev2 ? 2 : 1, ike_cfg, me, other,
peer_cfg = peer_cfg_create(msg->add_conn.name,
msg->add_conn.ikev2 ? 2 : 1, ike_cfg,
msg->add_conn.me.sendcert, unique,
msg->add_conn.rekey.tries, rekey, reauth, jitter, over,
msg->add_conn.mobike, msg->add_conn.dpd.delay,
vip, msg->add_conn.other.sourceip_size ?
msg->add_conn.name : msg->add_conn.other.sourceip,
msg->add_conn.ikeme.mediation, mediated_by, peer_id);
}
/**
* fill in auth_info from stroke message
*/
static void build_auth_info(private_stroke_config_t *this,
stroke_msg_t *msg, auth_info_t *auth,
identification_t *my_ca,
identification_t *other_ca)
{
identification_t *id;
bool my_ca_same = FALSE;
bool other_ca_same = FALSE;
cert_validation_t valid;
switch (msg->add_conn.crl_policy)
{
case CRL_STRICT_YES:
valid = VALIDATION_GOOD;
auth->add_item(auth, AUTHZ_CRL_VALIDATION, &valid);
break;
case CRL_STRICT_IFURI:
valid = VALIDATION_SKIPPED;
auth->add_item(auth, AUTHZ_CRL_VALIDATION, &valid);
break;
default:
break;
}
if (msg->add_conn.me.ca)
/* build leftauth= */
auth_cfg = build_auth_cfg(this, msg, TRUE, TRUE);
if (auth_cfg)
{
if (my_ca)
{
my_ca->destroy(my_ca);
my_ca = NULL;
}
if (streq(msg->add_conn.me.ca, "%same"))
{
my_ca_same = TRUE;
}
else
{
my_ca = identification_create_from_string(msg->add_conn.me.ca);
}
peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, TRUE);
}
if (msg->add_conn.other.ca)
else
{ /* we require at least one config on our side */
peer_cfg->destroy(peer_cfg);
return NULL;
}
/* build leftauth2= */
auth_cfg = build_auth_cfg(this, msg, TRUE, FALSE);
if (auth_cfg)
{
if (other_ca)
{
other_ca->destroy(other_ca);
other_ca = NULL;
}
if (streq(msg->add_conn.other.ca, "%same"))
{
other_ca_same = TRUE;
}
else
{
other_ca = identification_create_from_string(msg->add_conn.other.ca);
}
peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, TRUE);
}
if (other_ca_same && my_ca)
/* build rightauth= */
auth_cfg = build_auth_cfg(this, msg, FALSE, TRUE);
if (auth_cfg)
{
other_ca = my_ca->clone(my_ca);
peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, FALSE);
}
else if (my_ca_same && other_ca)
/* build rightauth2= */
auth_cfg = build_auth_cfg(this, msg, FALSE, FALSE);
if (auth_cfg)
{
my_ca = other_ca->clone(other_ca);
}
if (other_ca)
{
DBG2(DBG_CFG, " other ca: %D", other_ca);
certificate_t *cert = charon->credentials->get_cert(charon->credentials,
CERT_X509, KEY_ANY, other_ca, TRUE);
if (cert)
{
auth->add_item(auth, AUTHZ_CA_CERT, cert);
cert->destroy(cert);
}
else
{
auth->add_item(auth, AUTHZ_CA_CERT_NAME, other_ca);
}
other_ca->destroy(other_ca);
}
if (my_ca)
{
DBG2(DBG_CFG, " my ca: %D", my_ca);
certificate_t *cert = charon->credentials->get_cert(charon->credentials,
CERT_X509, KEY_ANY, my_ca, TRUE);
if (cert)
{
auth->add_item(auth, AUTHN_CA_CERT, cert);
cert->destroy(cert);
}
else
{
auth->add_item(auth, AUTHN_CA_CERT_NAME, my_ca);
}
my_ca->destroy(my_ca);
}
auth->add_item(auth, AUTHN_AUTH_CLASS, &msg->add_conn.auth_method);
if (msg->add_conn.eap_type)
{
auth->add_item(auth, AUTHN_EAP_TYPE, &msg->add_conn.eap_type);
if (msg->add_conn.eap_vendor)
{
auth->add_item(auth, AUTHN_EAP_VENDOR, &msg->add_conn.eap_vendor);
}
}
if (msg->add_conn.eap_identity)
{
if (streq(msg->add_conn.eap_identity, "%identity"))
{
id = identification_create_from_encoding(ID_ANY, chunk_empty);
}
else
{
id = identification_create_from_encoding(ID_EAP, chunk_create(
msg->add_conn.eap_identity,
strlen(msg->add_conn.eap_identity)));
}
auth->add_item(auth, AUTHN_EAP_IDENTITY, id);
id->destroy(id);
}
if (msg->add_conn.other.groups)
{
chunk_t line = { msg->add_conn.other.groups,
strlen(msg->add_conn.other.groups) };
while (eat_whitespace(&line))
{
chunk_t group;
/* extract the next comma-separated group attribute */
if (!extract_token(&group, ',', &line))
{
group = line;
line.len = 0;
}
/* remove any trailing spaces */
while (group.len > 0 && *(group.ptr + group.len - 1) == ' ')
{
group.len--;
}
/* add the group attribute to the list */
if (group.len > 0)
{
identification_t *ac_group;
ac_group = identification_create_from_encoding(
ID_IETF_ATTR_STRING, group);
auth->add_item(auth, AUTHZ_AC_GROUP, ac_group);
ac_group->destroy(ac_group);
}
}
peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, FALSE);
}
return peer_cfg;
}
/**
@@ -799,7 +792,6 @@ static void add(private_stroke_config_t *this, stroke_msg_t *msg)
ike_cfg_t *ike_cfg, *existing_ike;
peer_cfg_t *peer_cfg, *existing;
child_cfg_t *child_cfg;
identification_t *my_issuer = NULL, *other_issuer = NULL;
enumerator_t *enumerator;
bool use_existing = FALSE;
@@ -808,15 +800,13 @@ static void add(private_stroke_config_t *this, stroke_msg_t *msg)
{
return;
}
peer_cfg = build_peer_cfg(this, msg, ike_cfg, &my_issuer, &other_issuer);
peer_cfg = build_peer_cfg(this, msg, ike_cfg);
if (!peer_cfg)
{
ike_cfg->destroy(ike_cfg);
return;
}
build_auth_info(this, msg, peer_cfg->get_auth(peer_cfg),
my_issuer, other_issuer);
enumerator = create_peer_cfg_enumerator(this, NULL, NULL);
while (enumerator->enumerate(enumerator, &existing))
{
@@ -850,9 +840,7 @@ static void add(private_stroke_config_t *this, stroke_msg_t *msg)
else
{
/* add config to backend */
DBG1(DBG_CFG, "added configuration '%s': %s[%D]...%s[%D]", msg->add_conn.name,
ike_cfg->get_my_addr(ike_cfg), peer_cfg->get_my_id(peer_cfg),
ike_cfg->get_other_addr(ike_cfg), peer_cfg->get_other_id(peer_cfg));
DBG1(DBG_CFG, "added configuration '%s'", msg->add_conn.name);
this->mutex->lock(this->mutex);
this->list->insert_last(this->list, peer_cfg);
this->mutex->unlock(this->mutex);
+6 -19
View File
@@ -905,26 +905,13 @@ static void load_secrets(private_stroke_cred_t *this)
continue;
}
if (type == SHARED_EAP)
/* NULL terminate the ID string */
*(id.ptr + id.len) = '\0';
peer_id = identification_create_from_string(id.ptr);
if (peer_id->get_type(peer_id) == ID_ANY)
{
/* we use a special EAP identity type for EAP secrets */
peer_id = identification_create_from_encoding(ID_EAP, id);
}
else
{
/* NULL terminate the ID string */
*(id.ptr + id.len) = '\0';
peer_id = identification_create_from_string(id.ptr);
if (peer_id == NULL)
{
DBG1(DBG_CFG, "line %d: malformed ID: %s", line_nr, id.ptr);
goto error;
}
if (peer_id->get_type(peer_id) == ID_ANY)
{
peer_id->destroy(peer_id);
continue;
}
peer_id->destroy(peer_id);
continue;
}
shared_key->add_owner(shared_key, peer_id);
+134 -129
View File
@@ -54,23 +54,6 @@ struct private_stroke_list_t {
stroke_attribute_t *attribute;
};
/**
* get the authentication class of a config
*/
auth_class_t get_auth_class(peer_cfg_t *config)
{
auth_class_t *class;
auth_info_t *auth_info;
auth_info = config->get_auth(config);
if (auth_info->get_item(auth_info, AUTHN_AUTH_CLASS, (void**)&class))
{
return *class;
}
/* fallback to pubkey authentication */
return AUTH_CLASS_PUBKEY;
}
/**
* log an IKE_SA to out
*/
@@ -110,9 +93,11 @@ static void log_ike_sa(FILE *out, ike_sa_t *ike_sa, bool all)
if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED)
{
time_t rekey, reauth;
peer_cfg_t *peer_cfg;
rekey = ike_sa->get_statistic(ike_sa, STAT_REKEY);
reauth = ike_sa->get_statistic(ike_sa, STAT_REAUTH);
peer_cfg = ike_sa->get_peer_cfg(ike_sa);
if (rekey)
{
@@ -120,9 +105,24 @@ static void log_ike_sa(FILE *out, ike_sa_t *ike_sa, bool all)
}
if (reauth)
{
fprintf(out, ", %N reauthentication in %V", auth_class_names,
get_auth_class(ike_sa->get_peer_cfg(ike_sa)),
&reauth, &now);
bool first = TRUE;
enumerator_t *enumerator;
auth_cfg_t *auth;
fprintf(out, ", ");
enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, TRUE);
while (enumerator->enumerate(enumerator, &auth))
{
if (!first)
{
fprintf(out, "+");
}
first = FALSE;
fprintf(out, "%N", auth_class_names,
auth->get(auth, AUTH_RULE_AUTH_CLASS));
}
enumerator->destroy(enumerator);
fprintf(out, " reauthentication in %V", &reauth, &now);
}
if (!rekey && !reauth)
{
@@ -247,6 +247,107 @@ static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all)
child_sa->get_traffic_selectors(child_sa, FALSE));
}
/**
* Log a configs local or remote authentication config to out
*/
static void log_auth_cfgs(FILE *out, peer_cfg_t *peer_cfg, bool local)
{
enumerator_t *enumerator, *rules;
auth_rule_t rule;
auth_cfg_t *auth;
auth_class_t auth_class;
identification_t *id;
certificate_t *cert;
cert_validation_t valid;
char *name;
name = peer_cfg->get_name(peer_cfg);
enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, local);
while (enumerator->enumerate(enumerator, &auth))
{
fprintf(out, "%12s: %s [%D] uses ", name, local ? "local: " : "remote:",
auth->get(auth, AUTH_RULE_IDENTITY));
auth_class = (uintptr_t)auth->get(auth, AUTH_RULE_AUTH_CLASS);
if (auth_class != AUTH_CLASS_EAP)
{
fprintf(out, "%N authentication\n", auth_class_names, auth_class);
}
else
{
if ((uintptr_t)auth->get(auth, AUTH_RULE_EAP_TYPE) == EAP_NAK)
{
fprintf(out, "EAP authentication");
}
else
{
if ((uintptr_t)auth->get(auth, AUTH_RULE_EAP_VENDOR))
{
fprintf(out, "EAP_%d-%d authentication",
(uintptr_t)auth->get(auth, AUTH_RULE_EAP_TYPE),
(uintptr_t)auth->get(auth, AUTH_RULE_EAP_VENDOR));
}
else
{
fprintf(out, "%N authentication", eap_type_names,
(uintptr_t)auth->get(auth, AUTH_RULE_EAP_TYPE));
}
}
id = auth->get(auth, AUTH_RULE_EAP_IDENTITY);
if (id)
{
fprintf(out, " with EAP identity '%D'", id);
}
fprintf(out, "\n");
}
cert = auth->get(auth, AUTH_RULE_CA_CERT);
if (cert)
{
fprintf(out, "%12s: ca: \"%D\"\n", name, cert->get_subject(cert));
}
cert = auth->get(auth, AUTH_RULE_IM_CERT);
if (cert)
{
fprintf(out, "%12s: im-ca: \"%D\"\n", name, cert->get_subject(cert));
}
cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
if (cert)
{
fprintf(out, "%12s: cert: \"%D\"\n", name,
cert->get_subject(cert));
}
valid = (uintptr_t)auth->get(auth, AUTH_RULE_OCSP_VALIDATION);
if (valid != VALIDATION_FAILED)
{
fprintf(out, "%12s: ocsp: status must be GOOD%s\n", name,
(valid == VALIDATION_SKIPPED) ? " or SKIPPED" : "");
}
valid = (uintptr_t)auth->get(auth, AUTH_RULE_CRL_VALIDATION);
if (valid != VALIDATION_FAILED)
{
fprintf(out, "%12s: crl: status must be GOOD%s\n", name,
(valid == VALIDATION_SKIPPED) ? " or SKIPPED" : "");
}
rules = auth->create_enumerator(auth);
while (rules->enumerate(rules, &rule, &id))
{
if (rule == AUTH_RULE_AC_GROUP)
{
fprintf(out, "%12s: group: %D\n", name, id);
}
}
rules->destroy(rules);
}
enumerator->destroy(enumerator);
}
/**
* Implementation of stroke_list_t.status.
*/
@@ -313,138 +414,42 @@ static void status(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out, bo
enumerator->destroy(enumerator);
fprintf(out, "Connections:\n");
enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends);
while (enumerator->enumerate(enumerator, (void**)&peer_cfg))
enumerator = charon->backends->create_peer_cfg_enumerator(
charon->backends, NULL, NULL, NULL, NULL);
while (enumerator->enumerate(enumerator, &peer_cfg))
{
void *ptr;
certificate_t *cert;
auth_item_t item;
auth_info_t *auth;
enumerator_t *auth_enumerator;
identification_t *my_ca = NULL, *other_ca = NULL;
identification_t *eap_identity = NULL;
u_int32_t *eap_type = NULL;
bool ac_groups = FALSE;
if (peer_cfg->get_ike_version(peer_cfg) != 2 ||
(name && !streq(name, peer_cfg->get_name(peer_cfg))))
{
continue;
}
/* determine any required CAs, EAP type, EAP identity,
* and the presence of AC groups
*/
auth = peer_cfg->get_auth(peer_cfg);
auth_enumerator = auth->create_item_enumerator(auth);
while (auth_enumerator->enumerate(auth_enumerator, &item, &ptr))
{
switch (item)
{
case AUTHN_EAP_TYPE:
eap_type = (u_int32_t *)ptr;
break;
case AUTHN_EAP_IDENTITY:
eap_identity = (identification_t *)ptr;
break;
case AUTHN_CA_CERT:
cert = (certificate_t *)ptr;
my_ca = cert->get_subject(cert);
break;
case AUTHN_CA_CERT_NAME:
my_ca = (identification_t *)ptr;
break;
case AUTHZ_CA_CERT:
cert = (certificate_t *)ptr;
other_ca = cert->get_subject(cert);
break;
case AUTHZ_CA_CERT_NAME:
other_ca = (identification_t *)ptr;
break;
case AUTHZ_AC_GROUP:
ac_groups = TRUE;
break;
default:
break;
}
}
auth_enumerator->destroy(auth_enumerator);
ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
fprintf(out, "%12s: %s[%D]...%s[%D]\n", peer_cfg->get_name(peer_cfg),
ike_cfg->get_my_addr(ike_cfg), peer_cfg->get_my_id(peer_cfg),
ike_cfg->get_other_addr(ike_cfg), peer_cfg->get_other_id(peer_cfg));
if (my_ca || other_ca)
{
fprintf(out, "%12s: CAs: ", peer_cfg->get_name(peer_cfg));
if (my_ca)
{
fprintf(out, "\"%D\"...", my_ca);
}
else
{
fprintf(out, "%%any...");
}
if (other_ca)
{
fprintf(out, "\"%D\"\n", other_ca);
}
else
{
fprintf(out, "%%any\n");
}
}
if (ac_groups)
{
bool first = TRUE;
fprintf(out, "%12s: groups: ", peer_cfg->get_name(peer_cfg));
auth_enumerator = auth->create_item_enumerator(auth);
while (auth_enumerator->enumerate(auth_enumerator, &item, &ptr))
{
if (item == AUTHZ_AC_GROUP)
{
identification_t *group = (identification_t *)ptr;
fprintf(out, "%s%D", first? "":", ", group);
first = FALSE;
}
}
auth_enumerator->destroy(auth_enumerator);
fprintf(out, "\n");
}
fprintf(out, "%12s: %N ", peer_cfg->get_name(peer_cfg),
auth_class_names, get_auth_class(peer_cfg));
if (eap_type)
{
fprintf(out, "and %N ", eap_type_names, *eap_type);
}
fprintf(out, "authentication");
if (eap_identity)
{
fprintf(out, ", EAP identity: '%D'", eap_identity);
}
fprintf(out, "%12s: %s...%s", peer_cfg->get_name(peer_cfg),
ike_cfg->get_my_addr(ike_cfg), ike_cfg->get_other_addr(ike_cfg));
dpd = peer_cfg->get_dpd(peer_cfg);
if (dpd)
{
fprintf(out, ", dpddelay=%us", dpd);
}
fprintf(out, "\n");
log_auth_cfgs(out, peer_cfg, TRUE);
log_auth_cfgs(out, peer_cfg, FALSE);
children = peer_cfg->create_child_cfg_enumerator(peer_cfg);
while (children->enumerate(children, &child_cfg))
{
linked_list_t *my_ts, *other_ts;
my_ts = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL);
other_ts = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL, NULL);
fprintf(out, "%12s: %#R=== %#R", child_cfg->get_name(child_cfg),
fprintf(out, "%12s: child: %#R=== %#R", child_cfg->get_name(child_cfg),
my_ts, other_ts);
my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
if (dpd)
{
fprintf(out, ", dpdaction=%N", action_names,
+10
View File
@@ -143,18 +143,28 @@ static void pop_end(stroke_msg_t *msg, const char* label, stroke_end_t *end)
pop_string(msg, &end->address);
pop_string(msg, &end->subnets);
pop_string(msg, &end->sourceip);
pop_string(msg, &end->auth);
pop_string(msg, &end->auth2);
pop_string(msg, &end->id);
pop_string(msg, &end->id2);
pop_string(msg, &end->cert);
pop_string(msg, &end->cert2);
pop_string(msg, &end->ca);
pop_string(msg, &end->ca2);
pop_string(msg, &end->groups);
pop_string(msg, &end->updown);
DBG2(DBG_CFG, " %s=%s", label, end->address);
DBG2(DBG_CFG, " %ssubnet=%s", label, end->subnets);
DBG2(DBG_CFG, " %ssourceip=%s", label, end->sourceip);
DBG2(DBG_CFG, " %sauth=%s", label, end->auth);
DBG2(DBG_CFG, " %sauth2=%s", label, end->auth2);
DBG2(DBG_CFG, " %sid=%s", label, end->id);
DBG2(DBG_CFG, " %sid2=%s", label, end->id2);
DBG2(DBG_CFG, " %scert=%s", label, end->cert);
DBG2(DBG_CFG, " %scert2=%s", label, end->cert2);
DBG2(DBG_CFG, " %sca=%s", label, end->ca);
DBG2(DBG_CFG, " %sca2=%s", label, end->ca2);
DBG2(DBG_CFG, " %sgroups=%s", label, end->groups);
DBG2(DBG_CFG, " %supdown=%s", label, end->updown);
}
+16 -25
View File
@@ -82,24 +82,6 @@ static proposal_t *create_proposal(char *string, protocol_id_t proto)
return proposal;
}
/**
* create an identity, with fallback to %any
*/
static identification_t *create_id(char *string)
{
identification_t *id = NULL;
if (string)
{
id = identification_create_from_string(string);
}
if (!id)
{
id = identification_create_from_encoding(ID_ANY, chunk_empty);
}
return id;
}
/**
* create an traffic selector, fallback to dynamic
*/
@@ -163,8 +145,7 @@ static bool peer_enumerator_enumerate(peer_enumerator_t *this, peer_cfg_t **cfg)
char *remote_id, *remote_addr, *remote_net;
child_cfg_t *child_cfg;
ike_cfg_t *ike_cfg;
auth_info_t *auth;
auth_class_t class;
auth_cfg_t *auth;
/* defaults */
name = "unnamed";
@@ -187,16 +168,26 @@ static bool peer_enumerator_enumerate(peer_enumerator_t *this, peer_cfg_t **cfg)
ike_cfg = ike_cfg_create(FALSE, FALSE, local_addr, remote_addr);
ike_cfg->add_proposal(ike_cfg, create_proposal(ike_proposal, PROTO_IKE));
this->peer_cfg = peer_cfg_create(
name, 2, ike_cfg, create_id(local_id), create_id(remote_id),
CERT_SEND_IF_ASKED, UNIQUE_NO,
name, 2, ike_cfg, CERT_SEND_IF_ASKED, UNIQUE_NO,
1, create_rekey(ike_rekey), 0, /* keytries, rekey, reauth */
1800, 900, /* jitter, overtime */
TRUE, 60, /* mobike, dpddelay */
NULL, NULL, /* vip, pool */
FALSE, NULL, NULL); /* mediation, med by, peer id */
auth = this->peer_cfg->get_auth(this->peer_cfg);
class = AUTH_CLASS_PSK;
auth->add_item(auth, AUTHN_AUTH_CLASS, &class);
auth = auth_cfg_create();
auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
auth->add(auth, AUTH_RULE_IDENTITY,
identification_create_from_string(local_id));
this->peer_cfg->add_auth_cfg(this->peer_cfg, auth, TRUE);
auth = auth_cfg_create();
auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
if (remote_id)
{
auth->add(auth, AUTH_RULE_IDENTITY,
identification_create_from_string(remote_id));
}
this->peer_cfg->add_auth_cfg(this->peer_cfg, auth, FALSE);
child_cfg = child_cfg_create(name,
create_rekey(esp_rekey) + 300, create_rekey(ike_rekey), 300,
NULL, TRUE, MODE_TUNNEL, ACTION_NONE, ACTION_NONE, FALSE);
+23 -22
View File
@@ -39,15 +39,15 @@ typedef struct private_uci_control_t private_uci_control_t;
* private data of uci_control_t
*/
struct private_uci_control_t {
/**
* Public part
*/
* Public part
*/
uci_control_t public;
/**
* Job
*/
* Job
*/
callback_job_t *job;
};
@@ -86,13 +86,14 @@ static void status(private_uci_control_t *this, char *name)
char buf[2048];
FILE *out = NULL;
configs = charon->backends->create_peer_cfg_enumerator(charon->backends);
while (configs->enumerate(configs, &peer_cfg))
{
if (name && !streq(name, peer_cfg->get_name(peer_cfg)))
{
continue;
}
configs = charon->backends->create_peer_cfg_enumerator(charon->backends,
NULL, NULL, NULL, NULL);
while (configs->enumerate(configs, &peer_cfg))
{
if (name && !streq(name, peer_cfg->get_name(peer_cfg)))
{
continue;
}
sas = charon->controller->create_ike_sa_enumerator(charon->controller);
while (sas->enumerate(sas, &ike_sa))
{
@@ -108,9 +109,9 @@ static void status(private_uci_control_t *this, char *name)
continue;
}
}
fprintf(out, "%-8s %-20D %-16H ", ike_sa->get_name(ike_sa),
ike_sa->get_other_id(ike_sa), ike_sa->get_other_host(ike_sa));
fprintf(out, "%-8s %-20D %-16H ", ike_sa->get_name(ike_sa),
ike_sa->get_other_id(ike_sa), ike_sa->get_other_host(ike_sa));
children = ike_sa->create_child_sa_iterator(ike_sa);
while (children->iterate(children, (void**)&child_sa))
{
@@ -118,7 +119,7 @@ static void status(private_uci_control_t *this, char *name)
child_sa->get_traffic_selectors(child_sa, FALSE));
}
children->destroy(children);
fprintf(out, "\n");
fprintf(out, "\n");
}
sas->destroy(sas);
}
@@ -142,7 +143,7 @@ static void initiate(private_uci_control_t *this, char *name)
peer_cfg_t *peer_cfg;
child_cfg_t *child_cfg;
enumerator_t *enumerator;
peer_cfg = charon->backends->get_peer_cfg_by_name(charon->backends, name);
if (peer_cfg)
{
@@ -174,7 +175,7 @@ static void terminate(private_uci_control_t *this, char *name)
enumerator_t *enumerator;
ike_sa_t *ike_sa;
u_int id;
enumerator = charon->controller->create_ike_sa_enumerator(charon->controller);
while (enumerator->enumerate(enumerator, &ike_sa))
{
@@ -240,7 +241,7 @@ static job_requeue_t receive(private_uci_control_t *this)
char message[128];
int oldstate, len;
FILE *in;
memset(message, 0, sizeof(message));
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
in = fopen(FIFO_FILE, "r");
@@ -281,9 +282,9 @@ static void destroy(private_uci_control_t *this)
uci_control_t *uci_control_create()
{
private_uci_control_t *this = malloc_thing(private_uci_control_t);
this->public.destroy = (void(*)(uci_control_t*))destroy;
unlink(FIFO_FILE);
if (mkfifo(FIFO_FILE, S_IRUSR|S_IWUSR) != 0)
{
-8
View File
@@ -81,10 +81,6 @@ static bool shared_enumerator_enumerate(shared_enumerator_t *this,
if (me)
{
local = identification_create_from_string(local_id);
if (!local)
{
continue;
}
*me = this->me ? this->me->matches(this->me, local)
: ID_MATCH_ANY;
local->destroy(local);
@@ -96,10 +92,6 @@ static bool shared_enumerator_enumerate(shared_enumerator_t *this,
if (other)
{
remote = identification_create_from_string(remote_id);
if (!remote)
{
continue;
}
*other = this->other ? this->other->matches(this->other, remote)
: ID_MATCH_ANY;
remote->destroy(remote);
@@ -15,7 +15,7 @@
#include <daemon.h>
#include <library.h>
#include <credentials/auth_info.h>
#include <config/auth_cfg.h>
char buf[] = {0x01,0x02,0x03,0x04};
@@ -75,14 +75,14 @@ chunk_t certchunk = chunk_from_buf(certbuf);
/*******************************************************************************
* auth info test
******************************************************************************/
bool test_auth_info()
bool test_auth_cfg()
{
auth_info_t *auth = auth_info_create(), *auth2;
auth_cfg_t *auth = auth_cfg_create(), *auth2;
certificate_t *c1, *c2;
enumerator_t *enumerator;
int round = 0;
void *value;
auth_item_t type;
auth_rule_t type;
c1 = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
BUILD_BLOB_ASN1_DER, certchunk,
@@ -92,8 +92,9 @@ bool test_auth_info()
return FALSE;
}
auth->add_item(auth, AUTHN_SUBJECT_CERT, c1);
if (!auth->get_item(auth, AUTHN_SUBJECT_CERT, (void**)&c2))
auth->add(auth, AUTH_RULE_SUBJECT_CERT, c1->get_ref(c1));
c2 = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
if (!c2)
{
return FALSE;
}
@@ -102,11 +103,11 @@ bool test_auth_info()
return FALSE;
}
enumerator = auth->create_item_enumerator(auth);
enumerator = auth->create_enumerator(auth);
while (enumerator->enumerate(enumerator, &type, &value))
{
round++;
if (round == 1 && type == AUTHN_SUBJECT_CERT && value == c1)
if (round == 1 && type == AUTH_RULE_SUBJECT_CERT && value == c1)
{
continue;
}
@@ -114,20 +115,20 @@ bool test_auth_info()
}
enumerator->destroy(enumerator);
auth2 = auth_info_create();
auth2->add_item(auth2, AUTHN_CA_CERT, c1);
auth2->merge(auth2, auth);
auth2 = auth_cfg_create();
auth2->add(auth2, AUTH_RULE_CA_CERT, c1->get_ref(c1));
auth2->merge(auth2, auth, FALSE);
round = 0;
enumerator = auth2->create_item_enumerator(auth2);
enumerator = auth2->create_enumerator(auth2);
while (enumerator->enumerate(enumerator, &type, &value))
{
round++;
if (round == 1 && type == AUTHN_CA_CERT && value == c1)
if (round == 1 && type == AUTH_RULE_CA_CERT && value == c1)
{
continue;
}
if (round == 2 && type == AUTHN_SUBJECT_CERT && value == c1)
if (round == 2 && type == AUTH_RULE_SUBJECT_CERT && value == c1)
{
continue;
}
@@ -33,8 +33,8 @@ bool test_med_db()
chunk_t keyid = chunk_from_buf(keyid_buf);
identification_t *id, *found;
enumerator_t *enumerator;
auth_info_t *auth;
public_key_t *public;
auth_cfg_t *auth;
bool good = FALSE;
id = identification_create_from_encoding(ID_KEY_ID, keyid);
@@ -25,14 +25,10 @@
static void* testing(void *thread)
{
int i;
auth_info_t *auth;
int i;
host_t *addr[ALLOCS];
identification_t *id[ALLOCS];
auth = auth_info_create();
/* prepare identities */
for (i = 0; i < ALLOCS; i++)
{
@@ -40,17 +36,13 @@ static void* testing(void *thread)
snprintf(buf, sizeof(buf), "%d-%[email protected]", (int)thread, i);
id[i] = identification_create_from_string(buf);
if (!id[i])
{
return (void*)FALSE;
}
}
/* allocate addresses */
for (i = 0; i < ALLOCS; i++)
{
addr[i] = charon->attributes->acquire_address(charon->attributes,
"test", id[i], auth, NULL);
"test", id[i], NULL);
if (!addr[i])
{
return (void*)FALSE;
@@ -69,7 +61,6 @@ static void* testing(void *thread)
addr[i]->destroy(addr[i]);
id[i]->destroy(id[i]);
}
auth->destroy(auth);
return (void*)TRUE;
}