Patch from Frank Cusack to make RADIUS plugin support MS-CHAP authentication.
authorDavid F. Skoll <dfs@roaringpenguin.com>
Mon, 4 Mar 2002 14:59:52 +0000 (14:59 +0000)
committerDavid F. Skoll <dfs@roaringpenguin.com>
Mon, 4 Mar 2002 14:59:52 +0000 (14:59 +0000)
pppd/Makefile.linux
pppd/chap.c
pppd/chap_ms.c
pppd/chap_ms.h
pppd/plugins/radius/Makefile.linux
pppd/plugins/radius/pppd-radius.8
pppd/plugins/radius/radius.c
pppd/plugins/radius/radiusclient/include/radiusclient.h
pppd/plugins/radius/radiusclient/lib/sendserver.c

index 5f2de1f8accd8cdcd1fb7bee523da2406d6641a4..d16a71ef747a6a5982570c5f722d8dd28c329370 100644 (file)
@@ -1,6 +1,6 @@
 #
 # pppd makefile for Linux
-# $Id: Makefile.linux,v 1.44 2002/01/14 14:26:31 dfs Exp $
+# $Id: Makefile.linux,v 1.45 2002/03/04 14:59:51 dfs Exp $
 #
 
 # Default installation locations
@@ -34,7 +34,7 @@ LIBS += -lcrypt
 endif
 
 # Uncomment the next 2 lines to include support for Microsoft's
-# MS-CHAP authentication protocol.
+# MS-CHAP authentication protocol.  Also, edit plugins/radius/Makefile.
 CHAPMS=y
 USE_CRYPT=y
 ifneq ($(wildcard /usr/lib/libcrypt.*),)
index 25427e2d15b133c96ccefd147b4270fe284ea0b2..208a144fc8569051fbf18f2925c8aa93daf0449b 100644 (file)
@@ -33,7 +33,7 @@
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
-#define RCSID  "$Id: chap.c,v 1.27 2002/03/01 14:39:18 dfs Exp $"
+#define RCSID  "$Id: chap.c,v 1.28 2002/03/04 14:59:51 dfs Exp $"
 
 /*
  * TODO:
@@ -597,6 +597,7 @@ ChapReceiveResponse(cstate, inp, id, len)
            case CHAP_MICROSOFT:
            {
                int response_offset, response_size;
+               MS_ChapResponse *rmd = (MS_ChapResponse *) remmd;
 
                if (remmd_len != MS_CHAP_RESPONSE_LEN)
                    break;                      /* not even the right length */
@@ -604,13 +605,12 @@ ChapReceiveResponse(cstate, inp, id, len)
                       secret, secret_len);
 
                /* Determine which part of response to verify against */
-               if ((u_char *) (remmd + offsetof(MS_ChapResponse, UseNT))) {
+               if (rmd->UseNT[0]) {
                    response_offset = offsetof(MS_ChapResponse, NTResp);
-                   response_size = sizeof(((MS_ChapResponse *) remmd)->NTResp);
+                   response_size = sizeof(rmd->NTResp);
                } else {
                    response_offset = offsetof(MS_ChapResponse, LANManResp);
-                   response_size =
-                       sizeof(((MS_ChapResponse *) remmd)->LANManResp);
+                   response_size = sizeof(rmd->LANManResp);
                }
 
                /* compare MDs and send the appropriate status */
index 9a7002ced4201e572762951ec376371bedcd4c56..c4b7d20298dbf18758b2bc391521c96abaef5dfa 100644 (file)
@@ -31,7 +31,7 @@
  *   You should also use DOMAIN\\USERNAME as described in README.MSCHAP80
  */
 
-#define RCSID  "$Id: chap_ms.c,v 1.16 2002/03/01 14:39:18 dfs Exp $"
+#define RCSID  "$Id: chap_ms.c,v 1.17 2002/03/04 14:59:51 dfs Exp $"
 
 #ifdef CHAPMS
 
@@ -318,9 +318,9 @@ ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len)
     ChapMS_LANMan(rchallenge, rchallenge_len, secret, secret_len, &response);
 
     /* prefered method is set by option  */
-    response.UseNT = !ms_lanman;
+    response.UseNT[0] = !ms_lanman;
 #else
-    response.UseNT = 1;
+    response.UseNT[0] = 1;
 #endif
 
     BCOPY(&response, cstate->response, MS_CHAP_RESPONSE_LEN);
index e673f8aa24f9730efebc7368bbd9163412442a10..4418c9305f160e7b9c8c45f403c9e5a3eb1692ae 100644 (file)
@@ -19,7 +19,7 @@
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- * $Id: chap_ms.h,v 1.3 2002/03/01 14:39:18 dfs Exp $
+ * $Id: chap_ms.h,v 1.4 2002/03/04 14:59:51 dfs Exp $
  */
 
 #ifndef __CHAPMS_INCLUDE__
