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:
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.