]> git.ozlabs.org Git - ppp.git/commitdiff
First large MPPE patch from Frank Cusack.
authorDavid F. Skoll <dfs@roaringpenguin.com>
Tue, 2 Apr 2002 13:55:00 +0000 (13:55 +0000)
committerDavid F. Skoll <dfs@roaringpenguin.com>
Tue, 2 Apr 2002 13:55:00 +0000 (13:55 +0000)
18 files changed:
README.MSCHAP81
include/linux/ppp-comp.h
include/net/ppp-comp.h
pppd/Makefile.linux
pppd/auth.c
pppd/ccp.c
pppd/ccp.h
pppd/chap.c
pppd/chap_ms.c
pppd/chap_ms.h
pppd/options.c
pppd/plugins/radius/radius.c
pppd/pppd.8
pppd/pppd.h
pppd/sha1.c
pppd/sha1.h
pppd/sys-linux.c
pppd/upap.c

index 1d415a9753222ea5418f2f47cae47c96342a851a..c8e83f3966987afa0619386484e9295e301c76f6 100644 (file)
@@ -16,7 +16,7 @@ as plaintext-equivalent.  (Well, the Change-Password packet is arguably
 an advantage.)  It does introduce a significant weakness if the LM hash
 is used.  Additionally, the format of the failure packet potentially
 gives information to an attacker.  The weakness of the LM hash is partly
 an advantage.)  It does introduce a significant weakness if the LM hash
 is used.  Additionally, the format of the failure packet potentially
 gives information to an attacker.  The weakness of the LM hash is partly
-address in RFC 2433, which deprecates its use.
+addressed in RFC 2433, which deprecates its use.
 
 MS-CHAPv2 adds 2 benefits to MS-CHAP.  (1) The LM hash is no longer
 used.  (2) Mutual authentication is required.  Note that the mutual
 
 MS-CHAPv2 adds 2 benefits to MS-CHAP.  (1) The LM hash is no longer
 used.  (2) Mutual authentication is required.  Note that the mutual
index 92aa64572433c5c2cb3cff38162f566f8c143ed3..091a57539578e313113d550991e5fa5b4b97e6e0 100644 (file)
  * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
  * OR MODIFICATIONS.
  *
  * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
  * OR MODIFICATIONS.
  *
- * $Id: ppp-comp.h,v 1.8 1999/07/23 06:53:40 paulus Exp $
+ * $Id: ppp-comp.h,v 1.9 2002/04/02 13:54:59 dfs Exp $
  */
 
 /*
  */
 
 /*
- *  ==FILEVERSION 980319==
+ *  ==FILEVERSION 20020319==
  *
  *  NOTE TO MAINTAINERS:
  *     If you modify this file at all, please set the above date.
  *
  *  NOTE TO MAINTAINERS:
  *     If you modify this file at all, please set the above date.
@@ -186,6 +186,100 @@ struct compressor {
                                 + DEFLATE_METHOD_VAL)
 #define DEFLATE_CHK_SEQUENCE   0
 
                                 + DEFLATE_METHOD_VAL)
 #define DEFLATE_CHK_SEQUENCE   0
 
+/*
+ * Definitions for MPPE.
+ */
+
+#define CI_MPPE                        18      /* config option for MPPE */
+#define CILEN_MPPE             6       /* length of config option */
+
+#define MPPE_PAD               4       /* MPPE growth per frame */
+#define MPPE_MAX_KEY_LEN       16      /* largest key length (128-bit) */
+
+/* option bits for ccp_options.mppe */
+#define MPPE_OPT_40            0x01    /* 40 bit */
+#define MPPE_OPT_128           0x02    /* 128 bit */
+#define MPPE_OPT_STATEFUL      0x04    /* stateful mode */
+/* unsupported opts */
+#define MPPE_OPT_56            0x08    /* 56 bit */
+#define MPPE_OPT_MPPC          0x10    /* MPPC compression */
+#define MPPE_OPT_D             0x20    /* Unknown */
+#define MPPE_OPT_UNSUPPORTED (MPPE_OPT_56|MPPE_OPT_MPPC|MPPE_OPT_D)
+#define MPPE_OPT_UNKNOWN       0x40    /* Bits !defined in RFC 3078 were set */
+
+/*
+ * This is not nice ... the alternative is a bitfield struct though.
+ * And unfortunately, we cannot share the same bits for the option
+ * names above since C and H are the same bit.  We could do a u_int32
+ * but then we have to do a htonl() all the time and/or we still need
+ * to know which octet is which.
+ */
+#define MPPE_C_BIT             0x01    /* MPPC */
+#define MPPE_D_BIT             0x10    /* Obsolete, usage unknown */
+#define MPPE_L_BIT             0x20    /* 40-bit */
+#define MPPE_S_BIT             0x40    /* 128-bit */
+#define MPPE_M_BIT             0x80    /* 56-bit, not supported */
+#define MPPE_H_BIT             0x01    /* Stateless (in a different byte) */
+
+/* Does not include H bit; used for least significant octet only. */
+#define MPPE_ALL_BITS (MPPE_D_BIT|MPPE_L_BIT|MPPE_S_BIT|MPPE_M_BIT|MPPE_H_BIT)
+
+/* Build a CI from mppe opts (see RFC 3078) */
+#define MPPE_OPTS_TO_CI(opts, ci)              \
+    do {                                       \
+       u_char *ptr = ci; /* u_char[4] */       \
+                                               \
+       /* H bit */                             \
+       if (opts & MPPE_OPT_STATEFUL)           \
+           *ptr++ = 0x0;                       \
+       else                                    \
+           *ptr++ = MPPE_H_BIT;                \
+       *ptr++ = 0;                             \
+       *ptr++ = 0;                             \
+                                               \
+       /* S,L bits */                          \
+       *ptr = 0;                               \
+       if (opts & MPPE_OPT_128)                \
+           *ptr |= MPPE_S_BIT;                 \
+       if (opts & MPPE_OPT_40)                 \
+           *ptr |= MPPE_L_BIT;                 \
+       /* M,D,C bits not supported */          \
+    } while (/* CONSTCOND */ 0)
+
+/* The reverse of the above */
+#define MPPE_CI_TO_OPTS(ci, opts)              \
+    do {                                       \
+       u_char *ptr = ci; /* u_char[4] */       \
+                                               \
+       opts = 0;                               \
+                                               \
+       /* H bit */                             \
+       if (!(ptr[0] & MPPE_H_BIT))             \
+           opts |= MPPE_OPT_STATEFUL;          \
+                                               \
+       /* S,L bits */                          \
+       if (ptr[3] & MPPE_S_BIT)                \
+           opts |= MPPE_OPT_128;               \
+       if (ptr[3] & MPPE_L_BIT)                \
+           opts |= MPPE_OPT_40;                \
+                                               \
+       /* M,D,C bits */                        \
+       if (ptr[3] & MPPE_M_BIT)                \
+           opts |= MPPE_OPT_56;                \
+       if (ptr[3] & MPPE_D_BIT)                \
+           opts |= MPPE_OPT_D;                 \
+       if (ptr[3] & MPPE_C_BIT)                \
+           opts |= MPPE_OPT_MPPC;              \
+                                               \
+       /* Other bits */                        \
+       if (ptr[0] & ~MPPE_H_BIT)               \
+           opts |= MPPE_OPT_UNKNOWN;           \
+       if (ptr[1] || ptr[2])                   \
+           opts |= MPPE_OPT_UNKNOWN;           \
+       if (ptr[3] & ~MPPE_ALL_BITS)            \
+           opts |= MPPE_OPT_UNKNOWN;           \
+    } while (/* CONSTCOND */ 0)
+
 /*
  * Definitions for other, as yet unsupported, compression methods.
  */
 /*
  * Definitions for other, as yet unsupported, compression methods.
  */
index fe62a61f1cea008c96c90fc136a3968a1fac0fac..10fc3bc9cb595cae7b1b1420d8a506b4e7a15d78 100644 (file)
@@ -24,7 +24,7 @@
  * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
  * OR MODIFICATIONS.
  *
  * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
  * OR MODIFICATIONS.
  *
- * $Id: ppp-comp.h,v 1.11 1998/03/25 03:33:34 paulus Exp $
+ * $Id: ppp-comp.h,v 1.12 2002/04/02 13:54:59 dfs Exp $
  */
 
 #ifndef _NET_PPP_COMP_H
  */
 
 #ifndef _NET_PPP_COMP_H
@@ -154,6 +154,99 @@ struct compressor {
                                 + DEFLATE_METHOD_VAL)
 #define DEFLATE_CHK_SEQUENCE   0
 
                                 + DEFLATE_METHOD_VAL)
 #define DEFLATE_CHK_SEQUENCE   0
 
+/*
+ * Definitions for MPPE.
+ */
+#define CI_MPPE                        18      /* config option for MPPE */
+#define CILEN_MPPE             6       /* length of config option */
+
+#define MPPE_PAD               4       /* MPPE growth per frame */
+#define MPPE_MAX_KEY_LEN       16      /* largest key length (128-bit) */
+
+/* option bits for ccp_options.mppe */
+#define MPPE_OPT_40            0x01    /* 40 bit */
+#define MPPE_OPT_128           0x02    /* 128 bit */
+#define MPPE_OPT_STATEFUL      0x04    /* stateful mode */
+/* unsupported opts */
+#define MPPE_OPT_56            0x08    /* 56 bit */
+#define MPPE_OPT_MPPC          0x10    /* MPPC compression */
+#define MPPE_OPT_D             0x20    /* Unknown */
+#define MPPE_OPT_UNSUPPORTED (MPPE_OPT_56|MPPE_OPT_MPPC|MPPE_OPT_D)
+#define MPPE_OPT_UNKNOWN       0x40    /* Bits !defined in RFC 3078 were set */
+
+/*
+ * This is not nice ... the alternative is a bitfield struct though.
+ * And unfortunately, we cannot share the same bits for the option
+ * names above since C and H are the same bit.  We could do a u_int32
+ * but then we have to do a htonl() all the time and/or we still need
+ * to know which octet is which.
+ */
+#define MPPE_C_BIT             0x01    /* MPPC */
+#define MPPE_D_BIT             0x10    /* Obsolete, usage unknown */
+#define MPPE_L_BIT             0x20    /* 40-bit */
+#define MPPE_S_BIT             0x40    /* 128-bit */
+#define MPPE_M_BIT             0x80    /* 56-bit, not supported */
+#define MPPE_H_BIT             0x01    /* Stateless (in a different byte) */
+
+/* Does not include H bit; used for least significant octet only. */
+#define MPPE_ALL_BITS (MPPE_D_BIT|MPPE_L_BIT|MPPE_S_BIT|MPPE_M_BIT|MPPE_H_BIT)
+
+/* Build a CI from mppe opts (see RFC 3078) */
+#define MPPE_OPTS_TO_CI(opts, ci)              \
+    do {                                       \
+       u_char *ptr = ci; /* u_char[4] */       \
+                                               \
+       /* H bit */                             \
+       if (opts & MPPE_OPT_STATEFUL)           \
+           *ptr++ = 0x0;                       \
+       else                                    \
+           *ptr++ = MPPE_H_BIT;                \
+       *ptr++ = 0;                             \
+       *ptr++ = 0;                             \
+                                               \
+       /* S,L bits */                          \
+       *ptr = 0;                               \
+       if (opts & MPPE_OPT_128)                \
+           *ptr |= MPPE_S_BIT;                 \
+       if (opts & MPPE_OPT_40)                 \
+           *ptr |= MPPE_L_BIT;                 \
+       /* M,D,C bits not supported */          \
+    } while (/* CONSTCOND */ 0)
+
+/* The reverse of the above */
+#define MPPE_CI_TO_OPTS(ci, opts)              \
+    do {                                       \
+       u_char *ptr = ci; /* u_char[4] */       \
+                                               \
+       opts = 0;                               \
+                                               \
+       /* H bit */                             \
+       if (!(ptr[0] & MPPE_H_BIT))             \
+           opts |= MPPE_OPT_STATEFUL;          \
+                                               \
+       /* S,L bits */                          \
+       if (ptr[3] & MPPE_S_BIT)                \
+           opts |= MPPE_OPT_128;               \
+       if (ptr[3] & MPPE_L_BIT)                \
+           opts |= MPPE_OPT_40;                \
+                                               \
+       /* M,D,C bits */                        \
+       if (ptr[3] & MPPE_M_BIT)                \
+           opts |= MPPE_OPT_56;                \
+       if (ptr[3] & MPPE_D_BIT)                \
+           opts |= MPPE_OPT_D;                 \
+       if (ptr[3] & MPPE_C_BIT)                \
+           opts |= MPPE_OPT_MPPC;              \
+                                               \
+       /* Other bits */                        \
+       if (ptr[0] & ~MPPE_H_BIT)               \
+           opts |= MPPE_OPT_UNKNOWN;           \
+       if (ptr[1] || ptr[2])                   \
+           opts |= MPPE_OPT_UNKNOWN;           \
+       if (ptr[3] & ~MPPE_ALL_BITS)            \
+           opts |= MPPE_OPT_UNKNOWN;           \
+    } while (/* CONSTCOND */ 0)
+
 /*
  * Definitions for other, as yet unsupported, compression methods.
  */
 /*
  * Definitions for other, as yet unsupported, compression methods.
  */