@@ -36,7 +36,7 @@
 typedef struct {
     u_char LANManResp[24];
     u_char NTResp[24];
-    u_char UseNT;              /* If 1, ignore the LANMan response field */
+    u_char UseNT[1];           /* If 1, ignore the LANMan response field */
 } MS_ChapResponse;
 
 void ChapMS __P((chap_state *, char *, int, char *, int));
index 1fa7ff9730e1c95787030f41301110faaee64d97..30fcb7aad425783069f86525310ae3f9fd28a6f9 100644 (file)
@@ -7,6 +7,14 @@ MANDIR=/usr/man
 PLUGIN=radius.so radattr.so
 CFLAGS=-I../.. -Iradiusclient/include -O2
 
+# Uncomment the next line to include support for Microsoft's
+# MS-CHAP authentication protocol.
+CHAPMS=y
+
+ifdef CHAPMS
+CFLAGS += -DCHAPMS=1
+endif
+
 all: $(PLUGIN)
 
 install: all
index 4b9cddd080a675e0dfcfb74bcef49c506dab4ca2..5e9bc1aea4009f402cb20dcf62eb13067c126fff 100644 (file)
@@ -1,5 +1,5 @@
 .\" manual page [] for RADIUS plugin for pppd 2.4
-.\" $Id: pppd-radius.8,v 1.1 2002/01/22 16:03:00 dfs Exp $
+.\" $Id: pppd-radius.8,v 1.2 2002/03/04 14:59:51 dfs Exp $
 .\" SH section heading
 .\" SS subsection heading
 .\" LP paragraph
@@ -17,8 +17,8 @@ radius.so \- RADIUS authentication plugin for
 plugin radius.so
 .SH DESCRIPTION
 .LP
-The RADIUS plugin for pppd permits pppd to perform CHAP and PAP authentication
-against a RADIUS server instead of the usual
+The RADIUS plugin for pppd permits pppd to perform PAP, CHAP, and MS-CHAP
+authentication against a RADIUS server instead of the usual
 .I /etc/ppp/pap-secrets
 and
 .I /etc/ppp/chap-secrets
index fa638d0327d4fced1d478aba858d1d3515673bea..358fc95a654c733dcd704b9bb7857a1073fdbb41 100644 (file)
@@ -2,8 +2,8 @@
 *
 * radius.c
 *
-* RADIUS plugin for pppd.  Performs PAP and CHAP authentication using
-* RADIUS.
+* RADIUS plugin for pppd.  Performs PAP, CHAP and MS-CHAP authentication
+* using RADIUS.
 *
 * Copyright (C) 2002 Roaring Penguin Software Inc.
 *
 *
 ***********************************************************************/
 static char const RCSID[] =
-"$Id: radius.c,v 1.4 2002/03/01 15:16:51 dfs Exp $";
+"$Id: radius.c,v 1.5 2002/03/04 14:59:51 dfs Exp $";
 
 #include "pppd.h"
 #include "chap.h"
+#ifdef CHAPMS
+#include "chap_ms.h"
+#endif
 #include "radiusclient.h"
 #include "fsm.h"
 #include "ipcp.h"
