]> git.ozlabs.org Git - ppp.git/commitdiff
pppd: Expose the MPPE keys generated through an API (#267)
authorEivind Næss <eivnaes@yahoo.com>
Sat, 24 Apr 2021 10:00:34 +0000 (03:00 -0700)
committerGitHub <noreply@github.com>
Sat, 24 Apr 2021 10:00:34 +0000 (20:00 +1000)
The lengthy part of this fix is to refactor the handling of MPPE keys
by moving it into mppe.c and thus reducing the clutter in chap_ms.c.
It does so by renaming the mppe_set_keys/2 to the corresponding
mppe_set_chapv1/mppe_set_chapv2 versions and updates callers of these
functions.

Having done so, it conveniently allows the name "mppe_set_keys" to be
re-used for this new purpose which will copy the key material up to
its size and then clear the input parameters (avoids leaving the MPPE
keys on the stack).

Additional functiions added to the MPPE code allow plugins et al. to
access the MPPE keys, clear the keys, and check if they are set. All
plugin and CCP code has been updated to use this API.

This fixes GitHub Issue #258

Signed-off-by: Eivind Naess <eivnaes@yahoo.com>
pppd/Makefile.linux
pppd/Makefile.sol2
pppd/ccp.c
pppd/chap_ms.c
pppd/chap_ms.h
pppd/eap-tls.c
pppd/eap-tls.h
pppd/mppe.c [new file with mode: 0644]
pppd/mppe.h
pppd/plugins/radius/radius.c
pppd/plugins/winbind.c

index f92f7c081a976cb71c4f34578a57d95f3aa136a7..852945e8958edd2e607519ad6a7dc0cfe1cb23e2 100644 (file)
@@ -109,6 +109,8 @@ CFLAGS   += -DMSLANMAN=1
 endif
 ifdef MPPE
 CFLAGS   += -DMPPE=1
 endif
 ifdef MPPE
 CFLAGS   += -DMPPE=1
+PPPDOBJS += mppe.o
+PPPDSRC  += mppe.c
 HEADERS  += mppe.h
 endif
 endif
 HEADERS  += mppe.h
 endif
 endif
index 809cb4b3519fcd4af10e67601300dd707af84921..3a8681ce9167afe93d949262dd79216e46bd848a 100644 (file)
@@ -37,7 +37,7 @@ OBJS  += ipv6cp.o eui64.o
 
 # Uncomment to enable MS-CHAP
 CFLAGS += -DUSE_CRYPT -DCHAPMS -DMSLANMAN -DHAVE_CRYPT_H
 
 # Uncomment to enable MS-CHAP
 CFLAGS += -DUSE_CRYPT -DCHAPMS -DMSLANMAN -DHAVE_CRYPT_H
-OBJS += chap_ms.o pppcrypt.o md4.o sha1.o
+OBJS += chap_ms.o pppcrypt.o md4.o sha1.o mppe.o
 
 # Uncomment to enable MPPE (in both CHAP and EAP-TLS)
 CFLAGS += -DMPPE
 
 # Uncomment to enable MPPE (in both CHAP and EAP-TLS)
 CFLAGS += -DMPPE
index 052c4c61081bdc74489ea282e8e0df46ed1891fc..387b571d3db8cf4deec012a8888d51eab80891b9 100644 (file)
 #include "ccp.h"
 #include <net/ppp-comp.h>
 
 #include "ccp.h"
 #include <net/ppp-comp.h>
 
-#ifdef MPPE
-#include "chap_ms.h"   /* mppe_xxxx_key, mppe_keys_set */
+#include "chap_ms.h"
+#include "mppe.h"
 #include "lcp.h"       /* lcp_close(), lcp_fsm */
 #include "lcp.h"       /* lcp_close(), lcp_fsm */
-#endif
 
 
 /*
 
 
 /*
@@ -574,7 +573,7 @@ ccp_resetci(fsm *f)
        }
 
        /* A plugin (eg radius) may not have obtained key material. */
        }
 
        /* A plugin (eg radius) may not have obtained key material. */
