common-name-as-username

This is where we can discuss what we would like to see added or changed in OpenVPN.

Moderators: TinCanTech, TinCanTech, TinCanTech, TinCanTech, TinCanTech, TinCanTech

Post Reply
jpatterson
OpenVpn Newbie
Posts: 2
Joined: Fri Mar 04, 2011 7:14 pm

common-name-as-username

Post by jpatterson » Fri Mar 04, 2011 7:34 pm

Maybe I'm missing something here, but I sort of understand the rationale for having the "--username-as-common-name" configuration directive, but I can't understand why there isn't an option to do the reverse. A similar effect could be achieved by exporting the CN as a "special variable" in addition to to USERNAME and PASSWORD for authentication plugins and/or scripts.

My reason for wanting this is that, right now, if you have both certificate-based and username/password-based authentication enabled, a user can log in as any valid user, given any valid certificate. So if an attacker manages to compromise any of my user's certificates and any other user's password, they can successfully log in. I would much rather have things such that an attacker who compromises a single user's certificate must then also compromise that particular user's password, not just anyone's.

I can't figure out a way to do this given the current constraints, but it certainly seems like it would be a good idea...

User avatar
janjust
Forum Team
Posts: 2703
Joined: Fri Aug 20, 2010 2:57 pm
Location: Amsterdam
Contact:

Re: common-name-as-username

Post by janjust » Fri Mar 04, 2011 10:04 pm

during a client connect there are several env vars available. I'd recommend to add a 'client-connect' script which does little more than

Code: Select all

#!/bin/bash
echo [$@]
env
to see what is available. Amongst others:
* $username
* $common_name
* $tls_id_0

jpatterson
OpenVpn Newbie
Posts: 2
Joined: Fri Mar 04, 2011 7:14 pm

Re: common-name-as-username

Post by jpatterson » Mon Mar 07, 2011 3:52 pm

That's exactly the sort of solution I was looking for. Completely functional and doesn't require any changes...

I have also hacked up the pam auth plugin to do pretty much the same thing:

Code: Select all

Index: openvpn/plugin/auth-pam/README
===================================================================
--- openvpn/plugin/auth-pam/README	(revision 7003)
+++ openvpn/plugin/auth-pam/README	(working copy)
@@ -48,7 +48,7 @@
 
   plugin openvpn-auth-pam.so "test name USERNAME password PASSWORD"
 
-While "USERNAME" and "PASSWORD" are special strings which substitute
+While "USERNAME" "COMMONNAME" and "PASSWORD" are special strings which substitute
 to client-supplied values, it is also possible to name literal values
 to use as PAM module query responses.  For example, suppose that the
 login module queried for a third parameter, "domain" which
Index: openvpn/plugin/auth-pam/auth-pam.c
===================================================================
--- openvpn/plugin/auth-pam/auth-pam.c	(revision 7003)
+++ openvpn/plugin/auth-pam/auth-pam.c	(working copy)
@@ -81,6 +81,7 @@
  *
  *  "USERNAME" -- substitute client-supplied username
  *  "PASSWORD" -- substitute client-specified password
+ *  "COMMONNAME" -- substitute client certificate common name
  */
 
 #define N_NAME_VALUE 16
@@ -104,6 +105,7 @@
 
   char username[128];
   char password[128];
+  char common_name[128];
 
   const struct name_value_list *name_value_list;
 };
@@ -441,12 +443,14 @@
       /* get username/password from envp string array */
       const char *username = get_env ("username", envp);
       const char *password = get_env ("password", envp);
+      const char *common_name = get_env ("common_name", envp) ? get_env ("common_name", envp) : "";
 
       if (username && strlen (username) > 0 && password)
 	{
 	  if (send_control (context->foreground_fd, COMMAND_VERIFY) == -1
 	      || send_string (context->foreground_fd, username) == -1
-	      || send_string (context->foreground_fd, password) == -1)
+	      || send_string (context->foreground_fd, password) == -1
+	      || send_string (context->foreground_fd, common_name) == -1)
 	    {
 	      fprintf (stderr, "AUTH-PAM: Error sending auth info to background process\n");
 	    }
@@ -563,6 +567,8 @@
 		    return_value = up->username;
 		  else if (!strcmp (match_value, "PASSWORD"))
 		    return_value = up->password;
+                  else if (!strcmp (match_value, "COMMONNAME"))
+                    return_value = up->common_name;
 		  else
 		    return_value = match_value;
 
@@ -709,7 +715,8 @@
 	{
 	case COMMAND_VERIFY:
 	  if (recv_string (fd, up.username, sizeof (up.username)) == -1
-	      || recv_string (fd, up.password, sizeof (up.password)) == -1)
+	      || recv_string (fd, up.password, sizeof (up.password)) == -1
+		|| recv_string (fd, up.common_name, sizeof (up.common_name)) == -1)
 	    {
 	      fprintf (stderr, "AUTH-PAM: BACKGROUND: read error on command channel: code=%d, exiting\n",
 		       command);
in case anyone feels similarly and would rather use a plugin than a script.

Post Reply