@@ -252,7 +255,7 @@ radius_pap_auth(char *user,
 * %RETURNS:
 *  CHAP_SUCCESS if we can authenticate, CHAP_FAILURE if we cannot.
 * %DESCRIPTION:
-* Performs CHAP authentication using RADIUS
+* Performs CHAP and MS-CHAP authentication using RADIUS
 ***********************************************************************/
 static int
 radius_chap_auth(char *user,
@@ -264,7 +267,7 @@ radius_chap_auth(char *user,
     UINT4 av_type;
     static char radius_msg[BUF_LEN];
     int result;
-    u_char cpassword[MD5_SIGNATURE_SIZE+1];
+    u_char cpassword[MAX_RESPONSE_LENGTH + 1];
     radius_msg[0] = 0;
 
     if (radius_init(radius_msg) < 0) {
@@ -272,9 +275,13 @@ radius_chap_auth(char *user,
        return CHAP_FAILURE;
     }
 
-    /* we handle md5 digest at the moment */
-    if (cstate->chal_type != CHAP_DIGEST_MD5) {
-       error("RADIUS: Challenge type not MD5");
+    /* return error for types we can't handle */
+    if ((cstate->chal_type != CHAP_DIGEST_MD5)
+#ifdef CHAPMS
+       && (cstate->chal_type != CHAP_MICROSOFT)
+#endif
+       ) {
+       error("RADIUS: Challenge type %u unsupported", cstate->chal_type);
        return CHAP_FAILURE;
     }
 
@@ -300,16 +307,44 @@ radius_chap_auth(char *user,
     rc_avpair_add (&send, PW_USER_NAME, rstate.user , 0, VENDOR_NONE);
 
     /*
-     * add the CHAP-Password and CHAP-Challenge fields
+     * add the challenge and response fields
      */
+    switch (cstate->chal_type) {
+    case CHAP_DIGEST_MD5:
+       /* CHAP-Challenge and CHAP-Password */
+       cpassword[0] = cstate->chal_id;
+       memcpy(&cpassword[1], remmd, MD5_SIGNATURE_SIZE);
+
+       rc_avpair_add(&send, PW_CHAP_CHALLENGE,
+                     cstate->challenge, cstate->chal_len, VENDOR_NONE);
+       rc_avpair_add(&send, PW_CHAP_PASSWORD,
+                     cpassword, MD5_SIGNATURE_SIZE + 1, VENDOR_NONE);
+       break;
+
+#ifdef CHAPMS
+    case CHAP_MICROSOFT:
+    {
+       /* MS-CHAP-Challenge and MS-CHAP-Response */
+       MS_ChapResponse *rmd = remmd;
+       u_char *p = cpassword;
+
+       *p++ = cstate->chal_id;
+       /* The idiots use a different field order in RADIUS than PPP */
+       memcpy(p, rmd->UseNT, sizeof(rmd->UseNT));
+       p += sizeof(rmd->UseNT);
+       memcpy(p, rmd->LANManResp, sizeof(rmd->LANManResp));
+       p += sizeof(rmd->LANManResp);
+       memcpy(p, rmd->NTResp, sizeof(rmd->NTResp));
+
+       rc_avpair_add(&send, PW_MS_CHAP_CHALLENGE,
+                     cstate->challenge, cstate->chal_len, VENDOR_MICROSOFT);
+       rc_avpair_add(&send, PW_MS_CHAP_RESPONSE,
+                     cpassword, MS_CHAP_RESPONSE_LEN + 1, VENDOR_MICROSOFT);
+       break;
+    }
+#endif
 
-    cpassword[0] = cstate->chal_id;
-
-    memcpy(&cpassword[1], remmd, MD5_SIGNATURE_SIZE);
-
-    rc_avpair_add(&send, PW_CHAP_PASSWORD, cpassword, MD5_SIGNATURE_SIZE + 1, VENDOR_NONE);
-
-    rc_avpair_add(&send, PW_CHAP_CHALLENGE, cstate->challenge, cstate->chal_len, VENDOR_NONE);
+    }
 
     /*
      * make authentication with RADIUS server
index 5604987f8b950fb399a2d0722b3335f28d9b01cf..141e69039ac16ff88c6259fac91c2d2912ecbd8a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: radiusclient.h,v 1.3 2002/03/01 14:39:19 dfs Exp $
+ * $Id: radiusclient.h,v 1.4 2002/03/04 14:59:52 dfs Exp $
  *
  * Copyright (C) 1995,1996,1997,1998 Lars Fenneberg
  *
@@ -83,8 +83,8 @@ typedef struct pw_auth_hdr
 #define MAX_SECRET_LENGTH              (3 * 16) /* MUST be multiple of 16 */
 #define CHAP_VALUE_LENGTH              16
 
-#define PW_AUTH_UDP_PORT               1645
-#define PW_ACCT_UDP_PORT               1646
+#define PW_AUTH_UDP_PORT               1812
+#define PW_ACCT_UDP_PORT               1813
 
 #define PW_TYPE_STRING                 0
 #define PW_TYPE_INTEGER                        1
@@ -154,6 +154,10 @@ typedef struct pw_auth_hdr
 #define        PW_PORT_LIMIT                   62      /* integer */
 #define PW_LOGIN_LAT_PORT               63      /* string */
 
+/* Vendor RADIUS attribute-value pairs */
+#define PW_MS_CHAP_CHALLENGE           11      /* string */
+#define PW_MS_CHAP_RESPONSE            1       /* string */
+
 /*     Accounting */
 
 #define        PW_ACCT_STATUS_TYPE             40      /* integer */
@@ -277,6 +281,7 @@ typedef struct pw_auth_hdr
 
 /* Vendor codes */
 #define VENDOR_NONE     (-1)
+#define VENDOR_MICROSOFT       311
 
 /* Server data structures */
 
index 34c489cd9c140717c63b8d0b421c09123a46fd76..23a056695e59ee01f1031e8d6c34c2f5b7d70da0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: sendserver.c,v 1.1 2002/01/22 16:03:02 dfs Exp $
+ * $Id: sendserver.c,v 1.2 2002/03/04 14:59:52 dfs Exp $
  *
  * Copyright (C) 1995,1996,1997 Lars Fenneberg
  *
@@ -177,8 +177,8 @@ static int rc_pack_list (VALUE_PAIR *vp, char *secret, AUTH_HDR *auth)
                    }
                    break;
                }
-               vp = vp->next;
            }
+           vp = vp->next;
        }
     return total_length;
 }