[PATCH] Multi-factor authentication plugin hook

Michael McConnell <[email protected]>
Newsgroups gmane.linux.ppp
Message-ID <[email protected]>
Hi,

This patch introduces a plugin for MFA support for PPP servers.

This initial version has only been tested for CHAP logins, as that is
what we are using at work thus what I can test.  It is in production use
on our L2TP VPN server with a plugin that calls out to Duo.  It will
likely require expanding to cover all client-to-server authentication
paths.

The idea here is simple, for a MFA platform that just requires the
username being authenticated, this allows a plugin that will go off and
do this. Unlike the existing authentication hooks, this is enabled for
server-side use.

It won't work with those MFAs that require a one-time password to be 
entered in addition to the regular password, but does work for those 
that push an authentication request to an app on a mobile phone.

I am sharing this in the off-chance that it might be useful to somebody.

Michael McConnell
Fri 28 Jan 2022

diff -urN ppp-2.4.9.orig/pppd/auth.c ppp-2.4.9/pppd/auth.c
--- ppp-2.4.9.orig/pppd/auth.c  2021-01-04 23:06:37.000000000 +0000
+++ ppp-2.4.9/pppd/auth.c       2022-01-28 10:47:21.190270504 +0000
@@ -202,6 +202,9 @@

  int (*allowed_address_hook)(u_int32_t addr) = NULL;

+/* Hook for a plugin to perform MFA given the user/client name */
+int (*auth_mfa_hook) __P((char *mfauser)) = NULL;
+
  #ifdef HAVE_MULTILINK
  /* Hook for plugin to hear when an interface joins a multilink bundle */
  void (*multilink_join_hook)(void) = NULL;
@@ -1454,6 +1457,10 @@
      slprintf(user, sizeof(user), "%.*v", userlen, auser);
      *msg = "";

+    /* Try MFA, if the plugin returns nonzero we fail to authenticate */
+    if (auth_mfa_hook)
+      if ( (*auth_mfa_hook)(user) ) return UPAP_AUTHNAK;
+
      /*
       * Check if a plugin wants to handle this.
       */
@@ -1812,6 +1819,10 @@
             free_wordlist(addrs);
      }

+    /* Try MFA, if the plugin returns nonzero we fail to authenticate */
+    if (auth_mfa_hook)
+      if ( (*auth_mfa_hook)(client) ) return 0;
+
      len = strlen(secbuf);
      if (len > MAXSECRETLEN) {
         error("Secret for %s on %s is too long", client, server);
diff -urN ppp-2.4.9.orig/pppd/pppd.h ppp-2.4.9/pppd/pppd.h
--- ppp-2.4.9.orig/pppd/pppd.h  2021-01-04 23:06:37.000000000 +0000
+++ ppp-2.4.9/pppd/pppd.h       2022-01-28 10:47:21.192289610 +0000
@@ -767,6 +767,9 @@
  extern int (*eaptls_passwd_hook)(char *user, char *passwd);
  #endif

+/* Hook for a plugin to perform MFA given the user/client name */
+extern int (*auth_mfa_hook) __P((char *mfauser));
+
  /* Let a plugin snoop sent and received packets.  Useful for L2TP */
  extern void (*snoop_recv_hook)(unsigned char *p, int len);
  extern void (*snoop_send_hook)(unsigned char *p, int len);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.