If the user doesn't supply any arguments to the plugin in the OpenVPN
configuration file, then it defaults to setting the second argument to
the pam_start() function with the username that the other end of the
vpn supplied.  The pam libraries use this as the initial value for the
PAM_USER pam 'item'.

If the administrator supplies one or more arguments to the auth-pam
plugin, then this default behaviour is abandoned, and the user argument
is set to NULL.  The administrator must then supply a match for the
message text content which the pam module will (hopefully) supply in
order to try to discover the message (some pam modules will just give
up at this stage, and fail the authentication e.g. Google Authenticator
will fail if PAM_USER is set to NULL).

The message text which the pam module supplies is intended to be read
by a human, not parsed by other code (as is the current behaviour of
the plugin), and as such may be subject to change (e.g. because of
localisation changes etc.).

This patch allows the user to supply a value for the second argument of
pam_start, if they have supplied any arguments (by using the special
value of 'PAM_USER' as the question message).  This allows operation
with inflexible pam modules, and also decreases the likelihood that
other system changes (e.g. localisation changes, package updates etc.)
will break an existing OpenVPN setup.

Signed-off-by: Tim Small <t...@seoss.co.uk>
---
 src/plugins/auth-pam/auth-pam.c | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/src/plugins/auth-pam/auth-pam.c b/src/plugins/auth-pam/auth-pam.c
index 48279cd..2d0f4d0 100644
--- a/src/plugins/auth-pam/auth-pam.c
+++ b/src/plugins/auth-pam/auth-pam.c
@@ -699,11 +699,27 @@ pam_auth (const char *service, const struct user_pass *up)
   int status;
   int ret = 0;
   const int name_value_list_provided = (up->name_value_list && 
up->name_value_list->len > 0);
+  char *pam_user = NULL;
+  if (name_value_list_provided)
+    {
+      if (get_value_with_subst (up, "PAM_USER", &pam_user))
+        {
+          if (DEBUG (up->verb))
+            fprintf (stderr, "Passing user '%s' in pam_start\n", pam_user);
+        }
+      else
+        {
+          if (DEBUG (up->verb))
+            fprintf (stderr, "User didn't specify value for user argument to 
pam_start()\n");
+        }
+    }

   /* Initialize PAM */
   conv.conv = my_conv;
   conv.appdata_ptr = (void *)up;
-  status = pam_start (service, name_value_list_provided ? NULL : up->username, 
&conv, &pamh);
+  status = pam_start (service, name_value_list_provided ? pam_user : 
up->username, &conv, &pamh);
+  if (pam_user)
+    free(pam_user);
   if (status != PAM_SUCCESS)
     {
       fprintf (stderr, "AUTH-PAM: BACKGROUND: user '%s' / commonname '%s' "
-- 
2.1.4


Reply via email to