-       if (!mppe_keys_set) {
+       if (!mppe_keys_isset()) {
            error("MPPE required, but keys are not available.  "
                  "Possible plugin problem?");
            lcp_close(f->unit, "MPPE required but not available");
            error("MPPE required, but keys are not available.  "
                  "Possible plugin problem?");
            lcp_close(f->unit, "MPPE required but not available");
@@ -705,7 +704,7 @@ static void
        p[1] = opt_buf[1] = CILEN_MPPE;
        MPPE_OPTS_TO_CI(go->mppe, &p[2]);
        MPPE_OPTS_TO_CI(go->mppe, &opt_buf[2]);
        p[1] = opt_buf[1] = CILEN_MPPE;
        MPPE_OPTS_TO_CI(go->mppe, &p[2]);
        MPPE_OPTS_TO_CI(go->mppe, &opt_buf[2]);
-       BCOPY(mppe_recv_key, &opt_buf[CILEN_MPPE], MPPE_MAX_KEY_LEN);
+       mppe_get_recv_key(&opt_buf[CILEN_MPPE], MPPE_MAX_KEY_LEN);
        res = ccp_test(f->unit, opt_buf, CILEN_MPPE + MPPE_MAX_KEY_LEN, 0);
        if (res > 0)
            p += CILEN_MPPE;
        res = ccp_test(f->unit, opt_buf, CILEN_MPPE + MPPE_MAX_KEY_LEN, 0);
        if (res > 0)
            p += CILEN_MPPE;
@@ -1156,8 +1155,7 @@ ccp_reqci(fsm *f, u_char *p, int *lenp, int dont_nak)
                    int mtu;
 
                    BCOPY(p, opt_buf, CILEN_MPPE);
                    int mtu;
 
                    BCOPY(p, opt_buf, CILEN_MPPE);
-                   BCOPY(mppe_send_key, &opt_buf[CILEN_MPPE],
-                         MPPE_MAX_KEY_LEN);
+                   mppe_get_send_key(&opt_buf[CILEN_MPPE], MPPE_MAX_KEY_LEN);
                    if (ccp_test(f->unit, opt_buf,
                                 CILEN_MPPE + MPPE_MAX_KEY_LEN, 1) <= 0) {
                        /* This shouldn't happen, we've already tested it! */
                    if (ccp_test(f->unit, opt_buf,
                                 CILEN_MPPE + MPPE_MAX_KEY_LEN, 1) <= 0) {
                        /* This shouldn't happen, we've already tested it! */
@@ -1426,8 +1424,7 @@ ccp_up(fsm *f)
        notice("%s transmit compression enabled", method_name(ho, NULL));
 #ifdef MPPE
     if (go->mppe) {
        notice("%s transmit compression enabled", method_name(ho, NULL));
 #ifdef MPPE
     if (go->mppe) {
-       BZERO(mppe_recv_key, MPPE_MAX_KEY_LEN);
-       BZERO(mppe_send_key, MPPE_MAX_KEY_LEN);
+       mppe_clear_keys();
        continue_networks(f->unit);             /* Bring up IP et al */
     }
 #endif
        continue_networks(f->unit);             /* Bring up IP et al */
     }
 #endif
index df2dadd1220efcf354ebc0d628c5c7700f5a99ab..d315ab4acd0182258fb25bee21f472e2d021f42b 100644 (file)
@@ -93,8 +93,7 @@
 #include "sha1.h"
 #include "pppcrypt.h"
 #include "magic.h"
 #include "sha1.h"
 #include "pppcrypt.h"
 #include "magic.h"
-
-
+#include "mppe.h"
 
 static void    ascii2unicode (char[], int, u_char[]);
 static void    NTPasswordHash (u_char *, int, u_char[MD4_SIGNATURE_SIZE]);
 
 static void    ascii2unicode (char[], int, u_char[]);
 static void    NTPasswordHash (u_char *, int, u_char[MD4_SIGNATURE_SIZE]);
@@ -109,21 +108,12 @@ static void       GenerateAuthenticatorResponsePlain
 static void    ChapMS_LANMan (u_char *, char *, int, u_char *);
 #endif
 
 static void    ChapMS_LANMan (u_char *, char *, int, u_char *);
 #endif
 
-#ifdef MPPE
-static void    Set_Start_Key (u_char *, char *, int);
-static void    SetMasterKeys (char *, int, u_char[24], int);
-#endif
-
 #ifdef MSLANMAN
 bool   ms_lanman = 0;          /* Use LanMan password instead of NT */
                                /* Has meaning only with MS-CHAP challenges */
 #endif
 
 #ifdef MPPE
 #ifdef MSLANMAN
 bool   ms_lanman = 0;          /* Use LanMan password instead of NT */
                                /* Has meaning only with MS-CHAP challenges */
 #endif
 
 #ifdef MPPE
-u_char mppe_send_key[MPPE_MAX_KEY_LEN];
-u_char mppe_recv_key[MPPE_MAX_KEY_LEN];
-int mppe_keys_set = 0;         /* Have the MPPE keys been set? */
-
 #ifdef DEBUGMPPEKEY
 /* For MPPE debug */
 /* Use "[]|}{?/><,`!2&&(" (sans quotes) for RFC 3079 MS-CHAPv2 test value */
 #ifdef DEBUGMPPEKEY
 /* For MPPE debug */
 /* Use "[]|}{?/><,`!2&&(" (sans quotes) for RFC 3079 MS-CHAPv2 test value */
@@ -719,28 +709,6 @@ GenerateAuthenticatorResponsePlain
 
 
 #ifdef MPPE
 
 
 #ifdef MPPE
-/*
- * Set mppe_xxxx_key from the NTPasswordHashHash.
- * RFC 2548 (RADIUS support) requires us to export this function (ugh).
- */
-void
-mppe_set_keys(u_char *rchallenge, u_char PasswordHashHash[MD4_SIGNATURE_SIZE])
-{
-    SHA1_CTX   sha1Context;
-    u_char     Digest[SHA1_SIGNATURE_SIZE];    /* >= MPPE_MAX_KEY_LEN */
-
-    SHA1_Init(&sha1Context);
-    SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE);
-    SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE);
-    SHA1_Update(&sha1Context, rchallenge, 8);
-    SHA1_Final(Digest, &sha1Context);
-
-    /* Same key in both directions. */
-    BCOPY(Digest, mppe_send_key, sizeof(mppe_send_key));
-    BCOPY(Digest, mppe_recv_key, sizeof(mppe_recv_key));
-
-    mppe_keys_set = 1;
-}
 
 /*
  * Set mppe_xxxx_key from MS-CHAP credentials. (see RFC 3079)
 
 /*
  * Set mppe_xxxx_key from MS-CHAP credentials. (see RFC 3079)
@@ -757,104 +725,7 @@ Set_Start_Key(u_char *rchallenge, char *secret, int secret_len)
     NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash);
     NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash);
 
     NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash);
     NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash);
 
-    mppe_set_keys(rchallenge, PasswordHashHash);
-}
-
-/*
- * Set mppe_xxxx_key from MS-CHAPv2 credentials. (see RFC 3079)
- *
- * This helper function used in the Winbind module, which gets the
- * NTHashHash from the server.
- */
-void
-mppe_set_keys2(u_char PasswordHashHash[MD4_SIGNATURE_SIZE],
-              u_char NTResponse[24], int IsServer)
-{
-    SHA1_CTX   sha1Context;
-    u_char     MasterKey[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */
-    u_char     Digest[SHA1_SIGNATURE_SIZE];    /* >= MPPE_MAX_KEY_LEN */
-
-    u_char SHApad1[40] =
-       { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-    u_char SHApad2[40] =
-       { 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
-         0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
-         0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
-         0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2 };
-
-    /* "This is the MPPE Master Key" */
-    u_char Magic1[27] =
-       { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
-         0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
-         0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79 };
-    /* "On the client side, this is the send key; "
-       "on the server side, it is the receive key." */
-    u_char Magic2[84] =
-       { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
-         0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
-         0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
-         0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
-         0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
-         0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
-         0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
-         0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
-         0x6b, 0x65, 0x79, 0x2e };
-    /* "On the client side, this is the receive key; "
-       "on the server side, it is the send key." */
-    u_char Magic3[84] =
-       { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
-         0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
-         0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
-         0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
-         0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
-         0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
-         0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
-         0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
-         0x6b, 0x65, 0x79, 0x2e };
-    u_char *s;
-
-    SHA1_Init(&sha1Context);
-    SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE);
-    SHA1_Update(&sha1Context, NTResponse, 24);
-    SHA1_Update(&sha1Context, Magic1, sizeof(Magic1));
-    SHA1_Final(MasterKey, &sha1Context);
-
-    /*
-     * generate send key
-     */
-    if (IsServer)
-       s = Magic3;
-    else
-       s = Magic2;
-    SHA1_Init(&sha1Context);
-    SHA1_Update(&sha1Context, MasterKey, 16);
-    SHA1_Update(&sha1Context, SHApad1, sizeof(SHApad1));
-    SHA1_Update(&sha1Context, s, 84);
-    SHA1_Update(&sha1Context, SHApad2, sizeof(SHApad2));
-    SHA1_Final(Digest, &sha1Context);
-
-    BCOPY(Digest, mppe_send_key, sizeof(mppe_send_key));
-
-    /*
-     * generate recv key
-     */
-    if (IsServer)
-       s = Magic2;
-    else
-       s = Magic3;
-    SHA1_Init(&sha1Context);
-    SHA1_Update(&sha1Context, MasterKey, 16);
-    SHA1_Update(&sha1Context, SHApad1, sizeof(SHApad1));
-    SHA1_Update(&sha1Context, s, 84);
-    SHA1_Update(&sha1Context, SHApad2, sizeof(SHApad2));
-    SHA1_Final(Digest, &sha1Context);
-
-    BCOPY(Digest, mppe_recv_key, sizeof(mppe_recv_key));
-
-    mppe_keys_set = 1;
+    mppe_set_chapv1(rchallenge, PasswordHashHash);
 }
 
 /*
 }
 
 /*
@@ -870,7 +741,7 @@ SetMasterKeys(char *secret, int secret_len, u_char NTResponse[24], int IsServer)
     ascii2unicode(secret, secret_len, unicodePassword);
     NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash);
     NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash);
     ascii2unicode(secret, secret_len, unicodePassword);
     NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash);
     NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash);
-    mppe_set_keys2(PasswordHashHash, NTResponse, IsServer);
+    mppe_set_chapv2(PasswordHashHash, NTResponse, IsServer);
 }
 
 #endif /* MPPE */
 }
 
 #endif /* MPPE */
@@ -945,38 +816,6 @@ ChapMS2(u_char *rchallenge, u_char *PeerChallenge,
 #endif
 }
 
 #endif
 }
 
-#ifdef MPPE
-/*
- * Set MPPE options from plugins.
- */
-void
-set_mppe_enc_types(int policy, int types)
-{
-    /* Early exit for unknown policies. */
-    if (policy != MPPE_ENC_POL_ENC_ALLOWED &&
-       policy != MPPE_ENC_POL_ENC_REQUIRED)
-       return;
-
-    /* Don't modify MPPE if it's optional and wasn't already configured. */
-    if (policy == MPPE_ENC_POL_ENC_ALLOWED && !ccp_wantoptions[0].mppe)
-       return;
-
-    /*
-     * Disable undesirable encryption types.  Note that we don't ENABLE
-     * any encryption types, to avoid overriding manual configuration.
-     */
-    switch(types) {
-       case MPPE_ENC_TYPES_RC4_40:
-           ccp_wantoptions[0].mppe &= ~MPPE_OPT_128;   /* disable 128-bit */
-           break;
-       case MPPE_ENC_TYPES_RC4_128:
-           ccp_wantoptions[0].mppe &= ~MPPE_OPT_40;    /* disable 40-bit */
-           break;
-       default:
-           break;
-    }
-}
-#endif /* MPPE */
 
 static struct chap_digest_type chapms_digest = {
        CHAP_MICROSOFT,         /* code */
 
 static struct chap_digest_type chapms_digest = {
        CHAP_MICROSOFT,         /* code */
index 005eb63bc6dfb38987d977d78e50f5b9535402e0..4e6a62113c5be3573432fb018c044cd01459a010 100644 (file)
@@ -38,6 +38,7 @@
 #define MS_CHAP_RESPONSE_LEN   49      /* Response length for MS-CHAP */
 #define MS_CHAP2_RESPONSE_LEN  49      /* Response length for MS-CHAPv2 */
 #define MS_AUTH_RESPONSE_LENGTH        40      /* MS-CHAPv2 authenticator response, */
 #define MS_CHAP_RESPONSE_LEN   49      /* Response length for MS-CHAP */
 #define MS_CHAP2_RESPONSE_LEN  49      /* Response length for MS-CHAPv2 */
 #define MS_AUTH_RESPONSE_LENGTH        40      /* MS-CHAPv2 authenticator response, */
+#define MS_AUTH_NTRESP_LEN      24  /* Length of NT-response field */
                                        /* as ASCII */
 
 /* E=eeeeeeeeee error codes for MS-CHAP failure messages. */
                                        /* as ASCII */
 
 /* E=eeeeeeeeee error codes for MS-CHAP failure messages. */
 #define MS_CHAP2_NTRESP_LEN    24
 #define MS_CHAP2_FLAGS         48
 
 #define MS_CHAP2_NTRESP_LEN    24
 #define MS_CHAP2_FLAGS         48
 
-#ifdef MPPE
-#include "mppe.h"      /* MPPE_MAX_KEY_LEN */
-extern u_char mppe_send_key[MPPE_MAX_KEY_LEN];
-extern u_char mppe_recv_key[MPPE_MAX_KEY_LEN];
-extern int mppe_keys_set;
-
-/* These values are the RADIUS attribute values--see RFC 2548. */
-#define MPPE_ENC_POL_ENC_ALLOWED 1
-#define MPPE_ENC_POL_ENC_REQUIRED 2
-#define MPPE_ENC_TYPES_RC4_40 2
-#define MPPE_ENC_TYPES_RC4_128 4
-
-/* used by plugins (using above values) */
-extern void set_mppe_enc_types(int, int);
-#endif
-
 /* Are we the authenticator or authenticatee?  For MS-CHAPv2 key derivation. */
 #define MS_CHAP2_AUTHENTICATEE 0
 #define MS_CHAP2_AUTHENTICATOR 1
 /* Are we the authenticator or authenticatee?  For MS-CHAPv2 key derivation. */
 #define MS_CHAP2_AUTHENTICATEE 0
 #define MS_CHAP2_AUTHENTICATOR 1
@@ -90,11 +75,6 @@ extern void set_mppe_enc_types(int, int);
 void ChapMS (u_char *, char *, int, u_char *);
 void ChapMS2 (u_char *, u_char *, char *, char *, int,
              u_char *, u_char[MS_AUTH_RESPONSE_LENGTH+1], int);
 void ChapMS (u_char *, char *, int, u_char *);
 void ChapMS2 (u_char *, u_char *, char *, char *, int,
              u_char *, u_char[MS_AUTH_RESPONSE_LENGTH+1], int);
-#ifdef MPPE
-void mppe_set_keys (u_char *, u_char[MD4_SIGNATURE_SIZE]);
-void mppe_set_keys2(u_char PasswordHashHash[MD4_SIGNATURE_SIZE],
-                   u_char NTResponse[24], int IsServer);
-#endif
 
 void   ChallengeHash (u_char[16], u_char *, char *, u_char[8]);
 
 
 void   ChallengeHash (u_char[16], u_char *, char *, u_char[8]);
 
index 5c202c72bd3ded7bb1d771791157be92cbe6148f..bfcf199635d7532990cb3a5153cbc3e6269edcb1 100644 (file)
@@ -48,6 +48,8 @@
 #include "eap-tls.h"
 #include "fsm.h"
 #include "lcp.h"
 #include "eap-tls.h"
 #include "fsm.h"
 #include "lcp.h"
+#include "chap_ms.h"
+#include "mppe.h"
 #include "pathnames.h"
 
 typedef struct pw_cb_data
 #include "pathnames.h"
 
 typedef struct pw_cb_data
@@ -74,10 +76,6 @@ int ssl_new_session_cb(SSL *s, SSL_SESSION *sess);
 X509 *get_X509_from_file(char *filename);
 int ssl_cmp_certs(char *filename, X509 * a); 
 
 X509 *get_X509_from_file(char *filename);
 int ssl_cmp_certs(char *filename, X509 * a); 
 
-#ifdef MPPE
-
-#define EAPTLS_MPPE_KEY_LEN     32
-
 /*
  *  OpenSSL 1.1+ introduced a generic TLS_method()
  *  For older releases we substitute the appropriate method
 /*
  *  OpenSSL 1.1+ introduced a generic TLS_method()
  *  For older releases we substitute the appropriate method
@@ -119,6 +117,8 @@ static inline int SSL_CTX_set_max_proto_version(SSL_CTX *ctx, long tls_ver_max)
 
 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
 
 
 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
 
+#ifdef MPPE
+#define EAPTLS_MPPE_KEY_LEN     32
 
 /*
  *  Generate keys according to RFC 2716 and add to reply
 
 /*
  *  Generate keys according to RFC 2716 and add to reply
@@ -161,24 +161,17 @@ void eaptls_gen_mppe_keys(struct eaptls_session *ets, int client)
      */
     if (client)
     {
      */
     if (client)
     {
-        p = out;
-        BCOPY( p, mppe_send_key, sizeof(mppe_send_key) );
-        p += EAPTLS_MPPE_KEY_LEN;
-        BCOPY( p, mppe_recv_key, sizeof(mppe_recv_key) );
+        mppe_set_keys(out, out + EAPTLS_MPPE_KEY_LEN, EAPTLS_MPPE_KEY_LEN);
     }
     else
     {
     }
     else
     {
-        p = out;
-        BCOPY( p, mppe_recv_key, sizeof(mppe_recv_key) );
-        p += EAPTLS_MPPE_KEY_LEN;
-        BCOPY( p, mppe_send_key, sizeof(mppe_send_key) );
+        mppe_set_keys(out + EAPTLS_MPPE_KEY_LEN, out, EAPTLS_MPPE_KEY_LEN);
     }
     }
-
-    mppe_keys_set = 1;
 }
 
 #endif /* MPPE */
 
 }
 
 #endif /* MPPE */
 
+
 void log_ssl_errors( void )
 {
     unsigned long ssl_err = ERR_get_error();
 void log_ssl_errors( void )
 {
     unsigned long ssl_err = ERR_get_error();
index c74a831671faee87ef87749f4904044ec9c8f767..b935ec524321d5952979b03299f6ba9b862f69e4 100644 (file)
@@ -86,11 +86,6 @@ int get_eaptls_secret(int unit, char *client, char *server,
               char *capath, char *pkfile, int am_server);
 
 #ifdef MPPE
               char *capath, char *pkfile, int am_server);
 
 #ifdef MPPE
-#include "mppe.h"   /* MPPE_MAX_KEY_LEN */
-extern u_char mppe_send_key[MPPE_MAX_KEY_LEN];
-extern u_char mppe_recv_key[MPPE_MAX_KEY_LEN];
-extern int mppe_keys_set;
-
 void eaptls_gen_mppe_keys(struct eaptls_session *ets, int client);
 #endif
 
 void eaptls_gen_mppe_keys(struct eaptls_session *ets, int client);
 #endif
 
diff --git a/pppd/mppe.c b/pppd/mppe.c
new file mode 100644 (file)
index 0000000..4f3d131
--- /dev/null
@@ -0,0 +1,248 @@
+/* * mppe.c - MPPE key implementation
+ *
+ * Copyright (c) 2020 Eivind Naess. All rights reserved.
+ * Copyright (c) 2008 Paul Mackerras. 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. The name(s) of the authors of this software must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission.
+ *
+ * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
+ * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include <string.h>
+
+#include "pppd.h"
+#include "fsm.h"
+#include "md4.h"
+#include "sha1.h"
+#include "ccp.h"
+#include "chap_ms.h"
+#include "mppe.h"
+
+u_char mppe_send_key[MPPE_MAX_KEY_SIZE];
+u_char mppe_recv_key[MPPE_MAX_KEY_SIZE];
+int mppe_keys_set = 0;
+
+void
+mppe_set_keys(u_char *send_key, u_char *recv_key, int keylen)
+{
+       int length = keylen;
+       if (length > MPPE_MAX_KEY_SIZE)
+               length = MPPE_MAX_KEY_SIZE;
+       
+       if (send_key) {
+           BCOPY(send_key, mppe_send_key, length);
+           BZERO(send_key, keylen);
+       }
+
+       if (recv_key) {
+           BCOPY(recv_key, mppe_recv_key, length);
+           BZERO(recv_key, keylen);
+       }
+
+       mppe_keys_set = length;
+}
+
+bool
+mppe_keys_isset()
+{
+       return !!mppe_keys_set;
+}
+
+int
+mppe_get_recv_key(u_char *recv_key, int length)
+{
+       if (mppe_keys_isset()) {
+               if (length > mppe_keys_set)
+                       length = mppe_keys_set;
+               BCOPY(mppe_recv_key, recv_key, length);
+               return length;
+       }
+       return 0;
+}
+
+int
+mppe_get_send_key(u_char *send_key, int length)
+{
+       if (mppe_keys_isset()) {
+               if (length > mppe_keys_set)
+                       length = mppe_keys_set;
+               BCOPY(mppe_send_key, send_key, length);
+               return length;
+       }
+       return 0;
+}
+
+void
+mppe_clear_keys(void)
+{
+       mppe_keys_set = 0;
+       BZERO(mppe_send_key, sizeof(mppe_send_key));
+       BZERO(mppe_recv_key, sizeof(mppe_recv_key));
+}
+
+/*
+ * Set mppe_xxxx_key from the NTPasswordHashHash.
+ * RFC 2548 (RADIUS support) requires us to export this function (ugh).
+ */
+void
+mppe_set_chapv1(u_char *rchallenge, u_char PasswordHashHash[MD4_SIGNATURE_SIZE])
+{
+    SHA1_CTX   sha1Context;
+    u_char     Digest[SHA1_SIGNATURE_SIZE];
+
+    SHA1_Init(&sha1Context);
+    SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE);
+    SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE);
+    SHA1_Update(&sha1Context, rchallenge, 8);
+    SHA1_Final(Digest, &sha1Context);
+
+    /* Same key in both directions. */
+    mppe_set_keys(Digest, Digest, sizeof(Digest));
+}
+
+/*
+ * Set mppe_xxxx_key from MS-CHAPv2 credentials. (see RFC 3079)
+ *
+ * This helper function used in the Winbind module, which gets the
+ * NTHashHash from the server.
+ */
+void
+mppe_set_chapv2(u_char PasswordHashHash[MD4_SIGNATURE_SIZE],
+              u_char NTResponse[MS_AUTH_NTRESP_LEN], int IsServer)
+{
+    SHA1_CTX   sha1Context;
+    u_char     MasterKey[SHA1_SIGNATURE_SIZE];
+    u_char     SendKey[SHA1_SIGNATURE_SIZE];
+    u_char     RecvKey[SHA1_SIGNATURE_SIZE];
+
+    u_char SHApad1[40] =
+       { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+    u_char SHApad2[40] =
+       { 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
+         0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
+         0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
+         0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2 };
+
+    /* "This is the MPPE Master Key" */
+    u_char Magic1[27] =
+       { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
+         0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
+         0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79 };
+    /* "On the client side, this is the send key; "
+       "on the server side, it is the receive key." */
+    u_char Magic2[84] =
+       { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
+         0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
+         0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
+         0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
+         0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+         0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
+         0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
+         0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
+         0x6b, 0x65, 0x79, 0x2e };
+    /* "On the client side, this is the receive key; "
+       "on the server side, it is the send key." */
+    u_char Magic3[84] =
+       { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
+         0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
+         0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
+         0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
+         0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+         0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
+         0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
+         0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
+         0x6b, 0x65, 0x79, 0x2e };
+    u_char *s;
+
+    SHA1_Init(&sha1Context);
+    SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE);
+    SHA1_Update(&sha1Context, NTResponse, 24);
+    SHA1_Update(&sha1Context, Magic1, sizeof(Magic1));
+    SHA1_Final(MasterKey, &sha1Context);
+
+    /*
+     * generate send key
+     */
+    if (IsServer)
+       s = Magic3;
+    else
+       s = Magic2;
+    SHA1_Init(&sha1Context);
+    SHA1_Update(&sha1Context, MasterKey, 16);
+    SHA1_Update(&sha1Context, SHApad1, sizeof(SHApad1));
+    SHA1_Update(&sha1Context, s, 84);
+    SHA1_Update(&sha1Context, SHApad2, sizeof(SHApad2));
+    SHA1_Final(SendKey, &sha1Context);
+
+    /*
+     * generate recv key
+     */
+    if (IsServer)
+       s = Magic2;
+    else
+       s = Magic3;
+    SHA1_Init(&sha1Context);
+    SHA1_Update(&sha1Context, MasterKey, 16);
+    SHA1_Update(&sha1Context, SHApad1, sizeof(SHApad1));
+    SHA1_Update(&sha1Context, s, 84);
+    SHA1_Update(&sha1Context, SHApad2, sizeof(SHApad2));
+    SHA1_Final(RecvKey, &sha1Context);
+
+    mppe_set_keys(SendKey, RecvKey, SHA1_SIGNATURE_SIZE);
+}
+
+/*
+ * Set MPPE options from plugins.
+ */
+void
+mppe_set_enc_types(int policy, int types)
+{
+    /* Early exit for unknown policies. */
+    if (policy != MPPE_ENC_POL_ENC_ALLOWED &&
+       policy != MPPE_ENC_POL_ENC_REQUIRED)
+       return;
+
+    /* Don't modify MPPE if it's optional and wasn't already configured. */
+    if (policy == MPPE_ENC_POL_ENC_ALLOWED && !ccp_wantoptions[0].mppe)
+       return;
+
+    /*
+     * Disable undesirable encryption types.  Note that we don't ENABLE
+     * any encryption types, to avoid overriding manual configuration.
+     */
+    switch(types) {
+       case MPPE_ENC_TYPES_RC4_40:
+           ccp_wantoptions[0].mppe &= ~MPPE_OPT_128;   /* disable 128-bit */
+           break;
+       case MPPE_ENC_TYPES_RC4_128:
+           ccp_wantoptions[0].mppe &= ~MPPE_OPT_40;    /* disable 40-bit */
+           break;
+       default:
+           break;
+    }
+}
+
index 5eb3b37a99d65966e0ead25e9265a7db7f11a2bc..98a89d3043e77463adc3140ee0ca48c47a661998 100644 (file)
  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
