diff -Nru ppp-2.4.9/debian/changelog ppp-2.4.9/debian/changelog --- ppp-2.4.9/debian/changelog 2021-12-01 16:11:26.000000000 +0000 +++ ppp-2.4.9/debian/changelog 2022-02-24 17:14:02.000000000 +0000 @@ -1,3 +1,13 @@ +ppp (2.4.9-1+1ubuntu3~ppa1) jammy; urgency=medium + + * d/p/eap-mschap-v2-namelen.patch: fix the length of the username when + responding to an EAP MSCHAPv2 challenge (LP: #1958196). + * d/p/expose-mppe-keys-via-api.patch: allow plugins to access MPPE keys to + enable external SSTP support. + * Thanks to Eivind Næss. + + -- Robie Basak Thu, 24 Feb 2022 17:14:02 +0000 + ppp (2.4.9-1+1ubuntu2) jammy; urgency=medium * No-change rebuild against openssl3 diff -Nru ppp-2.4.9/debian/patches/eap-mschap-v2-namelen.patch ppp-2.4.9/debian/patches/eap-mschap-v2-namelen.patch --- ppp-2.4.9/debian/patches/eap-mschap-v2-namelen.patch 1970-01-01 00:00:00.000000000 +0000 +++ ppp-2.4.9/debian/patches/eap-mschap-v2-namelen.patch 2022-02-24 17:14:02.000000000 +0000 @@ -0,0 +1,22 @@ +Description: This fixes the length of the username when responding to an EAP + MSCHAPv2 challenge. + . + [rbasak] + Also see the discussion in the MP: + https://code.launchpad.net/~eivnaes/ubuntu/+source/ppp/+git/ppp/+merge/415397 +Author: Eivind Næss +Acked-By: Robie Basak +Origin: upstream, https://github.com/ppp-project/ppp/commit/d7e62a8499c4032d79e05afbd8fd3efd51c5b148 +Bug-Ubuntu: https://launchpad.net/bugs/1958196 +Last-Update: 2022-02-24 + +--- a/pppd/eap.c ++++ b/pppd/eap.c +@@ -2261,6 +2261,7 @@ + eap_send_nak(esp, id, EAPT_SRP); + break; + } ++ esp->es_client.ea_namelen = strlen(esp->es_client.ea_name); + + /* Create the MSCHAPv2 response (and add to cache) */ + unsigned char response[MS_CHAP2_RESPONSE_LEN+1]; // VLEN + VALUE diff -Nru ppp-2.4.9/debian/patches/expose-mppe-keys-via-api.patch ppp-2.4.9/debian/patches/expose-mppe-keys-via-api.patch --- ppp-2.4.9/debian/patches/expose-mppe-keys-via-api.patch 1970-01-01 00:00:00.000000000 +0000 +++ ppp-2.4.9/debian/patches/expose-mppe-keys-via-api.patch 2022-02-24 17:14:02.000000000 +0000 @@ -0,0 +1,870 @@ +Description: pppd: Expose the MPPE keys generated through an API + 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. + . + [rbasak] + The upstream patch was adjusted by the author against + d/p/replace-vendored-hash-functions.patch + . + Also see the discussion in the MP: + https://code.launchpad.net/~eivnaes/ubuntu/+source/ppp/+git/ppp/+merge/415397 +Author: Eivind Næss +Acked-By: Robie Basak +Origin: backport, https://github.com/ppp-project/ppp/commit/d706c95906d996534f13632a747af5dc617f306e +Bug: https://github.com/ppp-project/ppp/issues/258 +Last-Update: 2022-02-24 + +--- a/pppd/Makefile.sol2 ++++ b/pppd/Makefile.sol2 +@@ -37,7 +37,7 @@ + + # 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 +--- a/pppd/ccp.c ++++ b/pppd/ccp.c +@@ -38,10 +38,9 @@ + #include "ccp.h" + #include + +-#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 */ +-#endif + + + /* +@@ -574,7 +573,7 @@ + } + + /* 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"); +@@ -705,7 +704,7 @@ + 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; +@@ -1156,8 +1155,7 @@ + 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! */ +@@ -1426,8 +1424,7 @@ + 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 +--- a/pppd/chap_ms.c ++++ b/pppd/chap_ms.c +@@ -93,7 +93,7 @@ + #include + #include "pppcrypt.h" + #include "magic.h" +- ++#include "mppe.h" + + + static void ascii2unicode (char[], int, u_char[]); +@@ -109,10 +109,6 @@ + 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 */ +@@ -120,10 +116,6 @@ + #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 */ +@@ -705,32 +697,8 @@ + rchallenge, username, authResponse); + } + +- + #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]) +-{ +- SHA_CTX sha1Context; +- u_char Digest[SHA_DIGEST_LENGTH]; /* >= 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) + */ + static void +@@ -744,105 +712,7 @@ + ascii2unicode(secret, secret_len, unicodePassword); + NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); + NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash); +- +- mppe_set_keys(rchallenge, PasswordHashHash); +-} +- +-/* +- * Set mppe_xxxx_key from MS-CHAPv2 credentials. (see RFC 3079) +- * +- * 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) +-{ +- SHA_CTX sha1Context; +- u_char MasterKey[SHA_DIGEST_LENGTH]; /* >= MPPE_MAX_KEY_LEN */ +- u_char Digest[SHA_DIGEST_LENGTH]; /* >= 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); + } + + /* +@@ -858,12 +728,11 @@ + 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 */ + +- + void + ChapMS(u_char *rchallenge, char *secret, int secret_len, + unsigned char *response) +@@ -933,39 +802,6 @@ + #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 */ + chapms_generate_challenge, +--- a/pppd/chap_ms.h ++++ b/pppd/chap_ms.h +@@ -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_AUTH_NTRESP_LEN 24 /* Length of NT-response field */ + /* as ASCII */ + + /* E=eeeeeeeeee error codes for MS-CHAP failure messages. */ +@@ -67,22 +68,6 @@ + #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 +@@ -90,12 +75,6 @@ + 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 GenerateAuthenticatorResponse(u_char PasswordHashHash[MD4_SIGNATURE_SIZE], +--- a/pppd/eap-tls.c ++++ b/pppd/eap-tls.c +@@ -48,6 +48,8 @@ + #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 +@@ -72,10 +74,6 @@ + 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 +@@ -118,6 +116,10 @@ + #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */ + + ++#ifdef MPPE ++ ++#define EAPTLS_MPPE_KEY_LEN 32 ++ + /* + * Generate keys according to RFC 2716 and add to reply + */ +@@ -159,20 +161,12 @@ + */ + 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 + { +- 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 */ +--- a/pppd/eap-tls.h ++++ b/pppd/eap-tls.h +@@ -85,11 +85,6 @@ + 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 + +--- /dev/null ++++ b/pppd/mppe.c +@@ -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 ++ ++#include "pppd.h" ++#include "fsm.h" ++#include "ccp.h" ++#include "chap_ms.h" ++#include "mppe.h" ++#include ++#include ++ ++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]) ++{ ++ SHA_CTX sha1Context; ++ u_char Digest[SHA_DIGEST_LENGTH]; ++ ++ 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) ++{ ++ SHA_CTX sha1Context; ++ u_char MasterKey[SHA_DIGEST_LENGTH]; ++ u_char SendKey[SHA_DIGEST_LENGTH]; ++ u_char RecvKey[SHA_DIGEST_LENGTH]; ++ ++ 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, SHA_DIGEST_LENGTH); ++} ++ ++/* ++ * 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; ++ } ++} ++ +--- a/pppd/mppe.h ++++ b/pppd/mppe.h +@@ -32,9 +32,12 @@ + * 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_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 */ +@@ -119,3 +122,68 @@ + 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__ +--- a/pppd/plugins/radius/radius.c ++++ b/pppd/plugins/radius/radius.c +@@ -31,6 +31,7 @@ + #ifdef CHAPMS + #include "chap_ms.h" + #ifdef MPPE ++#include "mppe.h" + #include + #endif + #endif +@@ -743,11 +744,12 @@ + * 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_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; +@@ -803,7 +805,7 @@ + * 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; + } +@@ -855,7 +857,7 @@ + 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; +@@ -869,9 +871,9 @@ + 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 +- memcpy(mppe_recv_key, plain + 1, 16); ++ mppe_set_keys(NULL, plain + 1, 16); + + return 0; + } +--- a/pppd/plugins/winbind.c ++++ b/pppd/plugins/winbind.c +@@ -37,11 +37,9 @@ + #include "pppd.h" + #include "chap-new.h" + #include "chap_ms.h" +-#ifdef MPPE +-#include +-#endif + #include "fsm.h" + #include "ipcp.h" ++#include "mppe.h" + #include + #include + #include +@@ -583,7 +581,7 @@ + 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; + +@@ -628,7 +626,7 @@ + &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); +--- a/pppd/Makefile.linux ++++ b/pppd/Makefile.linux +@@ -105,6 +105,8 @@ + endif + ifdef MPPE + CFLAGS += -DMPPE=1 ++PPPDOBJS += mppe.o ++PPPDSRC += mppe.c + HEADERS += mppe.h + endif + endif diff -Nru ppp-2.4.9/debian/patches/series ppp-2.4.9/debian/patches/series --- ppp-2.4.9/debian/patches/series 2021-08-16 16:59:45.000000000 +0000 +++ ppp-2.4.9/debian/patches/series 2022-02-24 17:14:02.000000000 +0000 @@ -15,3 +15,5 @@ zzz_config pppd-soname-hack.patch replace-vendored-hash-functions.patch +eap-mschap-v2-namelen.patch +expose-mppe-keys-via-api.patch diff -Nru ppp-2.4.9/debian/ppp.symbols ppp-2.4.9/debian/ppp.symbols --- ppp-2.4.9/debian/ppp.symbols 2021-02-25 18:12:30.000000000 +0000 +++ ppp-2.4.9/debian/ppp.symbols 2022-02-24 17:14:02.000000000 +0000 @@ -1,11 +1,11 @@ pppd.so.2.4.9 ppp #MINVER# * Build-Depends-Package: ppp-dev # Ignore all symbols that start with an underscore in the Base module - (regex|optional)"^_.*@Base$" 2.4.7-1+2~ + (regex|optional)"^_.*@Base$" 2.4.9-1+1~ # Ignore $global$ which seems to appear on hppa only - (optional)$global$@Base 2.4.7-1+2~ + (optional)$global$@Base 2.4.9-1+1~ # Ignore everything that claims it's part of glibc - (regex|optional)"@GLIBC_" 2.4.7-1+2~ + (regex|optional)"@GLIBC_" 2.4.9-1+1~ # All others should be pppd symbols ChallengeHash@Base 2.4.7-1+2~ ChapMS2@Base 2.4.7-1+2~ @@ -302,11 +302,17 @@ mp_check_options@Base 2.4.7-1+2~ mp_exit_bundle@Base 2.4.7-1+2~ mp_join_bundle@Base 2.4.7-1+2~ + mppe_clear_keys@Base 2.4.9-1+1~ + mppe_get_recv_key@Base 2.4.9-1+1~ + mppe_get_send_key@Base 2.4.9-1+1~ + mppe_keys_isset@Base 2.4.9-1+1~ mppe_keys_set@Base 2.4.7-1+2~ mppe_recv_key@Base 2.4.7-1+2~ mppe_send_key@Base 2.4.7-1+2~ - mppe_set_keys2@Base 2.4.7-1+2~ mppe_set_keys@Base 2.4.7-1+2~ + mppe_set_chapv1@Base 2.4.9-1+1~ + mppe_set_chapv2@Base 2.4.9-1+1~ + mppe_set_enc_types@Base 2.4.9-1+1~ multilink@Base 2.4.7-1+2~ multilink_join_hook@Base 2.4.7-1+2~ multilink_master@Base 2.4.7-1+2~ @@ -419,7 +425,6 @@ session_start@Base 2.4.7-1+2~ set_filters@Base 2.4.7-1+2~ set_ifunit@Base 2.4.7-1+2~ - set_mppe_enc_types@Base 2.4.7-1+2~ set_up_tty@Base 2.4.7-1+2~ setdtr@Base 2.4.7-1+2~ setipaddr@Base 2.4.7-1+2~