Description: Adding EAP-MSCHAPv2 support This patch add support for MSCHAPv2 via EAP. . ppp (2.4.7-2+4.1ubuntu4) eoan; urgency=medium . * Author: Thomas Omerzu --- Origin: Thomas Omerzu, https://w3logistics.com/blog/archives/438-EAP-MSCHAPv2-for-pppd-2-4-7.html Bug: https://github.com/paulusmack/ppp/issues/138 Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/ppp/+bug/1858349 Last-Update: 2020-02-24 --- ppp-2.4.7.orig/pppd/eap.c +++ ppp-2.4.7/pppd/eap.c @@ -68,6 +68,9 @@ #include "pppd.h" #include "pathnames.h" #include "eap.h" +#ifdef CHAPMS +#include "chap_ms.h" +#endif #ifdef USE_EAPTLS #include "eap-tls.h" #else @@ -1261,6 +1264,47 @@ int namelen; output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen); } #if CHAPMS /* * Format and send an CHAPV2-Challenge EAP Response message. */ static void eap_chapv2_response(esp, id, chapid, response, user, user_len) eap_state *esp; u_char id; u_char chapid; u_char *response; char *user; int user_len; { u_char *outp; int msglen; outp = outpacket_buf; MAKEHEADER(outp, PPP_EAP); PUTCHAR(EAP_RESPONSE, outp); PUTCHAR(id, outp); esp->es_client.ea_id = id; msglen = EAP_HEADERLEN + 6 * sizeof (u_char) + MS_CHAP2_RESPONSE_LEN + user_len; PUTSHORT(msglen, outp); PUTCHAR(EAPT_MSCHAPV2, outp); PUTCHAR(CHAP_RESPONSE, outp); PUTCHAR(chapid, outp); PUTCHAR(0, outp); /* len */ PUTCHAR(5 + user_len +MS_CHAP2_RESPONSE_LEN, outp); /* len response */ PUTCHAR(MS_CHAP2_RESPONSE_LEN, outp) BCOPY(response, outp, MS_CHAP2_RESPONSE_LEN); INCPTR(MS_CHAP2_RESPONSE_LEN, outp); BCOPY(user, outp, user_len); output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen); } #endif #ifdef USE_SRP /* * Format and send a SRP EAP Response message. @@ -1790,6 +1834,97 @@ int len; break; #endif /* USE_EAPTLS */ #ifdef MSCHAP case EAPT_MSCHAPV2: if (len < 1) { error("EAP: received short MSCHAPv2"); /* Bogus request; wait for something real. */ return; } unsigned char chopcode; GETCHAR(chopcode, inp); len--; dbglog("EAP: CHAPopcode %d", chopcode); if (chopcode==CHAP_CHALLENGE) { unsigned char chapid; /* Chapv2-ID */ GETCHAR(chapid, inp); short mssize; GETSHORT(mssize, inp); unsigned char vsize; GETCHAR(vsize, inp); len-=4; dbglog("EAP: chapid %d mssize %d vsize %d inplen %d, challen %d", chapid, mssize, vsize, len, MS_CHAP2_PEER_CHAL_LEN); unsigned char *rchallenge = calloc(1, MS_CHAP2_PEER_CHAL_LEN); BCOPY(inp, rchallenge, MS_CHAP2_PEER_CHAL_LEN); INCPTR(MS_CHAP2_PEER_CHAL_LEN,inp); /* * Get the secret for authenticating ourselves with * the specified host. */ if (!get_secret(esp->es_unit, esp->es_client.ea_name, rhostname, secret, &secret_len, 0)) { dbglog("EAP: no CHAP secret for auth to %q", rhostname); eap_send_nak(esp, id, EAPT_SRP); break; } char *user = calloc(1, esp->es_client.ea_namelen + 1); memcpy(user, esp->es_client.ea_name, esp->es_client.ea_namelen); *(user + esp->es_client.ea_namelen) = '\0'; dbglog("EAP: user %s, user_len %d", user, esp->es_client.ea_namelen); /* mschapv2 response */ unsigned char response[49]; unsigned char authResponse[41]; ChapMS2(rchallenge, NULL, user, secret, secret_len, response, authResponse, MS_CHAP2_AUTHENTICATEE); eap_chapv2_response(esp, id, chapid, response, esp->es_client.ea_name, esp->es_client.ea_namelen); free(user); free(rchallenge); } else if (chopcode==CHAP_SUCCESS) { unsigned char chapid; /* Chapv2-ID */ GETCHAR(chapid, inp); short mssize; GETSHORT(mssize, inp); len-=3; dbglog("EAP: chapid %d mssize %d inplen %d", chapid, mssize, len ); dbglog("Chap authentication succeeded: %.*v", len, inp); u_char response[1]; response[0]=CHAP_SUCCESS; eap_send_response(esp, id, EAPT_MSCHAPV2, response, 1); } else if (chopcode==CHAP_FAILURE) { unsigned char chapid; /* Chapv2-ID */ GETCHAR(chapid, inp); short mssize; GETSHORT(mssize, inp); len-=3; dbglog("EAP: chapid %d mssize %d inplen %d", chapid, mssize, len ); dbglog("Chap authentication failed: %.*v", len, inp); u_char response[1]; response[0]=CHAP_FAILURE; eap_send_response(esp, id, EAPT_MSCHAPV2, response, 1); goto client_failure; /* force termination */ } else { dbglog("EAP: Unknown CHAPopcode %d", chopcode); eap_send_nak(esp, id, EAPT_SRP); } break; #endif #ifdef USE_SRP case EAPT_SRP: if (len < 1) { @@ -2035,16 +2170,16 @@ int len; } return; -#ifdef USE_SRP client_failure: esp->es_client.ea_state = eapBadAuth; if (esp->es_client.ea_timeout > 0) { UNTIMEOUT(eap_client_timeout, (void *)esp); } esp->es_client.ea_session = NULL; +#ifdef USE_SRP t_clientclose(tc); +#endif auth_withpeer_fail(esp->es_unit, PPP_EAP); -#endif /* USE_SRP */ } /* @@ -2555,7 +2690,9 @@ static char *eap_typenames[] = { "OTP", "Generic-Token", NULL, NULL, "RSA", "DSS", "KEA", "KEA-Validate", "TLS", "Defender", "Windows 2000", "Arcot", - "Cisco", "Nokia", "SRP" + "Cisco", "Nokia", "SRP", NULL, + "TTLS", "RAS", "AKA", "3COM", "PEAP", + "MSCHAPv2" }; static int --- ppp-2.4.7.orig/pppd/eap.h +++ ppp-2.4.7/pppd/eap.h @@ -59,6 +59,18 @@ extern "C" { #define EAPT_NOKIACARD 18 /* Nokia IP smart card */ #define EAPT_SRP 19 /* Secure Remote Password */ /* 20 is deprecated */ +#define EAPT_TTLS 21 /* EAP Tunneled TLS Authentication Protocol RFC5281 */ +#define EAPT_RAS 22 /* Remote Access Service */ +#define EAPT_AKA 23 /* EAP method for 3rd Generation Authentication and Key Agreement RFC4187 */ +#define EAPT_3COM 24 /* EAP-3Com Wireless */ +#define EAPT_PEAP 25 /* Protected EAP */ +#define EAPT_MSCHAPV2 26 /* EAP-MSCHAPv2 RFC-draft-kamath-pppext-eap-mschapv2-02 */ + +/* OpCodes for MSCHAPv2 */ +#define CHAP_CHALLENGE 1 +#define CHAP_RESPONSE 2 +#define CHAP_SUCCESS 3 +#define CHAP_FAILURE 4 /* EAP SRP-SHA1 Subtypes */ #define EAPSRP_CHALLENGE 1 /* Request 1 - Challenge */