+#ifndef __MPPE_H__
+#define __MPPE_H__
 
 #define MPPE_PAD               4       /* MPPE growth per frame */
 
 #define MPPE_PAD               4       /* MPPE growth per frame */
-#define MPPE_MAX_KEY_LEN       16      /* largest key length (128-bit) */
+#define MPPE_MAX_KEY_SIZE      32      /* Largest key length */
+#define MPPE_MAX_KEY_LEN       16      /* Largest key size accepted by the kernel */
 
 /* option bits for ccp_options.mppe */
 #define MPPE_OPT_40            0x01    /* 40 bit */
 
 /* option bits for ccp_options.mppe */
 #define MPPE_OPT_40            0x01    /* 40 bit */
        if (ptr[3] & ~MPPE_ALL_BITS)            \
            opts |= MPPE_OPT_UNKNOWN;           \
     } while (/* CONSTCOND */ 0)
        if (ptr[3] & ~MPPE_ALL_BITS)            \
            opts |= MPPE_OPT_UNKNOWN;           \
     } while (/* CONSTCOND */ 0)
+
+
+#if MPPE
+
+/*
+ * NOTE:
+ *   Access to these variables directly is discuraged. Please
+ *   change your code to use below accessor functions.
+ */
+
+/* The key material generated which is used for MPPE send key */
+extern u_char mppe_send_key[MPPE_MAX_KEY_SIZE];
+/* The key material generated which is used for MPPE recv key */
+extern u_char mppe_recv_key[MPPE_MAX_KEY_SIZE];
+/* Keys are set if value is non-zero */
+extern int mppe_keys_set;
+
+/* These values are the RADIUS attribute values--see RFC 2548. */
+#define MPPE_ENC_POL_ENC_ALLOWED 1
+#define MPPE_ENC_POL_ENC_REQUIRED 2
+#define MPPE_ENC_TYPES_RC4_40 2
+#define MPPE_ENC_TYPES_RC4_128 4
+
+/* used by plugins (using above values) */
+void mppe_set_enc_types (int policy, int types);
+
+/*
+ * Set the MPPE send and recv keys. NULL values for keys are ignored
+ *   and input values are cleared to avoid leaving them on the stack
+ */
+void mppe_set_keys(u_char *send_key, u_char *recv_key, int keylen);
+
+/*
+ * Get the MPPE recv key
+ */
+int mppe_get_recv_key(u_char *recv_key, int length);
+
+/*
+ * Get the MPPE send key
+ */
+int mppe_get_send_key(u_char *send_key, int length);
+
+/*
+ * Clear the MPPE keys
+ */
+void mppe_clear_keys(void);
+
+/*
+ * Check if the MPPE keys are set
+ */
+bool mppe_keys_isset(void);
+
+/*
+ * Set mppe_xxxx_key from NT Password Hash Hash (MSCHAPv1), see RFC3079
+ */
+void mppe_set_chapv1(u_char *rchallenge, u_char PasswordHashHash[MD4_SIGNATURE_SIZE]);
+
+/*
+ * Set the mppe_xxxx_key from MS-CHAP-v2 credentials, see RFC3079
+ */
+void mppe_set_chapv2(u_char PasswordHashHash[MD4_SIGNATURE_SIZE],
+                   u_char NTResponse[MS_AUTH_NTRESP_LEN], int IsServer);
+
+#endif  // #ifdef MPPE
+#endif  // #ifdef __MPPE_H__
index c5798316719af431a6f1dc6926845bde76b95b88..cf4c0f2adf395d24a6f2bd72d48fb600886802e5 100644 (file)
@@ -31,6 +31,7 @@ static char const RCSID[] =
 #ifdef CHAPMS
 #include "chap_ms.h"
 #ifdef MPPE
 #ifdef CHAPMS
 #include "chap_ms.h"
 #ifdef MPPE
