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:
Martin Willi
2012-08-10 10:43:44 +02:00
parent b9e4916321
commit 27128c1e32
2 changed files with 45 additions and 88 deletions
+1 -1
View File
@@ -13,4 +13,4 @@ endif
libstrongswan_eap_gtc_la_SOURCES = \
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
+44 -87
View File
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2007 Martin Willi
* Copyright (C) 2007-2012 Martin Willi
* Copyright (C) 2012 revosec AG
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -17,12 +18,8 @@
#include <daemon.h>
#include <library.h>
#include <crypto/hashers/hasher.h>
#include <security/pam_appl.h>
#define GTC_REQUEST_MSG "password"
#define GTC_PAM_SERVICE "login"
typedef struct private_eap_gtc_t private_eap_gtc_t;
@@ -77,63 +74,6 @@ METHOD(eap_method_t, initiate_peer, status_t,
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,
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,
private_eap_gtc_t *this, eap_payload_t *in, eap_payload_t **out)
{
chunk_t data, encoding;
char *user, *password, *service, *pos;
status_t status = FAILED;
chunk_t user, pass;
xauth_method_t *xauth;
cp_payload_t *ci, *co;
char *backend;
data = chunk_skip(in->get_data(in), 5);
if (this->identifier != in->get_identifier(in) || !data.len)
user = this->peer->get_encoding(this->peer);
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");
return FAILED;
}
encoding = this->peer->get_encoding(this->peer);
/* if a RFC822_ADDR id is provided, we use the username part only */
pos = memchr(encoding.ptr, '@', encoding.len);
if (pos)
{
encoding.len = (u_char*)pos - encoding.ptr;
}
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))
/* get XAuth backend to use for credential verification. Default to PAM
* to support legacy EAP-GTC configurations */
backend = lib->settings->get_str(lib->settings,
"%s.plugins.eap-gtc.backend", "pam", charon->name);
xauth = charon->xauth->create_instance(charon->xauth, backend, XAUTH_SERVER,
this->server, this->peer);
if (!xauth)
{
DBG1(DBG_IKE, "creating EAP-GTC XAuth backend '%s' failed", backend);
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,