index aea5fb9e9590f6c52344ed4bfc8b64efabb9b9cc..57b6b08091a78e105ad039c3df3785dcaa9f0965 100644 (file)
@@ -1,6 +1,6 @@
 #
 # pppd makefile for Linux
 #
 # pppd makefile for Linux
-# $Id: Makefile.linux,v 1.46 2002/03/05 15:14:04 dfs Exp $
+# $Id: Makefile.linux,v 1.47 2002/04/02 13:54:59 dfs Exp $
 #
 
 # Default installation locations
 #
 
 # Default installation locations
@@ -34,9 +34,12 @@ LIBS += -lcrypt
 endif
 
 # Uncomment the next 2 lines to include support for Microsoft's
 endif
 
 # Uncomment the next 2 lines to include support for Microsoft's
-# MS-CHAP authentication protocol.  Also, edit plugins/radius/Makefile.
+# MS-CHAP authentication protocol.  Also, edit plugins/radius/Makefile.linux.
 CHAPMS=y
 USE_CRYPT=y
 CHAPMS=y
 USE_CRYPT=y
+# Uncomment the next line to include support for MPPE.  CHAPMS (above) must
+# also be enabled.  Also, edit plugins/radius/Makefile.linux.
+MPPE=y
 ifneq ($(wildcard /usr/lib/libcrypt.*),)
 HAVE_CRYPT_H=y
 endif
 ifneq ($(wildcard /usr/lib/libcrypt.*),)
 HAVE_CRYPT_H=y
 endif
@@ -83,6 +86,9 @@ PPPDOBJS += md4.o chap_ms.o
 ifdef MSLANMAN
 CFLAGS   += -DMSLANMAN=1
 endif
 ifdef MSLANMAN
 CFLAGS   += -DMSLANMAN=1
 endif
+ifdef MPPE
+CFLAGS   += -DMPPE=1
+endif
 endif
 
 ifdef HAS_SHADOW
 endif
 
 ifdef HAS_SHADOW
index 61b50e5b95d68e9bf249f683ab2b9c6faf504e0a..67f12782584c279b21fc705f05e3fbac0393db50 100644 (file)
@@ -32,7 +32,7 @@
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
-#define RCSID  "$Id: auth.c,v 1.75 2002/03/05 15:14:04 dfs Exp $"
+#define RCSID  "$Id: auth.c,v 1.76 2002/04/02 13:54:59 dfs Exp $"
 
 #include <stdio.h>
 #include <stddef.h>
 
 #include <stdio.h>
 #include <stddef.h>
@@ -91,6 +91,9 @@ char peer_authname[MAXNAMELEN];
 /* Records which authentication operations haven't completed yet. */
 static int auth_pending[NUM_PPP];
 
 /* Records which authentication operations haven't completed yet. */
 static int auth_pending[NUM_PPP];
 
+/* Records which authentication operations have been completed. */
+int auth_done[NUM_PPP];
+
 /* Set if we have successfully called plogin() */
 static int logged_in;
 
 /* Set if we have successfully called plogin() */
 static int logged_in;
 
@@ -184,12 +187,6 @@ char remote_name[MAXNAMELEN];      /* Peer's name for authentication */
 
 static char *uafname;          /* name of most recent +ua file */
 
 
 static char *uafname;          /* name of most recent +ua file */
 
-/* Bits in auth_pending[] */
-#define PAP_WITHPEER   1
-#define PAP_PEER       2
-#define CHAP_WITHPEER  4
-#define CHAP_PEER      8
-
 extern char *crypt __P((const char *, const char *));
 
 /* Prototypes for procedures local to this file. */
 extern char *crypt __P((const char *, const char *));
 
 /* Prototypes for procedures local to this file. */
@@ -552,6 +549,7 @@ link_established(unit)
        auth |= PAP_WITHPEER;
     }
     auth_pending[unit] = auth;
        auth |= PAP_WITHPEER;
     }
     auth_pending[unit] = auth;
+    auth_done[unit] = 0;
 
     if (!auth)
        network_phase(unit);
 
     if (!auth)
        network_phase(unit);
@@ -653,8 +651,8 @@ auth_peer_fail(unit, protocol)
  * The peer has been successfully authenticated using `protocol'.
  */
 void
  * The peer has been successfully authenticated using `protocol'.
  */
 void
