X-Git-Url: https://git.ozlabs.org/?a=blobdiff_plain;f=pppd%2Feap.c;h=6cb595f5b7c57b78cdd22ed790928535f4f29777;hb=4a54e34cf5629f9fed61f0b7d69ee3ba4d874bc6;hp=0cffa8bf6c40603690f27f06d14c86caa906f25f;hpb=14c1a77816e837852138e87a4adccfd66030b2c3;p=ppp.git diff --git a/pppd/eap.c b/pppd/eap.c index 0cffa8b..6cb595f 100644 --- a/pppd/eap.c +++ b/pppd/eap.c @@ -48,6 +48,10 @@ * Implemented EAP-TLS authentication */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include @@ -63,12 +67,14 @@ #include "pathnames.h" #include "md5.h" #include "eap.h" - -#ifdef CHAPMS -#include "chap_ms.h" -#endif +#ifdef USE_PEAP +#include "peap.h" +#endif /* USE_PEAP */ #ifdef USE_SRP +#ifdef HAVE_TIME_H +#include +#endif #include #include #include @@ -82,10 +88,12 @@ #ifdef USE_EAPTLS #include "eap-tls.h" #endif /* USE_EAPTLS */ + #ifdef CHAPMS -#include "magic.h" #include "chap_ms.h" #include "chap-new.h" + +extern int chapms_strip_domain; #endif /* CHAPMS */ eap_state eap_states[NUM_PPP]; /* EAP state; one for each unit */ @@ -223,7 +231,8 @@ eap_init(int unit) esp->es_client.ea_using_eaptls = 0; #endif /* USE_EAPTLS */ #ifdef CHAPMS - esp->es_client.digest = chap_find_digest(CHAP_MICROSOFT_V2); + esp->es_client.digest = chap_find_digest(CHAP_MICROSOFT_V2); + esp->es_server.digest = chap_find_digest(CHAP_MICROSOFT_V2); #endif } @@ -553,7 +562,7 @@ eap_figure_next_state(eap_state *esp, int status) tpw.pebuf.name = esp->es_server.ea_peer; tpw.pebuf.password.len = t_fromb64((char *)tpw.pwbuf, cp); - tpw.pebuf.password.data = tpw.pwbuf; + tpw.pebuf.password.data = (char*) tpw.pwbuf; tpw.pebuf.salt.len = t_fromb64((char *)tpw.saltbuf, cp2); tpw.pebuf.salt.data = tpw.saltbuf; @@ -719,92 +728,6 @@ eap_figure_next_state(eap_state *esp, int status) } #if CHAPMS -static int -eap_chapms2_verify_response(int id, char *name, - unsigned char *secret, int secret_len, - unsigned char *challenge, unsigned char *response, - char *message, int message_space) -{ - unsigned char md[MS_CHAP2_RESPONSE_LEN]; - char saresponse[MS_AUTH_RESPONSE_LENGTH+1]; - int challenge_len, response_len; - - challenge_len = *challenge++; /* skip length, is 16 */ - response_len = *response++; - if (response_len != MS_CHAP2_RESPONSE_LEN) - goto bad; /* not even the right length */ - - /* Generate the expected response and our mutual auth. */ - ChapMS2(challenge, &response[MS_CHAP2_PEER_CHALLENGE], name, - (char *)secret, secret_len, md, - (unsigned char *)saresponse, MS_CHAP2_AUTHENTICATOR); - - /* compare MDs and send the appropriate status */ - /* - * Per RFC 2759, success message must be formatted as - * "S= M=" - * where - * is the Authenticator Response (mutual auth) - * is a text message - * - * However, some versions of Windows (win98 tested) do not know - * about the M= part (required per RFC 2759) and flag - * it as an error (reported incorrectly as an encryption error - * to the user). Since the RFC requires it, and it can be - * useful information, we supply it if the peer is a conforming - * system. Luckily (?), win98 sets the Flags field to 0x04 - * (contrary to RFC requirements) so we can use that to - * distinguish between conforming and non-conforming systems. - * - * Special thanks to Alex Swiridov for - * help debugging this. - */ - if (memcmp(&md[MS_CHAP2_NTRESP], &response[MS_CHAP2_NTRESP], - MS_CHAP2_NTRESP_LEN) == 0) { - if (response[MS_CHAP2_FLAGS]) - slprintf(message, message_space, "S=%s", saresponse); - else - slprintf(message, message_space, "S=%s M=%s", - saresponse, "Access granted"); - return 1; - } - - bad: - /* - * Failure message must be formatted as - * "E=e R=r C=c V=v M=m" - * where - * e = error code (we use 691, ERROR_AUTHENTICATION_FAILURE) - * r = retry (we use 1, ok to retry) - * c = challenge to use for next response, we reuse previous - * v = Change Password version supported, we use 0 - * m = text message - * - * The M=m part is only for MS-CHAPv2. Neither win2k nor - * win98 (others untested) display the message to the user anyway. - * They also both ignore the E=e code. - * - * Note that it's safe to reuse the same challenge as we don't - * actually accept another response based on the error message - * (and no clients try to resend a response anyway). - * - * Basically, this whole bit is useless code, even the small - * implementation here is only because of overspecification. - */ - slprintf(message, message_space, "E=691 R=1 C=%0.*B V=0 M=%s", - challenge_len, challenge, "Access denied"); - return 0; -} - -static struct chap_digest_type eap_chapms2_digest = { - CHAP_MICROSOFT_V2, /* code */ - NULL, /* chapms2_generate_challenge, */ - eap_chapms2_verify_response, - NULL, /* chapms2_make_response, */ - NULL, /* chapms2_check_success, */ - NULL, /* chapms_handle_failure, */ -}; - /* * eap_chap_verify_response - check whether the peer's response matches * what we think it should be. Returns 1 if it does (authentication @@ -961,10 +884,9 @@ eap_send_request(eap_state *esp) #ifdef CHAPMS case eapMSCHAPv2Chall: - challen = 0x10; + esp->es_server.digest->generate_challenge(esp->es_challenge); + challen = esp->es_challenge[0]; esp->es_challen = challen; - esp->es_challenge[0] = challen; - random_bytes(&esp->es_challenge[1], challen); PUTCHAR(EAPT_MSCHAPV2, outp); PUTCHAR(CHAP_CHALLENGE, outp); @@ -1951,7 +1873,7 @@ eap_request(eap_state *esp, u_char *inp, int id, int len) break; default: - eap_send_nak(esp, id, EAPT_TLS); + eap_send_nak(esp, id, EAPT_MSCHAPV2); esp->es_client.ea_using_eaptls = 0; break; } @@ -2260,6 +2182,7 @@ eap_request(eap_state *esp, u_char *inp, int id, int len) 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 @@ -2297,6 +2220,28 @@ eap_request(eap_state *esp, u_char *inp, int id, int len) break; #endif /* CHAPMS */ +#ifdef USE_PEAP + case EAPT_PEAP: + + /* Initialize the PEAP context (if not already initialized) */ + if (!esp->ea_peap) { + rhostname[0] = '\0'; + if (explicit_remote || (remote_name[0] != '\0')) { + strlcpy(rhostname, remote_name, sizeof (rhostname)); + } + if (peap_init(&esp->ea_peap, rhostname)) { + eap_send_nak(esp, id, EAPT_TLS); + break; + } + } + + /* Process the PEAP packet */ + if (peap_process(esp, id, inp, len)) { + eap_send_nak(esp, id, EAPT_TLS); + } + + break; +#endif /* USE_PEAP */ default: info("EAP: unknown authentication type %d; Naking", typenum); @@ -2341,8 +2286,6 @@ eap_response(eap_state *esp, u_char *inp, int id, int len) struct t_num A; SHA1_CTX ctxt; u_char dig[SHA_DIGESTSIZE]; - SHA1_CTX ctxt; - u_char dig[SHA_DIGESTSIZE]; #endif /* USE_SRP */ #ifdef USE_EAPTLS @@ -2500,6 +2443,12 @@ eap_response(eap_state *esp, u_char *inp, int id, int len) #ifdef CHAPMS case EAPT_MSCHAPV2: info("EAP: peer proposes MSCHAPv2"); + /* If MSCHAPv2 digest was not found, NAK the packet */ + if (!esp->es_server.digest) { + error("EAP MSCHAPv2 not supported"); + eap_send_nak(esp, id, EAPT_SRP); + break; + } esp->es_server.ea_state = eapMSCHAPv2Chall; break; #endif /* CHAPMS */ @@ -2629,6 +2578,14 @@ eap_response(eap_state *esp, u_char *inp, int id, int len) (remote_name[0] != '\0' && vallen == len)) strlcpy(rhostname, remote_name, sizeof (rhostname)); + /* strip the MS domain name */ + if (chapms_strip_domain && strrchr(rhostname, '\\')) { + char tmp[MAXNAMELEN+1]; + + strcpy(tmp, strrchr(rhostname, '\\') + 1); + strcpy(rhostname, tmp); + } + if (chap_verify_hook) chap_verifier = chap_verify_hook; else @@ -2638,7 +2595,7 @@ eap_response(eap_state *esp, u_char *inp, int id, int len) if ((*chap_verifier)(rhostname, esp->es_server.ea_name, id, - &eap_chapms2_digest, + esp->es_server.digest, esp->es_challenge, inp - 1, response_message, @@ -2838,6 +2795,10 @@ eap_success(eap_state *esp, u_char *inp, int id, int len) PRINTMSG(inp, len); } +#ifdef USE_PEAP + peap_finish(&esp->ea_peap); +#endif + esp->es_client.ea_state = eapOpen; auth_withpeer_success(esp->es_unit, PPP_EAP, 0); } @@ -2872,6 +2833,11 @@ eap_failure(eap_state *esp, u_char *inp, int id, int len) esp->es_client.ea_state = eapBadAuth; error("EAP: peer reports authentication failure"); + +#ifdef USE_PEAP + peap_finish(&esp->ea_peap); +#endif + auth_withpeer_fail(esp->es_unit, PPP_EAP); } @@ -3095,6 +3061,7 @@ eap_printpkt(u_char *inp, int inlen, break; #endif /* USE_EAPTLS */ +#ifdef USE_SRP case EAPT_SRP: if (len < 3) goto truncated; @@ -3182,6 +3149,7 @@ eap_printpkt(u_char *inp, int inlen, break; } break; +#endif /* USE_SRP */ } break; @@ -3307,6 +3275,7 @@ eap_printpkt(u_char *inp, int inlen, break; #endif /* CHAPMS */ +#ifdef USE_SRP case EAPT_SRP: if (len < 1) goto truncated; @@ -3351,6 +3320,7 @@ eap_printpkt(u_char *inp, int inlen, break; } break; +#endif /* USE_SRP */ } break;