Merge branch 'xauth-radius-multi'
Introduces multiple rounds in the eap-radius XAuth backend, concatenating answers to a single password to verify using a RADIUS User-Password attribute. This is known to work fine with iOS and OS X clients, allowing two-factor authentication with proper dialogs. Different XAuth "profiles" for each backend can be selected using a generic colon sperated suffix for the XAuth string.
This commit is contained in:
@@ -48,9 +48,9 @@ struct private_cmd_creds_t {
|
||||
callback_cred_t *cb;
|
||||
|
||||
/**
|
||||
* Already prompted for password?
|
||||
* Kind of secret we recently prompted
|
||||
*/
|
||||
bool prompted;
|
||||
shared_key_type_t prompted;
|
||||
|
||||
/**
|
||||
* Path to ssh-agent socket
|
||||
@@ -74,7 +74,7 @@ static shared_key_t* callback_shared(private_cmd_creds_t *this,
|
||||
shared_key_t *shared;
|
||||
char *label, *pwd;
|
||||
|
||||
if (this->prompted)
|
||||
if (type == this->prompted)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
@@ -89,6 +89,9 @@ static shared_key_t* callback_shared(private_cmd_creds_t *this,
|
||||
case SHARED_PRIVATE_KEY_PASS:
|
||||
label = "Password: ";
|
||||
break;
|
||||
case SHARED_PIN:
|
||||
label = "PIN: ";
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
@@ -97,7 +100,7 @@ static shared_key_t* callback_shared(private_cmd_creds_t *this,
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
this->prompted = TRUE;
|
||||
this->prompted = type;
|
||||
if (match_me)
|
||||
{
|
||||
*match_me = ID_MATCH_PERFECT;
|
||||
@@ -281,6 +284,7 @@ cmd_creds_t *cmd_creds_create()
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.creds = mem_cred_create(),
|
||||
.prompted = SHARED_ANY,
|
||||
);
|
||||
this->cb = callback_cred_create_shared((void*)callback_shared, this);
|
||||
|
||||
|
||||
@@ -1268,17 +1268,38 @@ static char* get_string(private_message_t *this, char *buf, int len)
|
||||
pos += written;
|
||||
len -= written;
|
||||
}
|
||||
if (payload->get_type(payload) == CONFIGURATION)
|
||||
if (payload->get_type(payload) == CONFIGURATION ||
|
||||
payload->get_type(payload) == CONFIGURATION_V1)
|
||||
{
|
||||
cp_payload_t *cp = (cp_payload_t*)payload;
|
||||
enumerator_t *attributes;
|
||||
configuration_attribute_t *attribute;
|
||||
bool first = TRUE;
|
||||
char *pfx;
|
||||
|
||||
switch (cp->get_type(cp))
|
||||
{
|
||||
case CFG_REQUEST:
|
||||
pfx = "RQ(";
|
||||
break;
|
||||
case CFG_REPLY:
|
||||
pfx = "RP(";
|
||||
break;
|
||||
case CFG_SET:
|
||||
pfx = "S(";
|
||||
break;
|
||||
case CFG_ACK:
|
||||
pfx = "A(";
|
||||
break;
|
||||
default:
|
||||
pfx = "(";
|
||||
break;
|
||||
}
|
||||
|
||||
attributes = cp->create_attribute_enumerator(cp);
|
||||
while (attributes->enumerate(attributes, &attribute))
|
||||
{
|
||||
written = snprintf(pos, len, "%s%N", first ? "(" : " ",
|
||||
written = snprintf(pos, len, "%s%N", first ? pfx : " ",
|
||||
configuration_attribute_type_short_names,
|
||||
attribute->get_type(attribute));
|
||||
if (written >= len || written < 0)
|
||||
|
||||
@@ -280,4 +280,3 @@ eap_gtc_t *eap_gtc_create_peer(identification_t *server, identification_t *peer)
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,9 +20,21 @@
|
||||
|
||||
#include <daemon.h>
|
||||
#include <radius_client.h>
|
||||
#include <collections/array.h>
|
||||
|
||||
|
||||
typedef struct private_eap_radius_xauth_t private_eap_radius_xauth_t;
|
||||
typedef struct xauth_round_t xauth_round_t;
|
||||
|
||||
/**
|
||||
* Configuration for an XAuth authentication exchange
|
||||
*/
|
||||
struct xauth_round_t {
|
||||
/** XAuth message type to send */
|
||||
configuration_attribute_type_t type;
|
||||
/** Message to present to user */
|
||||
char *message;
|
||||
};
|
||||
|
||||
/**
|
||||
* Private data of an eap_radius_xauth_t object.
|
||||
@@ -48,33 +60,74 @@ struct private_eap_radius_xauth_t {
|
||||
* RADIUS connection
|
||||
*/
|
||||
radius_client_t *client;
|
||||
|
||||
/**
|
||||
* XAuth authentication rounds, as xauth_round_t
|
||||
*/
|
||||
array_t *rounds;
|
||||
|
||||
/**
|
||||
* XAuth round currently in progress
|
||||
*/
|
||||
xauth_round_t round;
|
||||
|
||||
/**
|
||||
* Concatentated password of all rounds
|
||||
*/
|
||||
chunk_t pass;
|
||||
};
|
||||
|
||||
/**
|
||||
* Fetch next XAuth round, add attributes to CP payload
|
||||
*/
|
||||
static bool build_round(private_eap_radius_xauth_t *this, cp_payload_t *cp)
|
||||
{
|
||||
if (!array_remove(this->rounds, ARRAY_HEAD, &this->round))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
cp->add_attribute(cp, configuration_attribute_create_chunk(
|
||||
CONFIGURATION_ATTRIBUTE_V1, this->round.type, chunk_empty));
|
||||
|
||||
if (this->round.message && strlen(this->round.message))
|
||||
{
|
||||
cp->add_attribute(cp, configuration_attribute_create_chunk(
|
||||
CONFIGURATION_ATTRIBUTE_V1, XAUTH_MESSAGE,
|
||||
chunk_from_str(this->round.message)));
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(xauth_method_t, initiate, status_t,
|
||||
private_eap_radius_xauth_t *this, cp_payload_t **out)
|
||||
{
|
||||
cp_payload_t *cp;
|
||||
|
||||
cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REQUEST);
|
||||
/* first message always comes with username */
|
||||
cp->add_attribute(cp, configuration_attribute_create_chunk(
|
||||
CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_NAME, chunk_empty));
|
||||
cp->add_attribute(cp, configuration_attribute_create_chunk(
|
||||
CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_PASSWORD, chunk_empty));
|
||||
*out = cp;
|
||||
return NEED_MORE;
|
||||
|
||||
if (build_round(this, cp))
|
||||
{
|
||||
*out = cp;
|
||||
return NEED_MORE;
|
||||
}
|
||||
cp->destroy(cp);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify a password using RADIUS User-Name/User-Password attributes
|
||||
*/
|
||||
static status_t verify_radius(private_eap_radius_xauth_t *this, chunk_t pass)
|
||||
static status_t verify_radius(private_eap_radius_xauth_t *this)
|
||||
{
|
||||
radius_message_t *request, *response;
|
||||
status_t status = FAILED;
|
||||
|
||||
request = radius_message_create(RMC_ACCESS_REQUEST);
|
||||
request->add(request, RAT_USER_NAME, this->peer->get_encoding(this->peer));
|
||||
request->add(request, RAT_USER_PASSWORD, pass);
|
||||
request->add(request, RAT_USER_PASSWORD, this->pass);
|
||||
|
||||
eap_radius_build_attributes(request);
|
||||
eap_radius_forward_from_ike(request);
|
||||
@@ -114,34 +167,34 @@ METHOD(xauth_method_t, process, status_t,
|
||||
configuration_attribute_t *attr;
|
||||
enumerator_t *enumerator;
|
||||
identification_t *id;
|
||||
cp_payload_t *cp;
|
||||
chunk_t user = chunk_empty, pass = chunk_empty;
|
||||
|
||||
enumerator = in->create_attribute_enumerator(in);
|
||||
while (enumerator->enumerate(enumerator, &attr))
|
||||
{
|
||||
switch (attr->get_type(attr))
|
||||
if (attr->get_type(attr) == XAUTH_USER_NAME)
|
||||
{
|
||||
case XAUTH_USER_NAME:
|
||||
user = attr->get_chunk(attr);
|
||||
break;
|
||||
case XAUTH_USER_PASSWORD:
|
||||
pass = attr->get_chunk(attr);
|
||||
/* trim password to any null termination. As User-Password
|
||||
* uses null padding, we can't have any null in it, and some
|
||||
* clients actually send null terminated strings (Android). */
|
||||
pass.len = strnlen(pass.ptr, pass.len);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
user = attr->get_chunk(attr);
|
||||
}
|
||||
else if (attr->get_type(attr) == this->round.type)
|
||||
{
|
||||
pass = attr->get_chunk(attr);
|
||||
/* trim password to any null termination. As User-Password
|
||||
* uses null padding, we can't have any null in it, and some
|
||||
* clients actually send null terminated strings (Android). */
|
||||
pass.len = strnlen(pass.ptr, pass.len);
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
if (!user.ptr || !pass.ptr)
|
||||
if (!pass.ptr)
|
||||
{
|
||||
DBG1(DBG_IKE, "peer did not respond to our XAuth request");
|
||||
DBG1(DBG_IKE, "peer did not respond to our XAuth %N request",
|
||||
configuration_attribute_type_names, this->round.type);
|
||||
return FAILED;
|
||||
}
|
||||
this->pass = chunk_cat("mc", this->pass, pass);
|
||||
if (user.len)
|
||||
{
|
||||
id = identification_create_from_data(user);
|
||||
@@ -153,7 +206,19 @@ METHOD(xauth_method_t, process, status_t,
|
||||
this->peer->destroy(this->peer);
|
||||
this->peer = id;
|
||||
}
|
||||
return verify_radius(this, pass);
|
||||
|
||||
if (array_count(this->rounds) == 0)
|
||||
{
|
||||
return verify_radius(this);
|
||||
}
|
||||
cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REQUEST);
|
||||
if (build_round(this, cp))
|
||||
{
|
||||
*out = cp;
|
||||
return NEED_MORE;
|
||||
}
|
||||
cp->destroy(cp);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
METHOD(xauth_method_t, get_identity, identification_t*,
|
||||
@@ -162,10 +227,74 @@ METHOD(xauth_method_t, get_identity, identification_t*,
|
||||
return this->peer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse XAuth round configuration
|
||||
*/
|
||||
static bool parse_rounds(private_eap_radius_xauth_t *this, char *profile)
|
||||
{
|
||||
struct {
|
||||
char *str;
|
||||
configuration_attribute_type_t type;
|
||||
} map[] = {
|
||||
{ "password", XAUTH_USER_PASSWORD, },
|
||||
{ "passcode", XAUTH_PASSCODE, },
|
||||
{ "nextpin", XAUTH_NEXT_PIN, },
|
||||
{ "answer", XAUTH_ANSWER, },
|
||||
};
|
||||
enumerator_t *enumerator;
|
||||
char *type, *message;
|
||||
xauth_round_t round;
|
||||
int i;
|
||||
|
||||
if (!profile || strlen(profile) == 0)
|
||||
{
|
||||
/* no config, fallback to password */
|
||||
round.type = XAUTH_USER_PASSWORD;
|
||||
round.message = NULL;
|
||||
array_insert(this->rounds, ARRAY_TAIL, &round);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
enumerator = lib->settings->create_key_value_enumerator(lib->settings,
|
||||
"%s.plugins.eap-radius.xauth.%s", charon->name, profile);
|
||||
while (enumerator->enumerate(enumerator, &type, &message))
|
||||
{
|
||||
bool invalid = TRUE;
|
||||
|
||||
for (i = 0; i < countof(map); i++)
|
||||
{
|
||||
if (strcaseeq(map[i].str, type))
|
||||
{
|
||||
round.type = map[i].type;
|
||||
round.message = message;
|
||||
array_insert(this->rounds, ARRAY_TAIL, &round);
|
||||
invalid = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (invalid)
|
||||
{
|
||||
DBG1(DBG_CFG, "invalid XAuth round type: '%s'", type);
|
||||
enumerator->destroy(enumerator);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
if (array_count(this->rounds) == 0)
|
||||
{
|
||||
DBG1(DBG_CFG, "XAuth configuration profile '%s' invalid", profile);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(xauth_method_t, destroy, void,
|
||||
private_eap_radius_xauth_t *this)
|
||||
{
|
||||
DESTROY_IF(this->client);
|
||||
chunk_clear(&this->pass);
|
||||
array_destroy(this->rounds);
|
||||
this->server->destroy(this->server);
|
||||
this->peer->destroy(this->peer);
|
||||
free(this);
|
||||
@@ -175,7 +304,8 @@ METHOD(xauth_method_t, destroy, void,
|
||||
* Described in header.
|
||||
*/
|
||||
eap_radius_xauth_t *eap_radius_xauth_create_server(identification_t *server,
|
||||
identification_t *peer)
|
||||
identification_t *peer,
|
||||
char *profile)
|
||||
{
|
||||
private_eap_radius_xauth_t *this;
|
||||
|
||||
@@ -191,8 +321,14 @@ eap_radius_xauth_t *eap_radius_xauth_create_server(identification_t *server,
|
||||
.server = server->clone(server),
|
||||
.peer = peer->clone(peer),
|
||||
.client = eap_radius_create_client(),
|
||||
.rounds = array_create(sizeof(xauth_round_t), 0),
|
||||
);
|
||||
|
||||
if (!parse_rounds(this, profile))
|
||||
{
|
||||
destroy(this);
|
||||
return NULL;
|
||||
}
|
||||
if (!this->client)
|
||||
{
|
||||
destroy(this);
|
||||
|
||||
@@ -41,9 +41,11 @@ struct eap_radius_xauth_t {
|
||||
*
|
||||
* @param server ID of the XAuth server
|
||||
* @param peer ID of the XAuth client
|
||||
* @param profile configuration string
|
||||
* @return xauth_generic_t object
|
||||
*/
|
||||
eap_radius_xauth_t *eap_radius_xauth_create_server(identification_t *server,
|
||||
identification_t *peer);
|
||||
identification_t *peer,
|
||||
char *profile);
|
||||
|
||||
#endif /** EAP_RADIUS_XAUTH_H_ @}*/
|
||||
|
||||
@@ -266,7 +266,7 @@ METHOD(xauth_method_t, destroy, void,
|
||||
* Described in header.
|
||||
*/
|
||||
xauth_eap_t *xauth_eap_create_server(identification_t *server,
|
||||
identification_t *peer)
|
||||
identification_t *peer, char *profile)
|
||||
{
|
||||
private_xauth_eap_t *this;
|
||||
|
||||
|
||||
@@ -47,9 +47,11 @@ struct xauth_eap_t {
|
||||
*
|
||||
* @param server ID of the XAuth server
|
||||
* @param peer ID of the XAuth client
|
||||
* @param profile configuration string
|
||||
* @return xauth_eap_t object
|
||||
*/
|
||||
xauth_eap_t *xauth_eap_create_server(identification_t *server,
|
||||
identification_t *peer);
|
||||
identification_t *peer,
|
||||
char *profile);
|
||||
|
||||
#endif /** XAUTH_EAP_H_ @}*/
|
||||
|
||||
@@ -39,7 +39,6 @@ struct private_xauth_generic_t {
|
||||
* ID of the peer
|
||||
*/
|
||||
identification_t *peer;
|
||||
|
||||
};
|
||||
|
||||
METHOD(xauth_method_t, initiate_peer, status_t,
|
||||
@@ -52,28 +51,64 @@ METHOD(xauth_method_t, initiate_peer, status_t,
|
||||
METHOD(xauth_method_t, process_peer, status_t,
|
||||
private_xauth_generic_t *this, cp_payload_t *in, cp_payload_t **out)
|
||||
{
|
||||
configuration_attribute_t *attr;
|
||||
enumerator_t *enumerator;
|
||||
shared_key_t *shared;
|
||||
cp_payload_t *cp;
|
||||
chunk_t user, pass;
|
||||
chunk_t msg;
|
||||
|
||||
shared = lib->credmgr->get_shared(lib->credmgr, SHARED_EAP, this->peer,
|
||||
this->server);
|
||||
if (!shared)
|
||||
enumerator = in->create_attribute_enumerator(in);
|
||||
while (enumerator->enumerate(enumerator, &attr))
|
||||
{
|
||||
DBG1(DBG_IKE, "no XAuth secret found for '%Y' - '%Y'", this->peer,
|
||||
this->server);
|
||||
return FAILED;
|
||||
if (attr->get_type(attr) == XAUTH_MESSAGE)
|
||||
{
|
||||
chunk_printable(attr->get_chunk(attr), &msg, '?');
|
||||
DBG1(DBG_CFG, "XAuth message: %.*s", (int)msg.len, msg.ptr);
|
||||
free(msg.ptr);
|
||||
}
|
||||
}
|
||||
|
||||
user = this->peer->get_encoding(this->peer);
|
||||
pass = shared->get_key(shared);
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REPLY);
|
||||
cp->add_attribute(cp, configuration_attribute_create_chunk(
|
||||
CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_NAME, user));
|
||||
cp->add_attribute(cp, configuration_attribute_create_chunk(
|
||||
CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_PASSWORD, pass));
|
||||
shared->destroy(shared);
|
||||
|
||||
enumerator = in->create_attribute_enumerator(in);
|
||||
while (enumerator->enumerate(enumerator, &attr))
|
||||
{
|
||||
shared_key_type_t type = SHARED_EAP;
|
||||
|
||||
switch (attr->get_type(attr))
|
||||
{
|
||||
case XAUTH_USER_NAME:
|
||||
cp->add_attribute(cp, configuration_attribute_create_chunk(
|
||||
CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_NAME,
|
||||
this->peer->get_encoding(this->peer)));
|
||||
break;
|
||||
case XAUTH_NEXT_PIN:
|
||||
type = SHARED_PIN;
|
||||
/* FALL */
|
||||
case XAUTH_USER_PASSWORD:
|
||||
shared = lib->credmgr->get_shared(lib->credmgr, type,
|
||||
this->peer, this->server);
|
||||
if (!shared)
|
||||
{
|
||||
DBG1(DBG_IKE, "no XAuth %s found for '%Y' - '%Y'",
|
||||
type == SHARED_EAP ? "password" : "PIN",
|
||||
this->peer, this->server);
|
||||
enumerator->destroy(enumerator);
|
||||
cp->destroy(cp);
|
||||
return FAILED;
|
||||
}
|
||||
cp->add_attribute(cp, configuration_attribute_create_chunk(
|
||||
CONFIGURATION_ATTRIBUTE_V1, attr->get_type(attr),
|
||||
shared->get_key(shared)));
|
||||
shared->destroy(shared);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
*out = cp;
|
||||
return NEED_MORE;
|
||||
}
|
||||
@@ -187,7 +222,8 @@ METHOD(xauth_method_t, destroy, void,
|
||||
* Described in header.
|
||||
*/
|
||||
xauth_generic_t *xauth_generic_create_peer(identification_t *server,
|
||||
identification_t *peer)
|
||||
identification_t *peer,
|
||||
char *profile)
|
||||
{
|
||||
private_xauth_generic_t *this;
|
||||
|
||||
@@ -211,7 +247,8 @@ xauth_generic_t *xauth_generic_create_peer(identification_t *server,
|
||||
* Described in header.
|
||||
*/
|
||||
xauth_generic_t *xauth_generic_create_server(identification_t *server,
|
||||
identification_t *peer)
|
||||
identification_t *peer,
|
||||
char *profile)
|
||||
{
|
||||
private_xauth_generic_t *this;
|
||||
|
||||
|
||||
@@ -42,19 +42,23 @@ struct xauth_generic_t {
|
||||
*
|
||||
* @param server ID of the XAuth server
|
||||
* @param peer ID of the XAuth client
|
||||
* @param profile configuration string
|
||||
* @return xauth_generic_t object
|
||||
*/
|
||||
xauth_generic_t *xauth_generic_create_server(identification_t *server,
|
||||
identification_t *peer);
|
||||
identification_t *peer,
|
||||
char *profile);
|
||||
|
||||
/**
|
||||
* Creates the generic XAuth method, acting as peer.
|
||||
*
|
||||
* @param server ID of the XAuth server
|
||||
* @param peer ID of the XAuth client
|
||||
* @param profile configuration string
|
||||
* @return xauth_generic_t object
|
||||
*/
|
||||
xauth_generic_t *xauth_generic_create_peer(identification_t *server,
|
||||
identification_t *peer);
|
||||
identification_t *peer,
|
||||
char *profile);
|
||||
|
||||
#endif /** XAUTH_GENERIC_H_ @}*/
|
||||
|
||||
@@ -69,7 +69,8 @@ METHOD(xauth_method_t, destroy, void,
|
||||
* Described in header.
|
||||
*/
|
||||
xauth_noauth_t *xauth_noauth_create_server(identification_t *server,
|
||||
identification_t *peer)
|
||||
identification_t *peer,
|
||||
char *profile)
|
||||
{
|
||||
private_xauth_noauth_t *this;
|
||||
|
||||
|
||||
@@ -42,9 +42,11 @@ struct xauth_noauth_t {
|
||||
*
|
||||
* @param server ID of the XAuth server
|
||||
* @param peer ID of the XAuth client
|
||||
* @param profile configuration string
|
||||
* @return xauth_noauth_t object
|
||||
*/
|
||||
xauth_noauth_t *xauth_noauth_create_server(identification_t *server,
|
||||
identification_t *peer);
|
||||
identification_t *peer,
|
||||
char *profile);
|
||||
|
||||
#endif /** XAUTH_NOAUTH_H_ @}*/
|
||||
|
||||
@@ -195,7 +195,7 @@ METHOD(xauth_method_t, destroy, void,
|
||||
* Described in header.
|
||||
*/
|
||||
xauth_pam_t *xauth_pam_create_server(identification_t *server,
|
||||
identification_t *peer)
|
||||
identification_t *peer, char *profile)
|
||||
{
|
||||
private_xauth_pam_t *this;
|
||||
|
||||
|
||||
@@ -41,9 +41,10 @@ struct xauth_pam_t {
|
||||
*
|
||||
* @param server ID of the XAuth server
|
||||
* @param peer ID of the XAuth client
|
||||
* @param profile configuration string
|
||||
* @return xauth_pam_t object
|
||||
*/
|
||||
xauth_pam_t *xauth_pam_create_server(identification_t *server,
|
||||
identification_t *peer);
|
||||
identification_t *peer, char *profile);
|
||||
|
||||
#endif /** XAUTH_PAM_H_ @}*/
|
||||
|
||||
@@ -127,7 +127,7 @@ static xauth_method_t *load_method(private_xauth_t* this)
|
||||
{
|
||||
if (name)
|
||||
{
|
||||
DBG1(DBG_CFG, "no XAuth method found named '%s'", name);
|
||||
DBG1(DBG_CFG, "no XAuth method found for '%s'", name);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -107,6 +107,17 @@ METHOD(xauth_manager_t, create_instance, xauth_method_t*,
|
||||
enumerator_t *enumerator;
|
||||
xauth_entry_t *entry;
|
||||
xauth_method_t *method = NULL;
|
||||
char *profile = NULL;
|
||||
|
||||
if (name)
|
||||
{
|
||||
profile = strchr(name, ':');
|
||||
if (profile)
|
||||
{
|
||||
name = strndup(name, profile - name);
|
||||
profile++;
|
||||
}
|
||||
}
|
||||
|
||||
this->lock->read_lock(this->lock);
|
||||
enumerator = this->methods->create_enumerator(this->methods);
|
||||
@@ -118,7 +129,7 @@ METHOD(xauth_manager_t, create_instance, xauth_method_t*,
|
||||
}
|
||||
if (role == entry->role && (!name || streq(name, entry->name)))
|
||||
{
|
||||
method = entry->constructor(server, peer);
|
||||
method = entry->constructor(server, peer, profile);
|
||||
if (method)
|
||||
{
|
||||
break;
|
||||
@@ -127,6 +138,10 @@ METHOD(xauth_manager_t, create_instance, xauth_method_t*,
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
this->lock->unlock(this->lock);
|
||||
if (profile)
|
||||
{
|
||||
free(name);
|
||||
}
|
||||
return method;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,11 @@ struct xauth_manager_t {
|
||||
/**
|
||||
* Create a new XAuth method instance.
|
||||
*
|
||||
* @param name backend name, as it was registered with
|
||||
* The name may contain an option string, seperated by a colon. This option
|
||||
* string gets passed to the XAuth constructor to specify the behavior
|
||||
* of the XAuth method.
|
||||
*
|
||||
* @param name backend name, with optional config string
|
||||
* @param role XAUTH_SERVER or XAUTH_PEER
|
||||
* @param server identity of the server
|
||||
* @param peer identity of the peer (client)
|
||||
|
||||
@@ -104,10 +104,12 @@ struct xauth_method_t {
|
||||
*
|
||||
* @param server ID of the server to use for credential lookup
|
||||
* @param peer ID of the peer to use for credential lookup
|
||||
* @param profile configuration string to pass to XAuth method, or NULL
|
||||
* @return implementation of the eap_method_t interface
|
||||
*/
|
||||
typedef xauth_method_t *(*xauth_constructor_t)(identification_t *server,
|
||||
identification_t *peer);
|
||||
identification_t *peer,
|
||||
char *profile);
|
||||
|
||||
/**
|
||||
* Helper function to (un-)register XAuth methods from plugin features.
|
||||
|
||||
@@ -87,28 +87,28 @@ ENUM_BEGIN(configuration_attribute_type_short_names, INTERNAL_IP4_ADDRESS, HOME_
|
||||
"HOA");
|
||||
ENUM_NEXT(configuration_attribute_type_short_names, XAUTH_TYPE, XAUTH_ANSWER, HOME_AGENT_ADDRESS,
|
||||
"X_TYPE",
|
||||
"X_USER_NAME",
|
||||
"X_USER_PASSWORD",
|
||||
"X_PASSCODE",
|
||||
"X_MESSAGE",
|
||||
"X_CHALLENGE",
|
||||
"X_USER",
|
||||
"X_PWD",
|
||||
"X_CODE",
|
||||
"X_MSG",
|
||||
"X_CHALL",
|
||||
"X_DOMAIN",
|
||||
"X_STATUS",
|
||||
"X_NEXT_PIN",
|
||||
"X_PIN",
|
||||
"X_ANSWER");
|
||||
ENUM_NEXT(configuration_attribute_type_short_names, INTERNAL_IP4_SERVER, INTERNAL_IP6_SERVER, XAUTH_ANSWER,
|
||||
"SRV",
|
||||
"SRV6");
|
||||
ENUM_NEXT(configuration_attribute_type_short_names, UNITY_BANNER, UNITY_DDNS_HOSTNAME, INTERNAL_IP6_SERVER,
|
||||
"U_BANNER",
|
||||
"U_SAVE_PASSWD",
|
||||
"U_DEF_DOMAIN",
|
||||
"U_SPLITDNS_NAME",
|
||||
"U_SPLIT_INCLUDE",
|
||||
"U_NATT_PORT",
|
||||
"U_LOCAL_LAN",
|
||||
"U_SAVEPWD",
|
||||
"U_DEFDOM",
|
||||
"U_SPLITDNS",
|
||||
"U_SPLITINC",
|
||||
"U_NATTPORT",
|
||||
"U_LOCALLAN",
|
||||
"U_PFS",
|
||||
"U_FW_TYPE",
|
||||
"U_BACKUP_SERVERS",
|
||||
"U_DDNS_HOSTNAME");
|
||||
"U_FWTYPE",
|
||||
"U_BKPSRV",
|
||||
"U_DDNSHOST");
|
||||
ENUM_END(configuration_attribute_type_short_names, UNITY_DDNS_HOSTNAME);
|
||||
|
||||
Reference in New Issue
Block a user