-auth_peer_success(unit, protocol, name, namelen)
-    int unit, protocol;
+auth_peer_success(unit, protocol, prot_flavor, name, namelen)
+    int unit, protocol, prot_flavor;
     char *name;
     int namelen;
 {
     char *name;
     int namelen;
 {
@@ -663,6 +661,19 @@ auth_peer_success(unit, protocol, name, namelen)
     switch (protocol) {
     case PPP_CHAP:
        bit = CHAP_PEER;
     switch (protocol) {
     case PPP_CHAP:
        bit = CHAP_PEER;
+       switch (prot_flavor) {
+       case CHAP_DIGEST_MD5:
+           bit |= CHAP_MD5_PEER;
+           break;
+#ifdef CHAPMS
+       case CHAP_MICROSOFT:
+           bit |= CHAP_MS_PEER;
+           break;
+       case CHAP_MICROSOFT_V2:
+           bit |= CHAP_MS2_PEER;
+           break;
+#endif
+       }
        break;
     case PPP_PAP:
        bit = PAP_PEER;
        break;
     case PPP_PAP:
        bit = PAP_PEER;
@@ -681,6 +692,9 @@ auth_peer_success(unit, protocol, name, namelen)
     peer_authname[namelen] = 0;
     script_setenv("PEERNAME", peer_authname, 0);
 
     peer_authname[namelen] = 0;
     script_setenv("PEERNAME", peer_authname, 0);
 
+    /* Save the authentication method for later. */
+    auth_done[unit] |= bit;
+
     /*
      * If there is no more authentication still to be done,
      * proceed to the network (or callback) phase.
     /*
      * If there is no more authentication still to be done,
      * proceed to the network (or callback) phase.
@@ -712,14 +726,27 @@ auth_withpeer_fail(unit, protocol)
  * We have successfully authenticated ourselves with the peer using `protocol'.
  */
 void
  * We have successfully authenticated ourselves with the peer using `protocol'.
  */
 void
-auth_withpeer_success(unit, protocol)
-    int unit, protocol;
+auth_withpeer_success(unit, protocol, prot_flavor)
+    int unit, protocol, prot_flavor;
 {
     int bit;
 
     switch (protocol) {
     case PPP_CHAP:
        bit = CHAP_WITHPEER;
 {
     int bit;
 
     switch (protocol) {
     case PPP_CHAP:
        bit = CHAP_WITHPEER;
+       switch (prot_flavor) {
+       case CHAP_DIGEST_MD5:
+           bit |= CHAP_MD5_WITHPEER;
+           break;
+#ifdef CHAPMS
+       case CHAP_MICROSOFT:
+           bit |= CHAP_MS_WITHPEER;
+           break;
+       case CHAP_MICROSOFT_V2:
+           bit |= CHAP_MS2_WITHPEER;
+           break;
+#endif
+       }
        break;
     case PPP_PAP:
        if (passwd_from_file)
        break;
     case PPP_PAP:
        if (passwd_from_file)
@@ -731,6 +758,9 @@ auth_withpeer_success(unit, protocol)
        bit = 0;
     }
 
        bit = 0;
     }
 
+    /* Save the authentication method for later. */
+    auth_done[unit] |= bit;
+
     /*
      * If there is no more authentication still being done,
      * proceed to the network (or callback) phase.
     /*
      * If there is no more authentication still being done,
      * proceed to the network (or callback) phase.
index 6cbdafd12e7b0385ef5b1d5d2de245c7193e4412..fa8a5a0cb950f6993ebe51d008c98b556b1c5272 100644 (file)
@@ -25,7 +25,7 @@
  * OR MODIFICATIONS.
  */
 
  * OR MODIFICATIONS.
  */
 
-#define RCSID  "$Id: ccp.c,v 1.33 2002/03/06 15:00:30 dfs Exp $"
+#define RCSID  "$Id: ccp.c,v 1.34 2002/04/02 13:54:59 dfs Exp $"
 
 #include <stdlib.h>
 #include <string.h>
 
 #include <stdlib.h>
 #include <string.h>
 #include "ccp.h"
 #include <net/ppp-comp.h>
 
 #include "ccp.h"
 #include <net/ppp-comp.h>
 
+#ifdef MPPE
+#include "chap_ms.h"   /* mppe_xx_key */
+#include "lcp.h"       /* lcp_close() */
+#endif
+
 static const char rcsid[] = RCSID;
 
 /*
 static const char rcsid[] = RCSID;
 
 /*
@@ -54,6 +59,13 @@ static int setdeflate __P((char **));
 static char bsd_value[8];
 static char deflate_value[8];
 
 static char bsd_value[8];
 static char deflate_value[8];
 
+/*
+ * Option variables.
+ */
+#ifdef MPPE
+bool refuse_mppe_stateful = 1;         /* Allow stateful mode? */
+#endif
+
 static option_t ccp_option_list[] = {
     { "noccp", o_bool, &ccp_protent.enabled_flag,
       "Disable CCP negotiation" },
 static option_t ccp_option_list[] = {
     { "noccp", o_bool, &ccp_protent.enabled_flag,
       "Disable CCP negotiation" },
@@ -93,6 +105,56 @@ static option_t ccp_option_list[] = {
       "don't allow Predictor-1", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR,
       &ccp_allowoptions[0].predictor_1 },
 
       "don't allow Predictor-1", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR,
       &ccp_allowoptions[0].predictor_1 },
 
+#ifdef MPPE
+    /* MPPE options are symmetrical ... we only set wantoptions here */
+    { "require-mppe", o_bool, &ccp_wantoptions[0].mppe,
+      "require MPPE encryption",
+      OPT_PRIO | MPPE_OPT_40 | MPPE_OPT_128 },
+    { "+mppe", o_bool, &ccp_wantoptions[0].mppe,
+      "require MPPE encryption",
+      OPT_ALIAS | OPT_PRIO | MPPE_OPT_40 | MPPE_OPT_128 },
+    { "nomppe", o_bool, &ccp_wantoptions[0].mppe,
+      "don't allow MPPE encryption", OPT_PRIO },
+    { "-mppe", o_bool, &ccp_wantoptions[0].mppe,
+      "don't allow MPPE encryption", OPT_ALIAS | OPT_PRIO },
+
+    /* We use ccp_allowoptions[0].mppe as a junk var ... it is reset later */
+    { "require-mppe-40", o_bool, &ccp_allowoptions[0].mppe,
+      "require MPPE 40-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_40,
+      &ccp_wantoptions[0].mppe },
+    { "+mppe-40", o_bool, &ccp_allowoptions[0].mppe,
+      "require MPPE 40-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_40,
+      &ccp_wantoptions[0].mppe },
+    { "nomppe-40", o_bool, &ccp_allowoptions[0].mppe,
+      "don't allow MPPE 40-bit encryption",
+      OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_40, &ccp_wantoptions[0].mppe },
+    { "-mppe-40", o_bool, &ccp_allowoptions[0].mppe,
+      "don't allow MPPE 40-bit encryption",
+      OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_40,
+      &ccp_wantoptions[0].mppe },
+
+    { "require-mppe-128", o_bool, &ccp_allowoptions[0].mppe,
+      "require MPPE 128-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_128,
+      &ccp_wantoptions[0].mppe },
+    { "+mppe-128", o_bool, &ccp_allowoptions[0].mppe,
+      "require MPPE 128-bit encryption",
+      OPT_ALIAS | OPT_PRIO | OPT_A2OR | MPPE_OPT_128,
+      &ccp_wantoptions[0].mppe },
+    { "nomppe-128", o_bool, &ccp_allowoptions[0].mppe,
+      "don't allow MPPE 128-bit encryption",
+      OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_128, &ccp_wantoptions[0].mppe },
+    { "-mppe-128", o_bool, &ccp_allowoptions[0].mppe,
+      "don't allow MPPE 128-bit encryption",
+      OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_128,
+      &ccp_wantoptions[0].mppe },
+
+    /* strange one; we always request stateless, but will we allow stateful? */
+    { "mppe-stateful", o_bool, &refuse_mppe_stateful,
+      "allow MPPE stateful mode", OPT_PRIO },
+    { "nomppe-stateful", o_bool, &refuse_mppe_stateful,
+      "disallow MPPE stateful mode", OPT_PRIO | 1 },
+#endif /* MPPE */
+
     { NULL }
 };
 
     { NULL }
 };
 
@@ -175,7 +237,8 @@ static fsm_callbacks ccp_callbacks = {
  * Do we want / did we get any compression?
  */
 #define ANY_COMPRESS(opt)      ((opt).deflate || (opt).bsd_compress \
  * Do we want / did we get any compression?
  */
 #define ANY_COMPRESS(opt)      ((opt).deflate || (opt).bsd_compress \
-                                || (opt).predictor_1 || (opt).predictor_2)
+                                || (opt).predictor_1 || (opt).predictor_2 \
+                                || (opt).mppe)
 
 /*
  * Local state (mainly for handling reset-reqs and reset-acks).
 
 /*
  * Local state (mainly for handling reset-reqs and reset-acks).
@@ -386,8 +449,15 @@ ccp_input(unit, p, len)
      */
     oldstate = f->state;
     fsm_input(f, p, len);
      */
     oldstate = f->state;
     fsm_input(f, p, len);
-    if (oldstate == OPENED && p[0] == TERMREQ && f->state != OPENED)
+    if (oldstate == OPENED && p[0] == TERMREQ && f->state != OPENED) {
        notice("Compression disabled by peer.");
        notice("Compression disabled by peer.");
+#ifdef MPPE
+       if (ccp_gotoptions[unit].mppe) {
+           notice("MPPE disabled, closing LCP");
+           lcp_close(unit, "MPPE disabled by peer");
+       }
+#endif
+    }
 
     /*
      * If we get a terminate-ack and we're not asking for compression,
 
     /*
      * If we get a terminate-ack and we're not asking for compression,
@@ -450,15 +520,91 @@ ccp_resetci(f)
     fsm *f;
 {
     ccp_options *go = &ccp_gotoptions[f->unit];
     fsm *f;
 {
     ccp_options *go = &ccp_gotoptions[f->unit];
-    u_char opt_buf[16];
+    u_char opt_buf[CCP_MAX_OPTION_LENGTH];
 
     *go = ccp_wantoptions[f->unit];
     all_rejected[f->unit] = 0;
 
 
     *go = ccp_wantoptions[f->unit];
     all_rejected[f->unit] = 0;
 
+#ifdef MPPE
+    if (go->mppe) {
+       ccp_options *ao = &ccp_allowoptions[f->unit];
+       int auth_mschap_bits = auth_done[f->unit];
+       int numbits;
+
+       /*
+        * Start with a basic sanity check: mschap[v2] auth must be in
+        * exactly one direction.  RFC 3079 says that the keys are
+        * 'derived from the credentials of the peer that initiated the call',
+        * however the PPP protocol doesn't have such a concept, and pppd
+        * cannot get this info externally.  Instead we do the best we can.
+        * NB: If MPPE is required, all other compression opts are invalid.
+        *     So, we return right away if we can't do it.
+        */
+
+       /* Leave only the mschap auth bits set */
+       auth_mschap_bits &= ~(PAP_WITHPEER | PAP_PEER |
+                             CHAP_WITHPEER | CHAP_PEER |
+                             CHAP_MD5_WITHPEER | CHAP_MD5_PEER);
+       /* Count the mschap auths */
+       numbits = 0;
+       do {
+           numbits += auth_mschap_bits & 1;
+           auth_mschap_bits >>= 1;
+       } while (auth_mschap_bits);
+       if (numbits > 1) {
+           error("MPPE required, but auth done in both directions.");
+           lcp_close(f->unit, "MPPE required but not available");
+           return;
+       }
+       if (!numbits) {
+           error("MPPE required, but MS-CHAP[v2] auth not performed.");
+           lcp_close(f->unit, "MPPE required but not available");
+           return;
+       }
+
+       /* LM auth not supported for MPPE */
+       if (auth_done[f->unit] & (CHAP_MS_WITHPEER | CHAP_MS_PEER)) {
+           /* This might be noise */
+           if (go->mppe & MPPE_OPT_40) {
+               notice("Disabling 40-bit MPPE; MS-CHAP LM not supported");
+               go->mppe &= ~MPPE_OPT_40;
+           }
+       }
+
+       /* Last check: can we actually negotiate something? */
+       if (!(go->mppe & (MPPE_OPT_40 | MPPE_OPT_128))) {
+           /* Could be misconfig, could be 40-bit disabled above. */
+           error("MPPE required, but both 40-bit and 128-bit disabled.");
+           lcp_close(f->unit, "MPPE required but not available");
+           return;
+       }
+
+       /* sync options */
+       ao->mppe = go->mppe;
+       /* MPPE is not compatible with other compression types */
+       ao->bsd_compress = go->bsd_compress = 0;
+       ao->predictor_1  = go->predictor_1  = 0;
+       ao->predictor_2  = go->predictor_2  = 0;
+       ao->deflate      = go->deflate      = 0;
+    }
+#endif /* MPPE */
+
     /*
      * Check whether the kernel knows about the various
      * compression methods we might request.
      */
     /*
      * Check whether the kernel knows about the various
      * compression methods we might request.
      */
+#ifdef MPPE
+    if (go->mppe) {
+       opt_buf[0] = CI_MPPE;
+       opt_buf[1] = CILEN_MPPE;
+       MPPE_OPTS_TO_CI(go->mppe, &opt_buf[2]);
+       /* Key material unimportant here. */
+       if (ccp_test(f->unit, opt_buf, CILEN_MPPE + MPPE_MAX_KEY_LEN, 0) <= 0) {
+           error("MPPE required, but kernel has no support.");
+           lcp_close(f->unit, "MPPE required but not available");
+       }
+    }
+#endif
     if (go->bsd_compress) {
        opt_buf[0] = CI_BSD_COMPRESS;
        opt_buf[1] = CILEN_BSD_COMPRESS;
     if (go->bsd_compress) {
        opt_buf[0] = CI_BSD_COMPRESS;
        opt_buf[1] = CILEN_BSD_COMPRESS;
@@ -512,7 +658,8 @@ ccp_cilen(f)
     return (go->bsd_compress? CILEN_BSD_COMPRESS: 0)
        + (go->deflate? CILEN_DEFLATE: 0)
        + (go->predictor_1? CILEN_PREDICTOR_1: 0)
     return (go->bsd_compress? CILEN_BSD_COMPRESS: 0)
        + (go->deflate? CILEN_DEFLATE: 0)
        + (go->predictor_1? CILEN_PREDICTOR_1: 0)
-       + (go->predictor_2? CILEN_PREDICTOR_2: 0);
+       + (go->predictor_2? CILEN_PREDICTOR_2: 0)
+       + (go->mppe? CILEN_MPPE: 0);
 }
 
 /*
 }
 
 /*
@@ -530,21 +677,40 @@ ccp_addci(f, p, lenp)
 
     /*
      * Add the compression types that we can receive, in decreasing
 
     /*
      * Add the compression types that we can receive, in decreasing
-     * preference order.  Get the kernel to allocate the first one
-     * in case it gets Acked.
+     * preference order.
      */
      */
+#ifdef MPPE
+    if (go->mppe) {
+       u_char opt_buf[CILEN_MPPE + MPPE_MAX_KEY_LEN];
+
+       p[0] = opt_buf[0] = CI_MPPE;
+       p[1] = opt_buf[1] = CILEN_MPPE;
+       MPPE_OPTS_TO_CI(go->mppe, &p[2]);
+       MPPE_OPTS_TO_CI(go->mppe, &opt_buf[2]);
+       BCOPY(mppe_recv_key, &opt_buf[CILEN_MPPE], MPPE_MAX_KEY_LEN);
+       res = ccp_test(f->unit, opt_buf, CILEN_MPPE + MPPE_MAX_KEY_LEN, 0);
+       if (res > 0)
+           p += CILEN_MPPE;
+       else
+           /* This shouldn't happen, we've already tested it! */
+           lcp_close(f->unit, "MPPE required but not available in kernel");
+    }
+#endif
     if (go->deflate) {
        p[0] = go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT;
        p[1] = CILEN_DEFLATE;
        p[2] = DEFLATE_MAKE_OPT(go->deflate_size);
        p[3] = DEFLATE_CHK_SEQUENCE;
        for (;;) {
     if (go->deflate) {
        p[0] = go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT;
        p[1] = CILEN_DEFLATE;
        p[2] = DEFLATE_MAKE_OPT(go->deflate_size);
        p[3] = DEFLATE_CHK_SEQUENCE;
        for (;;) {
+           if (go->deflate_size < DEFLATE_MIN_WORKS) {
+               go->deflate = 0;
+               break;
+           }
            res = ccp_test(f->unit, p, CILEN_DEFLATE, 0);
            if (res > 0) {
                p += CILEN_DEFLATE;
                break;
            res = ccp_test(f->unit, p, CILEN_DEFLATE, 0);
            if (res > 0) {
                p += CILEN_DEFLATE;
                break;
-           }
-           if (res < 0 || go->deflate_size <= DEFLATE_MIN_WORKS) {
+           } else if (res < 0) {
                go->deflate = 0;
                break;
            }
                go->deflate = 0;
                break;
            }
@@ -563,22 +729,21 @@ ccp_addci(f, p, lenp)
        p[0] = CI_BSD_COMPRESS;
        p[1] = CILEN_BSD_COMPRESS;
        p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits);
        p[0] = CI_BSD_COMPRESS;
        p[1] = CILEN_BSD_COMPRESS;
        p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits);
-       if (p != p0) {
-           p += CILEN_BSD_COMPRESS;    /* not the first option */
-       } else {
-           for (;;) {
-               res = ccp_test(f->unit, p, CILEN_BSD_COMPRESS, 0);
-               if (res > 0) {
-                   p += CILEN_BSD_COMPRESS;
-                   break;
-               }
-               if (res < 0 || go->bsd_bits <= BSD_MIN_BITS) {
-                   go->bsd_compress = 0;
-                   break;
-               }
-               --go->bsd_bits;
-               p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits);
+       for (;;) {
+           if (go->bsd_bits < BSD_MIN_BITS) {
+               go->bsd_compress = 0;
+               break;
+           }
+           res = ccp_test(f->unit, p, CILEN_BSD_COMPRESS, 0);
+           if (res > 0) {
+               p += CILEN_BSD_COMPRESS;
+               break;
+           } else if (res < 0) {
+               go->bsd_compress = 0;
+               break;
            }
            }
+           --go->bsd_bits;
+           p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits);
        }
     }
     /* XXX Should Predictor 2 be preferable to Predictor 1? */
        }
     }
     /* XXX Should Predictor 2 be preferable to Predictor 1? */
@@ -619,6 +784,22 @@ ccp_ackci(f, p, len)
     ccp_options *go = &ccp_gotoptions[f->unit];
     u_char *p0 = p;
 
     ccp_options *go = &ccp_gotoptions[f->unit];
     u_char *p0 = p;
 
+#ifdef MPPE
+    if (go->mppe) {
+       u_char opt_buf[CILEN_MPPE];
+
+       opt_buf[0] = CI_MPPE;
+       opt_buf[1] = CILEN_MPPE;
+       MPPE_OPTS_TO_CI(go->mppe, &opt_buf[2]);
+       if (len < CILEN_MPPE || memcmp(opt_buf, p, CILEN_MPPE))
+           return 0;
+       p += CILEN_MPPE;
+       len -= CILEN_MPPE;
+       /* XXX Cope with first/fast ack */
+       if (len == 0)
+           return 1;
+    }
+#endif
     if (go->deflate) {
        if (len < CILEN_DEFLATE
            || p[0] != (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
     if (go->deflate) {
        if (len < CILEN_DEFLATE
            || p[0] != (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
@@ -696,6 +877,25 @@ ccp_nakci(f, p, len)
     memset(&no, 0, sizeof(no));
     try = *go;
 
     memset(&no, 0, sizeof(no));
     try = *go;
 
+#ifdef MPPE
+    if (go->mppe && len >= CILEN_MPPE
+       && p[0] == CI_MPPE && p[1] == CILEN_MPPE) {
+       no.mppe = 1;
+       /*
+        * Peer wants us to use a different strength or other setting.
+        * Fail if we aren't willing to use his suggestion.
+        */
+       MPPE_CI_TO_OPTS(&p[2], try.mppe);
+       if ((try.mppe & MPPE_OPT_STATEFUL) && refuse_mppe_stateful)
+           try.mppe = 0;
+       else if ((go->mppe & try.mppe) != try.mppe)
+           /* Peer must have set options we didn't request (suggest) */
+           try.mppe = 0;
+
+       if (!try.mppe)
+           lcp_close(f->unit, "MPPE required but peer negotiation failed");
+    }
+#endif /* MPPE */
     if (go->deflate && len >= CILEN_DEFLATE
        && p[0] == (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
        && p[1] == CILEN_DEFLATE) {
     if (go->deflate && len >= CILEN_DEFLATE
        && p[0] == (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
        && p[1] == CILEN_DEFLATE) {
@@ -767,6 +967,14 @@ ccp_rejci(f, p, len)
     if (len == 0 && all_rejected[f->unit])
        return -1;
 
     if (len == 0 && all_rejected[f->unit])
        return -1;
 
+#ifdef MPPE
+    if (go->mppe && len >= CILEN_MPPE
+       && p[0] == CI_MPPE && p[1] == CILEN_MPPE) {
+       lcp_close(f->unit, "MPPE required but peer refused");
+       p += CILEN_MPPE;
+       len -= CILEN_MPPE;
+    }
+#endif
     if (go->deflate && len >= CILEN_DEFLATE
        && p[0] == (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
        && p[1] == CILEN_DEFLATE) {
     if (go->deflate && len >= CILEN_DEFLATE
        && p[0] == (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
        && p[1] == CILEN_DEFLATE) {
@@ -859,6 +1067,100 @@ ccp_reqci(f, p, lenp, dont_nak)
            clen = p[1];
 
            switch (type) {
            clen = p[1];
 
            switch (type) {
+#ifdef MPPE
+           case CI_MPPE:
+               if (!ao->mppe || clen != CILEN_MPPE) {
+                   newret = CONFREJ;
+                   break;
+               }
+               MPPE_CI_TO_OPTS(&p[2], ho->mppe);
+
+               /* Nak if anything unsupported or unknown are set. */
+               if (ho->mppe & MPPE_OPT_UNSUPPORTED) {
+                   newret = CONFNAK;
+                   ho->mppe &= ~MPPE_OPT_UNSUPPORTED;
+               }
+               if (ho->mppe & MPPE_OPT_UNKNOWN) {
+                   newret = CONFNAK;
+                   ho->mppe &= ~MPPE_OPT_UNKNOWN;
+               }
+
+               /* Check state opt */
+               if (ho->mppe & MPPE_OPT_STATEFUL) {
+                  if (refuse_mppe_stateful) {
+                       /*
+                        * We can Nak and request stateless, but it's a
+                        * lot easier to just assume the peer will request
+                        * it if he can do it; stateful mode is bad over
+                        * the Internet -- which is where we expect MPPE.
+                        */
+                       newret = CONFREJ;
+                       break;
+                   } else {
+                       newret = CONFNAK;
+                   }
+               }
+
+               /* Find out which of {S,L} are set. */
+               if ((ho->mppe & MPPE_OPT_128)
+                    && (ho->mppe & MPPE_OPT_40)) {
+                   /* Both are set, negotiate the strongest. */
+                   newret = CONFNAK;
+                   if (ao->mppe & MPPE_OPT_128)
+                       ho->mppe &= ~MPPE_OPT_40;
+                   else if (ao->mppe & MPPE_OPT_40)
+                       ho->mppe &= ~MPPE_OPT_128;
+                   else {
+                       newret = CONFREJ;
+                       break;
+                   }
+               } else if (ho->mppe & MPPE_OPT_128) {
+                   if (!(ao->mppe & MPPE_OPT_128)) {
+                       newret = CONFREJ;
+                       break;
+                   }
+               } else if (ho->mppe & MPPE_OPT_40) {
+                   if (!(ao->mppe & MPPE_OPT_40)) {
+                       newret = CONFREJ;
+                       break;
+                   }
+               } else {
+                   /* Neither are set. */
+                   newret = CONFREJ;
+                   break;
+               }
+
+               /* rebuild the opts */
+               MPPE_OPTS_TO_CI(ho->mppe, &p[2]);
+               if (newret == CONFACK) {
+                   u_char opt_buf[CILEN_MPPE + MPPE_MAX_KEY_LEN];
+                   int mtu;
+
+                   BCOPY(p, opt_buf, CILEN_MPPE);
+                   BCOPY(mppe_send_key, &opt_buf[CILEN_MPPE],
+                         MPPE_MAX_KEY_LEN);
+                   if (ccp_test(f->unit, opt_buf,
+                                CILEN_MPPE + MPPE_MAX_KEY_LEN, 1) <= 0) {
+                       /* This shouldn't happen, we've already tested it! */
+                       error("MPPE required, but kernel has no support.");
+                       lcp_close(f->unit, "MPPE required but not available");
+                       newret = CONFREJ;
+                       break;
+                   }
+                   /*
+                    * We need to decrease the interface MTU by MPPE_PAD
+                    * because MPPE frames **grow**.  The kernel [must]
+                    * allocate MPPE_PAD extra bytes in xmit buffers.
+                    */
+                   mtu = netif_get_mtu(f->unit);
+                   if (mtu)
+                       netif_set_mtu(f->unit, mtu - MPPE_PAD);
+                   else
+                       newret = CONFREJ;
+               }
+
+               break;
+#endif /* MPPE */
            case CI_DEFLATE:
            case CI_DEFLATE_DRAFT:
                if (!ao->deflate || clen != CILEN_DEFLATE
            case CI_DEFLATE:
            case CI_DEFLATE_DRAFT:
                if (!ao->deflate || clen != CILEN_DEFLATE
@@ -1000,6 +1302,8 @@ ccp_reqci(f, p, lenp, dont_nak)
        else
            *lenp = retp - p0;
     }
        else
            *lenp = retp - p0;
     }
+    if (ret == CONFREJ && ao->mppe)
+       lcp_close(f->unit, "MPPE required but peer negotiation failed");
     return ret;
 }
 
     return ret;
 }
 
@@ -1015,6 +1319,30 @@ method_name(opt, opt2)
     if (!ANY_COMPRESS(*opt))
        return "(none)";
     switch (opt->method) {
     if (!ANY_COMPRESS(*opt))
        return "(none)";
     switch (opt->method) {
+#ifdef MPPE
+    case CI_MPPE:
+    {
+       char *p = result;
+       char *q = result + sizeof(result); /* 1 past result */
+
+       slprintf(p, q - p, "MPPE ");
+       p += 5;
+       if (opt->mppe & MPPE_OPT_128) {
+           slprintf(p, q - p, "128-bit ");
+           p += 8;
+       }
+       if (opt->mppe & MPPE_OPT_40) {
+           slprintf(p, q - p, "40-bit ");
+           p += 7;
+       }
+       if (opt->mppe & MPPE_OPT_STATEFUL)
+           slprintf(p, q - p, "stateful");
+       else
+           slprintf(p, q - p, "stateless");
+
+       break;
+    }
+#endif
     case CI_DEFLATE:
     case CI_DEFLATE_DRAFT:
        if (opt2 != NULL && opt2->deflate_size != opt->deflate_size)
     case CI_DEFLATE:
     case CI_DEFLATE_DRAFT:
        if (opt2 != NULL && opt2->deflate_size != opt->deflate_size)
@@ -1138,6 +1466,24 @@ ccp_printpkt(p, plen, printer, arg)
            len -= optlen;
            optend = p + optlen;
            switch (code) {
            len -= optlen;
            optend = p + optlen;
            switch (code) {
+#ifdef MPPE
+           case CI_MPPE:
+               if (optlen >= CILEN_MPPE) {
+                   u_char mppe_opts;
+
+                   MPPE_CI_TO_OPTS(&p[2], mppe_opts);
+                   printer(arg, "mppe %s %s %s %s %s %s%s",
+                           (p[2] & MPPE_H_BIT)? "+H": "-H",
+                           (p[5] & MPPE_M_BIT)? "+M": "-M",
+                           (p[5] & MPPE_S_BIT)? "+S": "-S",
+                           (p[5] & MPPE_L_BIT)? "+L": "-L",
+                           (p[5] & MPPE_D_BIT)? "+D": "-D",
+                           (p[5] & MPPE_C_BIT)? "+C": "-C",
+                           (mppe_opts & MPPE_OPT_UNKNOWN)? " +U": "");
+                   p += CILEN_MPPE;
+               }
+               break;
+#endif
            case CI_DEFLATE:
            case CI_DEFLATE_DRAFT:
                if (optlen >= CILEN_DEFLATE) {
            case CI_DEFLATE:
            case CI_DEFLATE_DRAFT:
                if (optlen >= CILEN_DEFLATE) {
@@ -1222,6 +1568,15 @@ ccp_datainput(unit, pkt, len)
             */
            error("Lost compression sync: disabling compression");
            ccp_close(unit, "Lost compression sync");
             */
            error("Lost compression sync: disabling compression");
            ccp_close(unit, "Lost compression sync");
+#ifdef MPPE
+           /*
+            * If we were doing MPPE, we must also take the link down.
+            */
+           if (ccp_gotoptions[unit].mppe) {
+               error("Too many MPPE errors, closing LCP");
+               lcp_close(unit, "Too many MPPE errors");
+           }
+#endif
        } else {
            /*
             * Send a reset-request to reset the peer's compressor.
        } else {
            /*
             * Send a reset-request to reset the peer's compressor.
index c28a5b885a65c629e4249a477883e64e7b701675..f796995bf3b75f46fa9afcba1c573dbbe93f477c 100644 (file)
@@ -24,7 +24,7 @@
  * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
  * OR MODIFICATIONS.
  *
  * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
  * OR MODIFICATIONS.
  *
- * $Id: ccp.h,v 1.9 1998/11/07 06:59:26 paulus Exp $
+ * $Id: ccp.h,v 1.10 2002/04/02 13:54:59 dfs Exp $
  */
 
 typedef struct ccp_options {
  */
 
 typedef struct ccp_options {
@@ -34,6 +34,7 @@ typedef struct ccp_options {
     bool predictor_2;          /* do Predictor-2? */
     bool deflate_correct;      /* use correct code for deflate? */
     bool deflate_draft;                /* use draft RFC code for deflate? */
     bool predictor_2;          /* do Predictor-2? */
     bool deflate_correct;      /* use correct code for deflate? */
     bool deflate_draft;                /* use draft RFC code for deflate? */
+    bool mppe;                 /* do MPPE? */
     u_short bsd_bits;          /* # bits/code for BSD Compress */
     u_short deflate_size;      /* lg(window size) for Deflate */
     short method;              /* code for chosen compression method */
     u_short bsd_bits;          /* # bits/code for BSD Compress */
     u_short deflate_size;      /* lg(window size) for Deflate */
     short method;              /* code for chosen compression method */
index 21b0280323577b5bc10896237a5bb267248a7729..114ed4d6bbfd7e05ee64a7b82d58d21309f3017e 100644 (file)
@@ -33,7 +33,7 @@
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
-#define RCSID  "$Id: chap.c,v 1.29 2002/03/05 15:14:04 dfs Exp $"
+#define RCSID  "$Id: chap.c,v 1.30 2002/04/02 13:54:59 dfs Exp $"
 
 /*
  * TODO:
 
 /*
  * TODO:
@@ -66,6 +66,14 @@ int (*chap_auth_hook) __P((char *user,
 
 static const char rcsid[] = RCSID;
 
 
 static const char rcsid[] = RCSID;
 
+#ifdef CHAPMS
+/* For MPPE debug */
+/* Use "[]|}{?/><,`!2&&(" (sans quotes) for RFC 3079 MS-CHAPv2 test value */
+static char *mschap_challenge = NULL;
+/* Use "!@\#$%^&*()_+:3|~" (sans quotes, backslash is to escape #) for ... */
+static char *mschap2_peer_challenge = NULL;
+#endif
+
 /*
  * Command-line options.
  */
 /*
  * Command-line options.
  */
@@ -79,6 +87,12 @@ static option_t chap_option_list[] = {
 #ifdef MSLANMAN
     { "ms-lanman", o_bool, &ms_lanman,
       "Use LanMan passwd when using MS-CHAP", 1 },
 #ifdef MSLANMAN
     { "ms-lanman", o_bool, &ms_lanman,
       "Use LanMan passwd when using MS-CHAP", 1 },
+#endif
+#ifdef DEBUGMPPEKEY
+    { "mschap-challenge", o_string, &mschap_challenge,
+      "specify CHAP challenge" },
+    { "mschap2-peer-challenge", o_string, &mschap2_peer_challenge,
+      "specify CHAP peer challenge" },
 #endif
     { NULL }
 };
 #endif
     { NULL }
 };
@@ -490,8 +504,11 @@ ChapReceiveChallenge(cstate, inp, id, len)
        break;
 
     case CHAP_MICROSOFT_V2:
        break;
 
     case CHAP_MICROSOFT_V2:
-       ChapMS2(cstate, rchallenge, NULL, cstate->resp_name, secret, secret_len,
-               (MS_Chap2Response *) cstate->response, cstate->earesponse);
+       ChapMS2(cstate, rchallenge,
+               mschap2_peer_challenge? mschap2_peer_challenge: NULL,
+               cstate->resp_name, secret, secret_len,
+               (MS_Chap2Response *) cstate->response, cstate->earesponse,
+                MS_CHAP2_AUTHENTICATEE);
        cstate->resp_length = MS_CHAP2_RESPONSE_LEN;
        break;
 #endif /* CHAPMS */
        cstate->resp_length = MS_CHAP2_RESPONSE_LEN;
        break;
 #endif /* CHAPMS */
@@ -649,7 +666,7 @@ ChapReceiveResponse(cstate, inp, id, len)
                ChapMS2(cstate, cstate->challenge, rmd->PeerChallenge,
                        (explicit_remote? remote_name: rhostname),
                        secret, secret_len, &md,
                ChapMS2(cstate, cstate->challenge, rmd->PeerChallenge,
                        (explicit_remote? remote_name: rhostname),
                        secret, secret_len, &md,
-                       cstate->saresponse);
+                       cstate->saresponse, MS_CHAP2_AUTHENTICATOR);
 
                /* compare MDs and send the appropriate status */
                if (memcmp(md.NTResp, rmd->NTResp, sizeof(md.NTResp)) == 0)
 
                /* compare MDs and send the appropriate status */
                if (memcmp(md.NTResp, rmd->NTResp, sizeof(md.NTResp)) == 0)
@@ -671,7 +688,8 @@ ChapReceiveResponse(cstate, inp, id, len)
        old_state = cstate->serverstate;
        cstate->serverstate = CHAPSS_OPEN;
        if (old_state == CHAPSS_INITIAL_CHAL) {
        old_state = cstate->serverstate;
        cstate->serverstate = CHAPSS_OPEN;
        if (old_state == CHAPSS_INITIAL_CHAL) {
-           auth_peer_success(cstate->unit, PPP_CHAP, rhostname, len);
+           auth_peer_success(cstate->unit, PPP_CHAP, cstate->chal_type,
+                             rhostname, len);
        }
        if (cstate->chal_interval != 0)
            TIMEOUT(ChapRechallenge, cstate, cstate->chal_interval);
        }
        if (cstate->chal_interval != 0)
            TIMEOUT(ChapRechallenge, cstate, cstate->chal_interval);
@@ -746,7 +764,7 @@ ChapReceiveSuccess(cstate, inp, id, len)
 
     cstate->clientstate = CHAPCS_OPEN;
 
 
     cstate->clientstate = CHAPCS_OPEN;
 
-    auth_withpeer_success(cstate->unit, PPP_CHAP);
+    auth_withpeer_success(cstate->unit, PPP_CHAP, cstate->resp_type);
 }
 
 
 }
 
 
@@ -786,7 +804,7 @@ ChapReceiveFailure(cstate, inp, id, len)
 #ifdef CHAPMS
     if ((cstate->resp_type == CHAP_MICROSOFT_V2) ||
        (cstate->resp_type == CHAP_MICROSOFT)) {
 #ifdef CHAPMS
     if ((cstate->resp_type == CHAP_MICROSOFT_V2) ||
        (cstate->resp_type == CHAP_MICROSOFT)) {
-       long error;
+       int error;
 
        /*
         * Deal with MS-CHAP formatted failure messages; just print the
 
        /*
         * Deal with MS-CHAP formatted failure messages; just print the
@@ -794,7 +812,7 @@ ChapReceiveFailure(cstate, inp, id, len)
         * to use M=<message>, but it shouldn't hurt.  See ChapSendStatus().
         */
        if (!strncmp(p, "E=", 2))
         * to use M=<message>, but it shouldn't hurt.  See ChapSendStatus().
         */
        if (!strncmp(p, "E=", 2))
-           error = strtol(p, NULL, 10); /* Remember the error code. */
+           error = (int) strtol(p, NULL, 10); /* Remember the error code. */
        else
            goto print_msg; /* Message is badly formatted. */
 
        else
            goto print_msg; /* Message is badly formatted. */
 
@@ -803,7 +821,7 @@ ChapReceiveFailure(cstate, inp, id, len)
            p += 3;
        } else {
            /* No M=<message>; use the error code. */
            p += 3;
        } else {
            /* No M=<message>; use the error code. */
-           switch(error - MS_CHAP_ERROR_BASE) {
+           switch(error) {
            case MS_CHAP_ERROR_RESTRICTED_LOGON_HOURS:
                p = "Restricted logon hours";
                break;
            case MS_CHAP_ERROR_RESTRICTED_LOGON_HOURS:
                p = "Restricted logon hours";
                break;
@@ -1023,9 +1041,15 @@ ChapGenChallenge(cstate)
     cstate->chal_id = ++cstate->id;
     cstate->chal_transmits = 0;
 
     cstate->chal_id = ++cstate->id;
     cstate->chal_transmits = 0;
 
-    /* generate a random string */
-    for (i = 0; i < chal_len; i++)
-       *ptr++ = (char) (drand48() * 0xff);
+#ifdef CHAPMS
+    if (mschap_challenge)
+       for (i = 0; i < chal_len; i++)
+           *ptr++ = mschap_challenge[i];
+    else
+#endif
+       /* generate a random string */
+       for (i = 0; i < chal_len; i++)
+           *ptr++ = (char) (drand48() * 0xff);
 }
 
 /*
 }
 
 /*
index d10b99a4f1980c6ac2f99fccd51d3bd2c202c9e2..318c0b60559f0706535cb161fb38bd86b256d627 100644 (file)
 /*
  * Modifications by Frank Cusack, frank@google.com, March 2002.
  *
 /*
  * Modifications by Frank Cusack, frank@google.com, March 2002.
  *
- *   Implemented MS-CHAPv2 functionality.  Heavily based on
- *   sample implementation in RFC 2759.
+ *   Implemented MS-CHAPv2 functionality, heavily based on sample
+ *   implementation in RFC 2759.  Implemented MPPE functionality,
+ *   heavily based on sample implementation in RFC 3079.
+ *   Copyright (c) 2002 Google, Inc.
  */
 
  */
 
-#define RCSID  "$Id: chap_ms.c,v 1.18 2002/03/05 15:14:04 dfs Exp $"
+#define RCSID  "$Id: chap_ms.c,v 1.19 2002/04/02 13:54:59 dfs Exp $"
 
 #ifdef CHAPMS
 
 
 #ifdef CHAPMS
 
@@ -88,6 +90,11 @@ static void  Expand __P((u_char *, u_char *));
 static void    Collapse __P((u_char *, u_char *));
 #endif
 
 static void    Collapse __P((u_char *, u_char *));
 #endif
 
+#ifdef MPPE
+static void    Set_Start_Key __P((u_char *, char *, int));
+static void    SetMasterKeys __P((char *, int, u_char[24], int));
+#endif
+
 extern double drand48 __P((void));
 
 #ifdef MSLANMAN
 extern double drand48 __P((void));
 
 #ifdef MSLANMAN
@@ -95,6 +102,11 @@ bool        ms_lanman = 0;          /* Use LanMan password instead of NT */
                                /* Has meaning only with MS-CHAP challenges */
 #endif
 
                                /* Has meaning only with MS-CHAP challenges */
 #endif
 
+#ifdef MPPE
+u_char mppe_send_key[MPPE_MAX_KEY_LEN];
+u_char mppe_recv_key[MPPE_MAX_KEY_LEN];
+#endif
+
 static void
 ChallengeResponse(u_char *challenge,
                  u_char PasswordHash[MD4_SIGNATURE_SIZE],
 static void
 ChallengeResponse(u_char *challenge,
                  u_char PasswordHash[MD4_SIGNATURE_SIZE],
@@ -356,16 +368,16 @@ GenerateAuthenticatorResponse(char *secret, int secret_len,
      * "Magic" constants used in response generation, from RFC 2759.
      */
     u_char Magic1[39] = /* "Magic server to client signing constant" */
      * "Magic" constants used in response generation, from RFC 2759.
      */
     u_char Magic1[39] = /* "Magic server to client signing constant" */
-       {0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
-        0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
-        0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
-        0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74};
+       { 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
+         0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
+         0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
+         0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74 };
     u_char Magic2[41] = /* "Pad to make it do more than one iteration" */
     u_char Magic2[41] = /* "Pad to make it do more than one iteration" */
-       {0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
-        0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
-        0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
-        0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
-        0x6E};
+       { 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
+         0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
+         0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
+         0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
+         0x6E };
 
     int                i;
     SHA1_CTX   sha1Context;
 
     int                i;
     SHA1_CTX   sha1Context;
@@ -400,6 +412,148 @@ GenerateAuthenticatorResponse(char *secret, int secret_len,
 }
 
 
 }
 
 
+#ifdef MPPE
+/*
+ * Set mppe_xxxx_key from the NTPasswordHashHash.
+ * RFC 2548 (RADIUS support) requires us to export this function (ugh).
+ */
+void
+mppe_set_keys(u_char *rchallenge, u_char PasswordHashHash[MD4_SIGNATURE_SIZE])
+{
+    SHA1_CTX   sha1Context;
+    u_char     Digest[SHA1_SIGNATURE_SIZE];    /* >= MPPE_MAX_KEY_LEN */
+
+    SHA1_Init(&sha1Context);
+    SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE);
+    SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE);
+    SHA1_Update(&sha1Context, rchallenge, 8);
+    SHA1_Final(Digest, &sha1Context);
+
+    /* Same key in both directions. */
+    BCOPY(Digest, mppe_send_key, sizeof(mppe_send_key));
+    BCOPY(Digest, mppe_recv_key, sizeof(mppe_recv_key));
+}
+
+/*
+ * Set mppe_xxxx_key from MS-CHAP credentials. (see RFC 3079)
+ */
+static void
+Set_Start_Key(u_char *rchallenge, char *secret, int secret_len)
+{
+    u_char     unicodePassword[MAX_NT_PASSWORD * 2];
+    u_char     PasswordHash[MD4_SIGNATURE_SIZE];
+    u_char     PasswordHashHash[MD4_SIGNATURE_SIZE];
+
+    /* Hash (x2) the Unicode version of the secret (== password). */
+    ascii2unicode(secret, secret_len, unicodePassword);
+    NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash);
+    NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash);
+
+    mppe_set_keys(rchallenge, PasswordHashHash);
+}
+
+/*
+ * Set mppe_xxxx_key from MS-CHAPv2 credentials. (see RFC 3079)
+ */
+static void
+SetMasterKeys(char *secret, int secret_len, u_char NTResponse[24], int IsServer)
+{
+    SHA1_CTX   sha1Context;
+    u_char     unicodePassword[MAX_NT_PASSWORD * 2];
+    u_char     PasswordHash[MD4_SIGNATURE_SIZE];
+    u_char     PasswordHashHash[MD4_SIGNATURE_SIZE];
+    u_char     MasterKey[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */
+    u_char     Digest[SHA1_SIGNATURE_SIZE];    /* >= MPPE_MAX_KEY_LEN */
+
+    u_char SHApad1[40] =
+       { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+    u_char SHApad2[40] =
+       { 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
+         0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
+         0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
+         0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2 };
+
+    /* "This is the MPPE Master Key" */
+    u_char Magic1[27] =
+       { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
+         0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
+         0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79 };
+    /* "On the client side, this is the send key; "
+       "on the server side, it is the receive key." */
+    u_char Magic2[84] =
+       { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
+         0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
+         0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
+         0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
+         0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+         0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
+         0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
+         0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
+         0x6b, 0x65, 0x79, 0x2e };
+    /* "On the client side, this is the receive key; "
+       "on the server side, it is the send key." */
+    u_char Magic3[84] =
+       { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
+         0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
+         0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
+         0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
+         0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+         0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
+         0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
+         0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
+         0x6b, 0x65, 0x79, 0x2e };
+    u_char *s;
+
+    /* Hash (x2) the Unicode version of the secret (== password). */
+    ascii2unicode(secret, secret_len, unicodePassword);
+    NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash);
+    NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash);
+
+    SHA1_Init(&sha1Context);
+    SHA1_Update(&sha1Context, PasswordHashHash, sizeof(PasswordHashHash));
+    SHA1_Update(&sha1Context, NTResponse, 24);
+    SHA1_Update(&sha1Context, Magic1, sizeof(Magic1));
+    SHA1_Final(MasterKey, &sha1Context);
+
+    /*
+     * generate send key
+     */
+    if (IsServer)
+       s = Magic3;
+    else
+       s = Magic2;
+    SHA1_Init(&sha1Context);
+    SHA1_Update(&sha1Context, MasterKey, 16);
+    SHA1_Update(&sha1Context, SHApad1, sizeof(SHApad1));
+    SHA1_Update(&sha1Context, s, 84);
+    SHA1_Update(&sha1Context, SHApad2, sizeof(SHApad2));
+    SHA1_Final(Digest, &sha1Context);
+
+    BCOPY(Digest, mppe_send_key, sizeof(mppe_send_key));
+
+    /*
+     * generate recv key
+     */
+    if (IsServer)
+       s = Magic2;
+    else
+       s = Magic3;
+    SHA1_Init(&sha1Context);
+    SHA1_Update(&sha1Context, MasterKey, 16);
+    SHA1_Update(&sha1Context, SHApad1, sizeof(SHApad1));
+    SHA1_Update(&sha1Context, s, 84);
+    SHA1_Update(&sha1Context, SHApad2, sizeof(SHApad2));
+    SHA1_Final(Digest, &sha1Context);
+
+    BCOPY(Digest, mppe_recv_key, sizeof(mppe_recv_key));
+}
+
+#endif /* MPPE */
+
+
 void
 ChapMS(chap_state *cstate, u_char *rchallenge, char *secret, int secret_len,
        MS_ChapResponse *response)
 void
 ChapMS(chap_state *cstate, u_char *rchallenge, char *secret, int secret_len,
        MS_ChapResponse *response)
@@ -407,7 +561,7 @@ ChapMS(chap_state *cstate, u_char *rchallenge, char *secret, int secret_len,
 #if 0
     CHAPDEBUG((LOG_INFO, "ChapMS: secret is '%.*s'", secret_len, secret));
 #endif
 #if 0
     CHAPDEBUG((LOG_INFO, "ChapMS: secret is '%.*s'", secret_len, secret));
 #endif
-    BZERO(response, sizeof(response));
+    BZERO(response, sizeof(*response));
 
     /* Calculate both always */
     ChapMS_NT(rchallenge, secret, secret_len, response->NTResp);
 
     /* Calculate both always */
     ChapMS_NT(rchallenge, secret, secret_len, response->NTResp);
@@ -421,6 +575,9 @@ ChapMS(chap_state *cstate, u_char *rchallenge, char *secret, int secret_len,
     response->UseNT[0] = 1;
 #endif
 
     response->UseNT[0] = 1;
 #endif
 
+#ifdef MPPE
+    Set_Start_Key(rchallenge, secret, secret_len);
+#endif
 }
 
 
 }
 
 
@@ -428,7 +585,8 @@ ChapMS(chap_state *cstate, u_char *rchallenge, char *secret, int secret_len,
  * If PeerChallenge is NULL, one is generated and response->PeerChallenge
  * is filled in.  Call this way when generating a response.
  * If PeerChallenge is supplied, it is copied into response->PeerChallenge.
  * If PeerChallenge is NULL, one is generated and response->PeerChallenge
  * is filled in.  Call this way when generating a response.
  * If PeerChallenge is supplied, it is copied into response->PeerChallenge.
- * Call this way when verifying a response.
+ * Call this way when verifying a response (or debugging).
+ * Do not call with PeerChallenge = response->PeerChallenge.
  *
  * response->PeerChallenge is then used for calculation of the
  * Authenticator Response.
  *
  * response->PeerChallenge is then used for calculation of the
  * Authenticator Response.
@@ -436,12 +594,13 @@ ChapMS(chap_state *cstate, u_char *rchallenge, char *secret, int secret_len,
 void
 ChapMS2(chap_state *cstate, u_char *rchallenge, u_char *PeerChallenge,
        char *user, char *secret, int secret_len, MS_Chap2Response *response,
 void
 ChapMS2(chap_state *cstate, u_char *rchallenge, u_char *PeerChallenge,
        char *user, char *secret, int secret_len, MS_Chap2Response *response,
-       u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1])
+       u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1], int authenticator)
 {
 {
+    /* ARGSUSED */
     u_char *p = response->PeerChallenge;
     int i;
 
     u_char *p = response->PeerChallenge;
     int i;
 
-    BZERO(response, sizeof(response));
+    BZERO(response, sizeof(*response));
 
     /* Generate the Peer-Challenge if requested, or copy it if supplied. */
     if (!PeerChallenge)
 
     /* Generate the Peer-Challenge if requested, or copy it if supplied. */
     if (!PeerChallenge)
@@ -459,6 +618,9 @@ ChapMS2(chap_state *cstate, u_char *rchallenge, u_char *PeerChallenge,
     GenerateAuthenticatorResponse(secret, secret_len, response->NTResp,
                                  response->PeerChallenge, rchallenge,
                                  user, authResponse);
     GenerateAuthenticatorResponse(secret, secret_len, response->NTResp,
                                  response->PeerChallenge, rchallenge,
                                  user, authResponse);
+#ifdef MPPE
+    SetMasterKeys(secret, secret_len, response->NTResp, authenticator);
+#endif
 }
 
 
 }
 
 
index a8a13950ab5f3448c2392e0a2939a2ba2bf40235..ec695860d9ff171f4a897acf06a7036ecf9c8b81 100644 (file)
@@ -19,7 +19,7 @@
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- * $Id: chap_ms.h,v 1.5 2002/03/05 15:14:04 dfs Exp $
+ * $Id: chap_ms.h,v 1.6 2002/04/02 13:54:59 dfs Exp $
  */
 
 #ifndef __CHAPMS_INCLUDE__
  */
 
 #ifndef __CHAPMS_INCLUDE__
 #define MS_CHAP_RESPONSE_LEN   49      /* Response length for MS-CHAP */
 #define MS_CHAP2_RESPONSE_LEN  49      /* Response length for MS-CHAPv2 */
 
 #define MS_CHAP_RESPONSE_LEN   49      /* Response length for MS-CHAP */
 #define MS_CHAP2_RESPONSE_LEN  49      /* Response length for MS-CHAPv2 */
 
-/*
- * E=eeeeeeeeee error codes for MS-CHAP failure messages. 
- * Offset by 646 (the minimum code) for switch() handling on older compilers.
- */
-#define MS_CHAP_ERROR_BASE                     646
-#define MS_CHAP_ERROR_RESTRICTED_LOGON_HOURS   (646 - MS_CHAP_ERROR_BASE)
-#define MS_CHAP_ERROR_ACCT_DISABLED            (647 - MS_CHAP_ERROR_BASE)
-#define MS_CHAP_ERROR_PASSWD_EXPIRED           (648 - MS_CHAP_ERROR_BASE)
-#define MS_CHAP_ERROR_NO_DIALIN_PERMISSION     (649 - MS_CHAP_ERROR_BASE)
-#define MS_CHAP_ERROR_AUTHENTICATION_FAILURE   (691 - MS_CHAP_ERROR_BASE)
-#define MS_CHAP_ERROR_CHANGING_PASSWORD                (709 - MS_CHAP_ERROR_BASE)
+/* E=eeeeeeeeee error codes for MS-CHAP failure messages. */
+#define MS_CHAP_ERROR_RESTRICTED_LOGON_HOURS   646
+#define MS_CHAP_ERROR_ACCT_DISABLED            647
+#define MS_CHAP_ERROR_PASSWD_EXPIRED           648
+#define MS_CHAP_ERROR_NO_DIALIN_PERMISSION     649
+#define MS_CHAP_ERROR_AUTHENTICATION_FAILURE   691
+#define MS_CHAP_ERROR_CHANGING_PASSWORD                709
 
 /*
  * Use MS_CHAP_RESPONSE_LEN, rather than sizeof(MS_ChapResponse),
 
 /*
  * Use MS_CHAP_RESPONSE_LEN, rather than sizeof(MS_ChapResponse),
@@ -63,9 +59,23 @@ typedef struct {
     u_char Flags[1];           /* Must be zero */
 } MS_Chap2Response;
 
     u_char Flags[1];           /* Must be zero */
 } MS_Chap2Response;
 
+#ifdef MPPE
+#include <net/ppp-comp.h>      /* MPPE_MAX_KEY_LEN */
+extern u_char mppe_send_key[MPPE_MAX_KEY_LEN];
+extern u_char mppe_recv_key[MPPE_MAX_KEY_LEN];
+#endif
+
+/* Are we the authenticator or authenticatee?  For MS-CHAPv2 key derivation. */
+#define MS_CHAP2_AUTHENTICATEE 0
+#define MS_CHAP2_AUTHENTICATOR 1
+
+#include "chap.h" /* chap_state, et al */
 void ChapMS __P((chap_state *, u_char *, char *, int, MS_ChapResponse *));
 void ChapMS2 __P((chap_state *, u_char *, u_char *, char *, char *, int,
 void ChapMS __P((chap_state *, u_char *, char *, int, MS_ChapResponse *));
 void ChapMS2 __P((chap_state *, u_char *, u_char *, char *, char *, int,
-                 MS_Chap2Response *, u_char[MS_AUTH_RESPONSE_LENGTH+1]));
+                 MS_Chap2Response *, u_char[MS_AUTH_RESPONSE_LENGTH+1], int));
+#ifdef MPPE
+void mppe_set_keys __P((u_char *, u_char[MD4_SIGNATURE_SIZE]));
+#endif
 
 #define __CHAPMS_INCLUDE__
 #endif /* __CHAPMS_INCLUDE__ */
 
 #define __CHAPMS_INCLUDE__
 #endif /* __CHAPMS_INCLUDE__ */
index 3779b289419ca491fb8baeedb26d07053ec5a367..b20f075ce885095c42c70144a5ee2af965ec74f1 100644 (file)
@@ -17,7 +17,7 @@
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
-#define RCSID  "$Id: options.c,v 1.82 2002/03/01 14:39:18 dfs Exp $"
+#define RCSID  "$Id: options.c,v 1.83 2002/04/02 13:54:59 dfs Exp $"
 
 #include <ctype.h>
 #include <stdio.h>
 
 #include <ctype.h>
 #include <stdio.h>
@@ -627,6 +627,8 @@ process_option(opt, cmd, argv)
            *(bool *)(opt->addr2) = 0;
        else if (opt->addr2 && (opt->flags & OPT_A2CLRB))
            *(u_char *)(opt->addr2) &= ~v;
            *(bool *)(opt->addr2) = 0;
        else if (opt->addr2 && (opt->flags & OPT_A2CLRB))
            *(u_char *)(opt->addr2) &= ~v;
+       else if (opt->addr2 && (opt->flags & OPT_A2OR))
+           *(u_char *)(opt->addr2) |= v;
        if (opt->addr3 && (opt->flags & OPT_A3OR))
            *(u_char *)(opt->addr3) |= v;
        break;
        if (opt->addr3 && (opt->flags & OPT_A3OR))
            *(u_char *)(opt->addr3) |= v;
        break;
@@ -730,7 +732,7 @@ process_option(opt, cmd, argv)
     }
 
     if (opt->addr2 && (opt->flags & (OPT_A2COPY|OPT_ENABLE
     }
 
     if (opt->addr2 && (opt->flags & (OPT_A2COPY|OPT_ENABLE
-               |OPT_A2PRINTER|OPT_A2STRVAL|OPT_A2LIST)) == 0)
+               |OPT_A2PRINTER|OPT_A2STRVAL|OPT_A2LIST|OPT_A2OR)) == 0)
        *(bool *)(opt->addr2) = !(opt->flags & OPT_A2CLR);
 
     mainopt->source = option_source;
        *(bool *)(opt->addr2) = !(opt->flags & OPT_A2CLR);
 
     mainopt->source = option_source;
