diff -urN ppp-2.4.1/Makefile ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/Makefile --- ppp-2.4.1/Makefile Wed Dec 31 19:00:00 1969 +++ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/Makefile Mon Apr 17 06:39:26 2000 @@ -0,0 +1,55 @@ +# PPP top-level Makefile for Linux. + + +BINDIR = $(DESTDIR)/usr/sbin +MANDIR = $(DESTDIR)/usr/man +ETCDIR = $(DESTDIR)/etc/ppp + +# uid 0 = root +INSTALL= install + +all: + cd chat; $(MAKE) $(MFLAGS) all + cd pppd; $(MAKE) $(MFLAGS) all + cd pppstats; $(MAKE) $(MFLAGS) all + cd pppdump; $(MAKE) $(MFLAGS) all + +install: $(BINDIR) $(MANDIR)/man8 install-progs install-etcppp + +install-progs: + cd chat; $(MAKE) BINDIR=$(BINDIR) MANDIR=$(MANDIR) $(MFLAGS) install + cd pppd; $(MAKE) BINDIR=$(BINDIR) MANDIR=$(MANDIR) $(MFLAGS) install + cd pppstats; $(MAKE) BINDIR=$(BINDIR) MANDIR=$(MANDIR) $(MFLAGS) install + cd pppdump; $(MAKE) BINDIR=$(BINDIR) MANDIR=$(MANDIR) $(MFLAGS) install + +install-etcppp: $(ETCDIR) $(ETCDIR)/options $(ETCDIR)/pap-secrets \ + $(ETCDIR)/chap-secrets + +$(ETCDIR)/options: + $(INSTALL) -c -m 644 etc.ppp/options $@ +$(ETCDIR)/pap-secrets: + $(INSTALL) -c -m 600 etc.ppp/pap-secrets $@ +$(ETCDIR)/chap-secrets: + $(INSTALL) -c -m 600 etc.ppp/chap-secrets $@ + +$(BINDIR): + $(INSTALL) -d -m 755 $@ +$(MANDIR)/man8: + $(INSTALL) -d -m 755 $@ +$(ETCDIR): + $(INSTALL) -d -m 755 $@ + +clean: + rm -f `find . -name '*.[oas]' -print` + rm -f `find . -name 'core' -print` + rm -f `find . -name '*~' -print` + cd chat; $(MAKE) clean + cd pppd; $(MAKE) clean + cd pppstats; $(MAKE) clean + cd pppdump; $(MAKE) clean + +dist-clean: clean + rm -f Makefile `find . -name Makefile -print` + +#kernel: +# cd linux; ./kinstall.sh diff -urN ppp-2.4.1/README.MPPE ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/README.MPPE --- ppp-2.4.1/README.MPPE Wed Dec 31 19:00:00 1969 +++ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/README.MPPE Tue Nov 5 20:00:52 2002 @@ -0,0 +1,54 @@ +Just a few quick notes. + +MPPE support was started by Árpád Magosányi +in 1994, and was finished by Tim Hockin, Cobalt Networks +Inc. in 1999. If you helped, and I don't know +it (which could be) please notify the maintainer of this code, and it +will be rectified. As far as I know, only Linux is supported (sorry - +it's all we had available). + +MPPE - Microsoft Point-to-Point Encryption uses rc4 (40 or 128 bit +key) as a bi-directional encryption algorithm. The rc4 session keys +are based on your MS-CHAP authentication info, so you must use chapms +or chapms-v2. The session keys are derived from your MS-CHAP info +using SHA, the Secure Hash Algorithm. + +This is NOT a particularly secure mode of operation, especially not +when using MS-CHAP version 1. For maximum possible security using +MPPE, it is advised in the RFC's to use the highest mode of encryption +that is legal, and to enable stateless mode (which renogotiates keys +with every packet). Even with these precautions, MPPE is not very +secure, but anything is better than nothing, right? + +That said, it seems to work pretty well, for what it is. MSChap-v2 +support was added by someone along the way, and MPPE needed some +finishing. It appears to work with Windows (tm) clients, with +encryption specified. It also works with a Windows server when +pptp-linux is used as a VPN client in conjunction with this pppd. + +Copyright for some code is owned by Eric Young (see +./include/openssl/sha.h for details). + +Rc4 is owned by RSA Data Security, and you may have to pay to use it, +or not use it at all, depending on your place of residence. No author +listed in this file claims any responsibility for misuse of this +software. Since the ppp-2.4 package no longer includes scripts for +patching the Linux kernel source, the kernel patches (which may +include the rc4 implementation) are distributed in a separate patch. +Pppd itself does not need rc4 because the encryption is implemented in +a kernel "compression" module, not in pppd. + +How to use it: +* Compile this pppd, and the associated kernel modules. +* Add +chapms and/or +chapms-v2 to your pppd command line, unless you + do not require the peer to authenticate itself to you. +* Add mppe-40 and/or mppe-128 and/or mppe-stateless to your pppd command line. +* Either load ppp_mppe.o manually or put this line in your /etc/conf.modules. + alias ppp-compress-18 ppp_mppe +* Go for it. + + +For further reading: + Use the source, Luke. + draft-ietf-pppext-mppe-05.txt (any RFC site should have this) + draft-ietf-pppext-mppe-keys-03.txt (ditto) diff -urN ppp-2.4.1/chat/Makefile ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/chat/Makefile --- ppp-2.4.1/chat/Makefile Wed Dec 31 19:00:00 1969 +++ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/chat/Makefile Thu Aug 12 21:54:32 1999 @@ -0,0 +1,27 @@ +# $Id: Makefile.linux,v 1.9 1999/08/13 01:54:32 paulus Exp $ + +CDEF1= -DTERMIOS # Use the termios structure +CDEF2= -DSIGTYPE=void # Standard definition +CDEF3= -UNO_SLEEP # Use the usleep function +CDEF4= -DFNDELAY=O_NDELAY # Old name value +CDEFS= $(CDEF1) $(CDEF2) $(CDEF3) $(CDEF4) + +CFLAGS= -O2 -g -pipe $(CDEFS) + +INSTALL= install + +all: chat + +chat: chat.o + $(CC) -o chat chat.o + +chat.o: chat.c + $(CC) -c $(CFLAGS) -o chat.o chat.c + +install: chat + mkdir -p $(BINDIR) + $(INSTALL) -s -c chat $(BINDIR) + $(INSTALL) -c -m 644 chat.8 $(MANDIR)/man8 + +clean: + rm -f chat.o chat *~ Binary files ppp-2.4.1/chat/chat and ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/chat/chat differ Binary files ppp-2.4.1/chat/chat.o and ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/chat/chat.o differ diff -urN ppp-2.4.1/include/linux/ppp-comp.h ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/include/linux/ppp-comp.h --- ppp-2.4.1/include/linux/ppp-comp.h Fri Jul 23 02:53:29 1999 +++ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/include/linux/ppp-comp.h Tue Nov 5 20:00:52 2002 @@ -28,7 +28,7 @@ */ /* - * ==FILEVERSION 980319== + * ==FILEVERSION 990623== * * NOTE TO MAINTAINERS: * If you modify this file at all, please set the above date. @@ -120,6 +120,7 @@ * Don't you just lurve software patents. */ +#define DECOMP_OK 0 /* no error occured */ #define DECOMP_ERROR -1 /* error detected before decomp. */ #define DECOMP_FATALERROR -2 /* error detected after decomp. */ @@ -138,7 +139,7 @@ * Max # bytes for a CCP option */ -#define CCP_MAX_OPTION_LENGTH 32 +#define CCP_MAX_OPTION_LENGTH 64 /* * Parts of a CCP packet. @@ -185,6 +186,20 @@ #define DEFLATE_MAKE_OPT(w) ((((w) - DEFLATE_MIN_SIZE) << 4) \ + 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 */ + +/* + * Definitions for Stac LZS. + */ + +#define CI_LZS 17 /* config option for Stac LZS */ +#define CILEN_LZS 5 /* length of config option */ /* * Definitions for other, as yet unsupported, compression methods. diff -urN ppp-2.4.1/include/net/ppp-comp.h ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/include/net/ppp-comp.h --- ppp-2.4.1/include/net/ppp-comp.h Tue Mar 24 22:33:32 1998 +++ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/include/net/ppp-comp.h Tue Nov 5 20:00:52 2002 @@ -109,7 +109,7 @@ /* * Max # bytes for a CCP option */ -#define CCP_MAX_OPTION_LENGTH 32 +#define CCP_MAX_OPTION_LENGTH 64 /* * Parts of a CCP packet. @@ -153,6 +153,20 @@ #define DEFLATE_MAKE_OPT(w) ((((w) - DEFLATE_MIN_SIZE) << 4) \ + 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 */ + +/* + * Definitions for Stac LZS. + */ + +#define CI_LZS 17 /* config option for Stac LZS */ +#define CILEN_LZS 5 /* length of config option */ /* * Definitions for other, as yet unsupported, compression methods. diff -urN ppp-2.4.1/include/openssl/opensslconf.h ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/include/openssl/opensslconf.h --- ppp-2.4.1/include/openssl/opensslconf.h Wed Dec 31 19:00:00 1969 +++ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/include/openssl/opensslconf.h Tue Nov 5 20:00:52 2002 @@ -0,0 +1,167 @@ +/* opensslconf.h */ +/* WARNING: Generated automatically from opensslconf.h.in by Configure. */ + +/* OpenSSL was configured with the following options: */ +#ifdef OPENSSL_ALGORITHM_DEFINES + /* no ciphers excluded */ +#endif +#ifdef OPENSSL_THREAD_DEFINES +#endif +#ifdef OPENSSL_OTHER_DEFINES +#endif + +/* crypto/opensslconf.h.in */ + +/* Generate 80386 code? */ +#undef I386_ONLY + +#if !(defined(VMS) || defined(__VMS)) /* VMS uses logical names instead */ +#if defined(HEADER_CRYPTLIB_H) && !defined(OPENSSLDIR) +#define OPENSSLDIR "/usr/local/ssl" +#endif +#endif + +#define OPENSSL_UNISTD + +#if defined(HEADER_IDEA_H) && !defined(IDEA_INT) +#define IDEA_INT unsigned int +#endif + +#if defined(HEADER_MD2_H) && !defined(MD2_INT) +#define MD2_INT unsigned int +#endif + +#if defined(HEADER_RC2_H) && !defined(RC2_INT) +/* I need to put in a mod for the alpha - eay */ +#define RC2_INT unsigned int +#endif + +#if defined(HEADER_RC4_H) +#if !defined(RC4_INT) +/* using int types make the structure larger but make the code faster + * on most boxes I have tested - up to %20 faster. */ +/* + * I don't know what does "most" mean, but declaring "int" is a must on: + * - Intel P6 because partial register stalls are very expensive; + * - elder Alpha because it lacks byte load/store instructions; + */ +#define RC4_INT unsigned int +#endif +#if !defined(RC4_CHUNK) +/* + * This enables code handling data aligned at natural CPU word + * boundary. See crypto/rc4/rc4_enc.c for further details. + */ +#undef RC4_CHUNK +#endif +#endif + +#if defined(HEADER_DES_H) && !defined(DES_LONG) +/* If this is set to 'unsigned int' on a DEC Alpha, this gives about a + * %20 speed up (longs are 8 bytes, int's are 4). */ +#ifndef DES_LONG +#define DES_LONG unsigned long +#endif +#endif + +#if defined(HEADER_BN_H) && !defined(CONFIG_HEADER_BN_H) +#define CONFIG_HEADER_BN_H +#undef BN_LLONG + +/* Should we define BN_DIV2W here? */ + +/* Only one for the following should be defined */ +/* The prime number generation stuff may not work when + * EIGHT_BIT but I don't care since I've only used this mode + * for debuging the bignum libraries */ +#undef SIXTY_FOUR_BIT_LONG +#undef SIXTY_FOUR_BIT +#define THIRTY_TWO_BIT +#undef SIXTEEN_BIT +#undef EIGHT_BIT +#endif + +#if defined(HEADER_RC4_LOCL_H) && !defined(CONFIG_HEADER_RC4_LOCL_H) +#define CONFIG_HEADER_RC4_LOCL_H +/* if this is defined data[i] is used instead of *data, this is a %20 + * speedup on x86 */ +#undef RC4_INDEX +#endif + +#if defined(HEADER_BF_LOCL_H) && !defined(CONFIG_HEADER_BF_LOCL_H) +#define CONFIG_HEADER_BF_LOCL_H +#undef BF_PTR +#endif /* HEADER_BF_LOCL_H */ + +#if defined(HEADER_DES_LOCL_H) && !defined(CONFIG_HEADER_DES_LOCL_H) +#define CONFIG_HEADER_DES_LOCL_H +#ifndef DES_DEFAULT_OPTIONS +/* the following is tweaked from a config script, that is why it is a + * protected undef/define */ +#ifndef DES_PTR +#undef DES_PTR +#endif + +/* This helps C compiler generate the correct code for multiple functional + * units. It reduces register dependancies at the expense of 2 more + * registers */ +#ifndef DES_RISC1 +#undef DES_RISC1 +#endif + +#ifndef DES_RISC2 +#undef DES_RISC2 +#endif + +#if defined(DES_RISC1) && defined(DES_RISC2) +YOU SHOULD NOT HAVE BOTH DES_RISC1 AND DES_RISC2 DEFINED!!!!! +#endif + +/* Unroll the inner loop, this sometimes helps, sometimes hinders. + * Very mucy CPU dependant */ +#ifndef DES_UNROLL +#undef DES_UNROLL +#endif + +/* These default values were supplied by + * Peter Gutman + * They are only used if nothing else has been defined */ +#if !defined(DES_PTR) && !defined(DES_RISC1) && !defined(DES_RISC2) && !defined(DES_UNROLL) +/* Special defines which change the way the code is built depending on the + CPU and OS. For SGI machines you can use _MIPS_SZLONG (32 or 64) to find + even newer MIPS CPU's, but at the moment one size fits all for + optimization options. Older Sparc's work better with only UNROLL, but + there's no way to tell at compile time what it is you're running on */ + +#if defined( sun ) /* Newer Sparc's */ +# define DES_PTR +# define DES_RISC1 +# define DES_UNROLL +#elif defined( __ultrix ) /* Older MIPS */ +# define DES_PTR +# define DES_RISC2 +# define DES_UNROLL +#elif defined( __osf1__ ) /* Alpha */ +# define DES_PTR +# define DES_RISC2 +#elif defined ( _AIX ) /* RS6000 */ + /* Unknown */ +#elif defined( __hpux ) /* HP-PA */ + /* Unknown */ +#elif defined( __aux ) /* 68K */ + /* Unknown */ +#elif defined( __dgux ) /* 88K (but P6 in latest boxes) */ +# define DES_UNROLL +#elif defined( __sgi ) /* Newer MIPS */ +# define DES_PTR +# define DES_RISC2 +# define DES_UNROLL +#elif defined( i386 ) /* x86 boxes, should be gcc */ +# define DES_PTR +# define DES_RISC1 +# define DES_UNROLL +#endif /* Systems-specific speed defines */ +#endif + +#endif /* DES_DEFAULT_OPTIONS */ +#endif /* HEADER_DES_LOCL_H */ diff -urN ppp-2.4.1/include/openssl/opensslv.h ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/include/openssl/opensslv.h --- ppp-2.4.1/include/openssl/opensslv.h Wed Dec 31 19:00:00 1969 +++ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/include/openssl/opensslv.h Tue Nov 5 20:00:52 2002 @@ -0,0 +1,85 @@ +#ifndef HEADER_OPENSSLV_H +#define HEADER_OPENSSLV_H + +/* Numeric release version identifier: + * MMNNFFPPS: major minor fix patch status + * The status nibble has one of the values 0 for development, 1 to e for betas + * 1 to 14, and f for release. The patch level is exactly that. + * For example: + * 0.9.3-dev 0x00903000 + * 0.9.3-beta1 0x00903001 + * 0.9.3-beta2-dev 0x00903002 + * 0.9.3-beta2 0x00903002 (same as ...beta2-dev) + * 0.9.3 0x0090300f + * 0.9.3a 0x0090301f + * 0.9.4 0x0090400f + * 1.2.3z 0x102031af + * + * For continuity reasons (because 0.9.5 is already out, and is coded + * 0x00905100), between 0.9.5 and 0.9.6 the coding of the patch level + * part is slightly different, by setting the highest bit. This means + * that 0.9.5a looks like this: 0x0090581f. At 0.9.6, we can start + * with 0x0090600S... + * + * (Prior to 0.9.3-dev a different scheme was used: 0.9.2b is 0x0922.) + * (Prior to 0.9.5a beta1, a different scheme was used: MMNNFFRBB for + * major minor fix final patch/beta) + */ +#define OPENSSL_VERSION_NUMBER 0x0090600fL +#define OPENSSL_VERSION_TEXT "OpenSSL 0.9.6 24 Sep 2000" +#define OPENSSL_VERSION_PTEXT " part of " OPENSSL_VERSION_TEXT + + +/* The macros below are to be used for shared library (.so, .dll, ...) + * versioning. That kind of versioning works a bit differently between + * operating systems. The most usual scheme is to set a major and a minor + * number, and have the runtime loader check that the major number is equal + * to what it was at application link time, while the minor number has to + * be greater or equal to what it was at application link time. With this + * scheme, the version number is usually part of the file name, like this: + * + * libcrypto.so.0.9 + * + * Some unixen also make a softlink with the major verson number only: + * + * libcrypto.so.0 + * + * On True64 it works a little bit differently. There, the shared library + * version is stored in the file, and is actually a series of versions, + * separated by colons. The rightmost version present in the library when + * linking an application is stored in the application to be matched at + * run time. When the application is run, a check is done to see if the + * library version stored in the application matches any of the versions + * in the version string of the library itself. + * This version string can be constructed in any way, depending on what + * kind of matching is desired. However, to implement the same scheme as + * the one used in the other unixen, all compatible versions, from lowest + * to highest, should be part of the string. Consecutive builds would + * give the following versions strings: + * + * 3.0 + * 3.0:3.1 + * 3.0:3.1:3.2 + * 4.0 + * 4.0:4.1 + * + * Notice how version 4 is completely incompatible with version, and + * therefore give the breach you can see. + * + * There may be other schemes as well that I haven't yet discovered. + * + * So, here's the way it works here: first of all, the library version + * number doesn't need at all to match the overall OpenSSL version. + * However, it's nice and more understandable if it actually does. + * The current library version is stored in the macro SHLIB_VERSION_NUMBER, + * which is just a piece of text in the format "M.m.e" (Major, minor, edit). + * For the sake of True64 and any other OS that behaves in similar ways, + * we need to keep a history of version numbers, which is done in the + * macro SHLIB_VERSION_HISTORY. The numbers are separated by colons and + * should only keep the versions that are binary compatible with the current. + */ +#define SHLIB_VERSION_HISTORY "" +#define SHLIB_VERSION_NUMBER "0.9.6" + + +#endif /* HEADER_OPENSSLV_H */ diff -urN ppp-2.4.1/include/openssl/sha.h ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/include/openssl/sha.h --- ppp-2.4.1/include/openssl/sha.h Wed Dec 31 19:00:00 1969 +++ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/include/openssl/sha.h Tue Nov 5 20:00:52 2002 @@ -0,0 +1,119 @@ +/* crypto/sha/sha.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_SHA_H +#define HEADER_SHA_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(NO_SHA) || (defined(NO_SHA0) && defined(NO_SHA1)) +#error SHA is disabled. +#endif + +/* + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * ! SHA_LONG has to be at least 32 bits wide. If it's wider, then ! + * ! SHA_LONG_LOG2 has to be defined along. ! + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + */ + +#if defined(WIN16) || defined(__LP32__) +#define SHA_LONG unsigned long +#elif defined(_CRAY) || defined(__ILP64__) +#define SHA_LONG unsigned long +#define SHA_LONG_LOG2 3 +#else +#define SHA_LONG unsigned int +#endif + +#define SHA_LBLOCK 16 +#define SHA_CBLOCK (SHA_LBLOCK*4) /* SHA treats input data as a + * contiguous array of 32 bit + * wide big-endian values. */ +#define SHA_LAST_BLOCK (SHA_CBLOCK-8) +#define SHA_DIGEST_LENGTH 20 + +typedef struct SHAstate_st + { + SHA_LONG h0,h1,h2,h3,h4; + SHA_LONG Nl,Nh; + SHA_LONG data[SHA_LBLOCK]; + int num; + } SHA_CTX; + +#ifndef NO_SHA0 +void SHA_Init(SHA_CTX *c); +void SHA_Update(SHA_CTX *c, const void *data, unsigned long len); +void SHA_Final(unsigned char *md, SHA_CTX *c); +unsigned char *SHA(const unsigned char *d, unsigned long n,unsigned char *md); +void SHA_Transform(SHA_CTX *c, const unsigned char *data); +#endif +#ifndef NO_SHA1 +void SHA1_Init(SHA_CTX *c); +void SHA1_Update(SHA_CTX *c, const void *data, unsigned long len); +void SHA1_Final(unsigned char *md, SHA_CTX *c); +unsigned char *SHA1(const unsigned char *d, unsigned long n,unsigned char *md); +void SHA1_Transform(SHA_CTX *c, const unsigned char *data); +#endif +#ifdef __cplusplus +} +#endif + +#endif diff -urN ppp-2.4.1/pppd/Makefile ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/Makefile --- ppp-2.4.1/pppd/Makefile Wed Dec 31 19:00:00 1969 +++ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/Makefile Tue Nov 5 20:04:39 2002 @@ -0,0 +1,155 @@ +# +# pppd makefile for Linux +# $Id: Makefile.linux,v 1.41 2001/03/08 05:00:35 paulus 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 \ + ipxcp.c auth.c options.c sys-linux.c md4.c chap_ms.c cbcp.c \ + demand.c utils.c multilink.c tdb.c tty.c sha1dgst.c mppe.c \ + extra_crypto.c +HEADERS = callout.h pathnames.h patchlevel.h chap.h md5.h chap_ms.h md4.h \ + ipxcp.h cbcp.h tdb.h sha_locl.h mppe.h extra_crypto.h +MANPAGES = pppd.8 +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-linux.o ipxcp.o multilink.o \ + tdb.o tty.o cbcp.o mppe.o sha1dgst.o extra_crypto.o + +all: pppd + +# +# include dependancies if present and backup if as a header file +ifeq (.depend,$(wildcard .depend)) +include .depend +endif + +# CC = gcc +# +COPTS = -O2 -pipe -Wall -g -DJES +LIBS = -lpam -lsmbpw +DEBUGFLAGS = -DDEBUGALL -DUSE_PAM + +ifneq ($(wildcard /usr/lib/libcrypt.*),) +LIBS += -lcrypt +endif + +# Uncomment the next 2 lines to include support for Microsoft's +# MS-CHAP authentication protocol. +CHAPMS=y +USE_CRYPT=y +ifneq ($(wildcard /usr/lib/libcrypt.*),) +HAVE_CRYPT_H=y +endif + +# Uncomment these lines to use MSLANMAN and MPPE options +# both need the MS-CHAP protocol above +# MSLANMAN=y +MPPE=y + +# Uncomment the following for dynamic IP allocation +#DYNAMIC=y + +# Uncomment the following for CBCP support +# CBCP_SUPPORT=y + +# Uncomment the next line to include support for PPP packet filtering. +# This requires that the libpcap library and headers be installed +# and that the kernel driver support PPP packet filtering, which it +# doesn't yet. +#FILTER=y + +HAS_SHADOW=y +#USE_PAM=y +#HAVE_INET6=y + +PLUGIN=y + +INCLUDE_DIRS= -I../include + +COMPILE_FLAGS= -D_linux_=1 -DHAVE_PATHS_H -DIPX_CHANGE -DHAVE_MULTILINK -DHAVE_MMAP + +CFLAGS= $(COPTS) $(COMPILE_FLAGS) $(INCLUDE_DIRS) + +ifdef CHAPMS +CFLAGS += -DCHAPMS=1 +ifndef USE_CRYPT +LIBS := -ldes $(LIBS) +else +CFLAGS += -DUSE_CRYPT=1 +ifneq ($(wildcard /usr/include/crypt.h),) +CFLAGS += -DHAVE_CRYPT_H=1 +endif +endif +PPPDOBJS += md4.o chap_ms.o +ifdef MSLANMAN +CFLAGS += -DMSLANMAN=1 +endif +ifdef MPPE +CFLAGS += -DMPPE=1 +endif +endif + +ifdef HAS_SHADOW +CFLAGS += -DHAS_SHADOW +#LIBS := -lshadow $(LIBS) +endif + +# For "Pluggable Authentication Modules", see ftp.redhat.com:/pub/pam/. +ifdef USE_PAM +CFLAGS += -DUSE_PAM +LIBS := -lpam -ldl $(LIBS) +endif + +# Lock library binary for Linux is included in 'linux' subdirectory. +ifdef LOCKLIB +LIBS := -llock $(LIBS) +CFLAGS += -DLOCKLIB=1 +endif + +ifdef DYNAMIC +CFLAGS += -DDYNAMIC=1 +endif + +ifdef CBCP_SUPPORT +CFLAGS += -DCBCP_SUPPORT=1 +endif + +ifdef PLUGIN +CFLAGS += -DPLUGIN +LDFLAGS += -Wl,-E +LIBS += -ldl +endif + +ifdef FILTER +LIBS += -lpcap +CFLAGS += -DPPP_FILTER -I/usr/include/pcap +endif + +ifdef HAVE_INET6 + PPPDSRCS += ipv6cp.c eui64.c + HEADERS += ipv6cp.h eui64.h + PPPDOBJS += ipv6cp.o eui64.o + CFLAGS += -DINET6=1 +endif + + +INSTALL= install -o root + +install: pppd + mkdir -p $(BINDIR) $(MANDIR) + $(INSTALL) -s -c -m 555 pppd $(BINDIR)/pppd + if chgrp pppusers $(BINDIR)/pppd 2>/dev/null; then \ + chmod o-rx,u+s $(BINDIR)/pppd; fi + $(INSTALL) -c -m 444 pppd.8 $(MANDIR)/man8 + +pppd: $(PPPDOBJS) + $(CC) $(CFLAGS) $(LDFLAGS) -o pppd $(PPPDOBJS) $(LIBS) + +clean: + rm -f $(PPPDOBJS) pppd *~ #* core + +depend: + $(CPP) -M $(CFLAGS) $(PPPDSRCS) >.depend diff -urN ppp-2.4.1/pppd/Makefile.linux ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/Makefile.linux --- ppp-2.4.1/pppd/Makefile.linux Thu Mar 8 00:00:35 2001 +++ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/Makefile.linux Tue Nov 5 20:04:39 2002 @@ -9,13 +9,14 @@ PPPDSRCS = main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c \ ipxcp.c auth.c options.c sys-linux.c md4.c chap_ms.c cbcp.c \ - demand.c utils.c multilink.c tdb.c tty.c + demand.c utils.c multilink.c tdb.c tty.c sha1dgst.c mppe.c \ + extra_crypto.c HEADERS = callout.h pathnames.h patchlevel.h chap.h md5.h chap_ms.h md4.h \ - ipxcp.h cbcp.h tdb.h + ipxcp.h cbcp.h tdb.h sha_locl.h mppe.h extra_crypto.h MANPAGES = pppd.8 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-linux.o ipxcp.o multilink.o \ - tdb.o tty.o + tdb.o tty.o cbcp.o mppe.o sha1dgst.o extra_crypto.o all: pppd @@ -27,8 +28,9 @@ # CC = gcc # -COPTS = -O2 -pipe -Wall -g -LIBS = +COPTS = -O2 -pipe -Wall -g -DJES +LIBS = -lpam -lsmbpw +DEBUGFLAGS = -DDEBUGALL -DUSE_PAM ifneq ($(wildcard /usr/lib/libcrypt.*),) LIBS += -lcrypt @@ -42,6 +44,17 @@ HAVE_CRYPT_H=y endif +# Uncomment these lines to use MSLANMAN and MPPE options +# both need the MS-CHAP protocol above +# MSLANMAN=y +MPPE=y + +# Uncomment the following for dynamic IP allocation +#DYNAMIC=y + +# Uncomment the following for CBCP support +# CBCP_SUPPORT=y + # Uncomment the next line to include support for PPP packet filtering. # This requires that the libpcap library and headers be installed # and that the kernel driver support PPP packet filtering, which it @@ -74,6 +87,9 @@ ifdef MSLANMAN CFLAGS += -DMSLANMAN=1 endif +ifdef MPPE +CFLAGS += -DMPPE=1 +endif endif ifdef HAS_SHADOW @@ -91,6 +107,14 @@ ifdef LOCKLIB LIBS := -llock $(LIBS) CFLAGS += -DLOCKLIB=1 +endif + +ifdef DYNAMIC +CFLAGS += -DDYNAMIC=1 +endif + +ifdef CBCP_SUPPORT +CFLAGS += -DCBCP_SUPPORT=1 endif ifdef PLUGIN diff -urN ppp-2.4.1/pppd/auth.c ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/auth.c --- ppp-2.4.1/pppd/auth.c Tue Mar 13 00:54:33 2001 +++ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/auth.c Tue Nov 5 20:08:32 2002 @@ -74,8 +74,20 @@ #ifdef CBCP_SUPPORT #include "cbcp.h" #endif +#ifdef CHAPMS +#include "chap_ms.h" +#endif #include "pathnames.h" +#ifdef JES +#include "smbpwd.h" +#define NTPASS 32 +#endif +#ifdef DYNAMIC +#define _PATH_DYNAMIC "/etc/ppp/getaddr" +#endif +static char xuser[MAXNAMELEN]; + static const char rcsid[] = RCSID; /* Bits in scan_authfile return value */ @@ -132,6 +144,11 @@ /* Hook for a plugin to get the PAP password for authenticating us */ int (*pap_passwd_hook) __P((char *user, char *passwd)) = NULL; +#ifdef CBCP_SUPPORT +/* Set if we have done call-back sequences. */ +static int did_callback; +#endif + /* * This is used to ensure that we don't start an auth-up/down * script while one is already running. @@ -172,7 +189,7 @@ /* Prototypes for procedures local to this file. */ -static void network_phase __P((int)); +void network_phase __P((int)); static void check_idle __P((void *)); static void connect_time_expired __P((void *)); static int plogin __P((char *, char *, char **)); @@ -222,12 +239,36 @@ "Don't agree to auth to peer with PAP", 1 }, { "-pap", o_bool, &refuse_pap, "Don't allow PAP authentication with peer", OPT_ALIAS | 1 }, - + { "require-chap", o_special_noarg, reqchap, + "Require CHAP authentication from peer" }, + { "+chap", o_special_noarg, reqchap, + "Require CHAP authentication from peer" }, { "refuse-chap", o_bool, &refuse_chap, "Don't agree to auth to peer with CHAP", 1 }, { "-chap", o_bool, &refuse_chap, "Don't allow CHAP authentication with peer", OPT_ALIAS | 1 }, - + { "refuse-chap-md5", o_bool, &lcp_wantoptions[0].use_digest, + "Don't allow md5-digest style CHAP", 0 }, + { "-chap-md5", o_bool, &lcp_wantoptions[0].use_digest, + "Don't allow md5-digest style CHAP", 0 }, +#ifdef CHAPMS + { "require-chapms", o_special_noarg, reqchapms, + "Require MSCHAP (v1) authentication" }, + { "+chapms", o_special_noarg, reqchapms, + "Require MSCHAP (v1) authentication" }, + { "refuse-chapms", o_special_noarg, nochapms, + "Refuse MSCHAP (v1) authentication" }, + { "-chapms", o_special_noarg, nochapms, + "Refuse MSCHAP (v1) authentication" }, + { "require-chapms-v2", o_special_noarg, reqchapms_v2, + "Require MSCHAP-v2 authentication" }, + { "+chapms-v2", o_special_noarg, reqchapms_v2, + "Require MSCHAP-v2 authentication" }, + { "refuse-chapms-v2", o_special_noarg, nochapms_v2, + "Refuse MSCHAP-v2 authentication" }, + { "-chapms-v2", o_special_noarg, nochapms_v2, + "Refuse MSCHAP-v2 authentication" }, +#endif { "name", o_string, our_name, "Set local name for authentication", OPT_PRIO | OPT_PRIV | OPT_STATIC, NULL, MAXNAMELEN }, @@ -499,12 +540,15 @@ /* * Proceed to the network phase. */ -static void +void network_phase(unit) int unit; { lcp_options *go = &lcp_gotoptions[unit]; - +#ifdef CBCP_SUPPORT + lcp_options *ho = &lcp_hisoptions[unit]; +#endif + /* * If the peer had to authenticate, run the auth-up script now. */ @@ -520,8 +564,9 @@ /* * If we negotiated callback, do it now. */ - if (go->neg_cbcp) { + if ((go->neg_cbcp || ho->neg_cbcp) && !did_callback) { new_phase(PHASE_CALLBACK); + did_callback = 1; (*cbcp_protent.open)(unit); return; } @@ -617,6 +662,8 @@ namelen = sizeof(peer_authname) - 1; BCOPY(name, peer_authname, namelen); peer_authname[namelen] = 0; + BCOPY(name, xuser, namelen); + xuser[namelen] = 0; script_setenv("PEERNAME", peer_authname, 0); /* @@ -1459,6 +1506,61 @@ return 1; } +#ifdef DYNAMIC +/* + * get_ip_addr_dynamic - scans dynamic-givable address space for + * most recently used address for given user. + */ +int +get_ip_addr_dynamic(unit, addr) + int unit; + u_int32_t *addr; +{ + u_int32_t a; + struct wordlist *addrs; + FILE *fd; + int dfd; + char command[256]; + char mypid[40], *s; + char address[50]; + u_int32_t mask; + + if ((addrs = addresses[unit]) == NULL) + return 0; /* no restriction */ + + fd = (FILE *)NULL; + for(; addrs != NULL; addrs = addrs->next) { + if(strcmp(addrs->word, "*") != 0) + continue; + sprintf(mypid, "/var/tmp/ppp_dynamic.%d", getpid()); + sprintf(command, "%s %s %s %s", _PATH_DYNAMIC, xuser, devnam, mypid); + dfd = open("/dev/null", O_RDWR); + device_script(command, dfd, dfd); + close(dfd); + fd = fopen(mypid, "r"); + if(fd == (FILE *)NULL) + break; + if(fgets(address, sizeof(address), fd) == (char *)NULL) + break; + if((s = strchr(address, '\n')) != (char *)NULL) + *s = '\0'; + a = inet_addr(address); + if(a == -1L) + break; + fclose(fd); + unlink(mypid); + *addr = a; + return 1; + } + if(fd != (FILE *)NULL) + { + fclose(fd); + unlink(mypid); + } + return 0; +} +#endif + /* * set_allowed_addrs() - set the list of allowed addresses. * Also looks for `--' indicating options to apply for this peer @@ -1701,6 +1803,24 @@ } +#ifdef JES +/* From libsmb - from SAMBA */ +/************************************************************* +* Routine to set 32 hex password characters from a 16 byte array. +* **************************************************************/ + +void sethexpwd(char *p, unsigned char *pwd) +{ + if (pwd != NULL) { + int i; + for (i = 0; i < 16; i++) { + snprintf(&p[i * 2], 33, "%02X", pwd[i]); + } + } +} +#endif + + /* * scan_authfile - Scan an authorization file for a secret suitable * for authenticating `client' on `server'. The return value is -1 @@ -1806,6 +1926,29 @@ } fclose(sf); } +#ifdef JES + else if (word[0] == '&') { + struct smb_passwd *smb; + char smbname[MAXWORDLEN]; + strlcpy(atfile, word+1, sizeof(atfile)); + setsmbfilepath(atfile); + setsmbpwent(); + while ((smb = getsmbpwent())!= NULL && + (client != NULL ? strcmp(client, smb->smb_name) != 0 : 1) && + (server != NULL ? strcmp(server, smb->smb_name) != 0 : 1)); + if (smb != NULL) { + sethexpwd(smbname, smb->smb_nt_passwd); + memcpy(word, smbname, NTPASS); + word[NTPASS]='\000'; + endsmbpwent(); + } else { + endsmbpwent(); + warn("no secret in samba secret file %s", atfile); + continue; + } + } +#endif + strlcpy(lsecret, word, sizeof(lsecret)); } Binary files ppp-2.4.1/pppd/auth.o and ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/auth.o differ diff -urN ppp-2.4.1/pppd/cbcp.c ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/cbcp.c --- ppp-2.4.1/pppd/cbcp.c Thu Mar 8 00:11:10 2001 +++ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/cbcp.c Tue Nov 5 20:00:52 2002 @@ -32,14 +32,24 @@ static const char rcsid[] = RCSID; +void network_phase __P((int)); + /* * Options. */ static int setcbcp __P((char **)); +static int setcbcpreq __P((char **)); +static int setnocbcp __P((char **)); static option_t cbcp_option_list[] = { { "callback", o_special, setcbcp, "Ask for callback", OPT_PRIO | OPT_A2STRVAL, &cbcp[0].us_number }, + { "+callback", o_special_noarg, setcbcpreq, + "Ask for callback" }, + { "nocallback", o_special, setnocbcp, + "Don't allow callbacks" }, + { "-callback", o_special, setnocbcp, + "Don't allow callbacks" }, { NULL } }; @@ -48,7 +58,9 @@ */ static void cbcp_init __P((int unit)); static void cbcp_open __P((int unit)); +static void cbcp_close __P((int unit, char *)); static void cbcp_lowerup __P((int unit)); +static void cbcp_lowerdown __P((int unit)); static void cbcp_input __P((int unit, u_char *pkt, int len)); static void cbcp_protrej __P((int unit)); static int cbcp_printpkt __P((u_char *pkt, int len, @@ -61,12 +73,12 @@ cbcp_input, cbcp_protrej, cbcp_lowerup, - NULL, + cbcp_lowerdown, cbcp_open, - NULL, + cbcp_close, cbcp_printpkt, NULL, - 0, + 1, "CBCP", NULL, cbcp_option_list, @@ -80,23 +92,46 @@ /* internal prototypes */ static void cbcp_recvreq __P((cbcp_state *us, char *pckt, int len)); -static void cbcp_resp __P((cbcp_state *us)); -static void cbcp_up __P((cbcp_state *us)); static void cbcp_recvack __P((cbcp_state *us, char *pckt, int len)); +static void cbcp_recvresp __P((cbcp_state *us, char *pckt, int len)); +static void cbcp_resp __P((cbcp_state *us)); +static void cbcp_req __P((cbcp_state *us)); +static void cbcp_ack __P((cbcp_state *us)); static void cbcp_send __P((cbcp_state *us, u_char code, u_char *buf, int len)); +static void cbcp_up __P((cbcp_state *us)); /* option processing */ static int setcbcp(argv) char **argv; { - lcp_wantoptions[0].neg_cbcp = 1; - cbcp_protent.enabled_flag = 1; + lcp_allowoptions[0].neg_cbcp = 1; cbcp[0].us_number = strdup(*argv); if (cbcp[0].us_number == 0) novm("callback number"); - cbcp[0].us_type |= (1 << CB_CONF_USER); - cbcp[0].us_type |= (1 << CB_CONF_ADMIN); + if (cbcp[0].us_number[0] == '-') + cbcp[0].us_type = (1 << CB_CONF_NO); + else + { + cbcp[0].us_type = (1 << CB_CONF_USER); + cbcp[0].us_type |= (1 << CB_CONF_ADMIN); + } + return (1); +} + +static int +setnocbcp(argv) + char **argv; +{ + lcp_allowoptions[0].neg_cbcp = lcp_wantoptions[0].neg_cbcp = 0; + return (1); +} + +static int +setcbcpreq(argv) + char **argv; +{ + lcp_wantoptions[0].neg_cbcp = 1; return (1); } @@ -110,7 +145,8 @@ us = &cbcp[iface]; memset(us, 0, sizeof(cbcp_state)); us->us_unit = iface; - us->us_type |= (1 << CB_CONF_NO); + us->us_type = (1 << CB_CONF_NO); + us->us_id = 1; } /* lower layer is up */ @@ -120,18 +156,60 @@ { cbcp_state *us = &cbcp[iface]; - dbglog("cbcp_lowerup"); - dbglog("want: %d", us->us_type); + if (debug) + { + dbglog("cbcp_lowerup"); + dbglog("want: %d", us->us_type); - if (us->us_type == CB_CONF_USER) - dbglog("phone no: %s", us->us_number); + if (us->us_type & (1 << CB_CONF_USER)) + dbglog("phone no: %s", us->us_number); + } +} + +static void +cbcp_lowerdown(iface) + int iface; +{ + if(debug) + dbglog("cbcp_lowerdown"); } static void cbcp_open(unit) int unit; { - dbglog("cbcp_open"); + lcp_options *ho = &lcp_hisoptions[unit]; + lcp_options *ao = &lcp_allowoptions[unit]; + lcp_options *wo = &lcp_wantoptions[unit]; + lcp_options *go = &lcp_gotoptions[unit]; + cbcp_state *us = &cbcp[unit]; + + if(debug) + dbglog("cbcp_open"); + if(ao->neg_cbcp) + { + if(ho->neg_cbcp) + { + cbcp_req(us); + return; + } + } + else if(wo->neg_cbcp) + { + if(!go->neg_cbcp) + lcp_close(0, "Callback required"); + return; + } + cbcp_up(us); +} + +static void +cbcp_close(unit, reason) + int unit; + char *reason; +{ + if(debug) + dbglog("cbcp_close: %s", reason); } /* process an incomming packet */ @@ -174,11 +252,13 @@ break; case CBCP_RESP: - dbglog("CBCP_RESP received"); + if (id != us->us_id && debug) + dbglog("id doesn't match: expected %d recv %d", us->us_id, id); + cbcp_recvresp(us, inp, len); break; case CBCP_ACK: - if (id != us->us_id) + if (id != us->us_id && debug) dbglog("id doesn't match: expected %d recv %d", us->us_id, id); @@ -298,7 +378,8 @@ address[0] = 0; while (len) { - dbglog("length: %d", len); + if (debug) + dbglog("length: %d", len); GETCHAR(type, pckt); GETCHAR(opt_len, pckt); @@ -310,22 +391,22 @@ switch(type) { case CB_CONF_NO: - dbglog("no callback allowed"); + dbglog("Callback: none"); break; case CB_CONF_USER: - dbglog("user callback allowed"); if (opt_len > 4) { GETCHAR(addr_type, pckt); memcpy(address, pckt, opt_len - 4); address[opt_len - 4] = 0; - if (address[0]) - dbglog("address: %s", address); + dbglog("Callback: user callback, address: '%s'", address); } + else + dbglog("Callback: user callback"); break; case CB_CONF_ADMIN: - dbglog("user admin defined allowed"); + dbglog("Callback: user admin defined"); break; case CB_CONF_LIST: @@ -347,29 +428,35 @@ int len = 0; cb_type = us->us_allowed & us->us_type; - dbglog("cbcp_resp cb_type=%d", cb_type); + if (debug) + dbglog("cbcp_resp cb_type=%d", cb_type); + if (!cb_type) { + dbglog("Your remote side wanted a callback-type you don't allow -> doing no callback"); + cb_type = 1 << CB_CONF_NO; #if 0 - if (!cb_type) lcp_down(us->us_unit); #endif + } if (cb_type & ( 1 << CB_CONF_USER ) ) { - dbglog("cbcp_resp CONF_USER"); + if (debug) + dbglog("cbcp_resp CONF_USER"); PUTCHAR(CB_CONF_USER, bufp); - len = 3 + 1 + strlen(us->us_number) + 1; + len = 2 + 1 + strlen(us->us_number); PUTCHAR(len , bufp); PUTCHAR(5, bufp); /* delay */ PUTCHAR(1, bufp); - BCOPY(us->us_number, bufp, strlen(us->us_number) + 1); + BCOPY(us->us_number, bufp, strlen(us->us_number)); cbcp_send(us, CBCP_RESP, buf, len); return; } if (cb_type & ( 1 << CB_CONF_ADMIN ) ) { - dbglog("cbcp_resp CONF_ADMIN"); + if (debug) + dbglog("cbcp_resp CONF_ADMIN"); PUTCHAR(CB_CONF_ADMIN, bufp); - len = 3; + len = 2 + 1; PUTCHAR(len, bufp); PUTCHAR(5, bufp); /* delay */ cbcp_send(us, CBCP_RESP, buf, len); @@ -377,11 +464,11 @@ } if (cb_type & ( 1 << CB_CONF_NO ) ) { - dbglog("cbcp_resp CONF_NO"); + if (debug) + dbglog("cbcp_resp CONF_NO"); PUTCHAR(CB_CONF_NO, bufp); - len = 3; + len = 2; PUTCHAR(len , bufp); - PUTCHAR(0, bufp); cbcp_send(us, CBCP_RESP, buf, len); start_networks(); return; @@ -389,6 +476,169 @@ } static void +cbcp_ack(us) + cbcp_state *us; +{ + u_char cb_type; + u_char buf[256]; + u_char *bufp = buf; + int len = 0; + + cb_type = us->us_allowed & us->us_type; + if(debug) + dbglog("cbcp_ack cb_type=%d", cb_type); + + if (!cb_type) { + dbglog("Your remote side wanted a callback-type you don't allow -> doing no callback"); + cb_type = 1 << CB_CONF_NO; + lcp_close(us->us_unit, "Invalid callback requested"); + return; + } + + if (cb_type & ( 1 << CB_CONF_USER ) ) { + if(debug) + dbglog("cbcp_ack CONF_USER"); + PUTCHAR(CB_CONF_USER, bufp); + len = 2 + 1 + strlen(us->us_number); + PUTCHAR(len , bufp); + PUTCHAR(5, bufp); /* delay */ + PUTCHAR(1, bufp); + BCOPY(us->us_number, bufp, strlen(us->us_number)); + cbcp_send(us, CBCP_ACK, buf, len); + cbcp_up(us); + return; + } + + if (cb_type & ( 1 << CB_CONF_ADMIN ) ) { + if(debug) + dbglog("cbcp_ack CONF_ADMIN"); + PUTCHAR(CB_CONF_ADMIN, bufp); + len = 2 + 1; + PUTCHAR(len , bufp); + PUTCHAR(5, bufp); /* delay */ + PUTCHAR(0, bufp); + cbcp_send(us, CBCP_ACK, buf, len); + cbcp_up(us); + return; + } + + if (cb_type & ( 1 << CB_CONF_NO ) ) { + if(debug) + dbglog("cbcp_ack CONF_NO"); + PUTCHAR(CB_CONF_NO, bufp); + len = 2; + PUTCHAR(len , bufp); + cbcp_send(us, CBCP_ACK, buf, len); + cbcp_up(us); + return; + } +} + +static void +cbcp_req(us) + cbcp_state *us; +{ + u_char cb_type; + u_char buf[256]; + u_char *bufp = buf; + int len = 0; + + cb_type = us->us_type; + + if (cb_type & ( 1 << CB_CONF_USER ) ) { + if(debug) + dbglog("cbcp_req CONF_USER"); + PUTCHAR(CB_CONF_USER, bufp); + len = 2 + 1 + strlen(us->us_number); + PUTCHAR(len , bufp); + PUTCHAR(5, bufp); /* delay */ + PUTCHAR(1, bufp); + BCOPY(us->us_number, bufp, strlen(us->us_number)); + cbcp_send(us, CBCP_REQ, buf, len); + return; + } + + if (cb_type & ( 1 << CB_CONF_ADMIN ) ) { + if(debug) + dbglog("cbcp_req CONF_ADMIN"); + PUTCHAR(CB_CONF_ADMIN, bufp); + len = 2 + 1; + PUTCHAR(len , bufp); + PUTCHAR(5, bufp); /* delay */ + PUTCHAR(0, bufp); + cbcp_send(us, CBCP_REQ, buf, len); + return; + } + + if (cb_type & ( 1 << CB_CONF_NO ) ) { + if(debug) + dbglog("cbcp_req CONF_NO"); + PUTCHAR(CB_CONF_NO, bufp); + len = 2; + PUTCHAR(len , bufp); + cbcp_send(us, CBCP_REQ, buf, len); + return; + } +} + +/* received CBCP request */ +static void +cbcp_recvresp(us, pckt, pcktlen) + cbcp_state *us; + char *pckt; + int pcktlen; +{ + u_char type, opt_len, delay, addr_type; + char address[256]; + int len = pcktlen; + + address[0] = 0; + + if(debug) + dbglog("CBCP_RESP received"); + + while (len) { + if(debug) + dbglog("length: %d", len); + + GETCHAR(type, pckt); + GETCHAR(opt_len, pckt); + + if (opt_len > 2) + GETCHAR(delay, pckt); + + us->us_allowed |= (1 << type); + + switch(type) { + case CB_CONF_NO: + dbglog("Callback: none"); + break; + + case CB_CONF_USER: + if (opt_len > 4) { + GETCHAR(addr_type, pckt); + memcpy(address, pckt, opt_len - 4); + address[opt_len - 4] = 0; + dbglog("Callback: user callback, address: '%s'", address); + } + else + dbglog("Callback: user callback"); + break; + + case CB_CONF_ADMIN: + dbglog("Callback: user admin defined"); + break; + + case CB_CONF_LIST: + break; + } + len -= opt_len; + } + + cbcp_ack(us); +} + +static void cbcp_send(us, code, buf, len) cbcp_state *us; u_char code; @@ -436,10 +686,14 @@ memcpy(address, pckt, opt_len - 4); address[opt_len - 4] = 0; if (address[0]) - dbglog("peer will call: %s", address); + dbglog("Callback: peer will call: '%s'", address); } - if (type == CB_CONF_NO) + if (type != CB_CONF_NO) + { + persist = 0; + lcp_close(0, "Call me back, please"); return; + } } cbcp_up(us); @@ -450,7 +704,6 @@ cbcp_up(us) cbcp_state *us; { - persist = 0; - lcp_close(0, "Call me back, please"); + network_phase(us->us_unit); status = EXIT_CALLBACK; } Binary files ppp-2.4.1/pppd/cbcp.o and ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/cbcp.o differ diff -urN ppp-2.4.1/pppd/ccp.c ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/ccp.c --- ppp-2.4.1/pppd/ccp.c Thu Mar 8 00:11:11 2001 +++ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/ccp.c Tue Nov 5 20:01:07 2002 @@ -33,7 +33,11 @@ #include "pppd.h" #include "fsm.h" #include "ccp.h" +#ifdef MPPE +#include "mppe.h" +#endif #include +#include "lcp.h" static const char rcsid[] = RCSID; @@ -92,6 +96,36 @@ { "-predictor1", o_bool, &ccp_wantoptions[0].predictor_1, "don't allow Predictor-1", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, &ccp_allowoptions[0].predictor_1 }, +#ifdef MPPE + { "mppe-40", o_special_noarg, setmppe_40, + "Allow 40 bit MPPE encryption" }, + { "+mppe-40", o_special_noarg, setmppe_40, + "Allow 40 bit MPPE encryption" }, + { "nomppe-40", o_special_noarg, setnomppe_40, + "Disallow 40 bit MPPE encryption" }, + { "-mppe-40", o_special_noarg, setnomppe_40, + "Disallow 40 bit MPPE encryption" }, + { "mppe-128", o_special_noarg, setmppe_128, + "Allow 128 bit MPPE encryption" }, + { "+mppe-128", o_special_noarg, setmppe_128, + "Allow 128 bit MPPE encryption" }, + { "nomppe-128", o_special_noarg, setnomppe_128, + "Disallow 128 bit MPPE encryption" }, + { "-mppe-128", o_special_noarg, setnomppe_128, + "Disallow 128 bit MPPE encryption" }, + { "mppe-stateless", o_special_noarg, setmppe_stateless, + "Allow stateless MPPE encryption" }, + { "+mppe-stateless", o_special_noarg, setmppe_stateless, + "Allow stateless MPPE encryption" }, + { "nomppe-stateless", o_special_noarg, setnomppe_stateless, + "Disallow stateless MPPE encryption" }, + { "-mppe-stateless", o_special_noarg, setnomppe_stateless, + "Disallow stateless MPPE encryption" }, + { "require-mppe", o_special_noarg, require_mppe, + "Require MPPE encryption" }, + { "require-mppe-stateless", o_special_noarg, require_mppe_stateless, + "Require stateless MPPE encryption" }, +#endif { NULL } }; @@ -175,7 +209,8 @@ * 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). @@ -312,6 +347,16 @@ ccp_allowoptions[0].bsd_bits = BSD_MAX_BITS; ccp_allowoptions[0].predictor_1 = 1; +#ifdef MPPE + ccp_wantoptions[0].mppe = 0; + ccp_wantoptions[0].mppe_stateless = 0; + ccp_wantoptions[0].mppe_40 = 0; + ccp_wantoptions[0].mppe_128 = 0; + ccp_allowoptions[0].mppe_stateless = 1; + ccp_allowoptions[0].mppe = 1; + ccp_allowoptions[0].mppe_40 = 1; + ccp_allowoptions[0].mppe_128 = 1; +#endif /* MPPE*/ } /* @@ -440,6 +485,8 @@ { ccp_flags_set(unit, 0, 0); fsm_lowerdown(&ccp_fsm[unit]); + if ( ccp_wantoptions[unit].require_mppe || ccp_wantoptions[unit].require_mppe_stateless ) + lcp_close(unit,"Encryption negotiation rejected"); } /* @@ -450,7 +497,7 @@ fsm *f; { ccp_options *go = &ccp_gotoptions[f->unit]; - u_char opt_buf[16]; + u_char opt_buf[256]; *go = ccp_wantoptions[f->unit]; all_rejected[f->unit] = 0; @@ -466,6 +513,18 @@ if (ccp_test(f->unit, opt_buf, CILEN_BSD_COMPRESS, 0) <= 0) go->bsd_compress = 0; } +#ifdef MPPE + if (go->mppe) { + opt_buf[0] = CI_MPPE; + opt_buf[1] = CILEN_MPPE; + opt_buf[2] = 0; + /* keysize is 8 here */ + BCOPY(mppe_master_send_key_40, opt_buf+3, 8); + BCOPY(mppe_master_recv_key_40, opt_buf+11, 8); + if (ccp_test(f->unit, opt_buf, (2*8)+3, 0) <= 0) + go->mppe = 0; + } +#endif /*MPPE*/ if (go->deflate) { if (go->deflate_correct) { opt_buf[0] = CI_DEFLATE; @@ -512,7 +571,8 @@ 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); } /* @@ -559,6 +619,41 @@ p += CILEN_DEFLATE; } } +#ifdef MPPE + if (go->mppe) { + u_char opt_buf[64]; + u_int keysize = 0; + + if(!mppe_allowed) + go->mppe_stateless = go->mppe_40 = go->mppe_128 = 0; + p[0]=CI_MPPE; + p[1]=CILEN_MPPE; + p[2]=(go->mppe_stateless ? MPPE_STATELESS : 0); + p[3]=0; + p[4]=0; + p[5]=(go->mppe_40 ? MPPE_40BIT : 0) | (go->mppe_128 ? MPPE_128BIT : 0); + if(p[5] & MPPE_40BIT) { + keysize = 8; + BCOPY(mppe_master_send_key_40, opt_buf+3, keysize); + BCOPY(mppe_master_recv_key_40, opt_buf+11, keysize); + } else if(p[5] & MPPE_128BIT) { + keysize = 16; + BCOPY(mppe_master_send_key_128, opt_buf+3, keysize); + BCOPY(mppe_master_recv_key_128, opt_buf+19, keysize); + } + if(p[5] != 0) { + opt_buf[0]=CI_MPPE; + opt_buf[1]=CILEN_MPPE; + opt_buf[2] = (go->mppe_stateless) ? 1 : 0; + res = ccp_test(f->unit, opt_buf, (2*keysize)+3, 0); + } else { + res = -1; + } + if (res > 0) { + p += CILEN_MPPE; + } + } +#endif /* MPPE*/ if (go->bsd_compress) { p[0] = CI_BSD_COMPRESS; p[1] = CILEN_BSD_COMPRESS; @@ -642,6 +737,22 @@ len -= CILEN_DEFLATE; } } +#ifdef MPPE + if (go->mppe) { + if ( len < CILEN_MPPE + || p[1] != CILEN_MPPE || p[0] != CI_MPPE + || p[2] != (go->mppe_stateless ? MPPE_STATELESS : 0) + || p[3] != 0 + || p[4] != 0 + || p[5] != ((go->mppe_40 ? MPPE_40BIT : 0) | (go->mppe_128 ? MPPE_128BIT : 0))) + return 0; + p += CILEN_MPPE; + len -= CILEN_MPPE; + /* Cope with first/fast ack */ + if (len == 0) + return 1; + } +#endif /* MPPE */ if (go->bsd_compress) { if (len < CILEN_BSD_COMPRESS || p[0] != CI_BSD_COMPRESS || p[1] != CILEN_BSD_COMPRESS @@ -720,6 +831,24 @@ } } +#ifdef MPPE + if (len >= CILEN_MPPE && p[0] == CI_MPPE && p[1] == CILEN_MPPE) { + no.mppe = 1; + if((p[5] & MPPE_128BIT) == 0) + try.mppe_128 = 0; + if((p[5] & MPPE_40BIT) == 0) + try.mppe_40 = 0; + if((p[2] & MPPE_STATELESS) == 0) + try.mppe_stateless = 0; + if(!try.mppe_128 && !try.mppe_40) { + no.mppe = 0; + try.mppe = 0; + } + p += CILEN_MPPE; + len -= CILEN_MPPE; + } +#endif /* MPPE */ + if (go->bsd_compress && len >= CILEN_BSD_COMPRESS && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) { no.bsd_compress = 1; @@ -792,6 +921,14 @@ if (!try.deflate_correct && !try.deflate_draft) try.deflate = 0; } +#ifdef MPPE + if (go->mppe && len >= CILEN_MPPE + && p[0] == CI_MPPE && p[1] == CILEN_MPPE) { + try.mppe = 0; + p += CILEN_MPPE; + len -= CILEN_MPPE; + } +#endif /*MPPE*/ if (go->bsd_compress && len >= CILEN_BSD_COMPRESS && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) { if (p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits)) @@ -905,6 +1042,82 @@ } break; +#ifdef MPPE + case CI_MPPE: + if (!ao->mppe || clen != CILEN_MPPE) { + newret = CONFREJ; + break; + } + if(!mppe_allowed) + { + newret = CONFREJ; + break; + } + ho->mppe = 1; + if((p[5]&(MPPE_40BIT|MPPE_128BIT)) == (MPPE_40BIT|MPPE_128BIT)) + { + /* if both are available, select the stronger */ + p[5] &= ~MPPE_40BIT; + newret = CONFNAK; + } + if((p[2] & ~MPPE_STATELESS) != 0 + || p[3] != 0 + || p[4] != 0 + || (p[5] & ~(MPPE_40BIT | MPPE_128BIT)) != 0) + { + ccp_options *wo = &ccp_wantoptions[f->unit]; + /* not sure what they want, tell 'em what we got */ + p[2] &= MPPE_STATELESS; + p[3] &= 0; + p[4] &= 0; + p[5] &= MPPE_40BIT | MPPE_128BIT; + if(wo->mppe_40) + p[5] |= MPPE_40BIT; + if(wo->mppe_128) + p[5] |= MPPE_128BIT; + newret = CONFNAK; + } + + if((newret == CONFACK) || (newret == CONFNAK)) + { + /* + * The kernel ppp driver needs the session key + * which is not sent via CCP :( + */ + unsigned int keysize; + unsigned char opt_buf[64]; + opt_buf[0] = CI_MPPE; + opt_buf[1] = CILEN_MPPE; + if(p[2] & MPPE_STATELESS) { + ho->mppe_stateless=1; + opt_buf[2] = MPPE_STATELESS; + } + /* push in our send/receive keys */ + if(p[5] & MPPE_40BIT) { + ho->mppe_40 = 1; + keysize = 8; + BCOPY(mppe_master_send_key_40, opt_buf+3, keysize); + BCOPY(mppe_master_recv_key_40, opt_buf+11, keysize); + } else if(p[5] & MPPE_128BIT) { + ho->mppe_128 = 1; + keysize = 16; + BCOPY(mppe_master_send_key_128, opt_buf+3, keysize); + BCOPY(mppe_master_recv_key_128, opt_buf+19, keysize); + } else { + ho->mppe = 0; + newret = CONFREJ; + break; + } + /* call ioctl and pass this nasty stuff to the kernel */ + if (ccp_test(f->unit, opt_buf, (2*keysize)+3, 1) <= 0){ + ho->mppe = 0; + newret = CONFREJ; + break; + } + } + break; +#endif /* MPPE */ + case CI_BSD_COMPRESS: if (!ao->bsd_compress || clen != CILEN_BSD_COMPRESS) { newret = CONFREJ; @@ -1026,6 +1239,30 @@ (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""), opt->deflate_size); break; +#ifdef MPPE + case CI_MPPE: + if (opt->mppe_40) { + if (opt->mppe_stateless) { + return "MPPE 40 bit, stateless"; + } else { + return "MPPE 40 bit, non-stateless"; + } + } else if (opt->mppe_128) { + if (opt->mppe_stateless) { + return "MPPE 128 bit, stateless"; + } else { + return "MPPE 128 bit, non-stateless"; + } + } else { + if (opt->mppe_stateless) { + return "MPPE unknown strength, stateless"; + } else { + return "MPPE unknown strength, stateless"; + } + } +#endif + case CI_LZS: + return "Stac LZS"; case CI_BSD_COMPRESS: if (opt2 != NULL && opt2->bsd_bits != opt->bsd_bits) slprintf(result, sizeof(result), "BSD-Compress (%d/%d)", @@ -1069,6 +1306,19 @@ notice("%s receive compression enabled", method_name(go, NULL)); } else if (ANY_COMPRESS(*ho)) notice("%s transmit compression enabled", method_name(ho, NULL)); + + if ( ccp_wantoptions[f->unit].require_mppe_stateless || ccp_wantoptions[f->unit].require_mppe ) { + if ( (go->mppe_128 && ho->mppe_128) || (go->mppe_40 && ho->mppe_40 ) ) + if ( ccp_wantoptions[f->unit].require_mppe_stateless ) + if ( go->mppe_stateless && ho->mppe_stateless ) + notice("stateless MPPE enforced"); + else + lcp_close(f->unit,"stateless encryption negotiation failed"); + else + notice("MPPE enforced"); + else + lcp_close(f->unit,"encryption negotiation failed"); + } } /* @@ -1164,6 +1414,18 @@ p += CILEN_PREDICTOR_1; } break; + case CI_MPPE: + if (optlen >= CILEN_MPPE) { + printer(arg, "mppe %x %x %x %x",p[2],p[3],p[4],p[5]); + p += CILEN_MPPE; + } + break; + case CI_LZS: + if (optlen >= CILEN_LZS) { + printer(arg, "lzs %x %x %x", p[2], p[3], p[4]); + p += CILEN_LZS; + } + break; case CI_PREDICTOR_2: if (optlen >= CILEN_PREDICTOR_2) { printer(arg, "predictor 2"); @@ -1222,7 +1484,12 @@ */ error("Lost compression sync: disabling compression"); ccp_close(unit, "Lost compression sync"); + if ( ccp_wantoptions[unit].require_mppe || ccp_wantoptions[unit].require_mppe_stateless ) + lcp_close(unit,"Encryption got out of order"); } else { + /* MPPE/MPPC does not requires CCP_RESETREQ */ + if (ccp_gotoptions[f->unit].method == CI_MPPE) + return; /* * Send a reset-request to reset the peer's compressor. * We don't do that if we are still waiting for an diff -urN ppp-2.4.1/pppd/ccp.c~ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/ccp.c~ --- ppp-2.4.1/pppd/ccp.c~ Wed Dec 31 19:00:00 1969 +++ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/ccp.c~ Tue Nov 5 20:00:52 2002 @@ -0,0 +1,1502 @@ +/* + * ccp.c - PPP Compression Control Protocol. + * + * Copyright (c) 1994 The Australian National University. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, provided that the above copyright + * notice appears in all copies. This software is provided without any + * warranty, express or implied. The Australian National University + * makes no representations about the suitability of this software for + * any purpose. + * + * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY + * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO + * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, + * OR MODIFICATIONS. + */ + +#define RCSID "$Id: ccp.c,v 1.32 2001/03/08 05:11:11 paulus Exp $" + +#include +#include + +#include "pppd.h" +#include "fsm.h" +#include "ccp.h" +#ifdef MPPE +#include "mppe.h" +#endif +#include + +static const char rcsid[] = RCSID; + +/* + * Unfortunately there is a bug in zlib which means that using a + * size of 8 (window size = 256) for Deflate compression will cause + * buffer overruns and kernel crashes in the deflate module. + * Until this is fixed we only accept sizes in the range 9 .. 15. + * Thanks to James Carlson for pointing this out. + */ +#define DEFLATE_MIN_WORKS 9 + +/* + * Command-line options. + */ +static int setbsdcomp __P((char **)); +static int setdeflate __P((char **)); +static char bsd_value[8]; +static char deflate_value[8]; + +static option_t ccp_option_list[] = { + { "noccp", o_bool, &ccp_protent.enabled_flag, + "Disable CCP negotiation" }, + { "-ccp", o_bool, &ccp_protent.enabled_flag, + "Disable CCP negotiation", OPT_ALIAS }, + + { "bsdcomp", o_special, (void *)setbsdcomp, + "Request BSD-Compress packet compression", + OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, bsd_value }, + { "nobsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress, + "don't allow BSD-Compress", OPT_PRIOSUB | OPT_A2CLR, + &ccp_allowoptions[0].bsd_compress }, + { "-bsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress, + "don't allow BSD-Compress", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, + &ccp_allowoptions[0].bsd_compress }, + + { "deflate", o_special, (void *)setdeflate, + "request Deflate compression", + OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, deflate_value }, + { "nodeflate", o_bool, &ccp_wantoptions[0].deflate, + "don't allow Deflate compression", OPT_PRIOSUB | OPT_A2CLR, + &ccp_allowoptions[0].deflate }, + { "-deflate", o_bool, &ccp_wantoptions[0].deflate, + "don't allow Deflate compression", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, + &ccp_allowoptions[0].deflate }, + + { "nodeflatedraft", o_bool, &ccp_wantoptions[0].deflate_draft, + "don't use draft deflate #", OPT_A2COPY, + &ccp_allowoptions[0].deflate_draft }, + + { "predictor1", o_bool, &ccp_wantoptions[0].predictor_1, + "request Predictor-1", 1, &ccp_allowoptions[0].predictor_1, OPT_PRIO }, + { "nopredictor1", o_bool, &ccp_wantoptions[0].predictor_1, + "don't allow Predictor-1", OPT_PRIOSUB | OPT_A2CLR, + &ccp_allowoptions[0].predictor_1 }, + { "-predictor1", o_bool, &ccp_wantoptions[0].predictor_1, + "don't allow Predictor-1", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, + &ccp_allowoptions[0].predictor_1 }, +#ifdef MPPE + { "mppe-40", o_special_noarg, setmppe_40, + "Allow 40 bit MPPE encryption" }, + { "+mppe-40", o_special_noarg, setmppe_40, + "Allow 40 bit MPPE encryption" }, + { "nomppe-40", o_special_noarg, setnomppe_40, + "Disallow 40 bit MPPE encryption" }, + { "-mppe-40", o_special_noarg, setnomppe_40, + "Disallow 40 bit MPPE encryption" }, + { "mppe-128", o_special_noarg, setmppe_128, + "Allow 128 bit MPPE encryption" }, + { "+mppe-128", o_special_noarg, setmppe_128, + "Allow 128 bit MPPE encryption" }, + { "nomppe-128", o_special_noarg, setnomppe_128, + "Disallow 128 bit MPPE encryption" }, + { "-mppe-128", o_special_noarg, setnomppe_128, + "Disallow 128 bit MPPE encryption" }, + { "mppe-stateless", o_special_noarg, setmppe_stateless, + "Allow stateless MPPE encryption" }, + { "+mppe-stateless", o_special_noarg, setmppe_stateless, + "Allow stateless MPPE encryption" }, + { "nomppe-stateless", o_special_noarg, setnomppe_stateless, + "Disallow stateless MPPE encryption" }, + { "-mppe-stateless", o_special_noarg, setnomppe_stateless, + "Disallow stateless MPPE encryption" }, +#endif + + { NULL } +}; + +/* + * Protocol entry points from main code. + */ +static void ccp_init __P((int unit)); +static void ccp_open __P((int unit)); +static void ccp_close __P((int unit, char *)); +static void ccp_lowerup __P((int unit)); +static void ccp_lowerdown __P((int)); +static void ccp_input __P((int unit, u_char *pkt, int len)); +static void ccp_protrej __P((int unit)); +static int ccp_printpkt __P((u_char *pkt, int len, + void (*printer) __P((void *, char *, ...)), + void *arg)); +static void ccp_datainput __P((int unit, u_char *pkt, int len)); + +struct protent ccp_protent = { + PPP_CCP, + ccp_init, + ccp_input, + ccp_protrej, + ccp_lowerup, + ccp_lowerdown, + ccp_open, + ccp_close, + ccp_printpkt, + ccp_datainput, + 1, + "CCP", + "Compressed", + ccp_option_list, + NULL, + NULL, + NULL +}; + +fsm ccp_fsm[NUM_PPP]; +ccp_options ccp_wantoptions[NUM_PPP]; /* what to request the peer to use */ +ccp_options ccp_gotoptions[NUM_PPP]; /* what the peer agreed to do */ +ccp_options ccp_allowoptions[NUM_PPP]; /* what we'll agree to do */ +ccp_options ccp_hisoptions[NUM_PPP]; /* what we agreed to do */ + +/* + * Callbacks for fsm code. + */ +static void ccp_resetci __P((fsm *)); +static int ccp_cilen __P((fsm *)); +static void ccp_addci __P((fsm *, u_char *, int *)); +static int ccp_ackci __P((fsm *, u_char *, int)); +static int ccp_nakci __P((fsm *, u_char *, int)); +static int ccp_rejci __P((fsm *, u_char *, int)); +static int ccp_reqci __P((fsm *, u_char *, int *, int)); +static void ccp_up __P((fsm *)); +static void ccp_down __P((fsm *)); +static int ccp_extcode __P((fsm *, int, int, u_char *, int)); +static void ccp_rack_timeout __P((void *)); +static char *method_name __P((ccp_options *, ccp_options *)); + +static fsm_callbacks ccp_callbacks = { + ccp_resetci, + ccp_cilen, + ccp_addci, + ccp_ackci, + ccp_nakci, + ccp_rejci, + ccp_reqci, + ccp_up, + ccp_down, + NULL, + NULL, + NULL, + NULL, + ccp_extcode, + "CCP" +}; + +/* + * Do we want / did we get any compression? + */ +#define ANY_COMPRESS(opt) ((opt).deflate || (opt).bsd_compress \ + || (opt).predictor_1 || (opt).predictor_2 \ + || (opt).mppe ) + +/* + * Local state (mainly for handling reset-reqs and reset-acks). + */ +static int ccp_localstate[NUM_PPP]; +#define RACK_PENDING 1 /* waiting for reset-ack */ +#define RREQ_REPEAT 2 /* send another reset-req if no reset-ack */ + +#define RACKTIMEOUT 1 /* second */ + +static int all_rejected[NUM_PPP]; /* we rejected all peer's options */ + +/* + * Option parsing. + */ +static int +setbsdcomp(argv) + char **argv; +{ + int rbits, abits; + char *str, *endp; + + str = *argv; + abits = rbits = strtol(str, &endp, 0); + if (endp != str && *endp == ',') { + str = endp + 1; + abits = strtol(str, &endp, 0); + } + if (*endp != 0 || endp == str) { + option_error("invalid parameter '%s' for bsdcomp option", *argv); + return 0; + } + if ((rbits != 0 && (rbits < BSD_MIN_BITS || rbits > BSD_MAX_BITS)) + || (abits != 0 && (abits < BSD_MIN_BITS || abits > BSD_MAX_BITS))) { + option_error("bsdcomp option values must be 0 or %d .. %d", + BSD_MIN_BITS, BSD_MAX_BITS); + return 0; + } + if (rbits > 0) { + ccp_wantoptions[0].bsd_compress = 1; + ccp_wantoptions[0].bsd_bits = rbits; + } else + ccp_wantoptions[0].bsd_compress = 0; + if (abits > 0) { + ccp_allowoptions[0].bsd_compress = 1; + ccp_allowoptions[0].bsd_bits = abits; + } else + ccp_allowoptions[0].bsd_compress = 0; + slprintf(bsd_value, sizeof(bsd_value), + rbits == abits? "%d": "%d,%d", rbits, abits); + + return 1; +} + +static int +setdeflate(argv) + char **argv; +{ + int rbits, abits; + char *str, *endp; + + str = *argv; + abits = rbits = strtol(str, &endp, 0); + if (endp != str && *endp == ',') { + str = endp + 1; + abits = strtol(str, &endp, 0); + } + if (*endp != 0 || endp == str) { + option_error("invalid parameter '%s' for deflate option", *argv); + return 0; + } + if ((rbits != 0 && (rbits < DEFLATE_MIN_SIZE || rbits > DEFLATE_MAX_SIZE)) + || (abits != 0 && (abits < DEFLATE_MIN_SIZE + || abits > DEFLATE_MAX_SIZE))) { + option_error("deflate option values must be 0 or %d .. %d", + DEFLATE_MIN_SIZE, DEFLATE_MAX_SIZE); + return 0; + } + if (rbits == DEFLATE_MIN_SIZE || abits == DEFLATE_MIN_SIZE) { + if (rbits == DEFLATE_MIN_SIZE) + rbits = DEFLATE_MIN_WORKS; + if (abits == DEFLATE_MIN_SIZE) + abits = DEFLATE_MIN_WORKS; + warn("deflate option value of %d changed to %d to avoid zlib bug", + DEFLATE_MIN_SIZE, DEFLATE_MIN_WORKS); + } + if (rbits > 0) { + ccp_wantoptions[0].deflate = 1; + ccp_wantoptions[0].deflate_size = rbits; + } else + ccp_wantoptions[0].deflate = 0; + if (abits > 0) { + ccp_allowoptions[0].deflate = 1; + ccp_allowoptions[0].deflate_size = abits; + } else + ccp_allowoptions[0].deflate = 0; + slprintf(deflate_value, sizeof(deflate_value), + rbits == abits? "%d": "%d,%d", rbits, abits); + + return 1; +} + +/* + * ccp_init - initialize CCP. + */ +static void +ccp_init(unit) + int unit; +{ + fsm *f = &ccp_fsm[unit]; + + f->unit = unit; + f->protocol = PPP_CCP; + f->callbacks = &ccp_callbacks; + fsm_init(f); + + memset(&ccp_wantoptions[unit], 0, sizeof(ccp_options)); + memset(&ccp_gotoptions[unit], 0, sizeof(ccp_options)); + memset(&ccp_allowoptions[unit], 0, sizeof(ccp_options)); + memset(&ccp_hisoptions[unit], 0, sizeof(ccp_options)); + + ccp_wantoptions[0].deflate = 1; + ccp_wantoptions[0].deflate_size = DEFLATE_MAX_SIZE; + ccp_wantoptions[0].deflate_correct = 1; + ccp_wantoptions[0].deflate_draft = 1; + ccp_allowoptions[0].deflate = 1; + ccp_allowoptions[0].deflate_size = DEFLATE_MAX_SIZE; + ccp_allowoptions[0].deflate_correct = 1; + ccp_allowoptions[0].deflate_draft = 1; + + ccp_wantoptions[0].bsd_compress = 1; + ccp_wantoptions[0].bsd_bits = BSD_MAX_BITS; + ccp_allowoptions[0].bsd_compress = 1; + ccp_allowoptions[0].bsd_bits = BSD_MAX_BITS; + + ccp_allowoptions[0].predictor_1 = 1; +#ifdef MPPE + ccp_wantoptions[0].mppe = 0; + ccp_wantoptions[0].mppe_stateless = 0; + ccp_wantoptions[0].mppe_40 = 0; + ccp_wantoptions[0].mppe_128 = 0; + ccp_allowoptions[0].mppe_stateless = 1; + ccp_allowoptions[0].mppe = 1; + ccp_allowoptions[0].mppe_40 = 1; + ccp_allowoptions[0].mppe_128 = 1; +#endif /* MPPE*/ +} + +/* + * ccp_open - CCP is allowed to come up. + */ +static void +ccp_open(unit) + int unit; +{ + fsm *f = &ccp_fsm[unit]; + + if (f->state != OPENED) + ccp_flags_set(unit, 1, 0); + + /* + * Find out which compressors the kernel supports before + * deciding whether to open in silent mode. + */ + ccp_resetci(f); + if (!ANY_COMPRESS(ccp_gotoptions[unit])) + f->flags |= OPT_SILENT; + + fsm_open(f); +} + +/* + * ccp_close - Terminate CCP. + */ +static void +ccp_close(unit, reason) + int unit; + char *reason; +{ + ccp_flags_set(unit, 0, 0); + fsm_close(&ccp_fsm[unit], reason); +} + +/* + * ccp_lowerup - we may now transmit CCP packets. + */ +static void +ccp_lowerup(unit) + int unit; +{ + fsm_lowerup(&ccp_fsm[unit]); +} + +/* + * ccp_lowerdown - we may not transmit CCP packets. + */ +static void +ccp_lowerdown(unit) + int unit; +{ + fsm_lowerdown(&ccp_fsm[unit]); +} + +/* + * ccp_input - process a received CCP packet. + */ +static void +ccp_input(unit, p, len) + int unit; + u_char *p; + int len; +{ + fsm *f = &ccp_fsm[unit]; + int oldstate; + + /* + * Check for a terminate-request so we can print a message. + */ + oldstate = f->state; + fsm_input(f, p, len); + if (oldstate == OPENED && p[0] == TERMREQ && f->state != OPENED) + notice("Compression disabled by peer."); + + /* + * If we get a terminate-ack and we're not asking for compression, + * close CCP. + */ + if (oldstate == REQSENT && p[0] == TERMACK + && !ANY_COMPRESS(ccp_gotoptions[unit])) + ccp_close(unit, "No compression negotiated"); +} + +/* + * Handle a CCP-specific code. + */ +static int +ccp_extcode(f, code, id, p, len) + fsm *f; + int code, id; + u_char *p; + int len; +{ + switch (code) { + case CCP_RESETREQ: + if (f->state != OPENED) + break; + /* send a reset-ack, which the transmitter will see and + reset its compression state. */ + fsm_sdata(f, CCP_RESETACK, id, NULL, 0); + break; + + case CCP_RESETACK: + if (ccp_localstate[f->unit] & RACK_PENDING && id == f->reqid) { + ccp_localstate[f->unit] &= ~(RACK_PENDING | RREQ_REPEAT); + UNTIMEOUT(ccp_rack_timeout, f); + } + break; + + default: + return 0; + } + + return 1; +} + +/* + * ccp_protrej - peer doesn't talk CCP. + */ +static void +ccp_protrej(unit) + int unit; +{ + ccp_flags_set(unit, 0, 0); + fsm_lowerdown(&ccp_fsm[unit]); +} + +/* + * ccp_resetci - initialize at start of negotiation. + */ +static void +ccp_resetci(f) + fsm *f; +{ + ccp_options *go = &ccp_gotoptions[f->unit]; + u_char opt_buf[256]; + + *go = ccp_wantoptions[f->unit]; + all_rejected[f->unit] = 0; + + /* + * Check whether the kernel knows about the various + * compression methods we might request. + */ + if (go->bsd_compress) { + opt_buf[0] = CI_BSD_COMPRESS; + opt_buf[1] = CILEN_BSD_COMPRESS; + opt_buf[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, BSD_MIN_BITS); + if (ccp_test(f->unit, opt_buf, CILEN_BSD_COMPRESS, 0) <= 0) + go->bsd_compress = 0; + } +#ifdef MPPE + if (go->mppe) { + opt_buf[0] = CI_MPPE; + opt_buf[1] = CILEN_MPPE; + opt_buf[2] = 0; + /* keysize is 8 here */ + BCOPY(mppe_master_send_key_40, opt_buf+3, 8); + BCOPY(mppe_master_recv_key_40, opt_buf+11, 8); + if (ccp_test(f->unit, opt_buf, (2*8)+3, 0) <= 0) + go->mppe = 0; + } +#endif /*MPPE*/ + if (go->deflate) { + if (go->deflate_correct) { + opt_buf[0] = CI_DEFLATE; + opt_buf[1] = CILEN_DEFLATE; + opt_buf[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_WORKS); + opt_buf[3] = DEFLATE_CHK_SEQUENCE; + if (ccp_test(f->unit, opt_buf, CILEN_DEFLATE, 0) <= 0) + go->deflate_correct = 0; + } + if (go->deflate_draft) { + opt_buf[0] = CI_DEFLATE_DRAFT; + opt_buf[1] = CILEN_DEFLATE; + opt_buf[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_WORKS); + opt_buf[3] = DEFLATE_CHK_SEQUENCE; + if (ccp_test(f->unit, opt_buf, CILEN_DEFLATE, 0) <= 0) + go->deflate_draft = 0; + } + if (!go->deflate_correct && !go->deflate_draft) + go->deflate = 0; + } + if (go->predictor_1) { + opt_buf[0] = CI_PREDICTOR_1; + opt_buf[1] = CILEN_PREDICTOR_1; + if (ccp_test(f->unit, opt_buf, CILEN_PREDICTOR_1, 0) <= 0) + go->predictor_1 = 0; + } + if (go->predictor_2) { + opt_buf[0] = CI_PREDICTOR_2; + opt_buf[1] = CILEN_PREDICTOR_2; + if (ccp_test(f->unit, opt_buf, CILEN_PREDICTOR_2, 0) <= 0) + go->predictor_2 = 0; + } +} + +/* + * ccp_cilen - Return total length of our configuration info. + */ +static int +ccp_cilen(f) + fsm *f; +{ + ccp_options *go = &ccp_gotoptions[f->unit]; + + 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->mppe? CILEN_MPPE: 0); +} + +/* + * ccp_addci - put our requests in a packet. + */ +static void +ccp_addci(f, p, lenp) + fsm *f; + u_char *p; + int *lenp; +{ + int res; + ccp_options *go = &ccp_gotoptions[f->unit]; + u_char *p0 = p; + + /* + * 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. + */ + 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 (;;) { + 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) { + go->deflate = 0; + break; + } + --go->deflate_size; + p[2] = DEFLATE_MAKE_OPT(go->deflate_size); + } + if (p != p0 && go->deflate_correct && go->deflate_draft) { + p[0] = CI_DEFLATE_DRAFT; + p[1] = CILEN_DEFLATE; + p[2] = p[2 - CILEN_DEFLATE]; + p[3] = DEFLATE_CHK_SEQUENCE; + p += CILEN_DEFLATE; + } + } +#ifdef MPPE + if (go->mppe) { + u_char opt_buf[64]; + u_int keysize = 0; + + if(!mppe_allowed) + go->mppe_stateless = go->mppe_40 = go->mppe_128 = 0; + p[0]=CI_MPPE; + p[1]=CILEN_MPPE; + p[2]=(go->mppe_stateless ? MPPE_STATELESS : 0); + p[3]=0; + p[4]=0; + p[5]=(go->mppe_40 ? MPPE_40BIT : 0) | (go->mppe_128 ? MPPE_128BIT : 0); + if(p[5] & MPPE_40BIT) { + keysize = 8; + BCOPY(mppe_master_send_key_40, opt_buf+3, keysize); + BCOPY(mppe_master_recv_key_40, opt_buf+11, keysize); + } else if(p[5] & MPPE_128BIT) { + keysize = 16; + BCOPY(mppe_master_send_key_128, opt_buf+3, keysize); + BCOPY(mppe_master_recv_key_128, opt_buf+19, keysize); + } + if(p[5] != 0) { + opt_buf[0]=CI_MPPE; + opt_buf[1]=CILEN_MPPE; + opt_buf[2] = (go->mppe_stateless) ? 1 : 0; + res = ccp_test(f->unit, opt_buf, (2*keysize)+3, 0); + } else { + res = -1; + } + if (res > 0) { + p += CILEN_MPPE; + } + } +#endif /* MPPE*/ + if (go->bsd_compress) { + 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); + } + } + } + /* XXX Should Predictor 2 be preferable to Predictor 1? */ + if (go->predictor_1) { + p[0] = CI_PREDICTOR_1; + p[1] = CILEN_PREDICTOR_1; + if (p == p0 && ccp_test(f->unit, p, CILEN_PREDICTOR_1, 0) <= 0) { + go->predictor_1 = 0; + } else { + p += CILEN_PREDICTOR_1; + } + } + if (go->predictor_2) { + p[0] = CI_PREDICTOR_2; + p[1] = CILEN_PREDICTOR_2; + if (p == p0 && ccp_test(f->unit, p, CILEN_PREDICTOR_2, 0) <= 0) { + go->predictor_2 = 0; + } else { + p += CILEN_PREDICTOR_2; + } + } + + go->method = (p > p0)? p0[0]: -1; + + *lenp = p - p0; +} + +/* + * ccp_ackci - process a received configure-ack, and return + * 1 iff the packet was OK. + */ +static int +ccp_ackci(f, p, len) + fsm *f; + u_char *p; + int len; +{ + ccp_options *go = &ccp_gotoptions[f->unit]; + u_char *p0 = p; + + if (go->deflate) { + if (len < CILEN_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) + return 0; + p += CILEN_DEFLATE; + len -= CILEN_DEFLATE; + /* XXX Cope with first/fast ack */ + if (len == 0) + return 1; + if (go->deflate_correct && go->deflate_draft) { + if (len < CILEN_DEFLATE + || p[0] != CI_DEFLATE_DRAFT + || p[1] != CILEN_DEFLATE + || p[2] != DEFLATE_MAKE_OPT(go->deflate_size) + || p[3] != DEFLATE_CHK_SEQUENCE) + return 0; + p += CILEN_DEFLATE; + len -= CILEN_DEFLATE; + } + } +#ifdef MPPE + if (go->mppe) { + if ( len < CILEN_MPPE + || p[1] != CILEN_MPPE || p[0] != CI_MPPE + || p[2] != (go->mppe_stateless ? MPPE_STATELESS : 0) + || p[3] != 0 + || p[4] != 0 + || p[5] != ((go->mppe_40 ? MPPE_40BIT : 0) | (go->mppe_128 ? MPPE_128BIT : 0))) + return 0; + p += CILEN_MPPE; + len -= CILEN_MPPE; + /* Cope with first/fast ack */ + if (len == 0) + return 1; + } +#endif /* MPPE */ + if (go->bsd_compress) { + if (len < CILEN_BSD_COMPRESS + || p[0] != CI_BSD_COMPRESS || p[1] != CILEN_BSD_COMPRESS + || p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits)) + return 0; + p += CILEN_BSD_COMPRESS; + len -= CILEN_BSD_COMPRESS; + /* XXX Cope with first/fast ack */ + if (p == p0 && len == 0) + return 1; + } + if (go->predictor_1) { + if (len < CILEN_PREDICTOR_1 + || p[0] != CI_PREDICTOR_1 || p[1] != CILEN_PREDICTOR_1) + return 0; + p += CILEN_PREDICTOR_1; + len -= CILEN_PREDICTOR_1; + /* XXX Cope with first/fast ack */ + if (p == p0 && len == 0) + return 1; + } + if (go->predictor_2) { + if (len < CILEN_PREDICTOR_2 + || p[0] != CI_PREDICTOR_2 || p[1] != CILEN_PREDICTOR_2) + return 0; + p += CILEN_PREDICTOR_2; + len -= CILEN_PREDICTOR_2; + /* XXX Cope with first/fast ack */ + if (p == p0 && len == 0) + return 1; + } + + if (len != 0) + return 0; + return 1; +} + +/* + * ccp_nakci - process received configure-nak. + * Returns 1 iff the nak was OK. + */ +static int +ccp_nakci(f, p, len) + fsm *f; + u_char *p; + int len; +{ + ccp_options *go = &ccp_gotoptions[f->unit]; + ccp_options no; /* options we've seen already */ + ccp_options try; /* options to ask for next time */ + + memset(&no, 0, sizeof(no)); + try = *go; + + if (go->deflate && len >= CILEN_DEFLATE + && p[0] == (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT) + && p[1] == CILEN_DEFLATE) { + no.deflate = 1; + /* + * Peer wants us to use a different code size or something. + * Stop asking for Deflate if we don't understand his suggestion. + */ + if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL + || DEFLATE_SIZE(p[2]) < DEFLATE_MIN_WORKS + || p[3] != DEFLATE_CHK_SEQUENCE) + try.deflate = 0; + else if (DEFLATE_SIZE(p[2]) < go->deflate_size) + try.deflate_size = DEFLATE_SIZE(p[2]); + p += CILEN_DEFLATE; + len -= CILEN_DEFLATE; + if (go->deflate_correct && go->deflate_draft + && len >= CILEN_DEFLATE && p[0] == CI_DEFLATE_DRAFT + && p[1] == CILEN_DEFLATE) { + p += CILEN_DEFLATE; + len -= CILEN_DEFLATE; + } + } + +#ifdef MPPE + if (len >= CILEN_MPPE && p[0] == CI_MPPE && p[1] == CILEN_MPPE) { + no.mppe = 1; + if((p[5] & MPPE_128BIT) == 0) + try.mppe_128 = 0; + if((p[5] & MPPE_40BIT) == 0) + try.mppe_40 = 0; + if((p[2] & MPPE_STATELESS) == 0) + try.mppe_stateless = 0; + if(!try.mppe_128 && !try.mppe_40) { + no.mppe = 0; + try.mppe = 0; + } + p += CILEN_MPPE; + len -= CILEN_MPPE; + } +#endif /* MPPE */ + + if (go->bsd_compress && len >= CILEN_BSD_COMPRESS + && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) { + no.bsd_compress = 1; + /* + * Peer wants us to use a different number of bits + * or a different version. + */ + if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION) + try.bsd_compress = 0; + else if (BSD_NBITS(p[2]) < go->bsd_bits) + try.bsd_bits = BSD_NBITS(p[2]); + p += CILEN_BSD_COMPRESS; + len -= CILEN_BSD_COMPRESS; + } + + /* + * Predictor-1 and 2 have no options, so they can't be Naked. + * + * There may be remaining options but we ignore them. + */ + + if (f->state != OPENED) + *go = try; + return 1; +} + +/* + * ccp_rejci - reject some of our suggested compression methods. + */ +static int +ccp_rejci(f, p, len) + fsm *f; + u_char *p; + int len; +{ + ccp_options *go = &ccp_gotoptions[f->unit]; + ccp_options try; /* options to request next time */ + + try = *go; + + /* + * Cope with empty configure-rejects by ceasing to send + * configure-requests. + */ + if (len == 0 && all_rejected[f->unit]) + return -1; + + if (go->deflate && len >= CILEN_DEFLATE + && p[0] == (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT) + && p[1] == CILEN_DEFLATE) { + if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size) + || p[3] != DEFLATE_CHK_SEQUENCE) + return 0; /* Rej is bad */ + if (go->deflate_correct) + try.deflate_correct = 0; + else + try.deflate_draft = 0; + p += CILEN_DEFLATE; + len -= CILEN_DEFLATE; + if (go->deflate_correct && go->deflate_draft + && len >= CILEN_DEFLATE && p[0] == CI_DEFLATE_DRAFT + && p[1] == CILEN_DEFLATE) { + if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size) + || p[3] != DEFLATE_CHK_SEQUENCE) + return 0; /* Rej is bad */ + try.deflate_draft = 0; + p += CILEN_DEFLATE; + len -= CILEN_DEFLATE; + } + if (!try.deflate_correct && !try.deflate_draft) + try.deflate = 0; + } +#ifdef MPPE + if (go->mppe && len >= CILEN_MPPE + && p[0] == CI_MPPE && p[1] == CILEN_MPPE) { + try.mppe = 0; + p += CILEN_MPPE; + len -= CILEN_MPPE; + } +#endif /*MPPE*/ + if (go->bsd_compress && len >= CILEN_BSD_COMPRESS + && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) { + if (p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits)) + return 0; + try.bsd_compress = 0; + p += CILEN_BSD_COMPRESS; + len -= CILEN_BSD_COMPRESS; + } + if (go->predictor_1 && len >= CILEN_PREDICTOR_1 + && p[0] == CI_PREDICTOR_1 && p[1] == CILEN_PREDICTOR_1) { + try.predictor_1 = 0; + p += CILEN_PREDICTOR_1; + len -= CILEN_PREDICTOR_1; + } + if (go->predictor_2 && len >= CILEN_PREDICTOR_2 + && p[0] == CI_PREDICTOR_2 && p[1] == CILEN_PREDICTOR_2) { + try.predictor_2 = 0; + p += CILEN_PREDICTOR_2; + len -= CILEN_PREDICTOR_2; + } + + if (len != 0) + return 0; + + if (f->state != OPENED) + *go = try; + + return 1; +} + +/* + * ccp_reqci - processed a received configure-request. + * Returns CONFACK, CONFNAK or CONFREJ and the packet modified + * appropriately. + */ +static int +ccp_reqci(f, p, lenp, dont_nak) + fsm *f; + u_char *p; + int *lenp; + int dont_nak; +{ + int ret, newret, res; + u_char *p0, *retp; + int len, clen, type, nb; + ccp_options *ho = &ccp_hisoptions[f->unit]; + ccp_options *ao = &ccp_allowoptions[f->unit]; + + ret = CONFACK; + retp = p0 = p; + len = *lenp; + + memset(ho, 0, sizeof(ccp_options)); + ho->method = (len > 0)? p[0]: -1; + + while (len > 0) { + newret = CONFACK; + if (len < 2 || p[1] < 2 || p[1] > len) { + /* length is bad */ + clen = len; + newret = CONFREJ; + + } else { + type = p[0]; + clen = p[1]; + + switch (type) { + case CI_DEFLATE: + case CI_DEFLATE_DRAFT: + if (!ao->deflate || clen != CILEN_DEFLATE + || (!ao->deflate_correct && type == CI_DEFLATE) + || (!ao->deflate_draft && type == CI_DEFLATE_DRAFT)) { + newret = CONFREJ; + break; + } + + ho->deflate = 1; + ho->deflate_size = nb = DEFLATE_SIZE(p[2]); + if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL + || p[3] != DEFLATE_CHK_SEQUENCE + || nb > ao->deflate_size || nb < DEFLATE_MIN_WORKS) { + newret = CONFNAK; + if (!dont_nak) { + p[2] = DEFLATE_MAKE_OPT(ao->deflate_size); + p[3] = DEFLATE_CHK_SEQUENCE; + /* fall through to test this #bits below */ + } else + break; + } + + /* + * Check whether we can do Deflate with the window + * size they want. If the window is too big, reduce + * it until the kernel can cope and nak with that. + * We only check this for the first option. + */ + if (p == p0) { + for (;;) { + res = ccp_test(f->unit, p, CILEN_DEFLATE, 1); + if (res > 0) + break; /* it's OK now */ + if (res < 0 || nb == DEFLATE_MIN_WORKS || dont_nak) { + newret = CONFREJ; + p[2] = DEFLATE_MAKE_OPT(ho->deflate_size); + break; + } + newret = CONFNAK; + --nb; + p[2] = DEFLATE_MAKE_OPT(nb); + } + } + break; + +#ifdef MPPE + case CI_MPPE: + if (!ao->mppe || clen != CILEN_MPPE) { + newret = CONFREJ; + break; + } + if(!mppe_allowed) + { + newret = CONFREJ; + break; + } + ho->mppe = 1; + if((p[5]&(MPPE_40BIT|MPPE_128BIT)) == (MPPE_40BIT|MPPE_128BIT)) + { + /* if both are available, select the stronger */ + p[5] &= ~MPPE_40BIT; + newret = CONFNAK; + } + if((p[2] & ~MPPE_STATELESS) != 0 + || p[3] != 0 + || p[4] != 0 + || (p[5] & ~(MPPE_40BIT | MPPE_128BIT)) != 0) + { + ccp_options *wo = &ccp_wantoptions[f->unit]; + /* not sure what they want, tell 'em what we got */ + p[2] &= MPPE_STATELESS; + p[3] &= 0; + p[4] &= 0; + p[5] &= MPPE_40BIT | MPPE_128BIT; + if(wo->mppe_40) + p[5] |= MPPE_40BIT; + if(wo->mppe_128) + p[5] |= MPPE_128BIT; + newret = CONFNAK; + } + + if((newret == CONFACK) || (newret == CONFNAK)) + { + /* + * The kernel ppp driver needs the session key + * which is not sent via CCP :( + */ + unsigned int keysize; + unsigned char opt_buf[64]; + opt_buf[0] = CI_MPPE; + opt_buf[1] = CILEN_MPPE; + if(p[2] & MPPE_STATELESS) { + ho->mppe_stateless=1; + opt_buf[2] = MPPE_STATELESS; + } + /* push in our send/receive keys */ + if(p[5] & MPPE_40BIT) { + ho->mppe_40 = 1; + keysize = 8; + BCOPY(mppe_master_send_key_40, opt_buf+3, keysize); + BCOPY(mppe_master_recv_key_40, opt_buf+11, keysize); + } else if(p[5] & MPPE_128BIT) { + ho->mppe_128 = 1; + keysize = 16; + BCOPY(mppe_master_send_key_128, opt_buf+3, keysize); + BCOPY(mppe_master_recv_key_128, opt_buf+19, keysize); + } else { + ho->mppe = 0; + newret = CONFREJ; + break; + } + /* call ioctl and pass this nasty stuff to the kernel */ + if (ccp_test(f->unit, opt_buf, (2*keysize)+3, 1) <= 0){ + ho->mppe = 0; + newret = CONFREJ; + break; + } + } + break; +#endif /* MPPE */ + + case CI_BSD_COMPRESS: + if (!ao->bsd_compress || clen != CILEN_BSD_COMPRESS) { + newret = CONFREJ; + break; + } + + ho->bsd_compress = 1; + ho->bsd_bits = nb = BSD_NBITS(p[2]); + if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION + || nb > ao->bsd_bits || nb < BSD_MIN_BITS) { + newret = CONFNAK; + if (!dont_nak) { + p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, ao->bsd_bits); + /* fall through to test this #bits below */ + } else + break; + } + + /* + * Check whether we can do BSD-Compress with the code + * size they want. If the code size is too big, reduce + * it until the kernel can cope and nak with that. + * We only check this for the first option. + */ + if (p == p0) { + for (;;) { + res = ccp_test(f->unit, p, CILEN_BSD_COMPRESS, 1); + if (res > 0) + break; + if (res < 0 || nb == BSD_MIN_BITS || dont_nak) { + newret = CONFREJ; + p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, + ho->bsd_bits); + break; + } + newret = CONFNAK; + --nb; + p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, nb); + } + } + break; + + case CI_PREDICTOR_1: + if (!ao->predictor_1 || clen != CILEN_PREDICTOR_1) { + newret = CONFREJ; + break; + } + + ho->predictor_1 = 1; + if (p == p0 + && ccp_test(f->unit, p, CILEN_PREDICTOR_1, 1) <= 0) { + newret = CONFREJ; + } + break; + + case CI_PREDICTOR_2: + if (!ao->predictor_2 || clen != CILEN_PREDICTOR_2) { + newret = CONFREJ; + break; + } + + ho->predictor_2 = 1; + if (p == p0 + && ccp_test(f->unit, p, CILEN_PREDICTOR_2, 1) <= 0) { + newret = CONFREJ; + } + break; + + default: + newret = CONFREJ; + } + } + + if (newret == CONFNAK && dont_nak) + newret = CONFREJ; + if (!(newret == CONFACK || (newret == CONFNAK && ret == CONFREJ))) { + /* we're returning this option */ + if (newret == CONFREJ && ret == CONFNAK) + retp = p0; + ret = newret; + if (p != retp) + BCOPY(p, retp, clen); + retp += clen; + } + + p += clen; + len -= clen; + } + + if (ret != CONFACK) { + if (ret == CONFREJ && *lenp == retp - p0) + all_rejected[f->unit] = 1; + else + *lenp = retp - p0; + } + return ret; +} + +/* + * Make a string name for a compression method (or 2). + */ +static char * +method_name(opt, opt2) + ccp_options *opt, *opt2; +{ + static char result[64]; + + if (!ANY_COMPRESS(*opt)) + return "(none)"; + switch (opt->method) { + case CI_DEFLATE: + case CI_DEFLATE_DRAFT: + if (opt2 != NULL && opt2->deflate_size != opt->deflate_size) + slprintf(result, sizeof(result), "Deflate%s (%d/%d)", + (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""), + opt->deflate_size, opt2->deflate_size); + else + slprintf(result, sizeof(result), "Deflate%s (%d)", + (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""), + opt->deflate_size); + break; +#ifdef MPPE + case CI_MPPE: + if (opt->mppe_40) { + if (opt->mppe_stateless) { + return "MPPE 40 bit, stateless"; + } else { + return "MPPE 40 bit, non-stateless"; + } + } else if (opt->mppe_128) { + if (opt->mppe_stateless) { + return "MPPE 128 bit, stateless"; + } else { + return "MPPE 128 bit, non-stateless"; + } + } else { + if (opt->mppe_stateless) { + return "MPPE unknown strength, stateless"; + } else { + return "MPPE unknown strength, stateless"; + } + } +#endif + case CI_LZS: + return "Stac LZS"; + case CI_BSD_COMPRESS: + if (opt2 != NULL && opt2->bsd_bits != opt->bsd_bits) + slprintf(result, sizeof(result), "BSD-Compress (%d/%d)", + opt->bsd_bits, opt2->bsd_bits); + else + slprintf(result, sizeof(result), "BSD-Compress (%d)", + opt->bsd_bits); + break; + case CI_PREDICTOR_1: + return "Predictor 1"; + case CI_PREDICTOR_2: + return "Predictor 2"; + default: + slprintf(result, sizeof(result), "Method %d", opt->method); + } + return result; +} + +/* + * CCP has come up - inform the kernel driver and log a message. + */ +static void +ccp_up(f) + fsm *f; +{ + ccp_options *go = &ccp_gotoptions[f->unit]; + ccp_options *ho = &ccp_hisoptions[f->unit]; + char method1[64]; + + ccp_flags_set(f->unit, 1, 1); + if (ANY_COMPRESS(*go)) { + if (ANY_COMPRESS(*ho)) { + if (go->method == ho->method) { + notice("%s compression enabled", method_name(go, ho)); + } else { + strlcpy(method1, method_name(go, NULL), sizeof(method1)); + notice("%s / %s compression enabled", + method1, method_name(ho, NULL)); + } + } else + notice("%s receive compression enabled", method_name(go, NULL)); + } else if (ANY_COMPRESS(*ho)) + notice("%s transmit compression enabled", method_name(ho, NULL)); +} + +/* + * CCP has gone down - inform the kernel driver. + */ +static void +ccp_down(f) + fsm *f; +{ + if (ccp_localstate[f->unit] & RACK_PENDING) + UNTIMEOUT(ccp_rack_timeout, f); + ccp_localstate[f->unit] = 0; + ccp_flags_set(f->unit, 1, 0); +} + +/* + * Print the contents of a CCP packet. + */ +static char *ccp_codenames[] = { + "ConfReq", "ConfAck", "ConfNak", "ConfRej", + "TermReq", "TermAck", "CodeRej", + NULL, NULL, NULL, NULL, NULL, NULL, + "ResetReq", "ResetAck", +}; + +static int +ccp_printpkt(p, plen, printer, arg) + u_char *p; + int plen; + void (*printer) __P((void *, char *, ...)); + void *arg; +{ + u_char *p0, *optend; + int code, id, len; + int optlen; + + p0 = p; + if (plen < HEADERLEN) + return 0; + code = p[0]; + id = p[1]; + len = (p[2] << 8) + p[3]; + if (len < HEADERLEN || len > plen) + return 0; + + if (code >= 1 && code <= sizeof(ccp_codenames) / sizeof(char *) + && ccp_codenames[code-1] != NULL) + printer(arg, " %s", ccp_codenames[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= HEADERLEN; + p += HEADERLEN; + + switch (code) { + case CONFREQ: + case CONFACK: + case CONFNAK: + case CONFREJ: + /* print list of possible compression methods */ + while (len >= 2) { + code = p[0]; + optlen = p[1]; + if (optlen < 2 || optlen > len) + break; + printer(arg, " <"); + len -= optlen; + optend = p + optlen; + switch (code) { + case CI_DEFLATE: + case CI_DEFLATE_DRAFT: + if (optlen >= CILEN_DEFLATE) { + printer(arg, "deflate%s %d", + (code == CI_DEFLATE_DRAFT? "(old#)": ""), + DEFLATE_SIZE(p[2])); + if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL) + printer(arg, " method %d", DEFLATE_METHOD(p[2])); + if (p[3] != DEFLATE_CHK_SEQUENCE) + printer(arg, " check %d", p[3]); + p += CILEN_DEFLATE; + } + break; + case CI_BSD_COMPRESS: + if (optlen >= CILEN_BSD_COMPRESS) { + printer(arg, "bsd v%d %d", BSD_VERSION(p[2]), + BSD_NBITS(p[2])); + p += CILEN_BSD_COMPRESS; + } + break; + case CI_PREDICTOR_1: + if (optlen >= CILEN_PREDICTOR_1) { + printer(arg, "predictor 1"); + p += CILEN_PREDICTOR_1; + } + break; + case CI_MPPE: + if (optlen >= CILEN_MPPE) { + printer(arg, "mppe %x %x %x %x",p[2],p[3],p[4],p[5]); + p += CILEN_MPPE; + } + break; + case CI_LZS: + if (optlen >= CILEN_LZS) { + printer(arg, "lzs %x %x %x", p[2], p[3], p[4]); + p += CILEN_LZS; + } + break; + case CI_PREDICTOR_2: + if (optlen >= CILEN_PREDICTOR_2) { + printer(arg, "predictor 2"); + p += CILEN_PREDICTOR_2; + } + break; + } + while (p < optend) + printer(arg, " %.2x", *p++); + printer(arg, ">"); + } + break; + + case TERMACK: + case TERMREQ: + if (len > 0 && *p >= ' ' && *p < 0x7f) { + print_string((char *)p, len, printer, arg); + p += len; + len = 0; + } + break; + } + + /* dump out the rest of the packet in hex */ + while (--len >= 0) + printer(arg, " %.2x", *p++); + + return p - p0; +} + +/* + * We have received a packet that the decompressor failed to + * decompress. Here we would expect to issue a reset-request, but + * Motorola has a patent on resetting the compressor as a result of + * detecting an error in the decompressed data after decompression. + * (See US patent 5,130,993; international patent publication number + * WO 91/10289; Australian patent 73296/91.) + * + * So we ask the kernel whether the error was detected after + * decompression; if it was, we take CCP down, thus disabling + * compression :-(, otherwise we issue the reset-request. + */ +static void +ccp_datainput(unit, pkt, len) + int unit; + u_char *pkt; + int len; +{ + fsm *f; + + f = &ccp_fsm[unit]; + if (f->state == OPENED) { + if (ccp_fatal_error(unit)) { + /* + * Disable compression by taking CCP down. + */ + error("Lost compression sync: disabling compression"); + ccp_close(unit, "Lost compression sync"); + } else { + /* MPPE/MPPC does not requires CCP_RESETREQ */ + if (ccp_gotoptions[f->unit].method == CI_MPPE) + return; + /* + * Send a reset-request to reset the peer's compressor. + * We don't do that if we are still waiting for an + * acknowledgement to a previous reset-request. + */ + if (!(ccp_localstate[f->unit] & RACK_PENDING)) { + fsm_sdata(f, CCP_RESETREQ, f->reqid = ++f->id, NULL, 0); + TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT); + ccp_localstate[f->unit] |= RACK_PENDING; + } else + ccp_localstate[f->unit] |= RREQ_REPEAT; + } + } +} + +/* + * Timeout waiting for reset-ack. + */ +static void +ccp_rack_timeout(arg) + void *arg; +{ + fsm *f = arg; + + if (f->state == OPENED && ccp_localstate[f->unit] & RREQ_REPEAT) { + fsm_sdata(f, CCP_RESETREQ, f->reqid, NULL, 0); + TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT); + ccp_localstate[f->unit] &= ~RREQ_REPEAT; + } else + ccp_localstate[f->unit] &= ~RACK_PENDING; +} + diff -urN ppp-2.4.1/pppd/ccp.h ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/ccp.h --- ppp-2.4.1/pppd/ccp.h Sat Nov 7 01:58:11 1998 +++ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/ccp.h Tue Nov 5 20:01:07 2002 @@ -34,6 +34,12 @@ 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 M$ encryption? */ + bool mppe_40; /* allow 40 bit encryption */ + bool mppe_128; /* allow 128 bit encryption */ + bool mppe_stateless; /* allow stateless encryption */ + bool require_mppe; /* force mppe encryption */ + bool require_mppe_stateless; /* force stateless encryption */ 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 */ @@ -46,3 +52,8 @@ extern ccp_options ccp_hisoptions[]; extern struct protent ccp_protent; + +#ifdef MPPE +size_t mppe_generate_session_key(char *optbuf); +#endif + Binary files ppp-2.4.1/pppd/ccp.o and ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/ccp.o differ diff -urN ppp-2.4.1/pppd/chap.c ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/chap.c --- ppp-2.4.1/pppd/chap.c Thu Mar 8 00:11:11 2001 +++ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/chap.c Tue Nov 5 20:00:52 2002 @@ -47,6 +47,8 @@ #include "pppd.h" #include "chap.h" #include "md5.h" +#include "fsm.h" +#include "lcp.h" #ifdef CHAPMS #include "chap_ms.h" #endif @@ -113,7 +115,7 @@ static void ChapSendStatus __P((chap_state *, int)); static void ChapSendChallenge __P((chap_state *)); static void ChapSendResponse __P((chap_state *)); -static void ChapGenChallenge __P((chap_state *)); +void ChapGenChallenge __P((chap_state *)); extern double drand48 __P((void)); extern void srand48 __P((long)); @@ -460,6 +462,7 @@ switch (cstate->resp_type) { case CHAP_DIGEST_MD5: + CHAPDEBUG(("ChapReceiveChallenge: rcvd type CHAP-DIGEST-MD5")); MD5Init(&mdContext); MD5Update(&mdContext, &cstate->resp_id, 1); MD5Update(&mdContext, secret, secret_len); @@ -471,8 +474,24 @@ #ifdef CHAPMS case CHAP_MICROSOFT: + CHAPDEBUG(("ChapReceiveChallenge: rcvd type MS-CHAP-V1.")); + if(rchallenge_len != 8) + { + CHAPDEBUG(("Invalid challenge length for MS-CHAP-V1")); + return; + } ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len); break; + + case CHAP_MICROSOFT_V2: + CHAPDEBUG(("ChapReceiveChallenge: rcvd type MS-CHAP-V2.")); + if(rchallenge_len != 16) + { + CHAPDEBUG(("Invalid challenge length for MS-CHAP-V2")); + return; + } + ChapMS_v2(cstate, rchallenge, rchallenge_len, secret, secret_len); + break; #endif default: @@ -518,7 +537,7 @@ * as we did for the first Response we saw. */ if (cstate->serverstate == CHAPSS_OPEN) { - ChapSendStatus(cstate, CHAP_SUCCESS); + ChapSendStatus(cstate, cstate->chal_type == CHAP_MICROSOFT_V2 ? CHAP_SUCCESS_R : CHAP_SUCCESS); return; } if (cstate->serverstate == CHAPSS_BADAUTH) { @@ -560,7 +579,8 @@ /* generate MD based on negotiated type */ switch (cstate->chal_type) { - case CHAP_DIGEST_MD5: /* only MD5 is defined for now */ + case CHAP_DIGEST_MD5: + CHAPDEBUG(("ChapReceiveResponse: rcvd type CHAP-DIGEST-MD5")); if (remmd_len != MD5_SIGNATURE_SIZE) break; /* it's not even the right length */ MD5Init(&mdContext); @@ -574,6 +594,27 @@ code = CHAP_SUCCESS; /* they are the same! */ break; +#ifdef CHAPMS + case CHAP_MICROSOFT: + CHAPDEBUG(("ChapReceiveResponse: rcvd type MS-CHAP-V1")); + if(remmd_len != MS_CHAP_RESPONSE_LEN) + break; + if(ChapMS_Resp(cstate, secret, secret_len, remmd) == 0) + code = CHAP_SUCCESS; + break; + + case CHAP_MICROSOFT_V2: + CHAPDEBUG(("ChapReceiveResponse: rcvd type MS-CHAP-V2")); + if(remmd_len != MS_CHAP_RESPONSE_LEN) + break; + if(ChapMS_v2_Resp(cstate,secret,secret_len,remmd,rhostname) == 0) + { + code = CHAP_SUCCESS_R; + ChapMS_v2_Auth(cstate, secret, secret_len, remmd, rhostname); + } + break; +#endif + default: CHAPDEBUG(("unknown digest type %d", cstate->chal_type)); } @@ -582,7 +623,7 @@ BZERO(secret, sizeof(secret)); ChapSendStatus(cstate, code); - if (code == CHAP_SUCCESS) { + if ((code == CHAP_SUCCESS) || (code == CHAP_SUCCESS_R)) { old_state = cstate->serverstate; cstate->serverstate = CHAPSS_OPEN; if (old_state == CHAPSS_INITIAL_CHAL) { @@ -590,10 +631,43 @@ } if (cstate->chal_interval != 0) TIMEOUT(ChapRechallenge, cstate, cstate->chal_interval); - notice("CHAP peer authentication succeeded for %q", rhostname); - + switch (cstate->chal_type) { + case CHAP_DIGEST_MD5: + notice("CHAP peer authentication succeeded for %q", rhostname); + break; +#ifdef CHAPMS + case CHAP_MICROSOFT: + notice("MSCHAP peer authentication succeeded for %q", rhostname); + break; + case CHAP_MICROSOFT_V2: + notice("MSCHAP-v2 peer authentication succeeded for %q", rhostname); + break; +#endif + default: + notice("CHAP (unknown) peer authentication succeeded for %q", + rhostname); + break; + } } else { - error("CHAP peer authentication failed for remote host %q", rhostname); + switch (cstate->chal_type) { + case CHAP_DIGEST_MD5: + error("CHAP peer authentication failed for remote host %q", + rhostname); + break; +#ifdef CHAPMS + case CHAP_MICROSOFT: + error("MSCHAP peer authentication failed for remote host %q", + rhostname); + break; + case CHAP_MICROSOFT_V2: + error("MSCHAP-v2 peer authentication failed for remote host %q", + rhostname); + break; +#endif + default: + error("CHAP (unknown) peer authentication failed for remote host %q", rhostname); + break; + } cstate->serverstate = CHAPSS_BADAUTH; auth_peer_fail(cstate->unit, PPP_CHAP); } @@ -712,6 +786,8 @@ if (code == CHAP_SUCCESS) slprintf(msg, sizeof(msg), "Welcome to %s.", hostname); + else if(code == CHAP_SUCCESS_R) + strcpy(msg, cstate->response); else slprintf(msg, sizeof(msg), "I don't like you. Go 'way."); msglen = strlen(msg); @@ -721,7 +797,7 @@ MAKEHEADER(outp, PPP_CHAP); /* paste in a header */ - PUTCHAR(code, outp); + PUTCHAR(code == CHAP_SUCCESS_R ? CHAP_SUCCESS : code, outp); PUTCHAR(cstate->chal_id, outp); PUTSHORT(outlen, outp); BCOPY(msg, outp, msglen); @@ -735,7 +811,7 @@ * *cstate are initialized. */ -static void +void ChapGenChallenge(cstate) chap_state *cstate; { @@ -743,6 +819,14 @@ u_char *ptr = cstate->challenge; int i; +#ifdef CHAPMS + if(cstate->chal_type == CHAP_MICROSOFT) + chal_len = 8; + else if(cstate->chal_type == CHAP_MICROSOFT_V2) + chal_len = 16; + else +#endif + /* pick a random challenge length between MIN_CHALLENGE_LENGTH and MAX_CHALLENGE_LENGTH */ chal_len = (unsigned) ((drand48() * @@ -857,4 +941,14 @@ } return len + CHAP_HEADERLEN; +} + +int +reqchap(argv) + char **argv; +{ + lcp_wantoptions[0].neg_chap = 1; + lcp_wantoptions[0].use_digest = 1; + auth_required = 1; + return 1; } diff -urN ppp-2.4.1/pppd/chap.c~ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/chap.c~ --- ppp-2.4.1/pppd/chap.c~ Wed Dec 31 19:00:00 1969 +++ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/chap.c~ Thu Mar 8 00:11:11 2001 @@ -0,0 +1,860 @@ +/* + * chap.c - Challenge Handshake Authentication Protocol. + * + * Copyright (c) 1993 The Australian National University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the Australian National University. The name of the University + * may not be used to endorse or promote products derived from this + * software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Copyright (c) 1991 Gregory M. Christy. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Gregory M. Christy. The name of the author may not be used to + * endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#define RCSID "$Id: chap.c,v 1.25 2001/03/08 05:11:11 paulus Exp $" + +/* + * TODO: + */ + +#include +#include +#include +#include + +#include "pppd.h" +#include "chap.h" +#include "md5.h" +#ifdef CHAPMS +#include "chap_ms.h" +#endif + +static const char rcsid[] = RCSID; + +/* + * Command-line options. + */ +static option_t chap_option_list[] = { + { "chap-restart", o_int, &chap[0].timeouttime, + "Set timeout for CHAP", OPT_PRIO }, + { "chap-max-challenge", o_int, &chap[0].max_transmits, + "Set max #xmits for challenge", OPT_PRIO }, + { "chap-interval", o_int, &chap[0].chal_interval, + "Set interval for rechallenge", OPT_PRIO }, +#ifdef MSLANMAN + { "ms-lanman", o_bool, &ms_lanman, + "Use LanMan passwd when using MS-CHAP", 1 }, +#endif + { NULL } +}; + +/* + * Protocol entry points. + */ +static void ChapInit __P((int)); +static void ChapLowerUp __P((int)); +static void ChapLowerDown __P((int)); +static void ChapInput __P((int, u_char *, int)); +static void ChapProtocolReject __P((int)); +static int ChapPrintPkt __P((u_char *, int, + void (*) __P((void *, char *, ...)), void *)); + +struct protent chap_protent = { + PPP_CHAP, + ChapInit, + ChapInput, + ChapProtocolReject, + ChapLowerUp, + ChapLowerDown, + NULL, + NULL, + ChapPrintPkt, + NULL, + 1, + "CHAP", + NULL, + chap_option_list, + NULL, + NULL, + NULL +}; + +chap_state chap[NUM_PPP]; /* CHAP state; one for each unit */ + +static void ChapChallengeTimeout __P((void *)); +static void ChapResponseTimeout __P((void *)); +static void ChapReceiveChallenge __P((chap_state *, u_char *, int, int)); +static void ChapRechallenge __P((void *)); +static void ChapReceiveResponse __P((chap_state *, u_char *, int, int)); +static void ChapReceiveSuccess __P((chap_state *, u_char *, int, int)); +static void ChapReceiveFailure __P((chap_state *, u_char *, int, int)); +static void ChapSendStatus __P((chap_state *, int)); +static void ChapSendChallenge __P((chap_state *)); +static void ChapSendResponse __P((chap_state *)); +static void ChapGenChallenge __P((chap_state *)); + +extern double drand48 __P((void)); +extern void srand48 __P((long)); + +/* + * ChapInit - Initialize a CHAP unit. + */ +static void +ChapInit(unit) + int unit; +{ + chap_state *cstate = &chap[unit]; + + BZERO(cstate, sizeof(*cstate)); + cstate->unit = unit; + cstate->clientstate = CHAPCS_INITIAL; + cstate->serverstate = CHAPSS_INITIAL; + cstate->timeouttime = CHAP_DEFTIMEOUT; + cstate->max_transmits = CHAP_DEFTRANSMITS; + /* random number generator is initialized in magic_init */ +} + + +/* + * ChapAuthWithPeer - Authenticate us with our peer (start client). + * + */ +void +ChapAuthWithPeer(unit, our_name, digest) + int unit; + char *our_name; + int digest; +{ + chap_state *cstate = &chap[unit]; + + cstate->resp_name = our_name; + cstate->resp_type = digest; + + if (cstate->clientstate == CHAPCS_INITIAL || + cstate->clientstate == CHAPCS_PENDING) { + /* lower layer isn't up - wait until later */ + cstate->clientstate = CHAPCS_PENDING; + return; + } + + /* + * We get here as a result of LCP coming up. + * So even if CHAP was open before, we will + * have to re-authenticate ourselves. + */ + cstate->clientstate = CHAPCS_LISTEN; +} + + +/* + * ChapAuthPeer - Authenticate our peer (start server). + */ +void +ChapAuthPeer(unit, our_name, digest) + int unit; + char *our_name; + int digest; +{ + chap_state *cstate = &chap[unit]; + + cstate->chal_name = our_name; + cstate->chal_type = digest; + + if (cstate->serverstate == CHAPSS_INITIAL || + cstate->serverstate == CHAPSS_PENDING) { + /* lower layer isn't up - wait until later */ + cstate->serverstate = CHAPSS_PENDING; + return; + } + + ChapGenChallenge(cstate); + ChapSendChallenge(cstate); /* crank it up dude! */ + cstate->serverstate = CHAPSS_INITIAL_CHAL; +} + + +/* + * ChapChallengeTimeout - Timeout expired on sending challenge. + */ +static void +ChapChallengeTimeout(arg) + void *arg; +{ + chap_state *cstate = (chap_state *) arg; + + /* if we aren't sending challenges, don't worry. then again we */ + /* probably shouldn't be here either */ + if (cstate->serverstate != CHAPSS_INITIAL_CHAL && + cstate->serverstate != CHAPSS_RECHALLENGE) + return; + + if (cstate->chal_transmits >= cstate->max_transmits) { + /* give up on peer */ + error("Peer failed to respond to CHAP challenge"); + cstate->serverstate = CHAPSS_BADAUTH; + auth_peer_fail(cstate->unit, PPP_CHAP); + return; + } + + ChapSendChallenge(cstate); /* Re-send challenge */ +} + + +/* + * ChapResponseTimeout - Timeout expired on sending response. + */ +static void +ChapResponseTimeout(arg) + void *arg; +{ + chap_state *cstate = (chap_state *) arg; + + /* if we aren't sending a response, don't worry. */ + if (cstate->clientstate != CHAPCS_RESPONSE) + return; + + ChapSendResponse(cstate); /* re-send response */ +} + + +/* + * ChapRechallenge - Time to challenge the peer again. + */ +static void +ChapRechallenge(arg) + void *arg; +{ + chap_state *cstate = (chap_state *) arg; + + /* if we aren't sending a response, don't worry. */ + if (cstate->serverstate != CHAPSS_OPEN) + return; + + ChapGenChallenge(cstate); + ChapSendChallenge(cstate); + cstate->serverstate = CHAPSS_RECHALLENGE; +} + + +/* + * ChapLowerUp - The lower layer is up. + * + * Start up if we have pending requests. + */ +static void +ChapLowerUp(unit) + int unit; +{ + chap_state *cstate = &chap[unit]; + + if (cstate->clientstate == CHAPCS_INITIAL) + cstate->clientstate = CHAPCS_CLOSED; + else if (cstate->clientstate == CHAPCS_PENDING) + cstate->clientstate = CHAPCS_LISTEN; + + if (cstate->serverstate == CHAPSS_INITIAL) + cstate->serverstate = CHAPSS_CLOSED; + else if (cstate->serverstate == CHAPSS_PENDING) { + ChapGenChallenge(cstate); + ChapSendChallenge(cstate); + cstate->serverstate = CHAPSS_INITIAL_CHAL; + } +} + + +/* + * ChapLowerDown - The lower layer is down. + * + * Cancel all timeouts. + */ +static void +ChapLowerDown(unit) + int unit; +{ + chap_state *cstate = &chap[unit]; + + /* Timeout(s) pending? Cancel if so. */ + if (cstate->serverstate == CHAPSS_INITIAL_CHAL || + cstate->serverstate == CHAPSS_RECHALLENGE) + UNTIMEOUT(ChapChallengeTimeout, cstate); + else if (cstate->serverstate == CHAPSS_OPEN + && cstate->chal_interval != 0) + UNTIMEOUT(ChapRechallenge, cstate); + if (cstate->clientstate == CHAPCS_RESPONSE) + UNTIMEOUT(ChapResponseTimeout, cstate); + + cstate->clientstate = CHAPCS_INITIAL; + cstate->serverstate = CHAPSS_INITIAL; +} + + +/* + * ChapProtocolReject - Peer doesn't grok CHAP. + */ +static void +ChapProtocolReject(unit) + int unit; +{ + chap_state *cstate = &chap[unit]; + + if (cstate->serverstate != CHAPSS_INITIAL && + cstate->serverstate != CHAPSS_CLOSED) + auth_peer_fail(unit, PPP_CHAP); + if (cstate->clientstate != CHAPCS_INITIAL && + cstate->clientstate != CHAPCS_CLOSED) + auth_withpeer_fail(unit, PPP_CHAP); + ChapLowerDown(unit); /* shutdown chap */ +} + + +/* + * ChapInput - Input CHAP packet. + */ +static void +ChapInput(unit, inpacket, packet_len) + int unit; + u_char *inpacket; + int packet_len; +{ + chap_state *cstate = &chap[unit]; + u_char *inp; + u_char code, id; + int len; + + /* + * Parse header (code, id and length). + * If packet too short, drop it. + */ + inp = inpacket; + if (packet_len < CHAP_HEADERLEN) { + CHAPDEBUG(("ChapInput: rcvd short header.")); + return; + } + GETCHAR(code, inp); + GETCHAR(id, inp); + GETSHORT(len, inp); + if (len < CHAP_HEADERLEN) { + CHAPDEBUG(("ChapInput: rcvd illegal length.")); + return; + } + if (len > packet_len) { + CHAPDEBUG(("ChapInput: rcvd short packet.")); + return; + } + len -= CHAP_HEADERLEN; + + /* + * Action depends on code (as in fact it usually does :-). + */ + switch (code) { + case CHAP_CHALLENGE: + ChapReceiveChallenge(cstate, inp, id, len); + break; + + case CHAP_RESPONSE: + ChapReceiveResponse(cstate, inp, id, len); + break; + + case CHAP_FAILURE: + ChapReceiveFailure(cstate, inp, id, len); + break; + + case CHAP_SUCCESS: + ChapReceiveSuccess(cstate, inp, id, len); + break; + + default: /* Need code reject? */ + warn("Unknown CHAP code (%d) received.", code); + break; + } +} + + +/* + * ChapReceiveChallenge - Receive Challenge and send Response. + */ +static void +ChapReceiveChallenge(cstate, inp, id, len) + chap_state *cstate; + u_char *inp; + int id; + int len; +{ + int rchallenge_len; + u_char *rchallenge; + int secret_len; + char secret[MAXSECRETLEN]; + char rhostname[256]; + MD5_CTX mdContext; + u_char hash[MD5_SIGNATURE_SIZE]; + + if (cstate->clientstate == CHAPCS_CLOSED || + cstate->clientstate == CHAPCS_PENDING) { + CHAPDEBUG(("ChapReceiveChallenge: in state %d", cstate->clientstate)); + return; + } + + if (len < 2) { + CHAPDEBUG(("ChapReceiveChallenge: rcvd short packet.")); + return; + } + + GETCHAR(rchallenge_len, inp); + len -= sizeof (u_char) + rchallenge_len; /* now name field length */ + if (len < 0) { + CHAPDEBUG(("ChapReceiveChallenge: rcvd short packet.")); + return; + } + rchallenge = inp; + INCPTR(rchallenge_len, inp); + + if (len >= sizeof(rhostname)) + len = sizeof(rhostname) - 1; + BCOPY(inp, rhostname, len); + rhostname[len] = '\000'; + + /* Microsoft doesn't send their name back in the PPP packet */ + if (explicit_remote || (remote_name[0] != 0 && rhostname[0] == 0)) { + strlcpy(rhostname, remote_name, sizeof(rhostname)); + CHAPDEBUG(("ChapReceiveChallenge: using '%q' as remote name", + rhostname)); + } + + /* get secret for authenticating ourselves with the specified host */ + if (!get_secret(cstate->unit, cstate->resp_name, rhostname, + secret, &secret_len, 0)) { + secret_len = 0; /* assume null secret if can't find one */ + warn("No CHAP secret found for authenticating us to %q", rhostname); + } + + /* cancel response send timeout if necessary */ + if (cstate->clientstate == CHAPCS_RESPONSE) + UNTIMEOUT(ChapResponseTimeout, cstate); + + cstate->resp_id = id; + cstate->resp_transmits = 0; + + /* generate MD based on negotiated type */ + switch (cstate->resp_type) { + + case CHAP_DIGEST_MD5: + MD5Init(&mdContext); + MD5Update(&mdContext, &cstate->resp_id, 1); + MD5Update(&mdContext, secret, secret_len); + MD5Update(&mdContext, rchallenge, rchallenge_len); + MD5Final(hash, &mdContext); + BCOPY(hash, cstate->response, MD5_SIGNATURE_SIZE); + cstate->resp_length = MD5_SIGNATURE_SIZE; + break; + +#ifdef CHAPMS + case CHAP_MICROSOFT: + ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len); + break; +#endif + + default: + CHAPDEBUG(("unknown digest type %d", cstate->resp_type)); + return; + } + + BZERO(secret, sizeof(secret)); + ChapSendResponse(cstate); +} + + +/* + * ChapReceiveResponse - Receive and process response. + */ +static void +ChapReceiveResponse(cstate, inp, id, len) + chap_state *cstate; + u_char *inp; + int id; + int len; +{ + u_char *remmd, remmd_len; + int secret_len, old_state; + int code; + char rhostname[256]; + MD5_CTX mdContext; + char secret[MAXSECRETLEN]; + u_char hash[MD5_SIGNATURE_SIZE]; + + if (cstate->serverstate == CHAPSS_CLOSED || + cstate->serverstate == CHAPSS_PENDING) { + CHAPDEBUG(("ChapReceiveResponse: in state %d", cstate->serverstate)); + return; + } + + if (id != cstate->chal_id) + return; /* doesn't match ID of last challenge */ + + /* + * If we have received a duplicate or bogus Response, + * we have to send the same answer (Success/Failure) + * as we did for the first Response we saw. + */ + if (cstate->serverstate == CHAPSS_OPEN) { + ChapSendStatus(cstate, CHAP_SUCCESS); + return; + } + if (cstate->serverstate == CHAPSS_BADAUTH) { + ChapSendStatus(cstate, CHAP_FAILURE); + return; + } + + if (len < 2) { + CHAPDEBUG(("ChapReceiveResponse: rcvd short packet.")); + return; + } + GETCHAR(remmd_len, inp); /* get length of MD */ + remmd = inp; /* get pointer to MD */ + INCPTR(remmd_len, inp); + + len -= sizeof (u_char) + remmd_len; + if (len < 0) { + CHAPDEBUG(("ChapReceiveResponse: rcvd short packet.")); + return; + } + + UNTIMEOUT(ChapChallengeTimeout, cstate); + + if (len >= sizeof(rhostname)) + len = sizeof(rhostname) - 1; + BCOPY(inp, rhostname, len); + rhostname[len] = '\000'; + + /* + * Get secret for authenticating them with us, + * do the hash ourselves, and compare the result. + */ + code = CHAP_FAILURE; + if (!get_secret(cstate->unit, (explicit_remote? remote_name: rhostname), + cstate->chal_name, secret, &secret_len, 1)) { + warn("No CHAP secret found for authenticating %q", rhostname); + } else { + + /* generate MD based on negotiated type */ + switch (cstate->chal_type) { + + case CHAP_DIGEST_MD5: /* only MD5 is defined for now */ + if (remmd_len != MD5_SIGNATURE_SIZE) + break; /* it's not even the right length */ + MD5Init(&mdContext); + MD5Update(&mdContext, &cstate->chal_id, 1); + MD5Update(&mdContext, secret, secret_len); + MD5Update(&mdContext, cstate->challenge, cstate->chal_len); + MD5Final(hash, &mdContext); + + /* compare local and remote MDs and send the appropriate status */ + if (memcmp (hash, remmd, MD5_SIGNATURE_SIZE) == 0) + code = CHAP_SUCCESS; /* they are the same! */ + break; + + default: + CHAPDEBUG(("unknown digest type %d", cstate->chal_type)); + } + } + + BZERO(secret, sizeof(secret)); + ChapSendStatus(cstate, code); + + if (code == CHAP_SUCCESS) { + old_state = cstate->serverstate; + cstate->serverstate = CHAPSS_OPEN; + if (old_state == CHAPSS_INITIAL_CHAL) { + auth_peer_success(cstate->unit, PPP_CHAP, rhostname, len); + } + if (cstate->chal_interval != 0) + TIMEOUT(ChapRechallenge, cstate, cstate->chal_interval); + notice("CHAP peer authentication succeeded for %q", rhostname); + + } else { + error("CHAP peer authentication failed for remote host %q", rhostname); + cstate->serverstate = CHAPSS_BADAUTH; + auth_peer_fail(cstate->unit, PPP_CHAP); + } +} + +/* + * ChapReceiveSuccess - Receive Success + */ +static void +ChapReceiveSuccess(cstate, inp, id, len) + chap_state *cstate; + u_char *inp; + u_char id; + int len; +{ + + if (cstate->clientstate == CHAPCS_OPEN) + /* presumably an answer to a duplicate response */ + return; + + if (cstate->clientstate != CHAPCS_RESPONSE) { + /* don't know what this is */ + CHAPDEBUG(("ChapReceiveSuccess: in state %d\n", cstate->clientstate)); + return; + } + + UNTIMEOUT(ChapResponseTimeout, cstate); + + /* + * Print message. + */ + if (len > 0) + PRINTMSG(inp, len); + + cstate->clientstate = CHAPCS_OPEN; + + auth_withpeer_success(cstate->unit, PPP_CHAP); +} + + +/* + * ChapReceiveFailure - Receive failure. + */ +static void +ChapReceiveFailure(cstate, inp, id, len) + chap_state *cstate; + u_char *inp; + u_char id; + int len; +{ + if (cstate->clientstate != CHAPCS_RESPONSE) { + /* don't know what this is */ + CHAPDEBUG(("ChapReceiveFailure: in state %d\n", cstate->clientstate)); + return; + } + + UNTIMEOUT(ChapResponseTimeout, cstate); + + /* + * Print message. + */ + if (len > 0) + PRINTMSG(inp, len); + + error("CHAP authentication failed"); + auth_withpeer_fail(cstate->unit, PPP_CHAP); +} + + +/* + * ChapSendChallenge - Send an Authenticate challenge. + */ +static void +ChapSendChallenge(cstate) + chap_state *cstate; +{ + u_char *outp; + int chal_len, name_len; + int outlen; + + chal_len = cstate->chal_len; + name_len = strlen(cstate->chal_name); + outlen = CHAP_HEADERLEN + sizeof (u_char) + chal_len + name_len; + outp = outpacket_buf; + + MAKEHEADER(outp, PPP_CHAP); /* paste in a CHAP header */ + + PUTCHAR(CHAP_CHALLENGE, outp); + PUTCHAR(cstate->chal_id, outp); + PUTSHORT(outlen, outp); + + PUTCHAR(chal_len, outp); /* put length of challenge */ + BCOPY(cstate->challenge, outp, chal_len); + INCPTR(chal_len, outp); + + BCOPY(cstate->chal_name, outp, name_len); /* append hostname */ + + output(cstate->unit, outpacket_buf, outlen + PPP_HDRLEN); + + TIMEOUT(ChapChallengeTimeout, cstate, cstate->timeouttime); + ++cstate->chal_transmits; +} + + +/* + * ChapSendStatus - Send a status response (ack or nak). + */ +static void +ChapSendStatus(cstate, code) + chap_state *cstate; + int code; +{ + u_char *outp; + int outlen, msglen; + char msg[256]; + + if (code == CHAP_SUCCESS) + slprintf(msg, sizeof(msg), "Welcome to %s.", hostname); + else + slprintf(msg, sizeof(msg), "I don't like you. Go 'way."); + msglen = strlen(msg); + + outlen = CHAP_HEADERLEN + msglen; + outp = outpacket_buf; + + MAKEHEADER(outp, PPP_CHAP); /* paste in a header */ + + PUTCHAR(code, outp); + PUTCHAR(cstate->chal_id, outp); + PUTSHORT(outlen, outp); + BCOPY(msg, outp, msglen); + output(cstate->unit, outpacket_buf, outlen + PPP_HDRLEN); +} + +/* + * ChapGenChallenge is used to generate a pseudo-random challenge string of + * a pseudo-random length between min_len and max_len. The challenge + * string and its length are stored in *cstate, and various other fields of + * *cstate are initialized. + */ + +static void +ChapGenChallenge(cstate) + chap_state *cstate; +{ + int chal_len; + u_char *ptr = cstate->challenge; + int i; + + /* pick a random challenge length between MIN_CHALLENGE_LENGTH and + MAX_CHALLENGE_LENGTH */ + chal_len = (unsigned) ((drand48() * + (MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH)) + + MIN_CHALLENGE_LENGTH); + cstate->chal_len = chal_len; + cstate->chal_id = ++cstate->id; + cstate->chal_transmits = 0; + + /* generate a random string */ + for (i = 0; i < chal_len; i++) + *ptr++ = (char) (drand48() * 0xff); +} + +/* + * ChapSendResponse - send a response packet with values as specified + * in *cstate. + */ +/* ARGSUSED */ +static void +ChapSendResponse(cstate) + chap_state *cstate; +{ + u_char *outp; + int outlen, md_len, name_len; + + md_len = cstate->resp_length; + name_len = strlen(cstate->resp_name); + outlen = CHAP_HEADERLEN + sizeof (u_char) + md_len + name_len; + outp = outpacket_buf; + + MAKEHEADER(outp, PPP_CHAP); + + PUTCHAR(CHAP_RESPONSE, outp); /* we are a response */ + PUTCHAR(cstate->resp_id, outp); /* copy id from challenge packet */ + PUTSHORT(outlen, outp); /* packet length */ + + PUTCHAR(md_len, outp); /* length of MD */ + BCOPY(cstate->response, outp, md_len); /* copy MD to buffer */ + INCPTR(md_len, outp); + + BCOPY(cstate->resp_name, outp, name_len); /* append our name */ + + /* send the packet */ + output(cstate->unit, outpacket_buf, outlen + PPP_HDRLEN); + + cstate->clientstate = CHAPCS_RESPONSE; + TIMEOUT(ChapResponseTimeout, cstate, cstate->timeouttime); + ++cstate->resp_transmits; +} + +/* + * ChapPrintPkt - print the contents of a CHAP packet. + */ +static char *ChapCodenames[] = { + "Challenge", "Response", "Success", "Failure" +}; + +static int +ChapPrintPkt(p, plen, printer, arg) + u_char *p; + int plen; + void (*printer) __P((void *, char *, ...)); + void *arg; +{ + int code, id, len; + int clen, nlen; + u_char x; + + if (plen < CHAP_HEADERLEN) + return 0; + GETCHAR(code, p); + GETCHAR(id, p); + GETSHORT(len, p); + if (len < CHAP_HEADERLEN || len > plen) + return 0; + + if (code >= 1 && code <= sizeof(ChapCodenames) / sizeof(char *)) + printer(arg, " %s", ChapCodenames[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= CHAP_HEADERLEN; + switch (code) { + case CHAP_CHALLENGE: + case CHAP_RESPONSE: + if (len < 1) + break; + clen = p[0]; + if (len < clen + 1) + break; + ++p; + nlen = len - clen - 1; + printer(arg, " <"); + for (; clen > 0; --clen) { + GETCHAR(x, p); + printer(arg, "%.2x", x); + } + printer(arg, ">, name = "); + print_string((char *)p, nlen, printer, arg); + break; + case CHAP_FAILURE: + case CHAP_SUCCESS: + printer(arg, " "); + print_string((char *)p, len, printer, arg); + break; + default: + for (clen = len; clen > 0; --clen) { + GETCHAR(x, p); + printer(arg, " %.2x", x); + } + } + + return len + CHAP_HEADERLEN; +} diff -urN ppp-2.4.1/pppd/chap.h ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/chap.h --- ppp-2.4.1/pppd/chap.h Sun Nov 14 20:44:41 1999 +++ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/chap.h Tue Nov 5 20:00:52 2002 @@ -46,11 +46,13 @@ #define MD5_SIGNATURE_SIZE 16 /* 16 bytes in a MD5 message digest */ #define CHAP_MICROSOFT 0x80 /* use Microsoft-compatible alg. */ #define MS_CHAP_RESPONSE_LEN 49 /* Response length for MS-CHAP */ +#define CHAP_MICROSOFT_V2 0x81 /* use MS-CHAP v2 */ #define CHAP_CHALLENGE 1 #define CHAP_RESPONSE 2 #define CHAP_SUCCESS 3 #define CHAP_FAILURE 4 +#define CHAP_SUCCESS_R 13 /* Send response, not text message */ /* * Challenge lengths (for challenges we send) and other limits. @@ -117,6 +119,9 @@ void ChapAuthWithPeer __P((int, char *, int)); void ChapAuthPeer __P((int, char *, int)); +void ChapGenChallenge __P((chap_state *)); + +int reqchap(char **); extern struct protent chap_protent; Binary files ppp-2.4.1/pppd/chap.o and ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/chap.o differ diff -urN ppp-2.4.1/pppd/chap_ms.c ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/chap_ms.c --- ppp-2.4.1/pppd/chap_ms.c Fri Aug 13 02:46:12 1999 +++ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/chap_ms.c Tue Nov 5 20:00:52 2002 @@ -49,11 +49,13 @@ #include "pppd.h" #include "chap.h" #include "chap_ms.h" -#include "md4.h" - -#ifndef USE_CRYPT -#include +#include +#include "fsm.h" +#include "lcp.h" +#ifdef MPPE +#include "mppe.h" #endif +#include "extra_crypto.h" static const char rcsid[] = RCSID; @@ -65,21 +67,19 @@ /* We use MS_CHAP_RESPONSE_LEN, rather than sizeof(MS_ChapResponse), in case this struct gets padded. */ +typedef struct { + u_char PeerChallenge[16]; + u_char Reserved[8]; + u_char NTResp[24]; + u_char Flags; +} MS_ChapResponse_v2; static void ChallengeResponse __P((u_char *, u_char *, u_char *)); -static void DesEncrypt __P((u_char *, u_char *, u_char *)); -static void MakeKey __P((u_char *, u_char *)); -static u_char Get7Bits __P((u_char *, int)); static void ChapMS_NT __P((char *, int, char *, int, MS_ChapResponse *)); #ifdef MSLANMAN static void ChapMS_LANMan __P((char *, int, char *, int, MS_ChapResponse *)); #endif -#ifdef USE_CRYPT -static void Expand __P((u_char *, u_char *)); -static void Collapse __P((u_char *, u_char *)); -#endif - #ifdef MSLANMAN bool ms_lanman = 0; /* Use LanMan password instead of NT */ /* Has meaning only with MS-CHAP challenges */ @@ -110,142 +110,6 @@ #endif } - -#ifdef USE_CRYPT -static void -DesEncrypt(clear, key, cipher) - u_char *clear; /* IN 8 octets */ - u_char *key; /* IN 7 octets */ - u_char *cipher; /* OUT 8 octets */ -{ - u_char des_key[8]; - u_char crypt_key[66]; - u_char des_input[66]; - - MakeKey(key, des_key); - - Expand(des_key, crypt_key); - setkey(crypt_key); - -#if 0 - CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %.8B", clear)); -#endif - - Expand(clear, des_input); - encrypt(des_input, 0); - Collapse(des_input, cipher); - -#if 0 - CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %.8B", cipher)); -#endif -} - -#else /* USE_CRYPT */ - -static void -DesEncrypt(clear, key, cipher) - u_char *clear; /* IN 8 octets */ - u_char *key; /* IN 7 octets */ - u_char *cipher; /* OUT 8 octets */ -{ - des_cblock des_key; - des_key_schedule key_schedule; - - MakeKey(key, des_key); - - des_set_key(&des_key, key_schedule); - -#if 0 - CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %.8B", clear)); -#endif - - des_ecb_encrypt((des_cblock *)clear, (des_cblock *)cipher, key_schedule, 1); - -#if 0 - CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %.8B", cipher)); -#endif -} - -#endif /* USE_CRYPT */ - - -static u_char Get7Bits(input, startBit) - u_char *input; - int startBit; -{ - register unsigned int word; - - word = (unsigned)input[startBit / 8] << 8; - word |= (unsigned)input[startBit / 8 + 1]; - - word >>= 15 - (startBit % 8 + 7); - - return word & 0xFE; -} - -#ifdef USE_CRYPT - -/* in == 8-byte string (expanded version of the 56-bit key) - * out == 64-byte string where each byte is either 1 or 0 - * Note that the low-order "bit" is always ignored by by setkey() - */ -static void Expand(in, out) - u_char *in; - u_char *out; -{ - int j, c; - int i; - - for(i = 0; i < 64; in++){ - c = *in; - for(j = 7; j >= 0; j--) - *out++ = (c >> j) & 01; - i += 8; - } -} - -/* The inverse of Expand - */ -static void Collapse(in, out) - u_char *in; - u_char *out; -{ - int j; - int i; - unsigned int c; - - for (i = 0; i < 64; i += 8, out++) { - c = 0; - for (j = 7; j >= 0; j--, in++) - c |= *in << j; - *out = c & 0xff; - } -} -#endif - -static void MakeKey(key, des_key) - u_char *key; /* IN 56 bit DES key missing parity bits */ - u_char *des_key; /* OUT 64 bit DES key with parity bits added */ -{ - des_key[0] = Get7Bits(key, 0); - des_key[1] = Get7Bits(key, 7); - des_key[2] = Get7Bits(key, 14); - des_key[3] = Get7Bits(key, 21); - des_key[4] = Get7Bits(key, 28); - des_key[5] = Get7Bits(key, 35); - des_key[6] = Get7Bits(key, 42); - des_key[7] = Get7Bits(key, 49); - -#ifndef USE_CRYPT - des_set_odd_parity((des_cblock *)des_key); -#endif - -#if 0 - CHAPDEBUG((LOG_INFO, "MakeKey: 56-bit input : %.7B", key)); - CHAPDEBUG((LOG_INFO, "MakeKey: 64-bit output: %.8B", des_key)); -#endif -} - static void ChapMS_NT(rchallenge, rchallenge_len, secret, secret_len, response) char *rchallenge; @@ -254,34 +118,13 @@ int secret_len; MS_ChapResponse *response; { - int i; -#ifdef __NetBSD__ - /* NetBSD uses the libc md4 routines which take bytes instead of bits */ - int mdlen = secret_len * 2; -#else - int mdlen = secret_len * 2 * 8; -#endif - MD4_CTX md4Context; u_char hash[MD4_SIGNATURE_SIZE]; - u_char unicodePassword[MAX_NT_PASSWORD * 2]; - - /* Initialize the Unicode version of the secret (== password). */ - /* This implicitly supports 8-bit ISO8859/1 characters. */ - BZERO(unicodePassword, sizeof(unicodePassword)); - for (i = 0; i < secret_len; i++) - unicodePassword[i * 2] = (u_char)secret[i]; - - MD4Init(&md4Context); - MD4Update(&md4Context, unicodePassword, mdlen); - - MD4Final(hash, &md4Context); /* Tell MD4 we're done */ + NtPasswordHash(secret, secret_len, hash); ChallengeResponse(rchallenge, hash, response->NTResp); } #ifdef MSLANMAN -static u_char *StdText = (u_char *)"KGS!@#$%"; /* key from rasapi32.dll */ - static void ChapMS_LANMan(rchallenge, rchallenge_len, secret, secret_len, response) char *rchallenge; @@ -290,16 +133,9 @@ int secret_len; MS_ChapResponse *response; { - int i; - u_char UcasePassword[MAX_NT_PASSWORD]; /* max is actually 14 */ u_char PasswordHash[MD4_SIGNATURE_SIZE]; - /* LANMan password is case insensitive */ - BZERO(UcasePassword, sizeof(UcasePassword)); - for (i = 0; i < secret_len; i++) - UcasePassword[i] = (u_char)toupper(secret[i]); - DesEncrypt( StdText, UcasePassword + 0, PasswordHash + 0 ); - DesEncrypt( StdText, UcasePassword + 7, PasswordHash + 8 ); + LmPasswordHash(secret, secret_len, PasswordHash); ChallengeResponse(rchallenge, PasswordHash, response->LANManResp); } #endif @@ -331,8 +167,209 @@ response.UseNT = 1; #endif +#ifdef MPPE + mppe_gen_master_key(secret, secret_len, rchallenge); +#endif + BCOPY(&response, cstate->response, MS_CHAP_RESPONSE_LEN); + cstate->resp_length = MS_CHAP_RESPONSE_LEN; +} + +int +ChapMS_Resp(cstate, secret, secret_len, remmd) + chap_state *cstate; + char *secret; + int secret_len; + u_char *remmd; +{ + MS_ChapResponse local; + MS_ChapResponse *response = (MS_ChapResponse *)remmd; + int i; + + BZERO(&local, sizeof(response)); + + if(response->UseNT) + { + ChapMS_NT(cstate->challenge,cstate->chal_len, secret, secret_len, &local); + i = memcmp(local.NTResp, response->NTResp, sizeof(local.NTResp)); + +#ifdef MPPE + if(i == 0) + mppe_gen_master_key(secret, secret_len, cstate->challenge); +#endif + return(i); + } + +#ifdef MSLANMAN + ChapMS_LANMan(cstate->challenge, cstate->chal_len, secret, secret_len, + &local); + if(memcmp(local.LANManResp, response->LANManResp, + sizeof(local.LANManResp)) == 0) { +#ifdef MPPE + mppe_gen_master_key(secret, secret_len, cstate->challenge); +#endif + return(0); + } +#endif /* MSLANMAN */ + return(1); +} + +void +ChallengeHash(PeerChallenge, AuthenticatorChallenge, UserName, Challenge) + char *PeerChallenge; + char *AuthenticatorChallenge; + char *UserName; + char *Challenge; +{ + SHA_CTX Context; + u_char Digest[SHA_DIGEST_LENGTH]; + char *username; + + if((username = strrchr(UserName, '\\')) != (char *)NULL) + ++username; + else + username = UserName; + SHA1_Init(&Context); + SHA1_Update(&Context, PeerChallenge, 16); + SHA1_Update(&Context, AuthenticatorChallenge, 16); + SHA1_Update(&Context, username, strlen(username)); + SHA1_Final(Digest, &Context); + BCOPY(Digest, Challenge, 8); +} + +void +ChapMS_v2(cstate, AuthenticatorChallenge, AuthenticatorChallengeLen, Password, PasswordLen) + chap_state *cstate; + char *AuthenticatorChallenge; + int AuthenticatorChallengeLen; + char *Password; + int PasswordLen; +{ + u_char Challenge[8]; + u_char PasswordHash[MD4_SIGNATURE_SIZE]; + MS_ChapResponse_v2 response; + + BZERO(&response, sizeof(response)); + ChapGenChallenge(cstate); + BCOPY(cstate->challenge, response.PeerChallenge, + sizeof(response.PeerChallenge)); + ChallengeHash(response.PeerChallenge, AuthenticatorChallenge, + cstate->resp_name, Challenge); + NtPasswordHash(Password, PasswordLen, PasswordHash); + ChallengeResponse(Challenge, PasswordHash, response.NTResp); BCOPY(&response, cstate->response, MS_CHAP_RESPONSE_LEN); cstate->resp_length = MS_CHAP_RESPONSE_LEN; +#ifdef MPPE + mppe_gen_master_key_v2(Password, PasswordLen, response.NTResp, 0); +#endif +} + +int +ChapMS_v2_Resp(cstate, Password, PasswordLen, remmd, UserName) + chap_state *cstate; + char *Password; + int PasswordLen; + u_char *remmd; + char *UserName; +{ + u_char Challenge[8]; + u_char PasswordHash[MD4_SIGNATURE_SIZE]; + MS_ChapResponse_v2 response, response1; + int i; + + BCOPY(remmd, &response, MS_CHAP_RESPONSE_LEN); + ChallengeHash(response.PeerChallenge,cstate->challenge,UserName,Challenge); + NtPasswordHash(Password, PasswordLen, PasswordHash); + ChallengeResponse(Challenge, PasswordHash, response1.NTResp); + i = memcmp(response.NTResp, response1.NTResp, sizeof(response.NTResp)); +#ifdef MPPE + if(i == 0) + mppe_gen_master_key_v2(Password, PasswordLen, response1.NTResp, 1); +#endif + return(i); +} + +void +ChapMS_v2_Auth(cstate, Password, PasswordLen, remmd, UserName) + chap_state *cstate; + char *Password; + int PasswordLen; + u_char *remmd; + char *UserName; +{ + u_char PasswordHash[MD4_SIGNATURE_SIZE]; + u_char PasswordHashHash[MD4_SIGNATURE_SIZE]; + u_char Challenge[8]; + static char Magic1[] = "Magic server to client signing constant"; + static char Magic2[] = "Pad to make it do more than one iteration"; + + SHA_CTX Context; + u_char Digest[SHA_DIGEST_LENGTH]; + MS_ChapResponse_v2 *response = (MS_ChapResponse_v2 *)remmd; + char StrResponse[SHA_DIGEST_LENGTH * 2 + 3], *s; + int i; + static char HexDigs[] = "0123456789ABCDEF"; + + NtPasswordHash(Password, PasswordLen, PasswordHash); + md4(PasswordHash, sizeof(PasswordHash), PasswordHashHash); + + SHA1_Init(&Context); + SHA1_Update(&Context, PasswordHashHash, 16); + SHA1_Update(&Context, response->NTResp, 24); + SHA1_Update(&Context, Magic1, sizeof(Magic1) - 1); + SHA1_Final(Digest, &Context); + + ChallengeHash(response->PeerChallenge,cstate->challenge,UserName,Challenge); + + SHA1_Init(&Context); + SHA1_Update(&Context, Digest, SHA_DIGEST_LENGTH); + SHA1_Update(&Context, Challenge, 8); + SHA1_Update(&Context, Magic2, sizeof(Magic2) - 1); + SHA1_Final(Digest, &Context); + s = stpcpy(StrResponse, "S="); + for(i = 0; i < SHA_DIGEST_LENGTH; ++i) { + *s++ = HexDigs[Digest[i] >> 4]; + *s++ = HexDigs[Digest[i] & 0x0F]; + } + *s = '\0'; + BCOPY(StrResponse, cstate->response, sizeof(StrResponse)); + cstate->resp_length = sizeof(StrResponse) - 1; +} + +/* + * functions called from config options + */ +int +reqchapms(char **argv) +{ + lcp_wantoptions[0].neg_chap = 1; + lcp_wantoptions[0].use_chapms = 1; + auth_required = 1; + + return 1; +} + +int +nochapms(char **argv) +{ + lcp_wantoptions[0].use_chapms = 0; + return 1; +} + +int +reqchapms_v2(char **argv) +{ + lcp_wantoptions[0].neg_chap = 1; + lcp_wantoptions[0].use_chapms_v2 = 1; + auth_required = 1; + + return 1; +} + +int +nochapms_v2(char **argv) +{ + lcp_wantoptions[0].use_chapms_v2 = 0; + return 1; } #endif /* CHAPMS */ diff -urN ppp-2.4.1/pppd/chap_ms.h ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/chap_ms.h --- ppp-2.4.1/pppd/chap_ms.h Sat Nov 7 01:55:39 1998 +++ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/chap_ms.h Tue Nov 5 20:00:52 2002 @@ -24,10 +24,16 @@ #ifndef __CHAPMS_INCLUDE__ -#define MD4_SIGNATURE_SIZE 16 /* 16 bytes in a MD4 message digest */ -#define MAX_NT_PASSWORD 256 /* Maximum number of (Unicode) chars in an NT password */ - void ChapMS __P((chap_state *, char *, int, char *, int)); +int ChapMS_Resp __P((chap_state *, char *, int, u_char *)); +void ChapMS_v2 __P((chap_state *, char *, int, char *, int)); +int ChapMS_v2_Resp __P((chap_state *, char *, int, u_char *, char *)); +void ChapMS_v2_Auth __P((chap_state *, char *, int, u_char *, char *)); + +int reqchapms(char **); +int nochapms(char **); +int reqchapms_v2(char **); +int nochapms_v2(char **); #define __CHAPMS_INCLUDE__ #endif /* __CHAPMS_INCLUDE__ */ Binary files ppp-2.4.1/pppd/chap_ms.o and ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/chap_ms.o differ Binary files ppp-2.4.1/pppd/demand.o and ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/demand.o differ diff -urN ppp-2.4.1/pppd/extra_crypto.c ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/extra_crypto.c --- ppp-2.4.1/pppd/extra_crypto.c Wed Dec 31 19:00:00 1969 +++ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/extra_crypto.c Tue Nov 5 20:10:38 2002 @@ -0,0 +1,206 @@ +/* + * Copyright (c) Tim Hockin, Cobalt Networks Inc. and others + * + * crypto routines used by multiple c files + */ +#include +#include +#include +#include +#include +#include "extra_crypto.h" +#include "pppd.h" +#include "md4.h" +#ifndef USE_CRYPT +#include +#endif + +/* quick wrapper for easy md4 */ +void +md4(unsigned char *from, int from_len, unsigned char *to) +{ + MD4_CTX Context; + +#ifndef __NetBSD__ + from_len <<= 3; /* bytes->bits */ +#endif + + MD4Init(&Context); + MD4Update(&Context, from, from_len); + MD4Final(to, &Context); +} + + +/* Microsoft LANMAN Password hashing */ +static u_char *MSStdText = (u_char *)"KGS!@#$%"; /* key from rasapi32.dll */ + +void +LmPasswordHash(char *password, int len, char *hash) +{ + int i; + u_char up_pass[MAX_NT_PASSWORD]; /* max is actually 14 */ + + /* LANMan password is case insensitive */ + BZERO(up_pass, sizeof(up_pass)); + for (i = 0; i < len; i++) + up_pass[i] = (u_char)toupper(up_pass[i]); + DesEncrypt(MSStdText, up_pass + 0, hash + 0); + DesEncrypt(MSStdText, up_pass + 7, hash + 8); +} + +#ifdef JES +/* From libsmb - From SAMBA */ +/************************************************************* + Routine to get the 32 hex characters and turn them + into a 16 byte array. +**************************************************************/ + +int gethexpwd(unsigned char *p, unsigned char *pwd) +{ + int i; + unsigned char lonybble, hinybble; + char *hexchars = "0123456789ABCDEF"; + char *p1, *p2; + + for (i = 0; i < 32; i += 2) { + hinybble = toupper(p[i]); + lonybble = toupper(p[i + 1]); + + p1 = strchr(hexchars, hinybble); + p2 = strchr(hexchars, lonybble); + + if (!p1 || !p2) { + return (0); + } + hinybble = (p1 - hexchars); + lonybble = (p2 - hexchars); + + pwd[i / 2] = (hinybble << 4) | lonybble; + } + return (1); +} + +#endif + + + +void +NtPasswordHash(char *secret, int secret_len, unsigned char *hash) +{ + int i; + u_char unicodePassword[MAX_NT_PASSWORD * 2]; + + /* Initialize the Unicode version of the secret (== password). */ + /* This implicitly supports 8-bit ISO8859/1 characters. */ +#ifdef JES + if(secret_len != 32) { +#endif + BZERO(unicodePassword, sizeof(unicodePassword)); + for (i = 0; i < secret_len; i++) + unicodePassword[i * 2] = (u_char)secret[i]; + + /* Unicode is 2 bytes per char */ + md4(unicodePassword, secret_len * 2, hash); +#ifdef JES + } else { + gethexpwd(secret, hash); + } +#endif +} + + +static u_char Get7Bits(unsigned char *input, int startBit) +{ + register unsigned int word; + + word = (unsigned)input[startBit / 8] << 8; + word |= (unsigned)input[startBit / 8 + 1]; + + word >>= 15 - (startBit % 8 + 7); + + return word & 0xFE; +} + + +static void MakeKey(unsigned char *key, unsigned char *des_key) +{ + des_key[0] = Get7Bits(key, 0); + des_key[1] = Get7Bits(key, 7); + des_key[2] = Get7Bits(key, 14); + des_key[3] = Get7Bits(key, 21); + des_key[4] = Get7Bits(key, 28); + des_key[5] = Get7Bits(key, 35); + des_key[6] = Get7Bits(key, 42); + des_key[7] = Get7Bits(key, 49); + +#ifndef USE_CRYPT + des_set_odd_parity((des_cblock *)des_key); +#endif +} + + +#ifdef USE_CRYPT +/* in == 8-byte string (expanded version of the 56-bit key) + * out == 64-byte string where each byte is either 1 or 0 + * Note that the low-order "bit" is always ignored by by setkey() + */ +static void Expand(unsigned char *in, unsigned char *out) +{ + int j, c; + int i; + + for(i = 0; i < 64; in++){ + c = *in; + for(j = 7; j >= 0; j--) + *out++ = (c >> j) & 01; + i += 8; + } +} + +/* The inverse of Expand + */ +static void Collapse(unsigned char *in, unsigned char *out) +{ + int j; + int i; + unsigned int c; + + for (i = 0; i < 64; i += 8, out++) { + c = 0; + for (j = 7; j >= 0; j--, in++) + c |= *in << j; + *out = c & 0xff; + } +} +void +DesEncrypt(unsigned char *clear, unsigned char *key, unsigned char *cipher) +{ + u_char des_key[8]; + u_char crypt_key[66]; + u_char des_input[66]; + + MakeKey(key, des_key); + + Expand(des_key, crypt_key); + setkey(crypt_key); + + Expand(clear, des_input); + encrypt(des_input, 0); + Collapse(des_input, cipher); +} +#else /* don't USE_CRYPT */ +void +DesEncrypt(unsigned char *clear, unsigned char *key, unsigned char *cipher) +{ + des_cblock des_key; + des_key_schedule key_schedule; + + MakeKey(key, des_key); + + des_set_key(&des_key, key_schedule); + + des_ecb_encrypt((des_cblock *)clear, (des_cblock *)cipher, key_schedule, 1); +} +#endif /* USE_CRYPT */ + + diff -urN ppp-2.4.1/pppd/extra_crypto.h ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/extra_crypto.h --- ppp-2.4.1/pppd/extra_crypto.h Wed Dec 31 19:00:00 1969 +++ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/extra_crypto.h Tue Nov 5 20:00:52 2002 @@ -0,0 +1,16 @@ +#ifndef __EXTRA_CRYPTO_INCLUDE__ +/* + * This is just a bunch of crypto routines that are needed by more than one + * piece of functionality, so they were broken out + */ + +void md4 __P((unsigned char *, int, unsigned char *)); +void LmPasswordHash __P((char *, int, char *)); +void NtPasswordHash __P((char *, int, unsigned char *)); +void DesEncrypt __P((unsigned char *, unsigned char *, unsigned char *)); + +#define MAX_NT_PASSWORD 256 /* Max len of a (Unicode) NT passwd */ +#define MD4_SIGNATURE_SIZE 16 /* 16 bytes in a MD4 message digest */ + +#define __EXTRA_CRYPTO_INCLUDE__ +#endif /* __EXTRA_CRYPTO_INCLUDE__ */ Binary files ppp-2.4.1/pppd/extra_crypto.o and ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/extra_crypto.o differ Binary files ppp-2.4.1/pppd/fsm.o and ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/fsm.o differ diff -urN ppp-2.4.1/pppd/ipcp.c ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/ipcp.c --- ppp-2.4.1/pppd/ipcp.c Thu Mar 8 00:11:12 2001 +++ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/ipcp.c Tue Nov 5 20:00:52 2002 @@ -148,6 +148,8 @@ { "ms-dns", 1, (void *)setdnsaddr, "DNS address for the peer's use" }, + { "dns-addr", 1, setdnsaddr, + "DNS address for the peer's use" }, { "ms-wins", 1, (void *)setwinsaddr, "Nameserver for SMB over TCP/IP for peer" }, @@ -1258,6 +1260,14 @@ */ GETLONG(tl, p); /* Parse source address (his) */ ciaddr1 = htonl(tl); +#ifdef DYNAMIC + if(!auth_ip_addr(f->unit, ciaddr1)) + if(get_ip_addr_dynamic(f->unit, &tl)) + { + wo->hisaddr = tl; + ciaddr1 = 0; + } +#endif if (ciaddr1 != wo->hisaddr && (ciaddr1 == 0 || !wo->accept_remote)) { orc = CONFNAK; @@ -1315,6 +1325,14 @@ */ GETLONG(tl, p); /* Parse source address (his) */ ciaddr1 = htonl(tl); +#ifdef DYNAMIC + if(!auth_ip_addr(f->unit, ciaddr1)) + if(get_ip_addr_dynamic(f->unit, &tl)) + { + wo->hisaddr = tl; + ciaddr1 = 0; + } +#endif if (ciaddr1 != wo->hisaddr && (ciaddr1 == 0 || !wo->accept_remote)) { orc = CONFNAK; Binary files ppp-2.4.1/pppd/ipcp.o and ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/ipcp.o differ Binary files ppp-2.4.1/pppd/ipxcp.o and ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/ipxcp.o differ diff -urN ppp-2.4.1/pppd/lcp.c ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/lcp.c --- ppp-2.4.1/pppd/lcp.c Thu Mar 8 00:11:14 2001 +++ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/lcp.c Tue Nov 5 20:00:52 2002 @@ -35,6 +35,8 @@ static const char rcsid[] = RCSID; +extern bool refuse_chap; + /* * When the link comes up we want to be able to wait for a short while, * or until seeing some input from the peer, before starting to send @@ -327,7 +329,18 @@ wo->neg_mru = 1; wo->mru = DEFMRU; wo->neg_asyncmap = 1; - wo->chap_mdtype = CHAP_DIGEST_MD5; + wo->use_digest = 1; +#ifdef CHAPMS + if(wo->use_chapms_v2) + wo->chap_mdtype = CHAP_MICROSOFT_V2; + else if(wo->use_chapms) + wo->chap_mdtype = CHAP_MICROSOFT; + else +#endif + if(wo->use_digest) + wo->chap_mdtype = CHAP_DIGEST_MD5; + else + refuse_chap = 1; wo->neg_magicnumber = 1; wo->neg_pcompression = 1; wo->neg_accompression = 1; @@ -337,7 +350,20 @@ ao->mru = MAXMRU; ao->neg_asyncmap = 1; ao->neg_chap = 1; - ao->chap_mdtype = CHAP_DIGEST_MD5; + ao->use_digest = 1; +#ifdef CHAPMS + ao->use_chapms_v2 = ao->use_chapms = 1; + if(ao->use_chapms_v2) + ao->chap_mdtype = CHAP_MICROSOFT_V2; + else if(ao->use_chapms) + ao->chap_mdtype = CHAP_MICROSOFT; + else +#else + if(ao->use_digest) + ao->chap_mdtype = CHAP_DIGEST_MD5; + else + refuse_chap = 1; +#endif ao->neg_upap = 1; ao->neg_magicnumber = 1; ao->neg_pcompression = 1; @@ -639,6 +665,18 @@ * NB: we only ask for one of CHAP and UPAP, even if we will * accept either. */ +#ifdef CHAPMS + if(go->use_chapms_v2) + go->chap_mdtype = CHAP_MICROSOFT_V2; + else if(go->use_chapms) + go->chap_mdtype = CHAP_MICROSOFT; + else +#endif + if(go->use_digest) + go->chap_mdtype = CHAP_DIGEST_MD5; + else + go->neg_chap = 0; + return (LENCISHORT(go->neg_mru && go->mru != DEFMRU) + LENCILONG(go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) + LENCICHAP(go->neg_chap) + @@ -1055,14 +1093,35 @@ * if we support it, otherwise we'll have to stop * asking for CHAP. */ - if (cichar != go->chap_mdtype) { -#ifdef CHAPMS - if (cichar == CHAP_MICROSOFT) - go->chap_mdtype = CHAP_MICROSOFT; - else -#endif /* CHAPMS */ + if (go->chap_mdtype == CHAP_MICROSOFT_V2) + { + try.use_chapms_v2 = 0; + if(try.use_chapms) + try.chap_mdtype = CHAP_MICROSOFT; + else if(try.use_digest) + try.chap_mdtype = CHAP_DIGEST_MD5; + else + try.neg_chap = 0; + } + else if(go->chap_mdtype == CHAP_MICROSOFT) + { + try.use_chapms = 0; + if(try.use_digest) + try.chap_mdtype = CHAP_DIGEST_MD5; + else + try.neg_chap = 0; + } + else if(go->chap_mdtype == CHAP_DIGEST_MD5) + { + try.use_digest = 0; + try.neg_chap = 0; + } + else + try.neg_chap = 0; + if ((cichar != CHAP_MICROSOFT_V2) && + (cichar != CHAP_MICROSOFT) && + (cichar != CHAP_DIGEST_MD5)) try.neg_chap = 0; - } } else { /* * Stop asking for PAP if we were asking for it. @@ -1306,8 +1365,22 @@ /* Check rejected value. */ \ if (cishort != val || cichar != digest) \ goto bad; \ - try.neg = 0; \ - try.neg_upap = 0; \ + switch(digest) \ + { \ + case CHAP_MICROSOFT_V2: \ + try.use_chapms_v2 = 0; \ + break; \ + case CHAP_MICROSOFT: \ + try.use_chapms = 0; \ + break; \ + case CHAP_DIGEST_MD5: \ + try.use_digest = 0; \ + } \ + if(!try.use_chapms_v2 && !try.use_chapms && !try.use_digest) \ + { \ + try.neg = 0; \ + try.neg_upap = 0; \ + } \ } #define REJCILONG(opt, neg, val) \ if (go->neg && \ @@ -1567,9 +1640,10 @@ if (cichar != CHAP_DIGEST_MD5 #ifdef CHAPMS && cichar != CHAP_MICROSOFT + && cichar != CHAP_MICROSOFT_V2 #endif ) { - orc = CONFNAK; + orc = CONFREJ; /* !!! CONFNAK !!! */ PUTCHAR(CI_AUTHTYPE, nakp); PUTCHAR(CILEN_CHAP, nakp); PUTSHORT(PPP_CHAP, nakp); @@ -1646,6 +1720,23 @@ ho->magicnumber = cilong; break; +#ifdef CBCP_SUPPORT + case CI_CALLBACK: + LCPDEBUG(("lcp_reqci: rcvd CBCP")); + if (!ao->neg_cbcp || + cilen != CILEN_CHAR) { + orc = CONFREJ; + break; + } + GETCHAR(cichar, p); + if(cichar != CBCP_OPT) + { + orc = CONFREJ; + break; + } + ho->neg_cbcp = 1; + break; +#endif case CI_PCOMPRESSION: if (!ao->neg_pcompression || @@ -1965,20 +2056,23 @@ } } break; +#ifdef CBCP_SUPPORT case CI_CALLBACK: - if (olen >= CILEN_CHAR) { + if (olen == CILEN_CHAR) { + u_char cichar; p += 2; printer(arg, "callback "); - GETCHAR(cishort, p); - switch (cishort) { + GETCHAR(cichar, p); + switch (cichar) { case CBCP_OPT: printer(arg, "CBCP"); break; default: - printer(arg, "0x%x", cishort); + printer(arg, "0x%x", cichar); } } break; +#endif case CI_MAGICNUMBER: if (olen == CILEN_LONG) { p += 2; diff -urN ppp-2.4.1/pppd/lcp.h ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/lcp.h --- ppp-2.4.1/pppd/lcp.h Thu Mar 8 00:11:14 2001 +++ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/lcp.h Tue Nov 5 20:00:52 2002 @@ -59,6 +59,9 @@ bool neg_accompression; /* HDLC Address/Control Field Compression? */ bool neg_lqr; /* Negotiate use of Link Quality Reports */ bool neg_cbcp; /* Negotiate use of CBCP */ + bool use_digest; + bool use_chapms; + bool use_chapms_v2; bool neg_mrru; /* negotiate multilink MRRU */ bool neg_ssnhf; /* negotiate short sequence numbers */ bool neg_endpoint; /* negotiate endpoint discriminator */ Binary files ppp-2.4.1/pppd/lcp.o and ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/lcp.o differ Binary files ppp-2.4.1/pppd/magic.o and ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/magic.o differ Binary files ppp-2.4.1/pppd/main.o and ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/main.o differ diff -urN ppp-2.4.1/pppd/md32_common.h ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/md32_common.h --- ppp-2.4.1/pppd/md32_common.h Wed Dec 31 19:00:00 1969 +++ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/md32_common.h Tue Nov 5 20:00:52 2002 @@ -0,0 +1,607 @@ +/* crypto/md32_common.h */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +/* + * This is a generic 32 bit "collector" for message digest algorithms. + * Whenever needed it collects input character stream into chunks of + * 32 bit values and invokes a block function that performs actual hash + * calculations. + * + * Porting guide. + * + * Obligatory macros: + * + * DATA_ORDER_IS_BIG_ENDIAN or DATA_ORDER_IS_LITTLE_ENDIAN + * this macro defines byte order of input stream. + * HASH_CBLOCK + * size of a unit chunk HASH_BLOCK operates on. + * HASH_LONG + * has to be at lest 32 bit wide, if it's wider, then + * HASH_LONG_LOG2 *has to* be defined along + * HASH_CTX + * context structure that at least contains following + * members: + * typedef struct { + * ... + * HASH_LONG Nl,Nh; + * HASH_LONG data[HASH_LBLOCK]; + * int num; + * ... + * } HASH_CTX; + * HASH_UPDATE + * name of "Update" function, implemented here. + * HASH_TRANSFORM + * name of "Transform" function, implemented here. + * HASH_FINAL + * name of "Final" function, implemented here. + * HASH_BLOCK_HOST_ORDER + * name of "block" function treating *aligned* input message + * in host byte order, implemented externally. + * HASH_BLOCK_DATA_ORDER + * name of "block" function treating *unaligned* input message + * in original (data) byte order, implemented externally (it + * actually is optional if data and host are of the same + * "endianess"). + * HASH_MAKE_STRING + * macro convering context variables to an ASCII hash string. + * + * Optional macros: + * + * B_ENDIAN or L_ENDIAN + * defines host byte-order. + * HASH_LONG_LOG2 + * defaults to 2 if not states otherwise. + * HASH_LBLOCK + * assumed to be HASH_CBLOCK/4 if not stated otherwise. + * HASH_BLOCK_DATA_ORDER_ALIGNED + * alternative "block" function capable of treating + * aligned input message in original (data) order, + * implemented externally. + * + * MD5 example: + * + * #define DATA_ORDER_IS_LITTLE_ENDIAN + * + * #define HASH_LONG MD5_LONG + * #define HASH_LONG_LOG2 MD5_LONG_LOG2 + * #define HASH_CTX MD5_CTX + * #define HASH_CBLOCK MD5_CBLOCK + * #define HASH_LBLOCK MD5_LBLOCK + * #define HASH_UPDATE MD5_Update + * #define HASH_TRANSFORM MD5_Transform + * #define HASH_FINAL MD5_Final + * #define HASH_BLOCK_HOST_ORDER md5_block_host_order + * #define HASH_BLOCK_DATA_ORDER md5_block_data_order + * + * + */ + +#if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN) +#error "DATA_ORDER must be defined!" +#endif + +#ifndef HASH_CBLOCK +#error "HASH_CBLOCK must be defined!" +#endif +#ifndef HASH_LONG +#error "HASH_LONG must be defined!" +#endif +#ifndef HASH_CTX +#error "HASH_CTX must be defined!" +#endif + +#ifndef HASH_UPDATE +#error "HASH_UPDATE must be defined!" +#endif +#ifndef HASH_TRANSFORM +#error "HASH_TRANSFORM must be defined!" +#endif +#ifndef HASH_FINAL +#error "HASH_FINAL must be defined!" +#endif + +#ifndef HASH_BLOCK_HOST_ORDER +#error "HASH_BLOCK_HOST_ORDER must be defined!" +#endif + +#if 0 +/* + * Moved below as it's required only if HASH_BLOCK_DATA_ORDER_ALIGNED + * isn't defined. + */ +#ifndef HASH_BLOCK_DATA_ORDER +#error "HASH_BLOCK_DATA_ORDER must be defined!" +#endif +#endif + +#ifndef HASH_LBLOCK +#define HASH_LBLOCK (HASH_CBLOCK/4) +#endif + +#ifndef HASH_LONG_LOG2 +#define HASH_LONG_LOG2 2 +#endif + +/* + * Engage compiler specific rotate intrinsic function if available. + */ +#undef ROTATE +#ifndef PEDANTIC +# if defined(_MSC_VER) +# define ROTATE(a,n) _lrotl(a,n) +# elif defined(__MWERKS__) +# if defined(__POWERPC__) +# define ROTATE(a,n) __rlwinm(a,n,0,31) +# elif defined(__MC68K__) + /* Motorola specific tweak. */ +# define ROTATE(a,n) ( n<24 ? __rol(a,n) : __ror(a,32-n) ) +# else +# define ROTATE(a,n) __rol(a,n) +# endif +# elif defined(__GNUC__) && __GNUC__>=2 && !defined(NO_ASM) && !defined(NO_INLINE_ASM) + /* + * Some GNU C inline assembler templates. Note that these are + * rotates by *constant* number of bits! But that's exactly + * what we need here... + * + * + */ +# if defined(__i386) +# define ROTATE(a,n) ({ register unsigned int ret; \ + asm ( \ + "roll %1,%0" \ + : "=r"(ret) \ + : "I"(n), "0"(a) \ + : "cc"); \ + ret; \ + }) +# elif defined(__powerpc) || defined(__ppc) +# define ROTATE(a,n) ({ register unsigned int ret; \ + asm ( \ + "rlwinm %0,%1,%2,0,31" \ + : "=r"(ret) \ + : "r"(a), "I"(n)); \ + ret; \ + }) +# endif +# endif + +/* + * Engage compiler specific "fetch in reverse byte order" + * intrinsic function if available. + */ +# if defined(__GNUC__) && __GNUC__>=2 && !defined(NO_ASM) && !defined(NO_INLINE_ASM) + /* some GNU C inline assembler templates by */ +# if defined(__i386) && !defined(I386_ONLY) +# define BE_FETCH32(a) ({ register unsigned int l=(a);\ + asm ( \ + "bswapl %0" \ + : "=r"(l) : "0"(l)); \ + l; \ + }) +# elif defined(__powerpc) +# define LE_FETCH32(a) ({ register unsigned int l; \ + asm ( \ + "lwbrx %0,0,%1" \ + : "=r"(l) \ + : "r"(a)); \ + l; \ + }) + +# elif defined(__sparc) && defined(ULTRASPARC) +# define LE_FETCH32(a) ({ register unsigned int l; \ + asm ( \ + "lda [%1]#ASI_PRIMARY_LITTLE,%0"\ + : "=r"(l) \ + : "r"(a)); \ + l; \ + }) +# endif +# endif +#endif /* PEDANTIC */ + +#if HASH_LONG_LOG2==2 /* Engage only if sizeof(HASH_LONG)== 4 */ +/* A nice byte order reversal from Wei Dai */ +#ifdef ROTATE +/* 5 instructions with rotate instruction, else 9 */ +#define REVERSE_FETCH32(a,l) ( \ + l=*(const HASH_LONG *)(a), \ + ((ROTATE(l,8)&0x00FF00FF)|(ROTATE((l&0x00FF00FF),24))) \ + ) +#else +/* 6 instructions with rotate instruction, else 8 */ +#define REVERSE_FETCH32(a,l) ( \ + l=*(const HASH_LONG *)(a), \ + l=(((l>>8)&0x00FF00FF)|((l&0x00FF00FF)<<8)), \ + ROTATE(l,16) \ + ) +/* + * Originally the middle line started with l=(((l&0xFF00FF00)>>8)|... + * It's rewritten as above for two reasons: + * - RISCs aren't good at long constants and have to explicitely + * compose 'em with several (well, usually 2) instructions in a + * register before performing the actual operation and (as you + * already realized:-) having same constant should inspire the + * compiler to permanently allocate the only register for it; + * - most modern CPUs have two ALUs, but usually only one has + * circuitry for shifts:-( this minor tweak inspires compiler + * to schedule shift instructions in a better way... + * + * + */ +#endif +#endif + +#ifndef ROTATE +#define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n)))) +#endif + +/* + * Make some obvious choices. E.g., HASH_BLOCK_DATA_ORDER_ALIGNED + * and HASH_BLOCK_HOST_ORDER ought to be the same if input data + * and host are of the same "endianess". It's possible to mask + * this with blank #define HASH_BLOCK_DATA_ORDER though... + * + * + */ +#if defined(B_ENDIAN) +# if defined(DATA_ORDER_IS_BIG_ENDIAN) +# if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2 +# define HASH_BLOCK_DATA_ORDER_ALIGNED HASH_BLOCK_HOST_ORDER +# endif +# elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) +# ifndef HOST_FETCH32 +# ifdef LE_FETCH32 +# define HOST_FETCH32(p,l) LE_FETCH32(p) +# elif defined(REVERSE_FETCH32) +# define HOST_FETCH32(p,l) REVERSE_FETCH32(p,l) +# endif +# endif +# endif +#elif defined(L_ENDIAN) +# if defined(DATA_ORDER_IS_LITTLE_ENDIAN) +# if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2 +# define HASH_BLOCK_DATA_ORDER_ALIGNED HASH_BLOCK_HOST_ORDER +# endif +# elif defined(DATA_ORDER_IS_BIG_ENDIAN) +# ifndef HOST_FETCH32 +# ifdef BE_FETCH32 +# define HOST_FETCH32(p,l) BE_FETCH32(p) +# elif defined(REVERSE_FETCH32) +# define HOST_FETCH32(p,l) REVERSE_FETCH32(p,l) +# endif +# endif +# endif +#endif + +#if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) +#ifndef HASH_BLOCK_DATA_ORDER +#error "HASH_BLOCK_DATA_ORDER must be defined!" +#endif +#endif + +#if defined(DATA_ORDER_IS_BIG_ENDIAN) + +#define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++)))<<24), \ + l|=(((unsigned long)(*((c)++)))<<16), \ + l|=(((unsigned long)(*((c)++)))<< 8), \ + l|=(((unsigned long)(*((c)++))) ), \ + l) +#define HOST_p_c2l(c,l,n) { \ + switch (n) { \ + case 0: l =((unsigned long)(*((c)++)))<<24; \ + case 1: l|=((unsigned long)(*((c)++)))<<16; \ + case 2: l|=((unsigned long)(*((c)++)))<< 8; \ + case 3: l|=((unsigned long)(*((c)++))); \ + } } +#define HOST_p_c2l_p(c,l,sc,len) { \ + switch (sc) { \ + case 0: l =((unsigned long)(*((c)++)))<<24; \ + if (--len == 0) break; \ + case 1: l|=((unsigned long)(*((c)++)))<<16; \ + if (--len == 0) break; \ + case 2: l|=((unsigned long)(*((c)++)))<< 8; \ + } } +/* NOTE the pointer is not incremented at the end of this */ +#define HOST_c2l_p(c,l,n) { \ + l=0; (c)+=n; \ + switch (n) { \ + case 3: l =((unsigned long)(*(--(c))))<< 8; \ + case 2: l|=((unsigned long)(*(--(c))))<<16; \ + case 1: l|=((unsigned long)(*(--(c))))<<24; \ + } } +#define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff), \ + l) + +#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) + +#define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++))) ), \ + l|=(((unsigned long)(*((c)++)))<< 8), \ + l|=(((unsigned long)(*((c)++)))<<16), \ + l|=(((unsigned long)(*((c)++)))<<24), \ + l) +#define HOST_p_c2l(c,l,n) { \ + switch (n) { \ + case 0: l =((unsigned long)(*((c)++))); \ + case 1: l|=((unsigned long)(*((c)++)))<< 8; \ + case 2: l|=((unsigned long)(*((c)++)))<<16; \ + case 3: l|=((unsigned long)(*((c)++)))<<24; \ + } } +#define HOST_p_c2l_p(c,l,sc,len) { \ + switch (sc) { \ + case 0: l =((unsigned long)(*((c)++))); \ + if (--len == 0) break; \ + case 1: l|=((unsigned long)(*((c)++)))<< 8; \ + if (--len == 0) break; \ + case 2: l|=((unsigned long)(*((c)++)))<<16; \ + } } +/* NOTE the pointer is not incremented at the end of this */ +#define HOST_c2l_p(c,l,n) { \ + l=0; (c)+=n; \ + switch (n) { \ + case 3: l =((unsigned long)(*(--(c))))<<16; \ + case 2: l|=((unsigned long)(*(--(c))))<< 8; \ + case 1: l|=((unsigned long)(*(--(c)))); \ + } } +#define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24)&0xff), \ + l) + +#endif + +/* + * Time for some action:-) + */ + +void HASH_UPDATE (HASH_CTX *c, const void *data_, unsigned long len) + { + const unsigned char *data=data_; + register HASH_LONG * p; + register unsigned long l; + int sw,sc,ew,ec; + + if (len==0) return; + + l=(c->Nl+(len<<3))&0xffffffffL; + /* 95-05-24 eay Fixed a bug with the overflow handling, thanks to + * Wei Dai for pointing it out. */ + if (l < c->Nl) /* overflow */ + c->Nh++; + c->Nh+=(len>>29); + c->Nl=l; + + if (c->num != 0) + { + p=c->data; + sw=c->num>>2; + sc=c->num&0x03; + + if ((c->num+len) >= HASH_CBLOCK) + { + l=p[sw]; HOST_p_c2l(data,l,sc); p[sw++]=l; + for (; swnum); + c->num=0; + /* drop through and do the rest */ + } + else + { + c->num+=len; + if ((sc+len) < 4) /* ugly, add char's to a word */ + { + l=p[sw]; HOST_p_c2l_p(data,l,sc,len); p[sw]=l; + } + else + { + ew=(c->num>>2); + ec=(c->num&0x03); + l=p[sw]; HOST_p_c2l(data,l,sc); p[sw++]=l; + for (; sw < ew; sw++) + { + HOST_c2l(data,l); p[sw]=l; + } + if (ec) + { + HOST_c2l_p(data,l,ec); p[sw]=l; + } + } + return; + } + } + + sw=len/HASH_CBLOCK; + if (sw > 0) + { +#if defined(HASH_BLOCK_DATA_ORDER_ALIGNED) + /* + * Note that HASH_BLOCK_DATA_ORDER_ALIGNED gets defined + * only if sizeof(HASH_LONG)==4. + */ + if ((((unsigned long)data)%4) == 0) + { + /* data is properly aligned so that we can cast it: */ + HASH_BLOCK_DATA_ORDER_ALIGNED (c,(HASH_LONG *)data,sw); + sw*=HASH_CBLOCK; + data+=sw; + len-=sw; + } + else +#if !defined(HASH_BLOCK_DATA_ORDER) + while (sw--) + { + memcpy (p=c->data,data,HASH_CBLOCK); + HASH_BLOCK_DATA_ORDER_ALIGNED(c,p,1); + data+=HASH_CBLOCK; + len-=HASH_CBLOCK; + } +#endif +#endif +#if defined(HASH_BLOCK_DATA_ORDER) + { + HASH_BLOCK_DATA_ORDER(c,data,sw); + sw*=HASH_CBLOCK; + data+=sw; + len-=sw; + } +#endif + } + + if (len!=0) + { + p = c->data; + c->num = len; + ew=len>>2; /* words to copy */ + ec=len&0x03; + for (; ew; ew--,p++) + { + HOST_c2l(data,l); *p=l; + } + HOST_c2l_p(data,l,ec); + *p=l; + } + } + + +void HASH_TRANSFORM (HASH_CTX *c, const unsigned char *data) + { +#if defined(HASH_BLOCK_DATA_ORDER_ALIGNED) + if ((((unsigned long)data)%4) == 0) + /* data is properly aligned so that we can cast it: */ + HASH_BLOCK_DATA_ORDER_ALIGNED (c,(HASH_LONG *)data,1); + else +#if !defined(HASH_BLOCK_DATA_ORDER) + { + memcpy (c->data,data,HASH_CBLOCK); + HASH_BLOCK_DATA_ORDER_ALIGNED (c,c->data,1); + } +#endif +#endif +#if defined(HASH_BLOCK_DATA_ORDER) + HASH_BLOCK_DATA_ORDER (c,data,1); +#endif + } + + +void HASH_FINAL (unsigned char *md, HASH_CTX *c) + { + register HASH_LONG *p; + register unsigned long l; + register int i,j; + static const unsigned char end[4]={0x80,0x00,0x00,0x00}; + const unsigned char *cp=end; + + /* c->num should definitly have room for at least one more byte. */ + p=c->data; + i=c->num>>2; + j=c->num&0x03; + +#if 0 + /* purify often complains about the following line as an + * Uninitialized Memory Read. While this can be true, the + * following p_c2l macro will reset l when that case is true. + * This is because j&0x03 contains the number of 'valid' bytes + * already in p[i]. If and only if j&0x03 == 0, the UMR will + * occur but this is also the only time p_c2l will do + * l= *(cp++) instead of l|= *(cp++) + * Many thanks to Alex Tang for pickup this + * 'potential bug' */ +#ifdef PURIFY + if (j==0) p[i]=0; /* Yeah, but that's not the way to fix it:-) */ +#endif + l=p[i]; +#else + l = (j==0) ? 0 : p[i]; +#endif + HOST_p_c2l(cp,l,j); p[i++]=l; /* i is the next 'undefined word' */ + + if (i>(HASH_LBLOCK-2)) /* save room for Nl and Nh */ + { + if (iNh; + p[HASH_LBLOCK-1]=c->Nl; +#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) + p[HASH_LBLOCK-2]=c->Nl; + p[HASH_LBLOCK-1]=c->Nh; +#endif + HASH_BLOCK_HOST_ORDER (c,p,1); + +#ifndef HASH_MAKE_STRING +#error "HASH_MAKE_STRING must be defined!" +#else + HASH_MAKE_STRING(c,md); +#endif + + c->num=0; + /* clear stuff, HASH_BLOCK may be leaving some stuff on the stack + * but I'm not worried :-) + memset((void *)c,0,sizeof(HASH_CTX)); + */ + } Binary files ppp-2.4.1/pppd/md4.o and ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/md4.o differ Binary files ppp-2.4.1/pppd/md5.o and ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/md5.o differ diff -urN ppp-2.4.1/pppd/mppe.c ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/mppe.c --- ppp-2.4.1/pppd/mppe.c Wed Dec 31 19:00:00 1969 +++ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/mppe.c Tue Nov 5 20:01:07 2002 @@ -0,0 +1,246 @@ +/* + * mppe - Mucking with PpP Encription + * + * Copyright (c) 1995 Árpád Magossányi + * All rights reserved. + * + * Copyright (c) 1999 Tim Hockin, Cobalt Networks Inc. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Pedro Roque Marques. The name of the author may not be used to + * endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifdef MPPE + +#include +#include +#include +#include +#include +#include +#include +#include "pppd.h" +#include "chap.h" +#include "fsm.h" +#include "ccp.h" +#include "md4.h" +#include +#include "chap_ms.h" +#include "extra_crypto.h" + +static void +mppe_get_start_key __P((unsigned char *, unsigned char *, unsigned char *)); +static void +mppe_get_master_key __P((unsigned char *, unsigned char *, unsigned char *)); +static void +GetAsymetricStartKey __P((unsigned char *, unsigned char *, int, int, int)); + +unsigned char mppe_master_send_key_40[8]; +unsigned char mppe_master_recv_key_40[8]; +unsigned char mppe_master_send_key_128[16]; +unsigned char mppe_master_recv_key_128[16]; +unsigned int mppe_allowed = 0; + +/* + * Pads used in key derivation - from sha1dgst.c + */ +static unsigned 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}; +static unsigned 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 used with chap-ms (v1) */ +void +mppe_gen_master_key(char *secret, int secret_len, unsigned char *challenge) +{ + unsigned char PasswordHash[MD4_SIGNATURE_SIZE]; + unsigned char PasswordHashHash[MD4_SIGNATURE_SIZE]; + + /* 40 bit */ + LmPasswordHash(secret, secret_len, PasswordHash); + BCOPY(PasswordHash, mppe_master_send_key_40, 8); + BCOPY(mppe_master_send_key_40, mppe_master_recv_key_40, 8); + + /* 128 bit */ + NtPasswordHash(secret, secret_len, PasswordHash); + md4(PasswordHash, sizeof(PasswordHash), PasswordHashHash); + mppe_get_start_key(challenge, PasswordHashHash, mppe_master_send_key_128); + BCOPY(mppe_master_send_key_128, mppe_master_recv_key_128, 16); + + mppe_allowed = 1; +} + + +/* This is used with chap-ms-v2 (per MS' draft RFC) - 2 different keys */ +void +mppe_gen_master_key_v2(char *secret, int secret_len, unsigned char *response, + int is_server) +{ + unsigned char PasswordHash[MD4_SIGNATURE_SIZE]; + unsigned char PasswordHashHash[MD4_SIGNATURE_SIZE]; + unsigned char MasterKey[MD4_SIGNATURE_SIZE]; + + /* 128 bit - 2 keys */ + NtPasswordHash(secret, secret_len, PasswordHash); + md4(PasswordHash, sizeof(PasswordHash), PasswordHashHash); + mppe_get_master_key(PasswordHashHash, response, MasterKey); + GetAsymetricStartKey(MasterKey, mppe_master_send_key_128, 16,1, is_server); + GetAsymetricStartKey(MasterKey, mppe_master_recv_key_128, 16,0, is_server); + + /* 40 bit - 2 keys */ + BCOPY(mppe_master_send_key_128, mppe_master_send_key_40, 8); + BCOPY(mppe_master_recv_key_128, mppe_master_recv_key_40, 8); + + mppe_allowed = 1; +} + + +static void +mppe_get_start_key(unsigned char *Challenge, unsigned char *NtPasswordHashHash, + unsigned char *InitialSessionKey) +{ + unsigned char Digest[SHA_DIGEST_LENGTH]; + SHA_CTX Context; + + SHA1_Init(&Context); + SHA1_Update(&Context, NtPasswordHashHash, 16); + SHA1_Update(&Context, NtPasswordHashHash, 16); + SHA1_Update(&Context, Challenge, 8); + SHA1_Final(Digest, &Context); + BCOPY(Digest, InitialSessionKey, 16); +} + +static void +mppe_get_master_key(unsigned char *PasswordHashHash, unsigned char *NtResponse, + unsigned char *MasterKey) +{ + unsigned char Digest[SHA_DIGEST_LENGTH]; + SHA_CTX Context; + static char Magic1[] = "This is the MPPE Master Key"; + + BZERO(Digest, sizeof(Digest)); + + SHA1_Init(&Context); + SHA1_Update(&Context, PasswordHashHash, 16); + SHA1_Update(&Context, NtResponse, 24); + SHA1_Update(&Context, Magic1, sizeof(Magic1) - 1); + SHA1_Final(Digest, &Context); + + BCOPY(Digest, MasterKey, 16); +} + +static void +GetAsymetricStartKey(unsigned char *MasterKey, unsigned char *SessionKey, + int SessionKeyLength, int IsSend, int IsServer) +{ + unsigned char Digest[SHA_DIGEST_LENGTH]; + SHA_CTX Context; + char *s; + static char Magic2[] = "On the client side, this is the send key; on the server side, it is the receive key."; + static char Magic3[] = "On the client side, this is the receive key; on the server side, it is the send key."; + + BZERO(Digest, sizeof(Digest)); + if(IsSend) + { + if(IsServer) + s = Magic3; + else + s = Magic2; + } + else + { + if(IsServer) + s = Magic2; + else + s = Magic3; + } + + SHA1_Init(&Context); + SHA1_Update(&Context, MasterKey, 16); + SHA1_Update(&Context, SHApad1, 40); + SHA1_Update(&Context, s, 84); + SHA1_Update(&Context, SHApad2, 40); + SHA1_Final(Digest, &Context); + BCOPY(Digest, SessionKey, SessionKeyLength); +} + +/* + * Functions called from config options + */ +int +setmppe_40(char **argv) +{ + ccp_allowoptions[0].mppe = ccp_wantoptions[0].mppe = 1; + ccp_allowoptions[0].mppe_40 = ccp_wantoptions[0].mppe_40 = 1; + return 1; +} + +int +setnomppe_40(char **argv) +{ + ccp_allowoptions[0].mppe_40 = ccp_wantoptions[0].mppe_40 = 0; + return 1; +} + +int +setmppe_128(char **argv) +{ + ccp_allowoptions[0].mppe = ccp_wantoptions[0].mppe = 1; + ccp_allowoptions[0].mppe_128 = ccp_wantoptions[0].mppe_128 = 1; + return 1; +} + +int +setnomppe_128(char **argv) +{ + ccp_allowoptions[0].mppe_128 = ccp_wantoptions[0].mppe_128 = 0; + return 1; +} + +int +setmppe_stateless(char **argv) +{ + ccp_allowoptions[0].mppe_stateless = ccp_wantoptions[0].mppe_stateless = 1; + return 1; +} + +int +setnomppe_stateless(char **argv) +{ + ccp_allowoptions[0].mppe_stateless = ccp_wantoptions[0].mppe_stateless = 0; + return 1; +} + +int +require_mppe(char **argv) +{ + ccp_allowoptions[0].require_mppe = ccp_wantoptions[0].require_mppe = 1; + return 1; +} + +int +require_mppe_stateless(char **argv) +{ + ccp_allowoptions[0].require_mppe = ccp_wantoptions[0].require_mppe = 1; + ccp_allowoptions[0].require_mppe_stateless = ccp_wantoptions[0].require_mppe_stateless = 1; + return 1; +} + +#endif /* MPPE */ diff -urN ppp-2.4.1/pppd/mppe.c~ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/mppe.c~ --- ppp-2.4.1/pppd/mppe.c~ Wed Dec 31 19:00:00 1969 +++ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/mppe.c~ Tue Nov 5 20:00:52 2002 @@ -0,0 +1,230 @@ +/* + * mppe - Mucking with PpP Encription + * + * Copyright (c) 1995 Árpád Magossányi + * All rights reserved. + * + * Copyright (c) 1999 Tim Hockin, Cobalt Networks Inc. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Pedro Roque Marques. The name of the author may not be used to + * endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifdef MPPE + +#include +#include +#include +#include +#include +#include +#include +#include "pppd.h" +#include "chap.h" +#include "fsm.h" +#include "ccp.h" +#include "md4.h" +#include +#include "chap_ms.h" +#include "extra_crypto.h" + +static void +mppe_get_start_key __P((unsigned char *, unsigned char *, unsigned char *)); +static void +mppe_get_master_key __P((unsigned char *, unsigned char *, unsigned char *)); +static void +GetAsymetricStartKey __P((unsigned char *, unsigned char *, int, int, int)); + +unsigned char mppe_master_send_key_40[8]; +unsigned char mppe_master_recv_key_40[8]; +unsigned char mppe_master_send_key_128[16]; +unsigned char mppe_master_recv_key_128[16]; +unsigned int mppe_allowed = 0; + +/* + * Pads used in key derivation - from sha1dgst.c + */ +static unsigned 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}; +static unsigned 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 used with chap-ms (v1) */ +void +mppe_gen_master_key(char *secret, int secret_len, unsigned char *challenge) +{ + unsigned char PasswordHash[MD4_SIGNATURE_SIZE]; + unsigned char PasswordHashHash[MD4_SIGNATURE_SIZE]; + + /* 40 bit */ + LmPasswordHash(secret, secret_len, PasswordHash); + BCOPY(PasswordHash, mppe_master_send_key_40, 8); + BCOPY(mppe_master_send_key_40, mppe_master_recv_key_40, 8); + + /* 128 bit */ + NtPasswordHash(secret, secret_len, PasswordHash); + md4(PasswordHash, sizeof(PasswordHash), PasswordHashHash); + mppe_get_start_key(challenge, PasswordHashHash, mppe_master_send_key_128); + BCOPY(mppe_master_send_key_128, mppe_master_recv_key_128, 16); + + mppe_allowed = 1; +} + + +/* This is used with chap-ms-v2 (per MS' draft RFC) - 2 different keys */ +void +mppe_gen_master_key_v2(char *secret, int secret_len, unsigned char *response, + int is_server) +{ + unsigned char PasswordHash[MD4_SIGNATURE_SIZE]; + unsigned char PasswordHashHash[MD4_SIGNATURE_SIZE]; + unsigned char MasterKey[MD4_SIGNATURE_SIZE]; + + /* 128 bit - 2 keys */ + NtPasswordHash(secret, secret_len, PasswordHash); + md4(PasswordHash, sizeof(PasswordHash), PasswordHashHash); + mppe_get_master_key(PasswordHashHash, response, MasterKey); + GetAsymetricStartKey(MasterKey, mppe_master_send_key_128, 16,1, is_server); + GetAsymetricStartKey(MasterKey, mppe_master_recv_key_128, 16,0, is_server); + + /* 40 bit - 2 keys */ + BCOPY(mppe_master_send_key_128, mppe_master_send_key_40, 8); + BCOPY(mppe_master_recv_key_128, mppe_master_recv_key_40, 8); + + mppe_allowed = 1; +} + + +static void +mppe_get_start_key(unsigned char *Challenge, unsigned char *NtPasswordHashHash, + unsigned char *InitialSessionKey) +{ + unsigned char Digest[SHA_DIGEST_LENGTH]; + SHA_CTX Context; + + SHA1_Init(&Context); + SHA1_Update(&Context, NtPasswordHashHash, 16); + SHA1_Update(&Context, NtPasswordHashHash, 16); + SHA1_Update(&Context, Challenge, 8); + SHA1_Final(Digest, &Context); + BCOPY(Digest, InitialSessionKey, 16); +} + +static void +mppe_get_master_key(unsigned char *PasswordHashHash, unsigned char *NtResponse, + unsigned char *MasterKey) +{ + unsigned char Digest[SHA_DIGEST_LENGTH]; + SHA_CTX Context; + static char Magic1[] = "This is the MPPE Master Key"; + + BZERO(Digest, sizeof(Digest)); + + SHA1_Init(&Context); + SHA1_Update(&Context, PasswordHashHash, 16); + SHA1_Update(&Context, NtResponse, 24); + SHA1_Update(&Context, Magic1, sizeof(Magic1) - 1); + SHA1_Final(Digest, &Context); + + BCOPY(Digest, MasterKey, 16); +} + +static void +GetAsymetricStartKey(unsigned char *MasterKey, unsigned char *SessionKey, + int SessionKeyLength, int IsSend, int IsServer) +{ + unsigned char Digest[SHA_DIGEST_LENGTH]; + SHA_CTX Context; + char *s; + static char Magic2[] = "On the client side, this is the send key; on the server side, it is the receive key."; + static char Magic3[] = "On the client side, this is the receive key; on the server side, it is the send key."; + + BZERO(Digest, sizeof(Digest)); + if(IsSend) + { + if(IsServer) + s = Magic3; + else + s = Magic2; + } + else + { + if(IsServer) + s = Magic2; + else + s = Magic3; + } + + SHA1_Init(&Context); + SHA1_Update(&Context, MasterKey, 16); + SHA1_Update(&Context, SHApad1, 40); + SHA1_Update(&Context, s, 84); + SHA1_Update(&Context, SHApad2, 40); + SHA1_Final(Digest, &Context); + BCOPY(Digest, SessionKey, SessionKeyLength); +} + +/* + * Functions called from config options + */ +int +setmppe_40(char **argv) +{ + ccp_allowoptions[0].mppe = ccp_wantoptions[0].mppe = 1; + ccp_allowoptions[0].mppe_40 = ccp_wantoptions[0].mppe_40 = 1; + return 1; +} + +int +setnomppe_40(char **argv) +{ + ccp_allowoptions[0].mppe_40 = ccp_wantoptions[0].mppe_40 = 0; + return 1; +} + +int +setmppe_128(char **argv) +{ + ccp_allowoptions[0].mppe = ccp_wantoptions[0].mppe = 1; + ccp_allowoptions[0].mppe_128 = ccp_wantoptions[0].mppe_128 = 1; + return 1; +} + +int +setnomppe_128(char **argv) +{ + ccp_allowoptions[0].mppe_128 = ccp_wantoptions[0].mppe_128 = 0; + return 1; +} + +int +setmppe_stateless(char **argv) +{ + ccp_allowoptions[0].mppe_stateless = ccp_wantoptions[0].mppe_stateless = 1; + return 1; +} + +int +setnomppe_stateless(char **argv) +{ + ccp_allowoptions[0].mppe_stateless = ccp_wantoptions[0].mppe_stateless = 0; + return 1; +} +#endif /* MPPE */ diff -urN ppp-2.4.1/pppd/mppe.h ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/mppe.h --- ppp-2.4.1/pppd/mppe.h Wed Dec 31 19:00:00 1969 +++ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/mppe.h Tue Nov 5 20:01:07 2002 @@ -0,0 +1,58 @@ +#ifndef __MPPE_INCLUDE__ + +typedef struct mppe_state { + int us_unit; /* Interface unit number */ + u_char us_id; /* Current id */ + u_char us_allowed; + int us_type; + char *us_number; /* Telefone Number */ +} mppe_state; + + +extern struct protent mppe_protent; + +#define MPPE_CONFOPTION 18 /* p[0] */ +#define MPPE_STATELESS 0x01 /* p[2] */ +#define MPPE_40BIT 0x20 /* p[5] */ +#define MPPE_128BIT 0x40 /* p[5] */ + +#define PPP_MPPE 0x00FD + +#define MPPE_BIT_A 0x80 +#define MPPE_BIT_B 0x40 +#define MPPE_BIT_C 0x20 +#define MPPE_BIT_D 0x10 +#define MPPE_BIT_FLUSHED MPPE_BIT_A +#define MPPE_BIT_ENCRYPTED MPPE_BIT_D +#define MPPE_CCOUNT 0x0FFF + +#define MPPE_40_SALT0 0xD1 +#define MPPE_40_SALT1 0x26 +#define MPPE_40_SALT2 0x9E + +#define MPPE_MINLEN 4 + +#define MPPE_REQ 1 +#define MPPE_RESP 2 +#define MPPE_ACK 3 + +extern char mppe_master_send_key_40[8]; +extern char mppe_master_send_key_128[16]; +extern char mppe_master_recv_key_40[8]; +extern char mppe_master_recv_key_128[16]; +extern unsigned int mppe_allowed; + +void mppe_gen_master_key __P((char *, int, unsigned char *)); +void mppe_gen_master_key_v2 __P((char *, int, unsigned char *, int)); + +int setmppe_40(char **); +int setnomppe_40(char **); +int setmppe_128(char **); +int setnomppe_128(char **); +int setmppe_stateless(char **); +int setnomppe_stateless(char **); +int require_mppe(char **); +int require_mppe_stateless(char **); + +#define __MPPE_INCLUDE__ +#endif /* __MPPE_INCLUDE__ */ Binary files ppp-2.4.1/pppd/mppe.o and ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/mppe.o differ Binary files ppp-2.4.1/pppd/multilink.o and ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/multilink.o differ Binary files ppp-2.4.1/pppd/options.o and ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/options.o differ Binary files ppp-2.4.1/pppd/pppd and ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/pppd differ diff -urN ppp-2.4.1/pppd/pppd.8 ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/pppd.8 --- ppp-2.4.1/pppd/pppd.8 Tue Mar 13 00:54:37 2001 +++ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/pppd.8 Tue Nov 5 20:00:52 2002 @@ -27,9 +27,14 @@ and configuring different network-layer protocols. .LP The encapsulation scheme is provided by driver code in the kernel. -Pppd provides the basic LCP, authentication support, and an NCP for +PPPD provides the basic LCP, authentication support, and an NCP for establishing and configuring the Internet Protocol (IP) (called the IP Control Protocol, IPCP). +.LP +This version includes support for multilink operations, Microsoft +specific CHAP authentication algorithms (known as CHAP-MS-V1 and +CHAP-MS-V2) and transparent encryption (Microsoft Point-to-Point +Encryption, MPPE) also. .SH FREQUENTLY USED OPTIONS .TP .I @@ -72,6 +77,15 @@ or include .. as a pathname component. The format of the options file is described below. .TP +.B callback \fIphone +Request client to call back to specified \fIphone\fR number. +.TP +.B nocallback +Don't argee to use callback negotiation. +.TP +.B +callback +Request server to negotiate callback and log negotiated results. +.TP .B connect \fIscript Use the executable or shell command specified by \fIscript\fR to set up the serial line. This script would typically use the chat(8) @@ -346,6 +360,10 @@ option is given, data packets which are rejected by the specified activity filter also count as the link being idle. .TP +.B ip +Enable IPCP and IP protocols. You can disable IP negotiation if you +want to use other protocols only. +.TP .B ipcp-accept-local With this option, pppd will accept the peer's idea of our local IP address, even if the local IP address was specified in an option. @@ -574,7 +592,7 @@ currently only available under Linux, and only has any effect if multilink is enabled (see the multilink option). .TP -.B ms-dns \fI +.B ms-dns \fI\fR If pppd is acting as a server for Microsoft Windows clients, this option allows pppd to supply one or two DNS (Domain Name Server) addresses to the clients. The first instance of this option specifies @@ -847,7 +865,11 @@ .TP .B refuse-chap With this option, pppd will not agree to authenticate itself to the -peer using CHAP. +peer using any CHAP protocol. +.TP +.B refuse-chap-md5 +With this option, pppd will not agree to authenticate itself to the +peer using standard MD5 CHAP. .TP .B refuse-pap With this option, pppd will not agree to authenticate itself to the @@ -913,6 +935,48 @@ .B xonxoff Use software flow control (i.e. XON/XOFF) to control the flow of data on the serial port. +.SH MICROSOFT SPECIFIC EXTENSIONS +This version of PPPD supports some Microsoft-specific extensions such +as non-standard CHAP algorithms (known as CHAP-MS-V1 and CHAP-MS-V2) and +transparent encryption of all sending and receiving traffic. +.LP +Those options allows to configure PPPD to work with Microsoft extensions of +standard PPP protocol. +.TP +.B require-chapms +Require the peer to authenticate itself using CHAP [Challenge +Handshake Authentication Protocol] authentication with Microsoft +extensions [known as CHAP-MS-V1]. +.TP +.B require-chapms-v2 +Require the peer to authenticate itself using CHAP authentication +with Microsoft extensions [known as CHAP-MS-V2]. +.TP +.B refuse-chapms +With this option, pppd will not agree to authenticate itself to the +peer using CHAP-MS-V1. +.TP +.B refuse-chapms-v2 +With this option, pppd will not agree to authenticate itself to the +peer using CHAP-MS-V2. +.TP +.B mppe-40 +This option enables use of Microsoft Point-to-point Encryption (MPPE) +using 40-bit encryption keys. These keys can be used with any Microsoft +software (Windows 95, Windows 98, Windows NT) because their cryptographic +strength is relatively low. This option requires that chapms or chapms-v2 +be enabled. +.TP +.B mppe-128 +This option enables use of Microsoft Point-to-Point Encryption (MPPE) +using 128-bit encryption keys. These keys can be used with software designed +for domestic usage (within US and Canada). This option requires that chapms +or chapms-v2 be enabled. +.TP +.B mppe-stateless +This option negotiates stateless mode for Microsoft Point-to-Point Encryption +(MPPE), which changes the encryption keys on every packet. The default mode is +stateful (non-stateless, or single key). .SH OPTIONS FILES Options can be taken from files as well as the command line. Pppd reads options from the files /etc/ppp/options, ~/.ppprc and @@ -1261,9 +1325,40 @@ rlogin implementations are not transparent; they will remove the sequence [0xff, 0xff, 0x73, 0x73, followed by any 8 bytes] from the stream. +.SH EXAMPLES OF MICROSOFT EXTENSIONS +To enable full-featured Microsoft encryption you must add those options +to your \fI/etc/ppp/options/fR file: +.IP ++chapms +.br ++chapms-v2 +.br +mppe-40 +.br +mppe-128 +.br +mppe-stateless +.LP +To authentificate client with Microsoft CHAP version 1 or 2, you need to +use those options: +.IP +auth +.br ++chap +.br ++chapms +.br ++chapms-v2 +.LP +To make possible to authentificate itself with Microsoft CHAP version 1 +or 2, you need to add those options: +.IP ++chapms +.br ++chapms-v2 .SH DIAGNOSTICS .LP -Messages are sent to the syslog daemon using facility LOG_DAEMON. +.Messages are sent to the syslog daemon using facility LOG_DAEMON. (This can be overriden by recompiling pppd with the macro LOG_PPP defined as the desired facility.) In order to see the error and debug messages, you will need to edit your /etc/syslog.conf file diff -urN ppp-2.4.1/pppd/pppd.h ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/pppd.h --- ppp-2.4.1/pppd/pppd.h Tue Mar 13 00:54:37 2001 +++ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/pppd.h Tue Nov 5 20:00:52 2002 @@ -27,6 +27,7 @@ #define __PPPD_H__ #include /* for FILE */ +#include #include /* for NGROUPS_MAX */ #include /* for MAXPATHLEN and BSD4_4, if defined */ #include /* for u_int32_t, if defined */ @@ -470,6 +471,8 @@ /* check if IP address is authorized */ int bad_ip_adrs __P((u_int32_t)); /* check if IP address is unreasonable */ +int get_ip_addr_dynamic __P((int, u_int32_t *)); + /* get dynamically-allocated IP address */ /* Procedures exported from demand.c */ void demand_conf __P((void)); /* config interface(s) for demand-dial */ diff -urN ppp-2.4.1/pppd/sha1dgst.c ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/sha1dgst.c --- ppp-2.4.1/pppd/sha1dgst.c Wed Dec 31 19:00:00 1969 +++ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/sha1dgst.c Tue Nov 5 20:00:52 2002 @@ -0,0 +1,73 @@ +/* crypto/sha/sha1dgst.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#if !defined(NO_SHA1) && !defined(NO_SHA) + +#undef SHA_0 +#define SHA_1 + +#include + +const char *SHA1_version="SHA1" OPENSSL_VERSION_PTEXT; + +/* The implementation is in ../md32_common.h */ + +#include "sha_locl.h" + +#endif + Binary files ppp-2.4.1/pppd/sha1dgst.o and ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/sha1dgst.o differ diff -urN ppp-2.4.1/pppd/sha_locl.h ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/sha_locl.h --- ppp-2.4.1/pppd/sha_locl.h Wed Dec 31 19:00:00 1969 +++ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/sha_locl.h Tue Nov 5 20:00:52 2002 @@ -0,0 +1,473 @@ +/* crypto/sha/sha_locl.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef __KERNEL__ +#include +#include +#endif + +#include +#include + +#ifndef SHA_LONG_LOG2 +#define SHA_LONG_LOG2 2 /* default to 32 bits */ +#endif + +#define DATA_ORDER_IS_BIG_ENDIAN + +#define HASH_LONG SHA_LONG +#define HASH_LONG_LOG2 SHA_LONG_LOG2 +#define HASH_CTX SHA_CTX +#define HASH_CBLOCK SHA_CBLOCK +#define HASH_LBLOCK SHA_LBLOCK +#define HASH_MAKE_STRING(c,s) do { \ + unsigned long ll; \ + ll=(c)->h0; HOST_l2c(ll,(s)); \ + ll=(c)->h1; HOST_l2c(ll,(s)); \ + ll=(c)->h2; HOST_l2c(ll,(s)); \ + ll=(c)->h3; HOST_l2c(ll,(s)); \ + ll=(c)->h4; HOST_l2c(ll,(s)); \ + } while (0) + +#if defined(SHA_0) + +# define HASH_UPDATE SHA_Update +# define HASH_TRANSFORM SHA_Transform +# define HASH_FINAL SHA_Final +# define HASH_INIT SHA_Init +# define HASH_BLOCK_HOST_ORDER sha_block_host_order +# define HASH_BLOCK_DATA_ORDER sha_block_data_order +# define Xupdate(a,ix,ia,ib,ic,id) (ix=(a)=(ia^ib^ic^id)) + + void sha_block_host_order (SHA_CTX *c, const void *p,int num); + void sha_block_data_order (SHA_CTX *c, const void *p,int num); + +#elif defined(SHA_1) + +# define HASH_UPDATE SHA1_Update +# define HASH_TRANSFORM SHA1_Transform +# define HASH_FINAL SHA1_Final +# define HASH_INIT SHA1_Init +# define HASH_BLOCK_HOST_ORDER sha1_block_host_order +# define HASH_BLOCK_DATA_ORDER sha1_block_data_order +# if defined(__MWERKS__) && defined(__MC68K__) + /* Metrowerks for Motorola fails otherwise:-( */ +# define Xupdate(a,ix,ia,ib,ic,id) do { (a)=(ia^ib^ic^id); \ + ix=(a)=ROTATE((a),1); \ + } while (0) +# else +# define Xupdate(a,ix,ia,ib,ic,id) ( (a)=(ia^ib^ic^id), \ + ix=(a)=ROTATE((a),1) \ + ) +# endif + +# ifdef SHA1_ASM +# if defined(__i386) || defined(_M_IX86) || defined(__INTEL__) +# define sha1_block_host_order sha1_block_asm_host_order +# define DONT_IMPLEMENT_BLOCK_HOST_ORDER +# define sha1_block_data_order sha1_block_asm_data_order +# define DONT_IMPLEMENT_BLOCK_DATA_ORDER +# define HASH_BLOCK_DATA_ORDER_ALIGNED sha1_block_asm_data_order +# endif +# endif + void sha1_block_host_order (SHA_CTX *c, const void *p,int num); + void sha1_block_data_order (SHA_CTX *c, const void *p,int num); + +#else +# error "Either SHA_0 or SHA_1 must be defined." +#endif + +#include "md32_common.h" + +#define INIT_DATA_h0 0x67452301UL +#define INIT_DATA_h1 0xefcdab89UL +#define INIT_DATA_h2 0x98badcfeUL +#define INIT_DATA_h3 0x10325476UL +#define INIT_DATA_h4 0xc3d2e1f0UL + +void HASH_INIT (SHA_CTX *c) + { + c->h0=INIT_DATA_h0; + c->h1=INIT_DATA_h1; + c->h2=INIT_DATA_h2; + c->h3=INIT_DATA_h3; + c->h4=INIT_DATA_h4; + c->Nl=0; + c->Nh=0; + c->num=0; + } + +#define K_00_19 0x5a827999UL +#define K_20_39 0x6ed9eba1UL +#define K_40_59 0x8f1bbcdcUL +#define K_60_79 0xca62c1d6UL + +/* As pointed out by Wei Dai , F() below can be + * simplified to the code in F_00_19. Wei attributes these optimisations + * to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel. + * #define F(x,y,z) (((x) & (y)) | ((~(x)) & (z))) + * I've just become aware of another tweak to be made, again from Wei Dai, + * in F_40_59, (x&a)|(y&a) -> (x|y)&a + */ +#define F_00_19(b,c,d) ((((c) ^ (d)) & (b)) ^ (d)) +#define F_20_39(b,c,d) ((b) ^ (c) ^ (d)) +#define F_40_59(b,c,d) (((b) & (c)) | (((b)|(c)) & (d))) +#define F_60_79(b,c,d) F_20_39(b,c,d) + +#define BODY_00_15(i,a,b,c,d,e,f,xi) \ + (f)=xi+(e)+K_00_19+ROTATE((a),5)+F_00_19((b),(c),(d)); \ + (b)=ROTATE((b),30); + +#define BODY_16_19(i,a,b,c,d,e,f,xi,xa,xb,xc,xd) \ + Xupdate(f,xi,xa,xb,xc,xd); \ + (f)+=(e)+K_00_19+ROTATE((a),5)+F_00_19((b),(c),(d)); \ + (b)=ROTATE((b),30); + +#define BODY_20_31(i,a,b,c,d,e,f,xi,xa,xb,xc,xd) \ + Xupdate(f,xi,xa,xb,xc,xd); \ + (f)+=(e)+K_20_39+ROTATE((a),5)+F_20_39((b),(c),(d)); \ + (b)=ROTATE((b),30); + +#define BODY_32_39(i,a,b,c,d,e,f,xa,xb,xc,xd) \ + Xupdate(f,xa,xa,xb,xc,xd); \ + (f)+=(e)+K_20_39+ROTATE((a),5)+F_20_39((b),(c),(d)); \ + (b)=ROTATE((b),30); + +#define BODY_40_59(i,a,b,c,d,e,f,xa,xb,xc,xd) \ + Xupdate(f,xa,xa,xb,xc,xd); \ + (f)+=(e)+K_40_59+ROTATE((a),5)+F_40_59((b),(c),(d)); \ + (b)=ROTATE((b),30); + +#define BODY_60_79(i,a,b,c,d,e,f,xa,xb,xc,xd) \ + Xupdate(f,xa,xa,xb,xc,xd); \ + (f)=xa+(e)+K_60_79+ROTATE((a),5)+F_60_79((b),(c),(d)); \ + (b)=ROTATE((b),30); + +#ifdef X +#undef X +#endif +#ifndef MD32_XARRAY + /* + * Originally X was an array. As it's automatic it's natural + * to expect RISC compiler to accomodate at least part of it in + * the register bank, isn't it? Unfortunately not all compilers + * "find" this expectation reasonable:-( On order to make such + * compilers generate better code I replace X[] with a bunch of + * X0, X1, etc. See the function body below... + * + */ +# define X(i) XX##i +#else + /* + * However! Some compilers (most notably HP C) get overwhelmed by + * that many local variables so that we have to have the way to + * fall down to the original behavior. + */ +# define X(i) XX[i] +#endif + +#ifndef DONT_IMPLEMENT_BLOCK_HOST_ORDER +void HASH_BLOCK_HOST_ORDER (SHA_CTX *c, const void *d, int num) + { + const SHA_LONG *W=d; + register unsigned long A,B,C,D,E,T; +#ifndef MD32_XARRAY + unsigned long XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7, + XX8, XX9,XX10,XX11,XX12,XX13,XX14,XX15; +#else + SHA_LONG XX[16]; +#endif + + A=c->h0; + B=c->h1; + C=c->h2; + D=c->h3; + E=c->h4; + + for (;;) + { + BODY_00_15( 0,A,B,C,D,E,T,W[ 0]); + BODY_00_15( 1,T,A,B,C,D,E,W[ 1]); + BODY_00_15( 2,E,T,A,B,C,D,W[ 2]); + BODY_00_15( 3,D,E,T,A,B,C,W[ 3]); + BODY_00_15( 4,C,D,E,T,A,B,W[ 4]); + BODY_00_15( 5,B,C,D,E,T,A,W[ 5]); + BODY_00_15( 6,A,B,C,D,E,T,W[ 6]); + BODY_00_15( 7,T,A,B,C,D,E,W[ 7]); + BODY_00_15( 8,E,T,A,B,C,D,W[ 8]); + BODY_00_15( 9,D,E,T,A,B,C,W[ 9]); + BODY_00_15(10,C,D,E,T,A,B,W[10]); + BODY_00_15(11,B,C,D,E,T,A,W[11]); + BODY_00_15(12,A,B,C,D,E,T,W[12]); + BODY_00_15(13,T,A,B,C,D,E,W[13]); + BODY_00_15(14,E,T,A,B,C,D,W[14]); + BODY_00_15(15,D,E,T,A,B,C,W[15]); + + BODY_16_19(16,C,D,E,T,A,B,X( 0),W[ 0],W[ 2],W[ 8],W[13]); + BODY_16_19(17,B,C,D,E,T,A,X( 1),W[ 1],W[ 3],W[ 9],W[14]); + BODY_16_19(18,A,B,C,D,E,T,X( 2),W[ 2],W[ 4],W[10],W[15]); + BODY_16_19(19,T,A,B,C,D,E,X( 3),W[ 3],W[ 5],W[11],X( 0)); + + BODY_20_31(20,E,T,A,B,C,D,X( 4),W[ 4],W[ 6],W[12],X( 1)); + BODY_20_31(21,D,E,T,A,B,C,X( 5),W[ 5],W[ 7],W[13],X( 2)); + BODY_20_31(22,C,D,E,T,A,B,X( 6),W[ 6],W[ 8],W[14],X( 3)); + BODY_20_31(23,B,C,D,E,T,A,X( 7),W[ 7],W[ 9],W[15],X( 4)); + BODY_20_31(24,A,B,C,D,E,T,X( 8),W[ 8],W[10],X( 0),X( 5)); + BODY_20_31(25,T,A,B,C,D,E,X( 9),W[ 9],W[11],X( 1),X( 6)); + BODY_20_31(26,E,T,A,B,C,D,X(10),W[10],W[12],X( 2),X( 7)); + BODY_20_31(27,D,E,T,A,B,C,X(11),W[11],W[13],X( 3),X( 8)); + BODY_20_31(28,C,D,E,T,A,B,X(12),W[12],W[14],X( 4),X( 9)); + BODY_20_31(29,B,C,D,E,T,A,X(13),W[13],W[15],X( 5),X(10)); + BODY_20_31(30,A,B,C,D,E,T,X(14),W[14],X( 0),X( 6),X(11)); + BODY_20_31(31,T,A,B,C,D,E,X(15),W[15],X( 1),X( 7),X(12)); + + BODY_32_39(32,E,T,A,B,C,D,X( 0),X( 2),X( 8),X(13)); + BODY_32_39(33,D,E,T,A,B,C,X( 1),X( 3),X( 9),X(14)); + BODY_32_39(34,C,D,E,T,A,B,X( 2),X( 4),X(10),X(15)); + BODY_32_39(35,B,C,D,E,T,A,X( 3),X( 5),X(11),X( 0)); + BODY_32_39(36,A,B,C,D,E,T,X( 4),X( 6),X(12),X( 1)); + BODY_32_39(37,T,A,B,C,D,E,X( 5),X( 7),X(13),X( 2)); + BODY_32_39(38,E,T,A,B,C,D,X( 6),X( 8),X(14),X( 3)); + BODY_32_39(39,D,E,T,A,B,C,X( 7),X( 9),X(15),X( 4)); + + BODY_40_59(40,C,D,E,T,A,B,X( 8),X(10),X( 0),X( 5)); + BODY_40_59(41,B,C,D,E,T,A,X( 9),X(11),X( 1),X( 6)); + BODY_40_59(42,A,B,C,D,E,T,X(10),X(12),X( 2),X( 7)); + BODY_40_59(43,T,A,B,C,D,E,X(11),X(13),X( 3),X( 8)); + BODY_40_59(44,E,T,A,B,C,D,X(12),X(14),X( 4),X( 9)); + BODY_40_59(45,D,E,T,A,B,C,X(13),X(15),X( 5),X(10)); + BODY_40_59(46,C,D,E,T,A,B,X(14),X( 0),X( 6),X(11)); + BODY_40_59(47,B,C,D,E,T,A,X(15),X( 1),X( 7),X(12)); + BODY_40_59(48,A,B,C,D,E,T,X( 0),X( 2),X( 8),X(13)); + BODY_40_59(49,T,A,B,C,D,E,X( 1),X( 3),X( 9),X(14)); + BODY_40_59(50,E,T,A,B,C,D,X( 2),X( 4),X(10),X(15)); + BODY_40_59(51,D,E,T,A,B,C,X( 3),X( 5),X(11),X( 0)); + BODY_40_59(52,C,D,E,T,A,B,X( 4),X( 6),X(12),X( 1)); + BODY_40_59(53,B,C,D,E,T,A,X( 5),X( 7),X(13),X( 2)); + BODY_40_59(54,A,B,C,D,E,T,X( 6),X( 8),X(14),X( 3)); + BODY_40_59(55,T,A,B,C,D,E,X( 7),X( 9),X(15),X( 4)); + BODY_40_59(56,E,T,A,B,C,D,X( 8),X(10),X( 0),X( 5)); + BODY_40_59(57,D,E,T,A,B,C,X( 9),X(11),X( 1),X( 6)); + BODY_40_59(58,C,D,E,T,A,B,X(10),X(12),X( 2),X( 7)); + BODY_40_59(59,B,C,D,E,T,A,X(11),X(13),X( 3),X( 8)); + + BODY_60_79(60,A,B,C,D,E,T,X(12),X(14),X( 4),X( 9)); + BODY_60_79(61,T,A,B,C,D,E,X(13),X(15),X( 5),X(10)); + BODY_60_79(62,E,T,A,B,C,D,X(14),X( 0),X( 6),X(11)); + BODY_60_79(63,D,E,T,A,B,C,X(15),X( 1),X( 7),X(12)); + BODY_60_79(64,C,D,E,T,A,B,X( 0),X( 2),X( 8),X(13)); + BODY_60_79(65,B,C,D,E,T,A,X( 1),X( 3),X( 9),X(14)); + BODY_60_79(66,A,B,C,D,E,T,X( 2),X( 4),X(10),X(15)); + BODY_60_79(67,T,A,B,C,D,E,X( 3),X( 5),X(11),X( 0)); + BODY_60_79(68,E,T,A,B,C,D,X( 4),X( 6),X(12),X( 1)); + BODY_60_79(69,D,E,T,A,B,C,X( 5),X( 7),X(13),X( 2)); + BODY_60_79(70,C,D,E,T,A,B,X( 6),X( 8),X(14),X( 3)); + BODY_60_79(71,B,C,D,E,T,A,X( 7),X( 9),X(15),X( 4)); + BODY_60_79(72,A,B,C,D,E,T,X( 8),X(10),X( 0),X( 5)); + BODY_60_79(73,T,A,B,C,D,E,X( 9),X(11),X( 1),X( 6)); + BODY_60_79(74,E,T,A,B,C,D,X(10),X(12),X( 2),X( 7)); + BODY_60_79(75,D,E,T,A,B,C,X(11),X(13),X( 3),X( 8)); + BODY_60_79(76,C,D,E,T,A,B,X(12),X(14),X( 4),X( 9)); + BODY_60_79(77,B,C,D,E,T,A,X(13),X(15),X( 5),X(10)); + BODY_60_79(78,A,B,C,D,E,T,X(14),X( 0),X( 6),X(11)); + BODY_60_79(79,T,A,B,C,D,E,X(15),X( 1),X( 7),X(12)); + + c->h0=(c->h0+E)&0xffffffffL; + c->h1=(c->h1+T)&0xffffffffL; + c->h2=(c->h2+A)&0xffffffffL; + c->h3=(c->h3+B)&0xffffffffL; + c->h4=(c->h4+C)&0xffffffffL; + + if (--num <= 0) break; + + A=c->h0; + B=c->h1; + C=c->h2; + D=c->h3; + E=c->h4; + + W+=SHA_LBLOCK; + } + } +#endif + +#ifndef DONT_IMPLEMENT_BLOCK_DATA_ORDER +void HASH_BLOCK_DATA_ORDER (SHA_CTX *c, const void *p, int num) + { + const unsigned char *data=p; + register unsigned long A,B,C,D,E,T,l; +#ifndef MD32_XARRAY + unsigned long XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7, + XX8, XX9,XX10,XX11,XX12,XX13,XX14,XX15; +#else + SHA_LONG XX[16]; +#endif + + A=c->h0; + B=c->h1; + C=c->h2; + D=c->h3; + E=c->h4; + + for (;;) + { + + HOST_c2l(data,l); X( 0)=l; HOST_c2l(data,l); X( 1)=l; + BODY_00_15( 0,A,B,C,D,E,T,X( 0)); HOST_c2l(data,l); X( 2)=l; + BODY_00_15( 1,T,A,B,C,D,E,X( 1)); HOST_c2l(data,l); X( 3)=l; + BODY_00_15( 2,E,T,A,B,C,D,X( 2)); HOST_c2l(data,l); X( 4)=l; + BODY_00_15( 3,D,E,T,A,B,C,X( 3)); HOST_c2l(data,l); X( 5)=l; + BODY_00_15( 4,C,D,E,T,A,B,X( 4)); HOST_c2l(data,l); X( 6)=l; + BODY_00_15( 5,B,C,D,E,T,A,X( 5)); HOST_c2l(data,l); X( 7)=l; + BODY_00_15( 6,A,B,C,D,E,T,X( 6)); HOST_c2l(data,l); X( 8)=l; + BODY_00_15( 7,T,A,B,C,D,E,X( 7)); HOST_c2l(data,l); X( 9)=l; + BODY_00_15( 8,E,T,A,B,C,D,X( 8)); HOST_c2l(data,l); X(10)=l; + BODY_00_15( 9,D,E,T,A,B,C,X( 9)); HOST_c2l(data,l); X(11)=l; + BODY_00_15(10,C,D,E,T,A,B,X(10)); HOST_c2l(data,l); X(12)=l; + BODY_00_15(11,B,C,D,E,T,A,X(11)); HOST_c2l(data,l); X(13)=l; + BODY_00_15(12,A,B,C,D,E,T,X(12)); HOST_c2l(data,l); X(14)=l; + BODY_00_15(13,T,A,B,C,D,E,X(13)); HOST_c2l(data,l); X(15)=l; + BODY_00_15(14,E,T,A,B,C,D,X(14)); + BODY_00_15(15,D,E,T,A,B,C,X(15)); + + BODY_16_19(16,C,D,E,T,A,B,X( 0),X( 0),X( 2),X( 8),X(13)); + BODY_16_19(17,B,C,D,E,T,A,X( 1),X( 1),X( 3),X( 9),X(14)); + BODY_16_19(18,A,B,C,D,E,T,X( 2),X( 2),X( 4),X(10),X(15)); + BODY_16_19(19,T,A,B,C,D,E,X( 3),X( 3),X( 5),X(11),X( 0)); + + BODY_20_31(20,E,T,A,B,C,D,X( 4),X( 4),X( 6),X(12),X( 1)); + BODY_20_31(21,D,E,T,A,B,C,X( 5),X( 5),X( 7),X(13),X( 2)); + BODY_20_31(22,C,D,E,T,A,B,X( 6),X( 6),X( 8),X(14),X( 3)); + BODY_20_31(23,B,C,D,E,T,A,X( 7),X( 7),X( 9),X(15),X( 4)); + BODY_20_31(24,A,B,C,D,E,T,X( 8),X( 8),X(10),X( 0),X( 5)); + BODY_20_31(25,T,A,B,C,D,E,X( 9),X( 9),X(11),X( 1),X( 6)); + BODY_20_31(26,E,T,A,B,C,D,X(10),X(10),X(12),X( 2),X( 7)); + BODY_20_31(27,D,E,T,A,B,C,X(11),X(11),X(13),X( 3),X( 8)); + BODY_20_31(28,C,D,E,T,A,B,X(12),X(12),X(14),X( 4),X( 9)); + BODY_20_31(29,B,C,D,E,T,A,X(13),X(13),X(15),X( 5),X(10)); + BODY_20_31(30,A,B,C,D,E,T,X(14),X(14),X( 0),X( 6),X(11)); + BODY_20_31(31,T,A,B,C,D,E,X(15),X(15),X( 1),X( 7),X(12)); + + BODY_32_39(32,E,T,A,B,C,D,X( 0),X( 2),X( 8),X(13)); + BODY_32_39(33,D,E,T,A,B,C,X( 1),X( 3),X( 9),X(14)); + BODY_32_39(34,C,D,E,T,A,B,X( 2),X( 4),X(10),X(15)); + BODY_32_39(35,B,C,D,E,T,A,X( 3),X( 5),X(11),X( 0)); + BODY_32_39(36,A,B,C,D,E,T,X( 4),X( 6),X(12),X( 1)); + BODY_32_39(37,T,A,B,C,D,E,X( 5),X( 7),X(13),X( 2)); + BODY_32_39(38,E,T,A,B,C,D,X( 6),X( 8),X(14),X( 3)); + BODY_32_39(39,D,E,T,A,B,C,X( 7),X( 9),X(15),X( 4)); + + BODY_40_59(40,C,D,E,T,A,B,X( 8),X(10),X( 0),X( 5)); + BODY_40_59(41,B,C,D,E,T,A,X( 9),X(11),X( 1),X( 6)); + BODY_40_59(42,A,B,C,D,E,T,X(10),X(12),X( 2),X( 7)); + BODY_40_59(43,T,A,B,C,D,E,X(11),X(13),X( 3),X( 8)); + BODY_40_59(44,E,T,A,B,C,D,X(12),X(14),X( 4),X( 9)); + BODY_40_59(45,D,E,T,A,B,C,X(13),X(15),X( 5),X(10)); + BODY_40_59(46,C,D,E,T,A,B,X(14),X( 0),X( 6),X(11)); + BODY_40_59(47,B,C,D,E,T,A,X(15),X( 1),X( 7),X(12)); + BODY_40_59(48,A,B,C,D,E,T,X( 0),X( 2),X( 8),X(13)); + BODY_40_59(49,T,A,B,C,D,E,X( 1),X( 3),X( 9),X(14)); + BODY_40_59(50,E,T,A,B,C,D,X( 2),X( 4),X(10),X(15)); + BODY_40_59(51,D,E,T,A,B,C,X( 3),X( 5),X(11),X( 0)); + BODY_40_59(52,C,D,E,T,A,B,X( 4),X( 6),X(12),X( 1)); + BODY_40_59(53,B,C,D,E,T,A,X( 5),X( 7),X(13),X( 2)); + BODY_40_59(54,A,B,C,D,E,T,X( 6),X( 8),X(14),X( 3)); + BODY_40_59(55,T,A,B,C,D,E,X( 7),X( 9),X(15),X( 4)); + BODY_40_59(56,E,T,A,B,C,D,X( 8),X(10),X( 0),X( 5)); + BODY_40_59(57,D,E,T,A,B,C,X( 9),X(11),X( 1),X( 6)); + BODY_40_59(58,C,D,E,T,A,B,X(10),X(12),X( 2),X( 7)); + BODY_40_59(59,B,C,D,E,T,A,X(11),X(13),X( 3),X( 8)); + + BODY_60_79(60,A,B,C,D,E,T,X(12),X(14),X( 4),X( 9)); + BODY_60_79(61,T,A,B,C,D,E,X(13),X(15),X( 5),X(10)); + BODY_60_79(62,E,T,A,B,C,D,X(14),X( 0),X( 6),X(11)); + BODY_60_79(63,D,E,T,A,B,C,X(15),X( 1),X( 7),X(12)); + BODY_60_79(64,C,D,E,T,A,B,X( 0),X( 2),X( 8),X(13)); + BODY_60_79(65,B,C,D,E,T,A,X( 1),X( 3),X( 9),X(14)); + BODY_60_79(66,A,B,C,D,E,T,X( 2),X( 4),X(10),X(15)); + BODY_60_79(67,T,A,B,C,D,E,X( 3),X( 5),X(11),X( 0)); + BODY_60_79(68,E,T,A,B,C,D,X( 4),X( 6),X(12),X( 1)); + BODY_60_79(69,D,E,T,A,B,C,X( 5),X( 7),X(13),X( 2)); + BODY_60_79(70,C,D,E,T,A,B,X( 6),X( 8),X(14),X( 3)); + BODY_60_79(71,B,C,D,E,T,A,X( 7),X( 9),X(15),X( 4)); + BODY_60_79(72,A,B,C,D,E,T,X( 8),X(10),X( 0),X( 5)); + BODY_60_79(73,T,A,B,C,D,E,X( 9),X(11),X( 1),X( 6)); + BODY_60_79(74,E,T,A,B,C,D,X(10),X(12),X( 2),X( 7)); + BODY_60_79(75,D,E,T,A,B,C,X(11),X(13),X( 3),X( 8)); + BODY_60_79(76,C,D,E,T,A,B,X(12),X(14),X( 4),X( 9)); + BODY_60_79(77,B,C,D,E,T,A,X(13),X(15),X( 5),X(10)); + BODY_60_79(78,A,B,C,D,E,T,X(14),X( 0),X( 6),X(11)); + BODY_60_79(79,T,A,B,C,D,E,X(15),X( 1),X( 7),X(12)); + + c->h0=(c->h0+E)&0xffffffffL; + c->h1=(c->h1+T)&0xffffffffL; + c->h2=(c->h2+A)&0xffffffffL; + c->h3=(c->h3+B)&0xffffffffL; + c->h4=(c->h4+C)&0xffffffffL; + + if (--num <= 0) break; + + A=c->h0; + B=c->h1; + C=c->h2; + D=c->h3; + E=c->h4; + + } + } +#endif diff -urN ppp-2.4.1/pppd/smbpwd.h ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/smbpwd.h --- ppp-2.4.1/pppd/smbpwd.h Wed Dec 31 19:00:00 1969 +++ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/smbpwd.h Tue Nov 5 20:12:47 2002 @@ -0,0 +1,79 @@ +/* SMB password reading library atp 1999, based on code from samba 2.0.5a */ +/* This code is licensed under the GPL Version 2 or later (at your option), + * and constitutes a derived work of the original samba code. + * + * oct 12 1999 - initial revision. atp. + * + * Include this file in your program to use this library. + * + */ + +#ifndef _SMBPWD_H +#define _SMBPWD_H 1 + +/* C++ needs to know that types and declarations are C, not C++. */ +#ifdef __cplusplus +# define __BEGIN_DECLS extern "C" { +# define __END_DECLS +} +#else +# define __BEGIN_DECLS +# define __END_DECLS +#endif + +#ifndef _SYS_TYPES_H +#include +#endif + +__BEGIN_DECLS + +/* Allowable account control bits */ +#define ACB_DISABLED 0x0001 /* 1 = User account disabled */ +#define ACB_HOMDIRREQ 0x0002 /* 1 = Home directory required */ +#define ACB_PWNOTREQ 0x0004 /* 1 = User password not required */ +#define ACB_TEMPDUP 0x0008 /* 1 = Temporary duplicate account */ +#define ACB_NORMAL 0x0010 /* 1 = Normal user account */ +#define ACB_MNS 0x0020 /* 1 = MNS logon user account */ +#define ACB_DOMTRUST 0x0040 /* 1 = Interdomain trust account */ +#define ACB_WSTRUST 0x0080 /* 1 = Workstation trust account */ +#define ACB_SVRTRUST 0x0100 /* 1 = Server trust account */ +#define ACB_PWNOEXP 0x0200 /* 1 = User password does not expire */ +#define ACB_AUTOLOCK 0x0400 /* 1 = Account auto locked */ + +#define MAX_HOURS_LEN 32 + +struct smb_passwd +{ + uid_t smb_userid; /* this is actually the unix uid_t */ + char *smb_name; /* username string */ + + unsigned char *smb_passwd; /* Null if no password */ + unsigned char *smb_nt_passwd; /* Null if no password */ + + unsigned short int smb_acct_ctrl; /* account info (ACB_xxxx bit-mask) */ + time_t smb_pwlst; /* password last set time */ + char *smb_gecos; /* realname */ +}; + +/* prototypes and forward declarations */ +struct smb_passwd *getsmbpwent(void); +void setsmbpwent(void); +void endsmbpwent(void); +#if 0 +int putpwent(const struct smb_passwd *p, FILE *stream); +#endif + +/* Function to explicity set the path to the smbpasswd file */ +int setsmbfilepath(char *path); + +/* Encryption stubs */ + +void smbcrypt (unsigned char *plain, unsigned char nt_pass[16], unsigned char smb_pass[16]); + +/* redhat */ +#define SMB_PASSWORD_FILE "/etc/smbpasswd" + + +__END_DECLS + +#endif /* smbpwd.h */ Binary files ppp-2.4.1/pppd/sys-linux.o and ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/sys-linux.o differ Binary files ppp-2.4.1/pppd/tdb.o and ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/tdb.o differ Binary files ppp-2.4.1/pppd/tty.o and ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/tty.o differ Binary files ppp-2.4.1/pppd/upap.o and ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/upap.o differ Binary files ppp-2.4.1/pppd/utils.o and ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppd/utils.o differ diff -urN ppp-2.4.1/pppdump/Makefile ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppdump/Makefile --- ppp-2.4.1/pppdump/Makefile Wed Dec 31 19:00:00 1969 +++ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppdump/Makefile Mon Jul 26 07:09:29 1999 @@ -0,0 +1,17 @@ +CFLAGS= -O -I../include/net +OBJS = pppdump.o bsd-comp.o deflate.o zlib.o + +INSTALL= install + +all: pppdump + +pppdump: $(OBJS) + $(CC) -o pppdump $(OBJS) + +clean: + rm -f pppdump $(OBJS) *~ + +install: + mkdir -p $(BINDIR) $(MANDIR)/man8 + $(INSTALL) -s -c pppdump $(BINDIR) + $(INSTALL) -c -m 444 pppdump.8 $(MANDIR)/man8 Binary files ppp-2.4.1/pppdump/bsd-comp.o and ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppdump/bsd-comp.o differ Binary files ppp-2.4.1/pppdump/deflate.o and ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppdump/deflate.o differ Binary files ppp-2.4.1/pppdump/pppdump and ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppdump/pppdump differ Binary files ppp-2.4.1/pppdump/pppdump.o and ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppdump/pppdump.o differ Binary files ppp-2.4.1/pppdump/zlib.o and ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppdump/zlib.o differ diff -urN ppp-2.4.1/pppstats/Makefile ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppstats/Makefile --- ppp-2.4.1/pppstats/Makefile Wed Dec 31 19:00:00 1969 +++ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppstats/Makefile Tue Mar 24 21:21:19 1998 @@ -0,0 +1,32 @@ +# +# pppstats makefile +# $Id: Makefile.linux,v 1.3 1998/03/25 02:21:20 paulus Exp $ +# + +PPPSTATSRCS = pppstats.c +PPPSTATOBJS = pppstats.o + +#CC = gcc +COPTS = -O +COMPILE_FLAGS = -D_linux_ -I../include +LIBS = + +INSTALL= install -o root -g daemon + +CFLAGS = $(COPTS) $(COMPILE_FLAGS) + +all: pppstats + +install: pppstats + $(INSTALL) -s -c pppstats $(BINDIR)/pppstats + $(INSTALL) -c -m 444 pppstats.8 $(MANDIR)/man8/pppstats.8 + +pppstats: $(PPPSTATSRCS) + $(CC) $(CFLAGS) -o pppstats pppstats.c $(LIBS) + +clean: + rm -f pppstats *~ #* core + +depend: + cpp -M $(CFLAGS) $(PPPSTATSRCS) >.depend +# makedepend $(CFLAGS) $(PPPSTATSRCS) Binary files ppp-2.4.1/pppstats/pppstats and ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/pppstats/pppstats differ diff -urN ppp-2.4.1/require-mppe.diff ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/require-mppe.diff --- ppp-2.4.1/require-mppe.diff Wed Dec 31 19:00:00 1969 +++ ppp-2.4.1-MSCHAPv2-mppe-require-mppe-smbpw/require-mppe.diff Tue Nov 5 20:00:59 2002 @@ -0,0 +1,108 @@ +diff -ur --new-file ppp-2.3.11/pppd/ccp.c ppp-2.3.11.mppe/pppd/ccp.c +--- ppp-2.3.11/pppd/ccp.c Thu Mar 16 17:47:42 2000 ++++ ppp-2.3.11.mppe/pppd/ccp.c Tue Mar 28 16:56:22 2000 +@@ -37,6 +37,7 @@ + #include "mppe.h" + #endif + #include ++#include "lcp.h" + + static const char rcsid[] = RCSID; + +@@ -103,6 +104,10 @@ + "Disallow stateless MPPE encryption" }, + { "-mppe-stateless", o_special_noarg, setnomppe_stateless, + "Disallow stateless MPPE encryption" }, ++ { "require-mppe", o_special_noarg, require_mppe, ++ "Require MPPE encryption" }, ++ { "require-mppe-stateless", o_special_noarg, require_mppe_stateless, ++ "Require stateless MPPE encryption" }, + #endif + + { NULL } +@@ -450,6 +455,8 @@ + { + ccp_flags_set(unit, 0, 0); + fsm_lowerdown(&ccp_fsm[unit]); ++ if ( ccp_wantoptions[unit].require_mppe || ccp_wantoptions[unit].require_mppe_stateless ) ++ lcp_close(unit,"Encryption negotiation rejected"); + } + + /* +@@ -1269,6 +1276,19 @@ + notice("%s receive compression enabled", method_name(go, NULL)); + } else if (ANY_COMPRESS(*ho)) + notice("%s transmit compression enabled", method_name(ho, NULL)); ++ ++ if ( ccp_wantoptions[f->unit].require_mppe_stateless || ccp_wantoptions[f->unit].require_mppe ) { ++ if ( (go->mppe_128 && ho->mppe_128) || (go->mppe_40 && ho->mppe_40 ) ) ++ if ( ccp_wantoptions[f->unit].require_mppe_stateless ) ++ if ( go->mppe_stateless && ho->mppe_stateless ) ++ notice("stateless MPPE enforced"); ++ else ++ lcp_close(f->unit,"stateless encryption negotiation failed"); ++ else ++ notice("MPPE enforced"); ++ else ++ lcp_close(f->unit,"encryption negotiation failed"); ++ } + } + + /* +@@ -1434,6 +1454,8 @@ + */ + error("Lost compression sync: disabling compression"); + ccp_close(unit, "Lost compression sync"); ++ if ( ccp_wantoptions[unit].require_mppe || ccp_wantoptions[unit].require_mppe_stateless ) ++ lcp_close(unit,"Encryption got out of order"); + } else { + /* MPPE/MPPC does not requires CCP_RESETREQ */ + if (ccp_gotoptions[f->unit].method == CI_MPPE) +diff -ur --new-file ppp-2.3.11/pppd/ccp.h ppp-2.3.11.mppe/pppd/ccp.h +--- ppp-2.3.11/pppd/ccp.h Thu Mar 16 17:47:42 2000 ++++ ppp-2.3.11.mppe/pppd/ccp.h Thu Mar 16 16:25:50 2000 +@@ -38,6 +38,8 @@ + bool mppe_40; /* allow 40 bit encryption */ + bool mppe_128; /* allow 128 bit encryption */ + bool mppe_stateless; /* allow stateless encryption */ ++ bool require_mppe; /* force mppe encryption */ ++ bool require_mppe_stateless; /* force stateless encryption */ + 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 */ +diff -ur --new-file ppp-2.3.11/pppd/mppe.c ppp-2.3.11.mppe/pppd/mppe.c +--- ppp-2.3.11/pppd/mppe.c Thu Mar 16 17:47:42 2000 ++++ ppp-2.3.11.mppe/pppd/mppe.c Thu Mar 16 17:06:34 2000 +@@ -226,4 +226,20 @@ + ccp_allowoptions[0].mppe_stateless = ccp_wantoptions[0].mppe_stateless = 0; + return 1; + } ++ ++int ++require_mppe(char **argv) ++{ ++ ccp_allowoptions[0].require_mppe = ccp_wantoptions[0].require_mppe = 1; ++ return 1; ++} ++ ++int ++require_mppe_stateless(char **argv) ++{ ++ ccp_allowoptions[0].require_mppe = ccp_wantoptions[0].require_mppe = 1; ++ ccp_allowoptions[0].require_mppe_stateless = ccp_wantoptions[0].require_mppe_stateless = 1; ++ return 1; ++} ++ + #endif /* MPPE */ +diff -ur --new-file ppp-2.3.11/pppd/mppe.h ppp-2.3.11.mppe/pppd/mppe.h +--- ppp-2.3.11/pppd/mppe.h Thu Mar 16 17:47:42 2000 ++++ ppp-2.3.11.mppe/pppd/mppe.h Thu Mar 16 16:25:00 2000 +@@ -51,6 +51,8 @@ + int setnomppe_128(char **); + int setmppe_stateless(char **); + int setnomppe_stateless(char **); ++int require_mppe(char **); ++int require_mppe_stateless(char **); + + #define __MPPE_INCLUDE__ + #endif /* __MPPE_INCLUDE__ */