<html>
  <head>

    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <meta charset="utf-8">
    Hello,<br>
    the following patch is a small improvement for the xauth_pam plugin.<br>
    The actual plugin performs the XAuth users authentication though PAM
    but don't open/close the user sessions with the PAM
    pam_open_session/pam_close_session methods.<br>
    Just as comparison, opening/closing the PAM session is the behavior
    of L2TP (strongswan -> xl2tpd -> pppd -> pam).<br>
    Cheers,<br>
    Andrea<br>
    <br>
    Signed-Off-By: Andrea Bonomi <a.bonomi at endian.com><br>
    ---<br>
     src/libcharon/plugins/xauth_pam/Makefile.am        |    3 +-<br>
     .../plugins/xauth_pam/xauth_pam_listener.c         |  156
    ++++++++++++++++++++<br>
     .../plugins/xauth_pam/xauth_pam_listener.h         |   50 +++++++<br>
     src/libcharon/plugins/xauth_pam/xauth_pam_plugin.c |   60 ++++++--<br>
     4 files changed, 258 insertions(+), 11 deletions(-)<br>
    <br>
    diff --git a/src/libcharon/plugins/xauth_pam/Makefile.am
    b/src/libcharon/plugins/xauth_pam/Makefile.am<br>
    index a7d4f64..370661b 100644<br>
    --- a/src/libcharon/plugins/xauth_pam/Makefile.am<br>
    +++ b/src/libcharon/plugins/xauth_pam/Makefile.am<br>
    @@ -14,6 +14,7 @@ endif<br>
     <br>
     libstrongswan_xauth_pam_la_SOURCES = \<br>
         xauth_pam_plugin.h xauth_pam_plugin.c \<br>
    -    xauth_pam.h xauth_pam.c<br>
    +    xauth_pam.h xauth_pam.c \<br>
    +    xauth_pam_listener.h xauth_pam_listener.c<br>
     <br>
     libstrongswan_xauth_pam_la_LDFLAGS = -module -avoid-version -lpam<br>
    diff --git a/src/libcharon/plugins/xauth_pam/xauth_pam_listener.c
    b/src/libcharon/plugins/xauth_pam/xauth_pam_listener.c<br>
    new file mode 100644<br>
    index 0000000..236f6fa<br>
    --- /dev/null<br>
    +++ b/src/libcharon/plugins/xauth_pam/xauth_pam_listener.c<br>
    @@ -0,0 +1,156 @@<br>
    +/*<br>
    + * Copyright (C) 2013 Endian srl<br>
    + * Author: Andrea Bonomi - <a class="moz-txt-link-rfc2396E" href="mailto:a.bonomi@endian.com"><a.bonomi@endian.com></a><br>
    + *<br>
    + * This program is free software; you can redistribute it and/or
    modify it<br>
    + * under the terms of the GNU General Public License as published
    by the<br>
    + * Free Software Foundation; either version 2 of the License, or
    (at your<br>
    + * option) any later version.  See
    <a class="moz-txt-link-rfc2396E" href="http://www.fsf.org/copyleft/gpl.txt"><http://www.fsf.org/copyleft/gpl.txt></a>.<br>
    + *<br>
    + * This program is distributed in the hope that it will be useful,
    but<br>
    + * WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY<br>
    + * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
    License<br>
    + * for more details.<br>
    + */<br>
    +<br>
    +#define _GNU_SOURCE<br>
    +#include <stdio.h><br>
    +<br>
    +#include "xauth_pam_listener.h"<br>
    +<br>
    +#include <daemon.h><br>
    +#include <library.h><br>
    +<br>
    +#include <security/pam_appl.h><br>
    +<br>
    +typedef struct private_xauth_pam_listener_t
    private_xauth_pam_listener_t;<br>
    +<br>
    +/**<br>
    + * Private data of an xauth_pam_listener_t object.<br>
    + */<br>
    +struct private_xauth_pam_listener_t {<br>
    +<br>
    +    /**<br>
    +     * Public xauth_pam_listener_t interface.<br>
    +     */<br>
    +    xauth_pam_listener_t public;<br>
    +<br>
    +};<br>
    +<br>
    +static struct pam_conv null_conv = {<br>
    +    NULL<br>
    +};<br>
    +<br>
    +static void open_close_session(private_xauth_pam_listener_t *this,
    ike_sa_t *ike_sa, bool up)<br>
    +{<br>
    +    pam_handle_t *pamh = NULL;<br>
    +    char *user = NULL;<br>
    +    char *service = NULL;<br>
    +    int ret;<br>
    +    enumerator_t *enumerator;<br>
    +    host_t *vip;<br>
    +<br>
    +    /* Look for PAM service, with a legacy fallback for the eap-gtc
    plugin.<br>
    +     * Default to "login". */<br>
    +    service = lib->settings->get_str(lib->settings,<br>
    +                "%s.plugins.xauth-pam.pam_service",<br>
    +                    lib->settings->get_str(lib->settings,<br>
    +                        "%s.plugins.eap-gtc.pam_service",<br>
    +                        "login", charon->name),<br>
    +                charon->name);<br>
    +<br>
    +    enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa,
    FALSE);<br>
    +    while (enumerator->enumerate(enumerator, &vip))<br>
    +    {<br>
    +        if (asprintf(&user, "%Y",
    ike_sa->get_other_eap_id(ike_sa)) == -1)<br>
    +        {<br>
    +            user = NULL;<br>
    +            continue;<br>
    +        }<br>
    +        ret = pam_start(service, user, &null_conv, &pamh);<br>
    +<br>
    +        if (ret != PAM_SUCCESS)<br>
    +        {<br>
    +            DBG1(DBG_IKE, "XAuth pam_start for '%s' failed: %s",<br>
    +                user, pam_strerror(pamh, ret));<br>
    +        }<br>
    +        else if (up)<br>
    +        {<br>
    +            ret = pam_open_session(pamh, 0);<br>
    +            if (ret != PAM_SUCCESS)<br>
    +            {<br>
    +                DBG1(DBG_IKE, "XAuth pam_open_session for '%s'
    failed: %s",<br>
    +                    user, pam_strerror(pamh, ret));<br>
    +            }<br>
    +        }<br>
    +        else<br>
    +        {<br>
    +            ret = pam_close_session(pamh, 0);<br>
    +            if (ret != PAM_SUCCESS)<br>
    +            {<br>
    +                DBG1(DBG_IKE, "XAuth pam_close_session for '%s'
    failed: %s",<br>
    +                    user, pam_strerror(pamh, ret));<br>
    +            }<br>
    +        }<br>
    +        pam_end(pamh, ret);<br>
    +        free(user);<br>
    +    }<br>
    +    enumerator->destroy(enumerator);<br>
    +<br>
    +    return TRUE;<br>
    +}<br>
    +<br>
    +METHOD(listener_t, message_hook, bool,<br>
    +    private_xauth_pam_listener_t *this, ike_sa_t *ike_sa,<br>
    +    message_t *message, bool incoming, bool plain)<br>
    +{<br>
    +    if (plain && ike_sa->get_state(ike_sa) ==
    IKE_ESTABLISHED &&<br>
    +        !incoming && !message->get_request(message))<br>
    +    {<br>
    +        if (ike_sa->get_version(ike_sa) == IKEV1 &&<br>
    +            message->get_exchange_type(message) == TRANSACTION)<br>
    +        {<br>
    +            open_close_session(this, ike_sa, TRUE);<br>
    +        }<br>
    +        if (ike_sa->get_version(ike_sa) == IKEV2 &&<br>
    +            message->get_exchange_type(message) == IKE_AUTH)<br>
    +        {<br>
    +            open_close_session(this, ike_sa, TRUE);<br>
    +        }<br>
    +    }<br>
    +    return TRUE;<br>
    +}<br>
    +<br>
    +METHOD(listener_t, ike_updown, bool,<br>
    +    private_xauth_pam_listener_t *this, ike_sa_t *ike_sa, bool up)<br>
    +{<br>
    +    if (!up)<br>
    +    {<br>
    +        open_close_session(this, ike_sa, FALSE);<br>
    +    }<br>
    +    return TRUE;<br>
    +}<br>
    +<br>
    +METHOD(xauth_pam_listener_t, listener_destroy, void,<br>
    +    private_xauth_pam_listener_t *this)<br>
    +{<br>
    +    free(this);<br>
    +}<br>
    +<br>
    +xauth_pam_listener_t *xauth_pam_listener_create()<br>
    +{<br>
    +    private_xauth_pam_listener_t *this;<br>
    +<br>
    +    INIT(this,<br>
    +        .public = {<br>
    +            .listener = {<br>
    +                .message = _message_hook,<br>
    +                .ike_updown = _ike_updown,<br>
    +            },<br>
    +            .destroy = _listener_destroy,<br>
    +        },<br>
    +    );<br>
    +<br>
    +    return &this->public;<br>
    +}<br>
    +<br>
    diff --git a/src/libcharon/plugins/xauth_pam/xauth_pam_listener.h
    b/src/libcharon/plugins/xauth_pam/xauth_pam_listener.h<br>
    new file mode 100644<br>
    index 0000000..6e25966<br>
    --- /dev/null<br>
    +++ b/src/libcharon/plugins/xauth_pam/xauth_pam_listener.h<br>
    @@ -0,0 +1,50 @@<br>
    +/*<br>
    + * Copyright (C) 2013 Endian srl<br>
    + * Author: Andrea Bonomi <a class="moz-txt-link-rfc2396E" href="mailto:a.bonomi@endian.com"><a.bonomi@endian.com></a><br>
    + *<br>
    + * This program is free software; you can redistribute it and/or
    modify it<br>
    + * under the terms of the GNU General Public License as published
    by the<br>
    + * Free Software Foundation; either version 2 of the License, or
    (at your<br>
    + * option) any later version.  See
    <a class="moz-txt-link-rfc2396E" href="http://www.fsf.org/copyleft/gpl.txt"><http://www.fsf.org/copyleft/gpl.txt></a>.<br>
    + *<br>
    + * This program is distributed in the hope that it will be useful,
    but<br>
    + * WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY<br>
    + * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
    License<br>
    + * for more details.<br>
    + */<br>
    +<br>
    +/**<br>
    + * @defgroup xauth_pam_i xauth_pam<br>
    + * @{ @ingroup xauth_pam<br>
    + */<br>
    +<br>
    +#ifndef XAUTH_PAM_LISENER_H_<br>
    +#define XAUTH_PAM_LISTENER_H_<br>
    +<br>
    +typedef struct xauth_pam_listener_t xauth_pam_listener_t;<br>
    +<br>
    +#include <bus/listeners/listener.h><br>
    +<br>
    +/**<br>
    + * Listener<br>
    + */<br>
    +struct xauth_pam_listener_t {<br>
    +<br>
    +    /**<br>
    +     * Implements listener_t interface.<br>
    +     */<br>
    +    listener_t listener;<br>
    +<br>
    +    /**<br>
    +     * Destroy a xauth_pam_listener_t.<br>
    +     */<br>
    +    void (*destroy)(xauth_pam_listener_t *this);<br>
    +};<br>
    +<br>
    +/**<br>
    + * Create a xauth_pam_listener instance.<br>
    + */<br>
    +xauth_pam_listener_t *xauth_pam_listener_create();<br>
    +<br>
    +<br>
    +#endif /** XAUTH_PAM_LISTENER_H_ @}*/<br>
    diff --git a/src/libcharon/plugins/xauth_pam/xauth_pam_plugin.c
    b/src/libcharon/plugins/xauth_pam/xauth_pam_plugin.c<br>
    index 2ef9a6c..6e13c0b 100644<br>
    --- a/src/libcharon/plugins/xauth_pam/xauth_pam_plugin.c<br>
    +++ b/src/libcharon/plugins/xauth_pam/xauth_pam_plugin.c<br>
    @@ -15,6 +15,7 @@<br>
     <br>
     #include "xauth_pam_plugin.h"<br>
     #include "xauth_pam.h"<br>
    +#include "xauth_pam_listener.h"<br>
     <br>
     #include <daemon.h><br>
     <br>
    @@ -22,17 +23,53 @@<br>
     #define CAP_AUDIT_WRITE 29<br>
     #endif<br>
     <br>
    +typedef struct private_xauth_pam_plugin_t
    private_xauth_pam_plugin_t;<br>
    +<br>
    +/**<br>
    + * private data of xauth_pam plugin<br>
    + */<br>
    +struct private_xauth_pam_plugin_t {<br>
    +<br>
    +    /**<br>
    +     * implements plugin interface<br>
    +     */<br>
    +    xauth_pam_plugin_t public;<br>
    +<br>
    +    /**<br>
    +     * Listener <br>
    +     */<br>
    +    xauth_pam_listener_t *listener;<br>
    +<br>
    +};<br>
    +<br>
    +bool xauth_pam_method_register(private_xauth_pam_plugin_t *this,
    plugin_feature_t *feature,<br>
    +                         bool reg, void *data)<br>
    +{<br>
    +    /* (un-)register XAuth methods from plugin features */<br>
    +    xauth_method_register(this, feature, reg, data);<br>
    +    if (reg)<br>
    +    {<br>
    +        charon->bus->add_listener(charon->bus,
    &this->listener->listener);<br>
    +    }<br>
    +    else<br>
    +    {<br>
    +        charon->bus->remove_listener(charon->bus,
    &this->listener->listener);<br>
    +    }<br>
    +    return TRUE;<br>
    +}<br>
    +<br>
    +<br>
     METHOD(plugin_t, get_name, char*,<br>
    -    xauth_pam_plugin_t *this)<br>
    +    private_xauth_pam_plugin_t *this)<br>
     {<br>
         return "xauth-pam";<br>
     }<br>
     <br>
     METHOD(plugin_t, get_features, int,<br>
    -    xauth_pam_plugin_t *this, plugin_feature_t *features[])<br>
    +    private_xauth_pam_plugin_t *this, plugin_feature_t *features[])<br>
     {<br>
         static plugin_feature_t f[] = {<br>
    -        PLUGIN_CALLBACK(xauth_method_register,
    xauth_pam_create_server),<br>
    +        PLUGIN_CALLBACK(xauth_pam_method_register,
    xauth_pam_create_server),<br>
                 PLUGIN_PROVIDE(XAUTH_SERVER, "pam"),<br>
         };<br>
         *features = f;<br>
    @@ -40,7 +77,7 @@ METHOD(plugin_t, get_features, int,<br>
     }<br>
     <br>
     METHOD(plugin_t, destroy, void,<br>
    -    xauth_pam_plugin_t *this)<br>
    +    private_xauth_pam_plugin_t *this)<br>
     {<br>
         free(this);<br>
     }<br>
    @@ -50,7 +87,7 @@ METHOD(plugin_t, destroy, void,<br>
      */<br>
     plugin_t *xauth_pam_plugin_create()<br>
     {<br>
    -    xauth_pam_plugin_t *this;<br>
    +    private_xauth_pam_plugin_t *this;<br>
     <br>
         /* required for PAM authentication */<br>
         if (!lib->caps->keep(lib->caps, CAP_AUDIT_WRITE))<br>
    @@ -60,12 +97,15 @@ plugin_t *xauth_pam_plugin_create()<br>
         }<br>
     <br>
         INIT(this,<br>
    -        .plugin = {<br>
    -            .get_name = _get_name,<br>
    -            .get_features = _get_features,<br>
    -            .destroy = _destroy,<br>
    +        .public = {<br>
    +            .plugin = {<br>
    +                .get_name = _get_name,<br>
    +                .get_features = _get_features,<br>
    +                .destroy = _destroy,<br>
    +            },<br>
             },<br>
    +        .listener = xauth_pam_listener_create(),<br>
         );<br>
     <br>
    -    return &this->plugin;<br>
    +    return &this->public.plugin;<br>
     }<br>
    <br>
  </body>
</html>