index 06f59ffc24747ac5eef148b01fd40ce6ffb1323f..c36bdf7072f2c15fe8e40b4d79b7a810f8cd3459 100644 (file)
@@ -21,7 +21,7 @@
 *
 ***********************************************************************/
 static char const RCSID[] =
 *
 ***********************************************************************/
 static char const RCSID[] =
-"$Id: radius.c,v 1.7 2002/03/12 00:28:56 dfs Exp $";
+"$Id: radius.c,v 1.8 2002/04/02 13:55:00 dfs Exp $";
 
 #include "pppd.h"
 #include "chap.h"
 
 #include "pppd.h"
 #include "chap.h"
index f6adc5daf2767ffff5ffe651aec596e33accab36..6befb316f31d4f4ccab9dadf7415f6f08cd3638b 100644 (file)
@@ -1,5 +1,5 @@
 .\" manual page [] for pppd 2.4
 .\" manual page [] for pppd 2.4
-.\" $Id: pppd.8,v 1.61 2002/03/05 15:14:04 dfs Exp $
+.\" $Id: pppd.8,v 1.62 2002/04/02 13:54:59 dfs Exp $
 .\" SH section heading
 .\" SS subsection heading
 .\" LP paragraph
 .\" SH section heading
 .\" SS subsection heading
 .\" LP paragraph
