From 27128c1e32355823e831162e06dc8ed32f1d1ad0 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Thu, 9 Aug 2012 15:16:59 +0200 Subject: [PATCH] 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. --- src/libcharon/plugins/eap_gtc/Makefile.am | 2 +- src/libcharon/plugins/eap_gtc/eap_gtc.c | 131 ++++++++-------------- 2 files changed, 45 insertions(+), 88 deletions(-) diff --git a/src/libcharon/plugins/eap_gtc/Makefile.am b/src/libcharon/plugins/eap_gtc/Makefile.am index d8722bf9d..e4234fab2 100644 --- a/src/libcharon/plugins/eap_gtc/Makefile.am +++ b/src/libcharon/plugins/eap_gtc/Makefile.am @@ -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 diff --git a/src/libcharon/plugins/eap_gtc/eap_gtc.c b/src/libcharon/plugins/eap_gtc/eap_gtc.c index 9c262131e..f090e94a8 100644 --- a/src/libcharon/plugins/eap_gtc/eap_gtc.c +++ b/src/libcharon/plugins/eap_gtc/eap_gtc.c @@ -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 #include -#include - -#include #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,