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
-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
index 92aa64572433c5c2cb3cff38162f566f8c143ed3..091a57539578e313113d550991e5fa5b4b97e6e0 100644 (file)
  * 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.
@@ -186,6 +186,100 @@ struct compressor {
                                 + 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.
  */
index fe62a61f1cea008c96c90fc136a3968a1fac0fac..10fc3bc9cb595cae7b1b1420d8a506b4e7a15d78 100644 (file)
@@ -24,7 +24,7 @@
  * 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
@@ -154,6 +154,99 @@ struct compressor {
                                 + 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.
  */
index aea5fb9e9590f6c52344ed4bfc8b64efabb9b9cc..57b6b08091a78e105ad039c3df3785dcaa9f0965 100644 (file)
@@ -1,6 +1,6 @@
 #
 # 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
@@ -34,9 +34,12 @@ LIBS += -lcrypt
 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
+# 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
@@ -83,6 +86,9 @@ PPPDOBJS += md4.o chap_ms.o
 ifdef MSLANMAN
 CFLAGS   += -DMSLANMAN=1
 endif
+ifdef MPPE
+CFLAGS   += -DMPPE=1
+endif
 endif
 
 ifdef HAS_SHADOW
index 61b50e5b95d68e9bf249f683ab2b9c6faf504e0a..67f12782584c279b21fc705f05e3fbac0393db50 100644 (file)
@@ -32,7 +32,7 @@
  * 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>
@@ -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 have been completed. */
+int auth_done[NUM_PPP];
+
 /* 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 */
 
-/* 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. */
@@ -552,6 +549,7 @@ link_established(unit)
        auth |= PAP_WITHPEER;
     }
     auth_pending[unit] = auth;
+    auth_done[unit] = 0;
 
     if (!auth)
        network_phase(unit);
@@ -653,8 +651,8 @@ auth_peer_fail(unit, protocol)
  * 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;
 {
@@ -663,6 +661,19 @@ auth_peer_success(unit, protocol, name, namelen)
     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;
@@ -681,6 +692,9 @@ auth_peer_success(unit, protocol, name, namelen)
     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.
@@ -712,14 +726,27 @@ auth_withpeer_fail(unit, protocol)
  * 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;
+       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)
@@ -731,6 +758,9 @@ auth_withpeer_success(unit, protocol)
        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.
index 6cbdafd12e7b0385ef5b1d5d2de245c7193e4412..fa8a5a0cb950f6993ebe51d008c98b556b1c5272 100644 (file)
@@ -25,7 +25,7 @@
  * 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 "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;
 
 /*
@@ -54,6 +59,13 @@ static int setdeflate __P((char **));
 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" },
@@ -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 },
 
+#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 }
 };
 
@@ -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 \
-                                || (opt).predictor_1 || (opt).predictor_2)
+                                || (opt).predictor_1 || (opt).predictor_2 \
+                                || (opt).mppe)
 
 /*
  * 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);
-    if (oldstate == OPENED && p[0] == TERMREQ && f->state != OPENED)
+    if (oldstate == OPENED && p[0] == TERMREQ && f->state != OPENED) {
        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,
@@ -450,15 +520,91 @@ ccp_resetci(f)
     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;
 
+#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.
      */
+#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;
@@ -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)
-       + (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
-     * 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_size < DEFLATE_MIN_WORKS) {
+               go->deflate = 0;
+               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;
            }
@@ -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);
-       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? */
@@ -619,6 +784,22 @@ ccp_ackci(f, p, len)
     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)
@@ -696,6 +877,25 @@ ccp_nakci(f, p, len)
     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) {
@@ -767,6 +967,14 @@ ccp_rejci(f, p, len)
     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) {
@@ -859,6 +1067,100 @@ ccp_reqci(f, p, lenp, dont_nak)
            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
@@ -1000,6 +1302,8 @@ ccp_reqci(f, p, lenp, dont_nak)
        else
            *lenp = retp - p0;
     }
+    if (ret == CONFREJ && ao->mppe)
+       lcp_close(f->unit, "MPPE required but peer negotiation failed");
     return ret;
 }
 
@@ -1015,6 +1319,30 @@ method_name(opt, opt2)
     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)
@@ -1138,6 +1466,24 @@ ccp_printpkt(p, plen, printer, arg)
            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) {
@@ -1222,6 +1568,15 @@ ccp_datainput(unit, pkt, len)
             */
            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.
index c28a5b885a65c629e4249a477883e64e7b701675..f796995bf3b75f46fa9afcba1c573dbbe93f477c 100644 (file)
@@ -24,7 +24,7 @@
  * 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 {
@@ -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 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 */
index 21b0280323577b5bc10896237a5bb267248a7729..114ed4d6bbfd7e05ee64a7b82d58d21309f3017e 100644 (file)
@@ -33,7 +33,7 @@
  * 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:
@@ -66,6 +66,14 @@ int (*chap_auth_hook) __P((char *user,
 
 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.
  */
@@ -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 },
+#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 }
 };
@@ -490,8 +504,11 @@ ChapReceiveChallenge(cstate, inp, id, len)
        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 */
@@ -649,7 +666,7 @@ ChapReceiveResponse(cstate, inp, id, len)
                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)
@@ -671,7 +688,8 @@ ChapReceiveResponse(cstate, inp, id, len)
        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);