@@ -561,6 +561,10 @@ control, as for the \fIcrtscts\fR option.
 Enables the use of PPP multilink; this is an alias for the `multilink'
 option.  This option is currently only available under Linux.
 .TP
 Enables the use of PPP multilink; this is an alias for the `multilink'
 option.  This option is currently only available under Linux.
 .TP
+.B mppe-stateful
+Allow MPPE to use stateful mode.  Stateless mode is still attempted first.
+The default is to disallow stateful mode.  
+.TP
 .B mpshortseq
 Enables the use of short (12-bit) sequence numbers in multilink
 headers, as opposed to 24-bit sequence numbers.  This option is only
 .B mpshortseq
 Enables the use of short (12-bit) sequence numbers in multilink
 headers, as opposed to 24-bit sequence numbers.  This option is only
@@ -703,6 +707,18 @@ peer is buggy.
 Disables the use of PPP multilink.  This option is currently only
 available under Linux.
 .TP
 Disables the use of PPP multilink.  This option is currently only
 available under Linux.
 .TP
+.B nomppe
+Disables MPPE (Microsoft Point to Point Encryption).  This is the default.
+.TP
+.B nomppe-40
+Disable 40\-bit encryption with MPPE.
+.TP
+.B nomppe-128
+Disable 128\-bit encryption with MPPE.
+.TP
+.B nomppe-stateful
+Disabled MPPE stateful mode.  This is the default.
+.TP
 .B nompshortseq
 Disables the use of short (12-bit) sequence numbers in the PPP
 multilink protocol, forcing the use of 24-bit sequence numbers.  This
 .B nompshortseq
 Disables the use of short (12-bit) sequence numbers in the PPP
 multilink protocol, forcing the use of 24-bit sequence numbers.  This
