From: David F. Skoll Date: Tue, 21 May 2002 17:26:49 +0000 (+0000) Subject: ECP patches from Frank Cusack: X-Git-Tag: ppp-2.4.7~418 X-Git-Url: https://git.ozlabs.org/?p=ppp.git;a=commitdiff_plain;h=7bb8beb860037a6c18dd0b64b8d542a20aa2c8c0 ECP patches from Frank Cusack: - If encryption is required, don't bring up IP/IPv6/IPX until the encryption negotiation has completed. - Shut down LCP if the peer sends an LCP ConfRej instead of CCP ConfRej to our MPPE offer. This fixes a bug where the server could not enforce use of encryption in some cases. - Don't send the M= part of an MS-CHAPv2 success packet to peers that don't know how to deal with it. This allows pre-win2k systems to authenticate. - Don't shut down lcp if MPPE was present in peer's CCP offer along with other options. This allows pre-win2k systems to do MPPE (they offer Stac LZS with MPPE). - Add the beginnings of ecp.c. - Other minor changes. --- diff --git a/README.MPPE b/README.MPPE index 7091d03..cdada34 100644 --- a/README.MPPE +++ b/README.MPPE @@ -58,14 +58,15 @@ RADIUS support for MPPE is from Ralf Hofmann, . BUILDING THE PPPD -The userland component of PPPD has no additional requirements above those -for MS-CHAP and MS-CHAPv2. The kernel, however, requires SHA-1 and ARCFOUR. -Public domain implementations of these are provided. Until such time as -MPPE support ships with kernels, you can use the Linux-2.2 implementation -that comes with PPPD. Run the linux/mppe/mppeinstall.sh script, then -rebuild your kernel. The ppp_mppe.o module is added, and the ppp.o module -is modified (unfortunately). You'll need the new ppp.o since it does the -right thing for the 4 extra bytes problem discussed above. +The userland component of PPPD has no additional requirements above +those for MS-CHAP and MS-CHAPv2. The kernel, however, requires SHA-1 +and ARCFOUR. Public domain implementations of these are provided. Until +such time as MPPE support ships with kernels, you can use the Linux-2.2 +implementation that comes with PPPD. Run the linux/mppe/mppeinstall.sh +script, then rebuild your kernel. The ppp_mppe.o module is added, and the +ppp.o module (2.2) or ppp_generic.o (2.4) is modified (unfortunately). +You'll need the new ppp.o/ppp_generic.o since it does the right thing +for the 4 extra bytes problem discussed above. CONFIGURATION diff --git a/README.MSCHAP81 b/README.MSCHAP81 index c8e83f3..91199f3 100644 --- a/README.MSCHAP81 +++ b/README.MSCHAP81 @@ -55,7 +55,7 @@ RFC 2759: You'll see these in your pppd log as a line similar to: - Remote message: No dialin permission + Remote message: E=649 No dialin permission Previously, pppd would log this as: diff --git a/include/linux/ppp_defs.h b/include/linux/ppp_defs.h index e390c56..489f84a 100644 --- a/include/linux/ppp_defs.h +++ b/include/linux/ppp_defs.h @@ -1,4 +1,4 @@ -/* $Id: ppp_defs.h,v 1.9 2000/03/27 06:03:36 paulus Exp $ */ +/* $Id: ppp_defs.h,v 1.10 2002/05/21 17:26:48 dfs Exp $ */ /* * ppp_defs.h - PPP definitions. @@ -28,7 +28,7 @@ */ /* - * ==FILEVERSION 20000114== + * ==FILEVERSION 20020521== * * NOTE TO MAINTAINERS: * If you modify this file at all, please set the above date. @@ -80,6 +80,8 @@ #define PPP_IPV6CP 0x8057 /* IPv6 Control Protocol */ #define PPP_CCPFRAG 0x80fb /* CCP at link level (below MP bundle) */ #define PPP_CCP 0x80fd /* Compression Control Protocol */ +#define PPP_ECPFRAG 0x8055 /* ECP at link level (below MP bundle) */ +#define PPP_ECP 0x8053 /* Encryption Control Protocol */ #define PPP_LCP 0xc021 /* Link Control Protocol */ #define PPP_PAP 0xc023 /* Password Authentication Protocol */ #define PPP_LQR 0xc025 /* Link Quality Report protocol */ diff --git a/include/net/ppp_defs.h b/include/net/ppp_defs.h index 4152b06..bda882e 100644 --- a/include/net/ppp_defs.h +++ b/include/net/ppp_defs.h @@ -1,4 +1,4 @@ -/* $Id: ppp_defs.h,v 1.14 1999/08/13 01:55:40 paulus Exp $ */ +/* $Id: ppp_defs.h,v 1.15 2002/05/21 17:26:48 dfs Exp $ */ /* * ppp_defs.h - PPP definitions. @@ -79,6 +79,7 @@ #define PPP_IPXCP 0x802b /* IPX Control Protocol */ #define PPP_IPV6CP 0x8057 /* IPv6 Control Protocol */ #define PPP_CCP 0x80fd /* Compression Control Protocol */ +#define PPP_ECP 0x8053 /* Encryption Control Protocol */ #define PPP_LCP 0xc021 /* Link Control Protocol */ #define PPP_PAP 0xc023 /* Password Authentication Protocol */ #define PPP_LQR 0xc025 /* Link Quality Report protocol */ diff --git a/linux/mppe/ppp_mppe_compress.c b/linux/mppe/ppp_mppe_compress.c index efdb5d1..0a75768 100644 --- a/linux/mppe/ppp_mppe_compress.c +++ b/linux/mppe/ppp_mppe_compress.c @@ -1,5 +1,5 @@ /* - * ==FILEVERSION 20020320== + * ==FILEVERSION 20020521== * * ppp_mppe_compress.c - interface MPPE to the PPP code. * This version is for use with Linux kernel 2.2.19+ and 2.4.x. @@ -62,13 +62,8 @@ typedef struct ppp_mppe_state { #define MPPE_CCOUNT(p) ((((p)[4] & 0x0f) << 8) + (p)[5]) #define MPPE_CCOUNT_SPACE 0x1000 /* The size of the ccount space */ -/* - * MPPE overhead/packet. - * Note that we use this differently than other compressors. - */ #define MPPE_OVHD 2 /* MPPE overhead/packet */ -/* Max bogon factor we will tolerate */ -#define SANITY_MAX 1600 +#define SANITY_MAX 1600 /* Max bogon factor we will tolerate */ static void GetNewKeyFromSHA __P((unsigned char *StartKey, unsigned char *SessionKey, @@ -236,17 +231,17 @@ mppe_init(void *arg, unsigned char *options, int optlen, int unit, int debug, if (debug) { int i; - char mkey[sizeof(state->master_key) * 3 + 1]; - char skey[sizeof(state->session_key) * 3 + 1]; + char mkey[sizeof(state->master_key) * 2 + 1]; + char skey[sizeof(state->session_key) * 2 + 1]; printk(KERN_DEBUG "%s[%d]: initialized with %d-bit %s mode\n", debugstr, unit, (state->keylen == 16)? 128: 40, (state->stateful)? "stateful": "stateless"); for (i = 0; i < sizeof(state->master_key); i++) - sprintf(mkey + i * 2, "%.2x ", state->master_key[i]); + sprintf(mkey + i * 2, "%.2x", state->master_key[i]); for (i = 0; i < sizeof(state->session_key); i++) - sprintf(skey + i * 2, "%.2x ", state->session_key[i]); + sprintf(skey + i * 2, "%.2x", state->session_key[i]); printk(KERN_DEBUG "%s[%d]: keys: master: %s initial session: %s\n", debugstr, unit, mkey, skey); } @@ -544,6 +539,7 @@ mppe_incomp(void *arg, unsigned char *ibuf, int icnt) { ppp_mppe_state *state = (ppp_mppe_state *) arg; +/* XXX */ if (state->debug && (PPP_PROTOCOL(ibuf) >= 0x0021 && PPP_PROTOCOL(ibuf) <= 0x00fa)) printk(KERN_DEBUG "mppe_incomp[%d]: incompressible (unencrypted) data! " diff --git a/pppd/Makefile.NeXT b/pppd/Makefile.NeXT index 11ecabd..7b873e2 100644 --- a/pppd/Makefile.NeXT +++ b/pppd/Makefile.NeXT @@ -2,7 +2,7 @@ # pppd makefile for NeXT # # $Orignial: Makefile.ultrix,v 1.4 1994/09/01 00:40:40 paulus Exp $ -# $Id: Makefile.NeXT,v 1.6 1999/04/12 06:24:44 paulus Exp $ +# $Id: Makefile.NeXT,v 1.7 2002/05/21 17:26:48 dfs Exp $ # ARCHFLAGS = @@ -11,7 +11,7 @@ BINDIR = /usr/local/ppp/bin MANDIR = /usr/local/ppp/man OBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o \ - auth.o options.o demand.o utils.o sys-NeXT.o + ecp.o auth.o options.o demand.o utils.o sys-NeXT.o # # For HPPA and SPARC, define FIXSIGS to get around posix bugs in diff --git a/pppd/Makefile.aix4 b/pppd/Makefile.aix4 index 05e503b..e173f6f 100644 --- a/pppd/Makefile.aix4 +++ b/pppd/Makefile.aix4 @@ -1,6 +1,6 @@ # # pppd makefile for AIX 4.1 -# $Id: Makefile.aix4,v 1.4 1999/04/12 06:24:44 paulus Exp $ +# $Id: Makefile.aix4,v 1.5 2002/05/21 17:26:48 dfs Exp $ # #ifndef BINDIR BINDIR = /usr/sbin @@ -10,11 +10,11 @@ MANDIR = /usr/man #ENDIF PPPDSRCS = main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c \ - auth.c options.c demand.c utils.c sys-aix4.c \ + ecp.c auth.c options.c demand.c utils.c sys-aix4.c \ gencode.c grammar.c scanner.c nametoaddr.c optimize.c PPPDOBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o \ - auth.o options.o demand.o utils.o sys-aix4.o \ + ecp.o auth.o options.o demand.o utils.o sys-aix4.o \ gencode.o grammar.o scanner.o nametoaddr.o optimize.o CC = xlc diff --git a/pppd/Makefile.bsd b/pppd/Makefile.bsd index ea94db5..83a899f 100644 --- a/pppd/Makefile.bsd +++ b/pppd/Makefile.bsd @@ -1,4 +1,4 @@ -# $Id: Makefile.bsd,v 1.15 1999/04/12 06:24:44 paulus Exp $ +# $Id: Makefile.bsd,v 1.16 2002/05/21 17:26:48 dfs Exp $ BINDIR?= /usr/sbin # -D_BITYPES is for FreeBSD, which doesn't define anything to @@ -8,7 +8,7 @@ CFLAGS+= -g -I../include -DHAVE_PATHS_H -D_BITYPES PROG= pppd SRCS= main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c \ - demand.c auth.c options.c utils.c sys-bsd.c + ecp.c demand.c auth.c options.c utils.c sys-bsd.c MAN= pppd.cat8 MAN8= pppd.8 BINMODE=4555 diff --git a/pppd/Makefile.linux b/pppd/Makefile.linux index 57b6b08..ada4ac8 100644 --- a/pppd/Makefile.linux +++ b/pppd/Makefile.linux @@ -1,19 +1,19 @@ # # pppd makefile for Linux -# $Id: Makefile.linux,v 1.47 2002/04/02 13:54:59 dfs Exp $ +# $Id: Makefile.linux,v 1.48 2002/05/21 17:26:48 dfs Exp $ # # Default installation locations BINDIR = /usr/sbin MANDIR = /usr/man -PPPDSRCS = main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c \ +PPPDSRCS = main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c ecp.c \ ipxcp.c auth.c options.c sys-linux.c md4.c chap_ms.c cbcp.c \ demand.c utils.c tty.c sha1.c HEADERS = callout.h pathnames.h patchlevel.h chap.h md5.h chap_ms.h md4.h \ ipxcp.h cbcp.h tdb.h sha1.h MANPAGES = pppd.8 -PPPDOBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o \ +PPPDOBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o ecp.o \ auth.o options.o demand.o utils.o sys-linux.o ipxcp.o tty.o sha1.o all: pppd diff --git a/pppd/Makefile.netbsd-1.2 b/pppd/Makefile.netbsd-1.2 index d10dfac..e50b7f5 100644 --- a/pppd/Makefile.netbsd-1.2 +++ b/pppd/Makefile.netbsd-1.2 @@ -3,7 +3,7 @@ PCAPDIR=${.CURDIR}/../../lib/libpcap PROG= pppd -SRCS= auth.c cbcp.c ccp.c chap.c chap_ms.c demand.c fsm.c ipcp.c \ +SRCS= auth.c cbcp.c ccp.c ecp.c chap.c chap_ms.c demand.c fsm.c ipcp.c \ ipxcp.c lcp.c magic.c main.c options.c sys-bsd.c upap.c .PATH: ${PCAPDIR} ${.CURDIR}/../../sys/net diff --git a/pppd/Makefile.osf b/pppd/Makefile.osf index 63f4eb9..e680d2a 100644 --- a/pppd/Makefile.osf +++ b/pppd/Makefile.osf @@ -1,15 +1,15 @@ # # pppd makefile for OSF/1 on DEC Alpha -# $Id: Makefile.osf,v 1.11 2002/03/05 15:14:04 dfs Exp $ +# $Id: Makefile.osf,v 1.12 2002/05/21 17:26:48 dfs Exp $ # BINDIR = /usr/local/etc MANDIR = /usr/local/man -PPPDSRCS = main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c \ +PPPDSRCS = main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c ecp.c \ auth.c options.c demand.c utils.c sys-osf.c md4.c chap_ms.c sha1.c -PPPDOBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o \ +PPPDOBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o ecp.o \ auth.o options.o demand.o utils.o sys-osf.o md4.o chap_ms.o sha1.o CC = cc diff --git a/pppd/Makefile.sol2 b/pppd/Makefile.sol2 index f1f08a8..2f32aaf 100644 --- a/pppd/Makefile.sol2 +++ b/pppd/Makefile.sol2 @@ -1,6 +1,6 @@ # # Makefile for pppd under Solaris 2. -# $Id: Makefile.sol2,v 1.20 2001/03/08 05:01:03 paulus Exp $ +# $Id: Makefile.sol2,v 1.21 2002/05/21 17:26:48 dfs Exp $ # include ../solaris/Makedefs @@ -10,7 +10,7 @@ CFLAGS = -I../include -DSVR4 -DSOL2 $(COPTS) LIBS = -lsocket -lnsl OBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o tty.o \ - ccp.o auth.o options.o demand.o utils.o sys-solaris.o tdb.o + ccp.o ecp.o auth.o options.o demand.o utils.o sys-solaris.o tdb.o # # uncomment the following to enable plugins diff --git a/pppd/Makefile.sunos4 b/pppd/Makefile.sunos4 index 714cb4d..09276d2 100644 --- a/pppd/Makefile.sunos4 +++ b/pppd/Makefile.sunos4 @@ -1,6 +1,6 @@ # # Makefile for pppd under SunOS 4. -# $Id: Makefile.sunos4,v 1.11 2001/03/08 05:01:03 paulus Exp $ +# $Id: Makefile.sunos4,v 1.12 2002/05/21 17:26:48 dfs Exp $ # include ../sunos4/Makedefs @@ -12,7 +12,7 @@ CFLAGS = $(COPTS) -I../include -DSUNOS4 -DGIDSET_TYPE=int \ all: pppd -OBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o \ +OBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o ecp.o \ auth.o options.o demand.o utils.o sys-sunos4.o tty.o pppd: $(OBJS) diff --git a/pppd/Makefile.svr4 b/pppd/Makefile.svr4 index 842c615..ea7e7f8 100644 --- a/pppd/Makefile.svr4 +++ b/pppd/Makefile.svr4 @@ -1,6 +1,6 @@ # # Makefile for pppd under Solaris 2. -# $Id: Makefile.svr4,v 1.14 1999/04/12 06:24:44 paulus Exp $ +# $Id: Makefile.svr4,v 1.15 2002/05/21 17:26:48 dfs Exp $ # include ../svr4/Makedefs @@ -10,7 +10,7 @@ LIBS = -lsocket -lnsl -lc -L/usr/ucblib -lucb all: pppd -OBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o \ +OBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o ecp.o \ auth.o options.o demand.o utils.o sys-svr4.o pppd: $(OBJS) diff --git a/pppd/Makefile.ultrix b/pppd/Makefile.ultrix index cfd191c..8ffa624 100644 --- a/pppd/Makefile.ultrix +++ b/pppd/Makefile.ultrix @@ -1,15 +1,15 @@ # # pppd makefile for Ultrix -# $Id: Makefile.ultrix,v 1.11 1999/04/12 06:24:44 paulus Exp $ +# $Id: Makefile.ultrix,v 1.12 2002/05/21 17:26:49 dfs Exp $ # BINDIR = /usr/local/etc MANDIR = /usr/local/man -PPPDSRCS = main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c \ +PPPDSRCS = main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c ecp.c \ auth.c options.c demand.c utils.c sys-ultrix.c -PPPDOBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o \ +PPPDOBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o ecp.o \ auth.o options.o demand.o utils.o sys-ultrix.o # CC = gcc diff --git a/pppd/auth.c b/pppd/auth.c index 67f1278..727c69d 100644 --- a/pppd/auth.c +++ b/pppd/auth.c @@ -32,7 +32,7 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#define RCSID "$Id: auth.c,v 1.76 2002/04/02 13:54:59 dfs Exp $" +#define RCSID "$Id: auth.c,v 1.77 2002/05/21 17:26:49 dfs Exp $" #include #include @@ -69,6 +69,8 @@ #include "pppd.h" #include "fsm.h" #include "lcp.h" +#include "ccp.h" +#include "ecp.h" #include "ipcp.h" #include "upap.h" #include "chap.h" @@ -595,42 +597,66 @@ network_phase(unit) free_wordlist(extra_options); extra_options = 0; } - start_networks(); + start_networks(unit); } void -start_networks() +start_networks(unit) + int unit; { + static int started = 0; int i; struct protent *protp; + int ecp_required, mppe_required; - new_phase(PHASE_NETWORK); + if (!started) { + started = 1; + new_phase(PHASE_NETWORK); #ifdef HAVE_MULTILINK - if (multilink) { - if (mp_join_bundle()) { - if (updetach && !nodetach) - detach(); - return; + if (multilink) { + if (mp_join_bundle()) { + if (updetach && !nodetach) + detach(); + return; + } } - } #endif /* HAVE_MULTILINK */ #ifdef PPP_FILTER - if (!demand) - set_filters(&pass_filter, &active_filter); + if (!demand) + set_filters(&pass_filter, &active_filter); #endif - for (i = 0; (protp = protocols[i]) != NULL; ++i) - if (protp->protocol < 0xC000 && protp->enabled_flag - && protp->open != NULL) { - (*protp->open)(0); - if (protp->protocol != PPP_CCP) + /* Start CCP and ECP */ + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if ((protp->protocol == PPP_ECP || protp->protocol == PPP_CCP) + && protp->enabled_flag && protp->open != NULL) + (*protp->open)(0); + } + + /* + * Bring up other network protocols after encryption has completed. + * OPENED here merely means that negotiation has completed. It is + * up to the protocol to correctly terminate or disable LCP/NCP + * based on the result of the negotiation. + */ + ecp_required = ecp_gotoptions[unit].required; + mppe_required = ccp_gotoptions[unit].mppe; + if ((!ecp_required && !mppe_required) + || (ecp_required && ecp_fsm[unit].state == OPENED) + || (mppe_required && ccp_fsm[unit].state == OPENED)) { + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (protp->protocol < 0xC000 + && protp->protocol != PPP_CCP && protp->protocol != PPP_ECP + && protp->enabled_flag && protp->open != NULL) { + (*protp->open)(0); ++num_np_open; - } + } - if (num_np_open == 0) - /* nothing to do */ - lcp_close(0, "No network protocols running"); + if (num_np_open == 0) + /* nothing to do */ + lcp_close(0, "No network protocols running"); + } } /* diff --git a/pppd/cbcp.c b/pppd/cbcp.c index e48aa46..439d7ed 100644 --- a/pppd/cbcp.c +++ b/pppd/cbcp.c @@ -18,7 +18,7 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#define RCSID "$Id: cbcp.c,v 1.11 2001/03/08 05:11:10 paulus Exp $" +#define RCSID "$Id: cbcp.c,v 1.12 2002/05/21 17:26:49 dfs Exp $" #include #include @@ -383,7 +383,7 @@ cbcp_resp(us) PUTCHAR(len , bufp); PUTCHAR(0, bufp); cbcp_send(us, CBCP_RESP, buf, len); - start_networks(); + start_networks(us->us_unit); return; } } diff --git a/pppd/ccp.c b/pppd/ccp.c index fa8a5a0..40bf77f 100644 --- a/pppd/ccp.c +++ b/pppd/ccp.c @@ -25,7 +25,7 @@ * OR MODIFICATIONS. */ -#define RCSID "$Id: ccp.c,v 1.34 2002/04/02 13:54:59 dfs Exp $" +#define RCSID "$Id: ccp.c,v 1.35 2002/05/21 17:26:49 dfs Exp $" #include #include @@ -36,7 +36,7 @@ #include #ifdef MPPE -#include "chap_ms.h" /* mppe_xx_key */ +#include "chap_ms.h" /* mppe_xxxx_key */ #include "lcp.h" /* lcp_close() */ #endif @@ -510,6 +510,12 @@ ccp_protrej(unit) { ccp_flags_set(unit, 0, 0); fsm_lowerdown(&ccp_fsm[unit]); + +#ifdef MPPE + if (ccp_gotoptions[unit].mppe) + lcp_close(unit, "MPPE required but peer negotiation failed"); +#endif + } /* @@ -542,10 +548,10 @@ ccp_resetci(f) */ /* Leave only the mschap auth bits set */ - auth_mschap_bits &= ~(PAP_WITHPEER | PAP_PEER | - CHAP_WITHPEER | CHAP_PEER | - CHAP_MD5_WITHPEER | CHAP_MD5_PEER); + auth_mschap_bits &= (CHAP_MS_WITHPEER | CHAP_MS_PEER | + CHAP_MS2_WITHPEER | CHAP_MS2_PEER); /* Count the mschap auths */ + auth_mschap_bits >>= CHAP_MS_SHIFT; numbits = 0; do { numbits += auth_mschap_bits & 1; @@ -568,6 +574,7 @@ ccp_resetci(f) if (go->mppe & MPPE_OPT_40) { notice("Disabling 40-bit MPPE; MS-CHAP LM not supported"); go->mppe &= ~MPPE_OPT_40; + ccp_wantoptions[f->unit].mppe &= ~MPPE_OPT_40; } } @@ -1047,6 +1054,9 @@ ccp_reqci(f, p, lenp, dont_nak) int len, clen, type, nb; ccp_options *ho = &ccp_hisoptions[f->unit]; ccp_options *ao = &ccp_allowoptions[f->unit]; +#ifdef MPPE + bool seen_ci_mppe = 0; +#endif ret = CONFACK; retp = p0 = p; @@ -1073,6 +1083,7 @@ ccp_reqci(f, p, lenp, dont_nak) newret = CONFREJ; break; } + seen_ci_mppe = 1; MPPE_CI_TO_OPTS(&p[2], ho->mppe); /* Nak if anything unsupported or unknown are set. */ @@ -1302,8 +1313,10 @@ ccp_reqci(f, p, lenp, dont_nak) else *lenp = retp - p0; } - if (ret == CONFREJ && ao->mppe) +#ifdef MPPE + if (ret == CONFREJ && ao->mppe && !seen_ci_mppe) lcp_close(f->unit, "MPPE required but peer negotiation failed"); +#endif return ret; } @@ -1397,6 +1410,13 @@ ccp_up(f) notice("%s receive compression enabled", method_name(go, NULL)); } else if (ANY_COMPRESS(*ho)) notice("%s transmit compression enabled", method_name(ho, NULL)); +#ifdef MPPE + if (go->mppe) { + BZERO(mppe_recv_key, MPPE_MAX_KEY_LEN); + BZERO(mppe_send_key, MPPE_MAX_KEY_LEN); + start_networks(f->unit); /* Bring up IP et al */ + } +#endif } /* @@ -1410,6 +1430,10 @@ ccp_down(f) UNTIMEOUT(ccp_rack_timeout, f); ccp_localstate[f->unit] = 0; ccp_flags_set(f->unit, 1, 0); +#ifdef MPPE + if (ccp_gotoptions[f->unit].mppe) + lcp_close(f->unit, "MPPE disabled"); +#endif } /* @@ -1480,6 +1504,9 @@ ccp_printpkt(p, plen, printer, arg) (p[5] & MPPE_D_BIT)? "+D": "-D", (p[5] & MPPE_C_BIT)? "+C": "-C", (mppe_opts & MPPE_OPT_UNKNOWN)? " +U": ""); + if (mppe_opts & MPPE_OPT_UNKNOWN) + printer(arg, " (%.2x %.2x %.2x %.2x)", + p[2], p[3], p[4], p[5]); p += CILEN_MPPE; } break; diff --git a/pppd/chap.c b/pppd/chap.c index a9dc78c..c295bb3 100644 --- a/pppd/chap.c +++ b/pppd/chap.c @@ -33,7 +33,7 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#define RCSID "$Id: chap.c,v 1.31 2002/04/02 14:15:07 dfs Exp $" +#define RCSID "$Id: chap.c,v 1.32 2002/05/21 17:26:49 dfs Exp $" /* * TODO: @@ -585,6 +585,11 @@ ChapReceiveResponse(cstate, inp, id, len) BCOPY(inp, rhostname, len); rhostname[len] = '\000'; +#ifdef CHAPMS + /* copy the flags into cstate for use elsewhere */ + if (cstate->chal_type == CHAP_MICROSOFT_V2) + cstate->resp_flags = ((MS_Chap2Response *) remmd)->Flags[0]; +#endif /* CHAPMS */ /* * Get secret for authenticating them with us, * do the hash ourselves, and compare the result. @@ -824,35 +829,35 @@ ChapReceiveFailure(cstate, inp, id, len) /* No M=; use the error code. */ switch(error) { case MS_CHAP_ERROR_RESTRICTED_LOGON_HOURS: - p = "Restricted logon hours"; + p = "E=646 Restricted logon hours"; break; case MS_CHAP_ERROR_ACCT_DISABLED: - p = "Account disabled"; + p = "E=647 Account disabled"; break; case MS_CHAP_ERROR_PASSWD_EXPIRED: - p = "Password expired"; + p = "E=648 Password expired"; break; case MS_CHAP_ERROR_NO_DIALIN_PERMISSION: - p = "No dialin permission"; + p = "E=649 No dialin permission"; break; case MS_CHAP_ERROR_AUTHENTICATION_FAILURE: - p = "Authentication failure"; + p = "E=691 Authentication failure"; break; case MS_CHAP_ERROR_CHANGING_PASSWORD: /* Should never see this, we don't support Change Password. */ - p = "Error changing password"; + p = "E=709 Error changing password"; break; default: free(msg); p = msg = malloc(len + 33); if (!msg) { - notice("Out of memory in ChapReceiveFailure"); + novm("ChapReceiveFailure"); goto print_msg; } slprintf(p, len + 33, "Unknown authentication failure: %.*s", @@ -935,16 +940,30 @@ ChapSendStatus(cstate, code) #ifdef CHAPMS if (cstate->chal_type == CHAP_MICROSOFT_V2) { /* - * Success message must be formatted as + * Per RFC 2759, success message must be formatted as * "S= M=" * where * is the Authenticator Response (mutual auth) * is a text message + * + * However, some versions of Windows (win98 tested) do not know + * about the M= part (required per RFC 2759) and flag + * it as an error (reported incorrectly as an encryption error + * to the user). Since the RFC requires it, and it can be + * useful information, we supply it if the peer is a conforming + * system. Luckily (?), win98 sets the Flags field to 0x04 + * (contrary to RFC requirements) so we can use that to + * distinguish between conforming and non-conforming systems. + * + * Special thanks to Alex Swiridov for + * help debugging this. */ slprintf(p, q - p, "S="); p += 2; slprintf(p, q - p, "%s", cstate->saresponse); p += strlen(cstate->saresponse); + if (cstate->resp_flags != 0) + goto msgdone; slprintf(p, q - p, " M="); p += 3; } @@ -967,7 +986,16 @@ ChapSendStatus(cstate, code) * * The M=m part is only for MS-CHAPv2, but MS-CHAP should ignore * any extra text according to RFC 2433. So we'll go the easy - * (read: lazy) route and include it always. + * (read: lazy) route and include it always. Neither win2k nor + * win98 (others untested) display the message to the user anyway. + * They also both ignore the E=e code. + * + * Note that it's safe to reuse the same challenge as we don't + * actually accept another response based on the error message + * (and no clients try to resend a response anyway). + * + * Basically, this whole bit is useless code, even the small + * implementation here is only because of overspecification. */ slprintf(p, q - p, "E=691 R=1 C="); p += 12; @@ -981,6 +1009,7 @@ ChapSendStatus(cstate, code) slprintf(p, q - p, "I don't like you. Go 'way."); } +msgdone: msglen = strlen(msg); outlen = CHAP_HEADERLEN + msglen; diff --git a/pppd/chap.h b/pppd/chap.h index 13f0511..ae42379 100644 --- a/pppd/chap.h +++ b/pppd/chap.h @@ -30,7 +30,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: chap.h,v 1.12 2002/04/02 13:54:59 dfs Exp $ + * $Id: chap.h,v 1.13 2002/05/21 17:26:49 dfs Exp $ */ #ifndef __CHAP_INCLUDE__ @@ -52,12 +52,12 @@ */ /* bitmask of supported algorithms */ -#define MDTYPE_MD5 0x1 -#define MDTYPE_MICROSOFT_V2 0x2 -#define MDTYPE_MICROSOFT 0x4 +#define MDTYPE_MICROSOFT_V2 0x1 +#define MDTYPE_MICROSOFT 0x2 +#define MDTYPE_MD5 0x4 #ifdef CHAPMS -#define MDTYPE_ALL (MDTYPE_MD5 | MDTYPE_MICROSOFT_V2 | MDTYPE_MICROSOFT) +#define MDTYPE_ALL (MDTYPE_MICROSOFT_V2 | MDTYPE_MICROSOFT |MDTYPE_MD5) #else #define MDTYPE_ALL (MDTYPE_MD5) #endif @@ -65,9 +65,9 @@ /* Return the digest alg. ID for the most preferred digest type. */ #define CHAP_DIGEST(mdtype) \ - ((mdtype) & MDTYPE_MD5)? CHAP_DIGEST_MD5: \ ((mdtype) & MDTYPE_MICROSOFT_V2)? CHAP_MICROSOFT_V2: \ ((mdtype) & MDTYPE_MICROSOFT)? CHAP_MICROSOFT: \ + ((mdtype) & MDTYPE_MD5)? CHAP_DIGEST_MD5: \ 0 /* Return the bit flag (lsb set) for our most preferred digest type. */ @@ -75,16 +75,16 @@ /* Return the bit flag for a given digest algorithm ID. */ #define CHAP_MDTYPE_D(digest) \ - ((digest) == CHAP_DIGEST_MD5)? MDTYPE_MD5: \ ((digest) == CHAP_MICROSOFT_V2)? MDTYPE_MICROSOFT_V2: \ ((digest) == CHAP_MICROSOFT)? MDTYPE_MICROSOFT: \ + ((digest) == CHAP_DIGEST_MD5)? MDTYPE_MD5: \ 0 /* Can we do the requested digest? */ #define CHAP_CANDIGEST(mdtype, digest) \ - ((digest) == CHAP_DIGEST_MD5)? (mdtype) & MDTYPE_MD5: \ ((digest) == CHAP_MICROSOFT_V2)? (mdtype) & MDTYPE_MICROSOFT_V2: \ ((digest) == CHAP_MICROSOFT)? (mdtype) & MDTYPE_MICROSOFT: \ + ((digest) == CHAP_DIGEST_MD5)? (mdtype) & MDTYPE_MD5: \ 0 #define CHAP_CHALLENGE 1 @@ -124,6 +124,7 @@ typedef struct chap_state { char saresponse[MS_AUTH_RESPONSE_LENGTH+1]; /* Auth response to send */ char earesponse[MS_AUTH_RESPONSE_LENGTH+1]; /* Auth response expected */ /* +1 for null terminator */ + u_char resp_flags; /* flags from MS-CHAPv2 auth response */ u_char resp_length; /* length of response */ u_char resp_id; /* ID for response messages */ u_char resp_type; /* hash algorithm for responses */ diff --git a/pppd/main.c b/pppd/main.c index 16231db..c6ba438 100644 --- a/pppd/main.c +++ b/pppd/main.c @@ -17,7 +17,7 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#define RCSID "$Id: main.c,v 1.112 2002/02/12 20:07:09 dfs Exp $" +#define RCSID "$Id: main.c,v 1.113 2002/05/21 17:26:49 dfs Exp $" #include #include @@ -53,6 +53,7 @@ #include "upap.h" #include "chap.h" #include "ccp.h" +#include "ecp.h" #include "pathnames.h" #ifdef USE_TDB @@ -222,6 +223,7 @@ struct protent *protocols[] = { &ipv6cp_protent, #endif &ccp_protent, + &ecp_protent, #ifdef IPX_CHANGE &ipxcp_protent, #endif @@ -1671,7 +1673,7 @@ remove_notifier(notif, func, arg) } /* - * notify - call a set of functions registered with add_notify. + * notify - call a set of functions registered with add_notifier. */ void notify(notif, val) diff --git a/pppd/pppd.8 b/pppd/pppd.8 index 6befb31..5b9a765 100644 --- a/pppd/pppd.8 +++ b/pppd/pppd.8 @@ -1,5 +1,5 @@ .\" manual page [] for pppd 2.4 -.\" $Id: pppd.8,v 1.62 2002/04/02 13:54:59 dfs Exp $ +.\" $Id: pppd.8,v 1.63 2002/05/21 17:26:49 dfs Exp $ .\" SH section heading .\" SS subsection heading .\" LP paragraph @@ -890,6 +890,8 @@ 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. +This option is presently only supported under Linux, and only if your +kernel has been configured to include MPPE support. .TP .B require-mppe-40 Require the use of MPPE, with 40\-bit encryption. diff --git a/pppd/pppd.h b/pppd/pppd.h index a9b780a..3ade18e 100644 --- a/pppd/pppd.h +++ b/pppd/pppd.h @@ -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.67 2002/04/02 13:54:59 dfs Exp $ + * $Id: pppd.h,v 1.68 2002/05/21 17:26:49 dfs Exp $ */ /* @@ -306,6 +306,7 @@ extern bool ms_lanman; /* Use LanMan password instead of NT */ #define CHAP_MD5_WITHPEER 0x10 #define CHAP_MD5_PEER 0x20 #ifdef CHAPMS +#define CHAP_MS_SHIFT 6 /* LSB position for MS auths */ #define CHAP_MS_WITHPEER 0x40 #define CHAP_MS_PEER 0x80 #define CHAP_MS2_WITHPEER 0x100 @@ -478,7 +479,7 @@ void link_required __P((int)); /* we are starting to use the link */ void link_terminated __P((int)); /* we are finished with the link */ void link_down __P((int)); /* the LCP layer has left the Opened state */ void link_established __P((int)); /* the link is up; authenticate now */ -void start_networks __P((void)); /* start all the network control protos */ +void start_networks __P((int)); /* start all the network control protos */ void np_up __P((int, int)); /* a network protocol has come up */ 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 */