+#include "mppe.h"
 #include "md5.h"
 #endif
 #endif
 #include "md5.h"
 #endif
 #endif
@@ -743,11 +744,12 @@ radius_setparams(VALUE_PAIR *vp, char *msg, REQUEST_INFO *req_info,
      * Note that if the policy value was '0' we don't set the key!
      */
     if (mppe_enc_policy && mppe_enc_keys) {
      * Note that if the policy value was '0' we don't set the key!
      */
     if (mppe_enc_policy && mppe_enc_keys) {
-       mppe_keys_set = 1;
        /* Set/modify allowed encryption types. */
        if (mppe_enc_types)
        /* Set/modify allowed encryption types. */
        if (mppe_enc_types)
-           set_mppe_enc_types(mppe_enc_policy, mppe_enc_types);
+           mppe_set_enc_types(mppe_enc_policy, mppe_enc_types);
+       return 0;
     }
     }
+    mppe_clear_keys();
 #endif
 
     return 0;
 #endif
 
     return 0;
@@ -803,7 +805,7 @@ radius_setmppekeys(VALUE_PAIR *vp, REQUEST_INFO *req_info,
      * the NAS (us) doesn't need; we only need the start key.  So we have
      * to generate the start key, sigh.  NB: We do not support the LM-Key.
      */
      * the NAS (us) doesn't need; we only need the start key.  So we have
      * to generate the start key, sigh.  NB: We do not support the LM-Key.
      */
-    mppe_set_keys(challenge, &plain[8]);
+    mppe_set_chapv1(challenge, &plain[8]);
 
     return 0;    
 }
 
     return 0;    
 }