@@ -869,6 +885,18 @@ peer using PAP.
 Require the peer to authenticate itself using CHAP [Challenge
 Handshake Authentication Protocol] authentication.
 .TP
 Require the peer to authenticate itself using CHAP [Challenge
 Handshake Authentication Protocol] authentication.
 .TP
+.B require-mppe
+Require the use of MPPE (Microsoft Point to Point Encryption).  This
+option disables all other compression types.  This option enables
+both 40\-bit and 128\-bit encryption.  In order for MPPE to successfully
+come up, you must have authenticated with either MS-CHAP or MS-CHAPv2.
+.TP
+.B require-mppe-40
+Require the use of MPPE, with 40\-bit encryption.
+.TP
+.B require-mppe-128
+Require the use of MPPE, with 128\-bit encryption.
+.TP
 .B require-mschap
 Require the peer to authenticate itself using MS-CHAP [Microsft Challenge
 Handshake Authentication Protocol] authentication.
 .B require-mschap
 Require the peer to authenticate itself using MS-CHAP [Microsft Challenge
 Handshake Authentication Protocol] authentication.
index d75a6fd8161d2876bfc24057d733c07e151ec627..a9b780a9e796d70575b76f8e1ed9960f079b7acf 100644 (file)
@@ -16,7 +16,7 @@
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- * $Id: pppd.h,v 1.66 2002/03/01 14:39:18 dfs Exp $
+ * $Id: pppd.h,v 1.67 2002/04/02 13:54:59 dfs Exp $
  */
 
 /*
  */
 
 /*
@@ -95,6 +95,7 @@ typedef struct {
 #define OPT_NOARG      0x200   /* option doesn't take argument */
 #define OPT_OR         0x400   /* OR in argument to value */
 #define OPT_INC                0x800   /* increment value */
 #define OPT_NOARG      0x200   /* option doesn't take argument */
 #define OPT_OR         0x400   /* OR in argument to value */
 #define OPT_INC                0x800   /* increment value */
