EAP-GTC can use any XAuth backend, including xauth-pam
This makes EAP-GTC a generic plain password authentication method, as it is used with XAuth. Instead of verifying credentials with PAM, any backend can be configured. The default is xauth-pam, providing the same functionality as EAP-GTC in strongSwan 4.x.
This commit is contained in:
@@ -13,4 +13,4 @@ endif
|
|||||||
libstrongswan_eap_gtc_la_SOURCES = \
|
libstrongswan_eap_gtc_la_SOURCES = \
|
||||||
eap_gtc_plugin.h eap_gtc_plugin.c eap_gtc.h eap_gtc.c
|
eap_gtc_plugin.h eap_gtc_plugin.c eap_gtc.h eap_gtc.c
|
||||||
|
|
||||||
libstrongswan_eap_gtc_la_LDFLAGS = -module -avoid-version -lpam
|
libstrongswan_eap_gtc_la_LDFLAGS = -module -avoid-version
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2007 Martin Willi
|
* Copyright (C) 2007-2012 Martin Willi
|
||||||
|
* Copyright (C) 2012 revosec AG
|
||||||
* Hochschule fuer Technik Rapperswil
|
* Hochschule fuer Technik Rapperswil
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
@@ -17,12 +18,8 @@
|
|||||||
|
|
||||||
#include <daemon.h>
|
#include <daemon.h>
|
||||||
#include <library.h>
|
#include <library.h>
|
||||||
#include <crypto/hashers/hasher.h>
|
|
||||||
|
|
||||||
#include <security/pam_appl.h>
|
|
||||||
|
|
||||||
#define GTC_REQUEST_MSG "password"
|
#define GTC_REQUEST_MSG "password"
|
||||||
#define GTC_PAM_SERVICE "login"
|
|
||||||
|
|
||||||
typedef struct private_eap_gtc_t private_eap_gtc_t;
|
typedef struct private_eap_gtc_t private_eap_gtc_t;
|
||||||
|
|
||||||
@@ -77,63 +74,6 @@ METHOD(eap_method_t, initiate_peer, status_t,
|
|||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* PAM conv callback function
|
|
||||||
*/
|
|
||||||
static int auth_conv(int num_msg, const struct pam_message **msg,
|
|
||||||
struct pam_response **resp, char *password)
|
|
||||||
{
|
|
||||||
struct pam_response *response;
|
|
||||||
|
|
||||||
if (num_msg != 1)
|
|
||||||
{
|
|
||||||
return PAM_CONV_ERR;
|
|
||||||
}
|
|
||||||
response = malloc(sizeof(struct pam_response));
|
|
||||||
response->resp = strdup(password);
|
|
||||||
response->resp_retcode = 0;
|
|
||||||
*resp = response;
|
|
||||||
return PAM_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Authenticate a username/password using PAM
|
|
||||||
*/
|
|
||||||
static bool authenticate(char *service, char *user, char *password)
|
|
||||||
{
|
|
||||||
pam_handle_t *pamh = NULL;
|
|
||||||
static struct pam_conv conv;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
conv.conv = (void*)auth_conv;
|
|
||||||
conv.appdata_ptr = password;
|
|
||||||
|
|
||||||
ret = pam_start(service, user, &conv, &pamh);
|
|
||||||
if (ret != PAM_SUCCESS)
|
|
||||||
{
|
|
||||||
DBG1(DBG_IKE, "EAP-GTC pam_start failed: %s",
|
|
||||||
pam_strerror(pamh, ret));
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
ret = pam_authenticate(pamh, 0);
|
|
||||||
if (ret == PAM_SUCCESS)
|
|
||||||
{
|
|
||||||
ret = pam_acct_mgmt(pamh, 0);
|
|
||||||
if (ret != PAM_SUCCESS)
|
|
||||||
{
|
|
||||||
DBG1(DBG_IKE, "EAP-GTC pam_acct_mgmt failed: %s",
|
|
||||||
pam_strerror(pamh, ret));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DBG1(DBG_IKE, "EAP-GTC pam_authenticate failed: %s",
|
|
||||||
pam_strerror(pamh, ret));
|
|
||||||
}
|
|
||||||
pam_end(pamh, ret);
|
|
||||||
return ret == PAM_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
METHOD(eap_method_t, initiate_server, status_t,
|
METHOD(eap_method_t, initiate_server, status_t,
|
||||||
private_eap_gtc_t *this, eap_payload_t **out)
|
private_eap_gtc_t *this, eap_payload_t **out)
|
||||||
{
|
{
|
||||||
@@ -192,40 +132,57 @@ METHOD(eap_method_t, process_peer, status_t,
|
|||||||
METHOD(eap_method_t, process_server, status_t,
|
METHOD(eap_method_t, process_server, status_t,
|
||||||
private_eap_gtc_t *this, eap_payload_t *in, eap_payload_t **out)
|
private_eap_gtc_t *this, eap_payload_t *in, eap_payload_t **out)
|
||||||
{
|
{
|
||||||
chunk_t data, encoding;
|
status_t status = FAILED;
|
||||||
char *user, *password, *service, *pos;
|
chunk_t user, pass;
|
||||||
|
xauth_method_t *xauth;
|
||||||
|
cp_payload_t *ci, *co;
|
||||||
|
char *backend;
|
||||||
|
|
||||||
data = chunk_skip(in->get_data(in), 5);
|
user = this->peer->get_encoding(this->peer);
|
||||||
if (this->identifier != in->get_identifier(in) || !data.len)
|
pass = chunk_skip(in->get_data(in), 5);
|
||||||
|
if (this->identifier != in->get_identifier(in) || !pass.len)
|
||||||
{
|
{
|
||||||
DBG1(DBG_IKE, "received invalid EAP-GTC message");
|
DBG1(DBG_IKE, "received invalid EAP-GTC message");
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
encoding = this->peer->get_encoding(this->peer);
|
/* get XAuth backend to use for credential verification. Default to PAM
|
||||||
/* if a RFC822_ADDR id is provided, we use the username part only */
|
* to support legacy EAP-GTC configurations */
|
||||||
pos = memchr(encoding.ptr, '@', encoding.len);
|
backend = lib->settings->get_str(lib->settings,
|
||||||
if (pos)
|
"%s.plugins.eap-gtc.backend", "pam", charon->name);
|
||||||
{
|
xauth = charon->xauth->create_instance(charon->xauth, backend, XAUTH_SERVER,
|
||||||
encoding.len = (u_char*)pos - encoding.ptr;
|
this->server, this->peer);
|
||||||
}
|
if (!xauth)
|
||||||
user = alloca(encoding.len + 1);
|
|
||||||
memcpy(user, encoding.ptr, encoding.len);
|
|
||||||
user[encoding.len] = '\0';
|
|
||||||
|
|
||||||
password = alloca(data.len + 1);
|
|
||||||
memcpy(password, data.ptr, data.len);
|
|
||||||
password[data.len] = '\0';
|
|
||||||
|
|
||||||
service = lib->settings->get_str(lib->settings,
|
|
||||||
"%s.plugins.eap-gtc.pam_service", GTC_PAM_SERVICE,
|
|
||||||
charon->name);
|
|
||||||
|
|
||||||
if (!authenticate(service, user, password))
|
|
||||||
{
|
{
|
||||||
|
DBG1(DBG_IKE, "creating EAP-GTC XAuth backend '%s' failed", backend);
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
return SUCCESS;
|
if (xauth->initiate(xauth, &co) == NEED_MORE)
|
||||||
|
{
|
||||||
|
/* assume that "out" contains username/password attributes */
|
||||||
|
co->destroy(co);
|
||||||
|
ci = cp_payload_create_type(CONFIGURATION_V1, CFG_REPLY);
|
||||||
|
ci->add_attribute(ci, configuration_attribute_create_chunk(
|
||||||
|
CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_NAME, user));
|
||||||
|
ci->add_attribute(ci, configuration_attribute_create_chunk(
|
||||||
|
CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_PASSWORD, pass));
|
||||||
|
switch (xauth->process(xauth, ci, &co))
|
||||||
|
{
|
||||||
|
case SUCCESS:
|
||||||
|
status = SUCCESS;
|
||||||
|
break;
|
||||||
|
case NEED_MORE:
|
||||||
|
/* TODO: multiple exchanges currently not supported */
|
||||||
|
co->destroy(co);
|
||||||
|
break;
|
||||||
|
case FAILED:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ci->destroy(ci);
|
||||||
|
}
|
||||||
|
xauth->destroy(xauth);
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(eap_method_t, get_type, eap_type_t,
|
METHOD(eap_method_t, get_type, eap_type_t,
|
||||||
|
|||||||
Reference in New Issue
Block a user