@@ -855,7 +857,7 @@ radius_setmppekeys2(VALUE_PAIR *vp, REQUEST_INFO *req_info)
     for (i = 0; i < 16; i++)
        plain[i] ^= buf[i];
 
     for (i = 0; i < 16; i++)
        plain[i] ^= buf[i];
 
-    if (plain[0] != sizeof(mppe_send_key) /* 16 */) {
+    if (plain[0] != 16) {
        error("RADIUS: Incorrect key length (%d) for MS-MPPE-%s-Key attribute",
              (int) plain[0], type);
        return -1;
        error("RADIUS: Incorrect key length (%d) for MS-MPPE-%s-Key attribute",
              (int) plain[0], type);
        return -1;
@@ -869,9 +871,9 @@ radius_setmppekeys2(VALUE_PAIR *vp, REQUEST_INFO *req_info)
     plain[16] ^= buf[0]; /* only need the first byte */
 
     if (vp->attribute == PW_MS_MPPE_SEND_KEY)
     plain[16] ^= buf[0]; /* only need the first byte */
 
     if (vp->attribute == PW_MS_MPPE_SEND_KEY)
-       memcpy(mppe_send_key, plain + 1, 16);
+       mppe_set_keys(plain + 1, NULL, 16);
     else
     else
-       memcpy(mppe_recv_key, plain + 1, 16);
+       mppe_set_keys(NULL, plain + 1, 16);
 
     return 0;
 }
 
     return 0;
 }