+#define OPT_A2OR       0x800   /* for o_bool, OR arg to *(u_char *)addr2 */
 #define OPT_PRIV       0x1000  /* privileged option */
 #define OPT_STATIC     0x2000  /* string option goes into static array */
 #define OPT_LLIMIT     0x4000  /* check value against lower limit */
 #define OPT_PRIV       0x1000  /* privileged option */
 #define OPT_STATIC     0x2000  /* string option goes into static array */
 #define OPT_LLIMIT     0x4000  /* check value against lower limit */
@@ -198,6 +199,7 @@ extern int  baud_rate;      /* Current link speed in bits/sec */
 extern char    *progname;      /* Name of this program */
 extern int     redirect_stderr;/* Connector's stderr should go to file */
 extern char    peer_authname[];/* Authenticated name of peer */
 extern char    *progname;      /* Name of this program */
 extern int     redirect_stderr;/* Connector's stderr should go to file */
 extern char    peer_authname[];/* Authenticated name of peer */
+extern int     auth_done[NUM_PPP]; /* Methods actually used for auth */
 extern int     privileged;     /* We were run by real-uid root */
 extern int     need_holdoff;   /* Need holdoff period after link terminates */
 extern char    **script_env;   /* Environment variables for scripts */
 extern int     privileged;     /* We were run by real-uid root */
 extern int     need_holdoff;   /* Need holdoff period after link terminates */
 extern char    **script_env;   /* Environment variables for scripts */