@@ -746,7 +764,7 @@ ChapReceiveSuccess(cstate, inp, id, len)
 
     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)) {
-       long error;
+       int error;
 
        /*
         * 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))
-           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. */
 
@@ -803,7 +821,7 @@ ChapReceiveFailure(cstate, inp, id, len)
            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;
@@ -1023,9 +1041,15 @@ ChapGenChallenge(cstate)
     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.
  *
- *   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
 
@@ -88,6 +90,11 @@ static void  Expand __P((u_char *, u_char *));
 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
@@ -95,6 +102,11 @@ bool        ms_lanman = 0;          /* Use LanMan password instead of NT */
                                /* 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],
@@ -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" */
-       {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" */
-       {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;
@@ -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)
@@ -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
-    BZERO(response, sizeof(response));
+    BZERO(response, sizeof(*response));
 
     /* 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
 
+#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.
- * 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.
@@ -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,
-       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;
 
-    BZERO(response, sizeof(response));
+    BZERO(response, sizeof(*response));
 
     /* 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);
+#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.
  *
- * $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__
 #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),
@@ -63,9 +59,23 @@ typedef struct {
     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,
-                 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__ */
index 3779b289419ca491fb8baeedb26d07053ec5a367..b20f075ce885095c42c70144a5ee2af965ec74f1 100644 (file)
@@ -17,7 +17,7 @@
  * 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>
@@ -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;
+       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;
@@ -730,7 +732,7 @@ process_option(opt, cmd, argv)
     }
 
     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;
index 06f59ffc24747ac5eef148b01fd40ce6ffb1323f..c36bdf7072f2c15fe8e40b4d79b7a810f8cd3459 100644 (file)
@@ -21,7 +21,7 @@
 *
 ***********************************************************************/
 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"
index f6adc5daf2767ffff5ffe651aec596e33accab36..6befb316f31d4f4ccab9dadf7415f6f08cd3638b 100644 (file)
@@ -1,5 +1,5 @@
 .\" 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
@@ -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
+.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
@@ -703,6 +707,18 @@ peer is buggy.
 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
@@ -869,6 +885,18 @@ peer using PAP.
 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.
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.
  *
- * $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_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 */
@@ -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 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 */
@@ -295,6 +297,21 @@ extern bool        ms_lanman;      /* Use LanMan password instead of NT */
                                /* 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 */
@@ -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 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 */
-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 */
@@ -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  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 */
index b56a7c9a6efb80decccd448a57838f3960377efb..b8701b4306e03621de80102d362818f2fce3b887 100644 (file)
@@ -20,6 +20,9 @@
 #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. */
@@ -38,7 +41,8 @@
 
 /* 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 {
@@ -94,7 +98,8 @@ void SHA1_Transform(unsigned long state[5], const unsigned char buffer[64])
 
 /* SHA1Init - Initialize new context */
 
-void SHA1_Init(SHA1_CTX *context)
+void
+SHA1_Init(SHA1_CTX *context)
 {
     /* SHA1 initialization constants */
     context->state[0] = 0x67452301;
@@ -108,7 +113,8 @@ void SHA1_Init(SHA1_CTX *context)
 
 /* 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;
 
@@ -132,7 +138,8 @@ void SHA1_Update(SHA1_CTX *context, const unsigned char *data, unsigned int len)
 
 /* 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];
index 6727afb27a9db6aa20e36313d7275adea6409bf2..dff8da88bd91a041f616e9fb34020c9958144099 100644 (file)
@@ -10,10 +10,9 @@ typedef struct {
 
 #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_ */
index 76fda67b3f9e94f5f59145b0e4d6eaff966a6c28..5f40b06d36a965c69dc6de66603f1169e7d41917 100644 (file)
@@ -1088,6 +1088,24 @@ netif_set_mtu(int unit, int mtu)
        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
@@ -1175,7 +1193,8 @@ void tty_recv_config (int mru,u_int32_t asyncmap,int pcomp,int accomp)
  * 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;
 
index ad13e39f201344fce7dbf96b97ab0201e5f7b93a..d3d9d9f41d47635066bbbddf1d0069a4f082a308 100644 (file)
@@ -17,7 +17,7 @@
  * 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:
@@ -409,7 +409,7 @@ upap_rauthreq(u, inp, id, len)
 
     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);
@@ -456,7 +456,7 @@ upap_rauthack(u, inp, id, len)
 
     u->us_clientstate = UPAPCS_OPEN;
 
-    auth_withpeer_success(u->us_unit, PPP_PAP);
+    auth_withpeer_success(u->us_unit, PPP_PAP, 0);
 }