index 0c395c34711af6cef39d3ac01e3603f7205ebbc5..67c72f65ef3f0533e5a648bb8dda7647401f44ce 100644 (file)
 #include "pppd.h"
 #include "chap-new.h"
 #include "chap_ms.h"
 #include "pppd.h"
 #include "chap-new.h"
 #include "chap_ms.h"
-#ifdef MPPE
-#include "md5.h"
-#endif
 #include "fsm.h"
 #include "ipcp.h"
 #include "fsm.h"
 #include "ipcp.h"
+#include "mppe.h"
 #include <syslog.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <syslog.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -583,7 +581,7 @@ winbind_chap_verify(char *user, char *ourname, int id,
                                  nt_response, nt_response_size,
                                  session_key,
                                  &error_string) == AUTHENTICATED) {
                                  nt_response, nt_response_size,
                                  session_key,
                                  &error_string) == AUTHENTICATED) {
-                       mppe_set_keys(challenge, session_key);
+                       mppe_set_chapv1(challenge, session_key);
                        slprintf(message, message_space, "Access granted");
                        return AUTHENTICATED;
                        
                        slprintf(message, message_space, "Access granted");
                        return AUTHENTICATED;
                        
@@ -628,7 +626,7 @@ winbind_chap_verify(char *user, char *ourname, int id,
                                &response[MS_CHAP2_NTRESP],
                                &response[MS_CHAP2_PEER_CHALLENGE],
                                challenge, user, saresponse);
                                &response[MS_CHAP2_NTRESP],
                                &response[MS_CHAP2_PEER_CHALLENGE],
                                challenge, user, saresponse);
-                       mppe_set_keys2(session_key, &response[MS_CHAP2_NTRESP],
+                       mppe_set_chapv2(session_key, &response[MS_CHAP2_NTRESP],
                                       MS_CHAP2_AUTHENTICATOR);
                        if (response[MS_CHAP2_FLAGS]) {
                                slprintf(message, message_space, "S=%s", saresponse);
                                       MS_CHAP2_AUTHENTICATOR);
                        if (response[MS_CHAP2_FLAGS]) {
                                slprintf(message, message_space, "S=%s", saresponse);