@@ -295,6 +297,21 @@ extern bool        ms_lanman;      /* Use LanMan password instead of NT */
                                /* Has meaning only with MS-CHAP challenges */
 #endif
 
                                /* Has meaning only with MS-CHAP challenges */
 #endif
 
+/* Values for auth_pending, auth_done */
+#define PAP_WITHPEER   0x1
+#define PAP_PEER       0x2
+#define CHAP_WITHPEER  0x4
+#define CHAP_PEER      0x8
+/* Values for auth_done only */
+#define CHAP_MD5_WITHPEER      0x10
+#define CHAP_MD5_PEER          0x20
+#ifdef CHAPMS
+#define CHAP_MS_WITHPEER       0x40
+#define CHAP_MS_PEER           0x80
+#define CHAP_MS2_WITHPEER      0x100
+#define CHAP_MS2_PEER          0x200
+#endif
+
 extern char *current_option;   /* the name of the option being parsed */
 extern int  privileged_option; /* set iff the current option came from root */
 extern char *option_source;    /* string saying where the option came from */
 extern char *current_option;   /* the name of the option being parsed */
 extern int  privileged_option; /* set iff the current option came from root */
 extern char *option_source;    /* string saying where the option came from */
@@ -467,11 +484,11 @@ void np_down __P((int, int));       /* a network protocol has gone down */
 void np_finished __P((int, int)); /* a network protocol no longer needs link */
 void auth_peer_fail __P((int, int));
                                /* peer failed to authenticate itself */
 void np_finished __P((int, int)); /* a network protocol no longer needs link */
 void auth_peer_fail __P((int, int));
                                /* peer failed to authenticate itself */
-void auth_peer_success __P((int, int, char *, int));
+void auth_peer_success __P((int, int, int, char *, int));
                                /* peer successfully authenticated itself */
 void auth_withpeer_fail __P((int, int));
                                /* we failed to authenticate ourselves */
                                /* peer successfully authenticated itself */
 void auth_withpeer_fail __P((int, int));
                                /* we failed to authenticate ourselves */
-void auth_withpeer_success __P((int, int));
+void auth_withpeer_success __P((int, int, int));
                                /* we successfully authenticated ourselves */
 void auth_check_options __P((void));
                                /* check authentication options supplied */
                                /* we successfully authenticated ourselves */
 void auth_check_options __P((void));
                                /* check authentication options supplied */
@@ -542,6 +559,7 @@ int  get_idle_time __P((int, struct ppp_idle *));
 int  get_ppp_stats __P((int, struct pppd_stats *));
                                /* Return link statistics */
 void netif_set_mtu __P((int, int)); /* Set PPP interface MTU */
 int  get_ppp_stats __P((int, struct pppd_stats *));
                                /* Return link statistics */
 void netif_set_mtu __P((int, int)); /* Set PPP interface MTU */
+int  netif_get_mtu __P((int));      /* Get PPP interface MTU */
 int  sifvjcomp __P((int, int, int, int));
                                /* Configure VJ TCP header compression */
 int  sifup __P((int));         /* Configure i/f up for one protocol */
 int  sifvjcomp __P((int, int, int, int));
                                /* Configure VJ TCP header compression */
 int  sifup __P((int));         /* Configure i/f up for one protocol */
index b56a7c9a6efb80decccd448a57838f3960377efb..b8701b4306e03621de80102d362818f2fce3b887 100644 (file)
@@ -20,6 +20,9 @@
 #include <netinet/in.h>        /* htonl() */
 #include "sha1.h"
 
 #include <netinet/in.h>        /* htonl() */
 #include "sha1.h"
 
+static void
+SHA1_Transform(unsigned long[5], const unsigned char[64]);
+
 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
 
 /* blk0() and blk() perform the initial expand. */
 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
 
 /* blk0() and blk() perform the initial expand. */
@@ -38,7 +41,8 @@
 
 /* Hash a single 512-bit block. This is the core of the algorithm. */
 
 
 /* Hash a single 512-bit block. This is the core of the algorithm. */
 
-void SHA1_Transform(unsigned long state[5], const unsigned char buffer[64])
+static void
+SHA1_Transform(unsigned long state[5], const unsigned char buffer[64])
 {
     unsigned long a, b, c, d, e;
     typedef union {
 {
     unsigned long a, b, c, d, e;
     typedef union {
@@ -94,7 +98,8 @@ void SHA1_Transform(unsigned long state[5], const unsigned char buffer[64])
 
 /* SHA1Init - Initialize new context */
 
 
 /* SHA1Init - Initialize new context */
 
-void SHA1_Init(SHA1_CTX *context)
+void
+SHA1_Init(SHA1_CTX *context)
 {
     /* SHA1 initialization constants */
     context->state[0] = 0x67452301;
 {
     /* SHA1 initialization constants */
     context->state[0] = 0x67452301;
@@ -108,7 +113,8 @@ void SHA1_Init(SHA1_CTX *context)
 
 /* Run your data through this. */
 
 
 /* Run your data through this. */
 
-void SHA1_Update(SHA1_CTX *context, const unsigned char *data, unsigned int len)
+void
+SHA1_Update(SHA1_CTX *context, const unsigned char *data, unsigned int len)
 {
     unsigned int i, j;
 
 {
     unsigned int i, j;
 
@@ -132,7 +138,8 @@ void SHA1_Update(SHA1_CTX *context, const unsigned char *data, unsigned int len)
 
 /* Add padding and return the message digest. */
 
 
 /* Add padding and return the message digest. */
 
-void SHA1_Final(unsigned char digest[20], SHA1_CTX *context)
+void
+SHA1_Final(unsigned char digest[20], SHA1_CTX *context)
 {
     unsigned long i, j;
     unsigned char finalcount[8];
 {
     unsigned long i, j;
     unsigned char finalcount[8];
index 6727afb27a9db6aa20e36313d7275adea6409bf2..dff8da88bd91a041f616e9fb34020c9958144099 100644 (file)
@@ -10,10 +10,9 @@ typedef struct {
 
 #define SHA1_SIGNATURE_SIZE 20
 
 
 #define SHA1_SIGNATURE_SIZE 20
 
-void SHA1_Transform(unsigned long[5], const unsigned char[64]);
-void SHA1_Init(SHA1_CTX *);
-void SHA1_Update(SHA1_CTX *, const unsigned char *, unsigned int);
-void SHA1_Final(unsigned char[20], SHA1_CTX *);
+extern void SHA1_Init(SHA1_CTX *);
+extern void SHA1_Update(SHA1_CTX *, const unsigned char *, unsigned int);
+extern void SHA1_Final(unsigned char[SHA1_SIGNATURE_SIZE], SHA1_CTX *);
 
 #define __SHA1_INCLUDE_
 #endif /* __SHA1_INCLUDE_ */
 
 #define __SHA1_INCLUDE_
 #endif /* __SHA1_INCLUDE_ */
index 76fda67b3f9e94f5f59145b0e4d6eaff966a6c28..5f40b06d36a965c69dc6de66603f1169e7d41917 100644 (file)
@@ -1088,6 +1088,24 @@ netif_set_mtu(int unit, int mtu)
        error("ioctl(SIOCSIFMTU): %m (line %d)", __LINE__);
 }
 
        error("ioctl(SIOCSIFMTU): %m (line %d)", __LINE__);
 }
 
+/*
+ * netif_get_mtu - get the MTU on the PPP network interface.
+ */
+int
+netif_get_mtu(int unit)
+{
+    struct ifreq ifr;
+
+    memset (&ifr, '\0', sizeof (ifr));
+    strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
+
+    if (ifunit >= 0 && ioctl(sock_fd, SIOCGIFMTU, (caddr_t) &ifr) < 0) {
+       error("ioctl(SIOCGIFMTU): %m (line %d)", __LINE__);
+       return 0;
+    }
+    return ifr.ifr_mtu;
+}
+
 /********************************************************************
  *
  * tty_send_config - configure the transmit characteristics of
 /********************************************************************
  *
  * tty_send_config - configure the transmit characteristics of
@@ -1175,7 +1193,8 @@ void tty_recv_config (int mru,u_int32_t asyncmap,int pcomp,int accomp)
  * is acceptable for use.
  */
 
  * is acceptable for use.
  */
 
-int ccp_test (int unit, u_char *opt_ptr, int opt_len, int for_transmit)
+int
+ccp_test(int unit, u_char *opt_ptr, int opt_len, int for_transmit)
 {
     struct ppp_option_data data;
 
 {
     struct ppp_option_data data;
 
index ad13e39f201344fce7dbf96b97ab0201e5f7b93a..d3d9d9f41d47635066bbbddf1d0069a4f082a308 100644 (file)
@@ -17,7 +17,7 @@
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
-#define RCSID  "$Id: upap.c,v 1.24 2001/03/08 05:11:16 paulus Exp $"
+#define RCSID  "$Id: upap.c,v 1.25 2002/04/02 13:54:59 dfs Exp $"
 
 /*
  * TODO:
 
 /*
  * TODO:
@@ -409,7 +409,7 @@ upap_rauthreq(u, inp, id, len)
 
     if (retcode == UPAP_AUTHACK) {
        u->us_serverstate = UPAPSS_OPEN;
 
     if (retcode == UPAP_AUTHACK) {
        u->us_serverstate = UPAPSS_OPEN;
-       auth_peer_success(u->us_unit, PPP_PAP, ruser, ruserlen);
+       auth_peer_success(u->us_unit, PPP_PAP, 0, ruser, ruserlen);
     } else {
        u->us_serverstate = UPAPSS_BADAUTH;
        auth_peer_fail(u->us_unit, PPP_PAP);
     } else {
        u->us_serverstate = UPAPSS_BADAUTH;
        auth_peer_fail(u->us_unit, PPP_PAP);
@@ -456,7 +456,7 @@ upap_rauthack(u, inp, id, len)
 
     u->us_clientstate = UPAPCS_OPEN;
 
 
     u->us_clientstate = UPAPCS_OPEN;
 
-    auth_withpeer_success(u->us_unit, PPP_PAP);
+    auth_withpeer_success(u->us_unit, PPP_PAP, 0);
 }
 
 
 }