From eb35ceacfb3367fb0996dcd8c1f3a6771387ab41 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 27 Nov 2003 22:16:24 +0000 Subject: [PATCH] Remove old CHAP implementation --- pppd/chap.c | 1207 --------------------------------------------------- pppd/chap.h | 189 -------- 2 files changed, 1396 deletions(-) delete mode 100644 pppd/chap.c delete mode 100644 pppd/chap.h diff --git a/pppd/chap.c b/pppd/chap.c deleted file mode 100644 index aa07d0e..0000000 --- a/pppd/chap.c +++ /dev/null @@ -1,1207 +0,0 @@ -/* - * chap.c - Challenge Handshake Authentication Protocol. - * - * Copyright (c) 1993-2002 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. - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Paul Mackerras - * ". - * - * 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. - * - * 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.41 2003/07/28 12:25:41 carlsonj Exp $" - -/* - * TODO: - */ - -#include -#include -#include -#include -#include - -#include "pppd.h" -#include "chap.h" -#include "md5.h" -#ifdef CHAPMS -#include "chap_ms.h" -#endif - -/* Hook for a plugin to validate CHAP challenge */ -int (*chap_auth_hook) __P((char *user, - u_char *remmd, - int remmd_len, - chap_state *cstate)) = NULL; - -static const char rcsid[] = RCSID; - -#ifdef CHAPMS -/* For MPPE debug */ -/* Use "[]|}{?/><,`!2&&(" (sans quotes) for RFC 3079 MS-CHAPv2 test value */ -static char *mschap_challenge = NULL; -/* Use "!@\#$%^&*()_+:3|~" (sans quotes, backslash is to escape #) for ... */ -static char *mschap2_peer_challenge = NULL; -#endif - -/* - * 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 MSCHAP -#ifdef MSLANMAN - { "ms-lanman", o_bool, &ms_lanman, - "Use LanMan passwd when using MS-CHAP", 1 }, -#endif -#ifdef DEBUGMPPEKEY - { "mschap-challenge", o_string, &mschap_challenge, - "specify CHAP challenge" }, - { "mschap2-peer-challenge", o_string, &mschap2_peer_challenge, - "specify CHAP peer challenge" }, -#endif -#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 */ -} - - -/* - * chap_auth_with_peer - Authenticate us with our peer (start client). - * - */ -void -chap_auth_with_peer(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; -} - - -/* - * chap_auth_peer - Authenticate our peer (start server). - */ -void -chap_auth_peer(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); - - /* Null terminate and clean remote name. */ - slprintf(rhostname, sizeof(rhostname), "%.*v", len, inp); - - /* 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, secret, secret_len, - (MS_ChapResponse *) cstate->response); - break; - - case CHAP_MICROSOFT_V2: - ChapMS2(cstate, rchallenge, - mschap2_peer_challenge? mschap2_peer_challenge: NULL, - cstate->resp_name, secret, secret_len, - (MS_Chap2Response *) cstate->response, cstate->earesponse, - MS_CHAP2_AUTHENTICATEE); - break; -#endif /* CHAPMS */ - - 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); - - /* Null terminate and clean remote name. */ - slprintf(rhostname, sizeof(rhostname), "%.*v", len, inp); - -#ifdef CHAPMS - /* copy the flags into cstate for use elsewhere */ - if (cstate->chal_type == CHAP_MICROSOFT_V2) - cstate->resp_flags = ((MS_Chap2Response *) remmd)->Flags[0]; -#endif /* CHAPMS */ - /* - * Get secret for authenticating them with us, - * do the hash ourselves, and compare the result. - */ - code = CHAP_FAILURE; - - /* If a plugin will verify the response, let the plugin do it. */ - if (chap_auth_hook) { - code = (*chap_auth_hook) ( (explicit_remote ? remote_name : rhostname), - remmd, (int) remmd_len, - cstate ); - /* - * Check remote number authorization. A plugin may have filled in - * the remote number or added an allowed number, and rather than - * return an authenticate failure, is leaving it for us to verify. - */ - if (code == CHAP_SUCCESS) { - if (!auth_number()) { - /* We do not want to leak info about the chap result. */ - code = CHAP_FAILURE; /* XXX exit value will be "wrong" */ - warn("calling number %q is not authorized", remote_number); - } - } - - } else { - 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: - if (remmd_len != MD5_SIGNATURE_SIZE) - break; /* 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 MDs and send the appropriate status */ - if (memcmp(hash, remmd, MD5_SIGNATURE_SIZE) == 0) - code = CHAP_SUCCESS; /* they are the same! */ - break; - -#ifdef CHAPMS - case CHAP_MICROSOFT: - { - int response_offset, response_size; - MS_ChapResponse *rmd = (MS_ChapResponse *) remmd; - MS_ChapResponse md; - - if (remmd_len != MS_CHAP_RESPONSE_LEN) - break; /* not even the right length */ - - /* Determine which part of response to verify against */ - if (rmd->UseNT[0]) { - response_offset = offsetof(MS_ChapResponse, NTResp); - response_size = sizeof(rmd->NTResp); - } else { -#ifdef MSLANMAN - response_offset = offsetof(MS_ChapResponse, LANManResp); - response_size = sizeof(rmd->LANManResp); -#else - /* Should really propagate this into the error packet. */ - notice("Peer request for LANMAN auth not supported"); - break; -#endif /* MSLANMAN */ - } - - /* Generate the expected response. */ - ChapMS(cstate, cstate->challenge, secret, secret_len, &md); - - /* compare MDs and send the appropriate status */ - if (memcmp((u_char *) &md + response_offset, - (u_char *) remmd + response_offset, - response_size) == 0) - code = CHAP_SUCCESS; /* they are the same! */ - break; - } - - case CHAP_MICROSOFT_V2: - { - MS_Chap2Response *rmd = (MS_Chap2Response *) remmd; - MS_Chap2Response md; - - if (remmd_len != MS_CHAP2_RESPONSE_LEN) - break; /* not even the right length */ - - /* Generate the expected response and our mutual auth. */ - ChapMS2(cstate, cstate->challenge, rmd->PeerChallenge, - (explicit_remote? remote_name: rhostname), - secret, secret_len, &md, - cstate->saresponse, MS_CHAP2_AUTHENTICATOR); - - /* compare MDs and send the appropriate status */ - if (memcmp(md.NTResp, rmd->NTResp, sizeof(md.NTResp)) == 0) - code = CHAP_SUCCESS; /* yay! */ - break; - } -#endif /* CHAPMS */ - - 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, cstate->chal_type, - rhostname, len); - } - if (cstate->chal_interval != 0) - TIMEOUT(ChapRechallenge, cstate, cstate->chal_interval); - notice("CHAP peer authentication succeeded for %q", rhostname); - - } else { - warn("CHAP peer authentication failed for %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); - -#ifdef CHAPMS - /* - * For MS-CHAPv2, we must verify that the peer knows our secret. - */ - if (cstate->resp_type == CHAP_MICROSOFT_V2) { - if ((len >= MS_AUTH_RESPONSE_LENGTH + 2) && !strncmp(inp, "S=", 2)) { - inp += 2; len -= 2; - if (!memcmp(inp, cstate->earesponse, MS_AUTH_RESPONSE_LENGTH)) { - /* Authenticator Response matches. */ - inp += MS_AUTH_RESPONSE_LENGTH; /* Eat it */ - len -= MS_AUTH_RESPONSE_LENGTH; - if ((len >= 3) && !strncmp(inp, " M=", 3)) { - inp += 3; len -= 3; /* Eat the delimiter */ - } else if (len) { - /* Packet has extra text which does not begin " M=" */ - error("MS-CHAPv2 Success packet is badly formed."); - auth_withpeer_fail(cstate->unit, PPP_CHAP); - } - } else { - /* Authenticator Response did not match expected. */ - error("MS-CHAPv2 mutual authentication failed."); - auth_withpeer_fail(cstate->unit, PPP_CHAP); - } - } else { - /* Packet does not start with "S=" */ - error("MS-CHAPv2 Success packet is badly formed."); - auth_withpeer_fail(cstate->unit, PPP_CHAP); - } - } -#endif - - /* - * Print message. - */ - if (len > 0) - PRINTMSG(inp, len); - - cstate->clientstate = CHAPCS_OPEN; - - notice("CHAP authentication succeeded"); - auth_withpeer_success(cstate->unit, PPP_CHAP, cstate->resp_type); -} - - -/* - * ChapReceiveFailure - Receive failure. - */ -static void -ChapReceiveFailure(cstate, inp, id, len) - chap_state *cstate; - u_char *inp; - u_char id; - int len; -{ -#ifdef CHAPMS - u_char *msg; -#endif - u_char *p = inp; - - if (cstate->clientstate != CHAPCS_RESPONSE) { - /* don't know what this is */ - CHAPDEBUG(("ChapReceiveFailure: in state %d\n", cstate->clientstate)); - return; - } - -#ifdef CHAPMS - /* We want a null-terminated string for strxxx(). */ - msg = malloc(len + 1); - if (!msg) { - p = NULL; - notice("Out of memory in ChapReceiveFailure"); - goto print_msg; - } - BCOPY(inp, msg, len); - p = msg + len; *p = '\0'; p = msg; -#endif - - UNTIMEOUT(ChapResponseTimeout, cstate); - -#ifdef CHAPMS - if ((cstate->resp_type == CHAP_MICROSOFT_V2) || - (cstate->resp_type == CHAP_MICROSOFT)) { - int error; - - /* - * Deal with MS-CHAP formatted failure messages; just print the - * M= part (if any). For MS-CHAP we're not really supposed - * to use M=, but it shouldn't hurt. See ChapSendStatus(). - */ - if (!strncmp(p, "E=", 2)) - error = (int) strtol(p, NULL, 10); /* Remember the error code. */ - else - goto print_msg; /* Message is badly formatted. */ - - if (len && ((p = strstr(p, " M=")) != NULL)) { - /* M= field found. */ - p += 3; - } else { - /* No M=; use the error code. */ - switch(error) { - case MS_CHAP_ERROR_RESTRICTED_LOGON_HOURS: - p = "E=646 Restricted logon hours"; - break; - - case MS_CHAP_ERROR_ACCT_DISABLED: - p = "E=647 Account disabled"; - break; - - case MS_CHAP_ERROR_PASSWD_EXPIRED: - p = "E=648 Password expired"; - break; - - case MS_CHAP_ERROR_NO_DIALIN_PERMISSION: - p = "E=649 No dialin permission"; - break; - - case MS_CHAP_ERROR_AUTHENTICATION_FAILURE: - p = "E=691 Authentication failure"; - break; - - case MS_CHAP_ERROR_CHANGING_PASSWORD: - /* Should never see this, we don't support Change Password. */ - p = "E=709 Error changing password"; - break; - - default: - free(msg); - p = msg = malloc(len + 33); - if (!msg) { - novm("ChapReceiveFailure"); - goto print_msg; - } - slprintf(p, len + 33, "Unknown authentication failure: %.*s", - len, inp); - break; - } - } - len = strlen(p); - } -#endif - - /* - * Print message. - */ -#ifdef CHAPMS -print_msg: -#endif - if (len > 0 && p != NULL) - PRINTMSG(p, len); - - error("CHAP authentication failed"); - auth_withpeer_fail(cstate->unit, PPP_CHAP); -#ifdef CHAPMS - if (msg) free(msg); -#endif -} - - -/* - * 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). - * See RFC 2433 and RFC 2759 for MS-CHAP and MS-CHAPv2 message formats. - */ -static void -ChapSendStatus(cstate, code) - chap_state *cstate; - int code; -{ - u_char *outp; - int outlen, msglen; - char msg[256]; - char *p, *q; - - p = msg; - q = p + sizeof(msg); /* points 1 byte past msg */ - - if (code == CHAP_SUCCESS) { -#ifdef CHAPMS - if (cstate->chal_type == CHAP_MICROSOFT_V2) { - /* - * 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. - */ - slprintf(p, q - p, "S="); - p += 2; - slprintf(p, q - p, "%s", cstate->saresponse); - p += strlen(cstate->saresponse); - if (cstate->resp_flags != 0) - goto msgdone; - slprintf(p, q - p, " M="); - p += 3; - } -#endif /* CHAPMS */ - - slprintf(p, q - p, "Welcome to %s.", hostname); - } else { -#ifdef CHAPMS - if ((cstate->chal_type == CHAP_MICROSOFT_V2) || - (cstate->chal_type == CHAP_MICROSOFT)) { - /* - * 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, but MS-CHAP should ignore - * any extra text according to RFC 2433. So we'll go the easy - * (read: lazy) route and include it always. 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. - */ - int i; - - slprintf(p, q - p, "E=691 R=1 C="); - p += 12; - for (i = 0; i < cstate->chal_len; i++) - sprintf(p + i * 2, "%02X", cstate->challenge[i]); - p += cstate->chal_len * 2; - slprintf(p, q - p, " V=0 M="); - p += 7; - } -#endif /* CHAPMS */ - - slprintf(p, q - p, "I don't like you. Go 'way."); - } -#ifdef CHAPMS -msgdone: -#endif - 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 = 0; /* Avoid compiler warning */ - u_char *ptr = cstate->challenge; - int i; - - switch (cstate->chal_type) { - case CHAP_DIGEST_MD5: - /* - * 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); - break; - -#ifdef CHAPMS - case CHAP_MICROSOFT: - /* MS-CHAP is fixed to an 8 octet challenge. */ - chal_len = 8; - break; - - case CHAP_MICROSOFT_V2: - /* MS-CHAPv2 is fixed to a 16 octet challenge. */ - chal_len = 16; - break; -#endif - default: - fatal("ChapGenChallenge: Unsupported challenge type %d", - (int) cstate->chal_type); - break; - } - - cstate->chal_len = chal_len; - cstate->chal_id = ++cstate->id; - cstate->chal_transmits = 0; - -#ifdef CHAPMS - if (mschap_challenge) - for (i = 0; i < chal_len; i++) - *ptr++ = mschap_challenge[i]; - else -#endif - /* 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 --git a/pppd/chap.h b/pppd/chap.h deleted file mode 100644 index 0e4cae1..0000000 --- a/pppd/chap.h +++ /dev/null @@ -1,189 +0,0 @@ -/* - * chap.h - Challenge Handshake Authentication Protocol definitions. - * - * Copyright (c) 1993-2002 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. - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Paul Mackerras - * ". - * - * 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. - * - * 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 the author. - * - * 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. - * - * $Id: chap.h,v 1.15 2002/12/04 23:03:32 paulus Exp $ - */ - -#ifndef __CHAP_INCLUDE__ - -/* Code + ID + length */ -#define CHAP_HEADERLEN 4 - -/* - * CHAP codes. - */ - -#define CHAP_DIGEST_MD5 5 /* use MD5 algorithm */ -#define MD5_SIGNATURE_SIZE 16 /* 16 bytes in a MD5 message digest */ -#define CHAP_MICROSOFT 0x80 /* use Microsoft-compatible alg. */ -#define CHAP_MICROSOFT_V2 0x81 /* use Microsoft-compatible alg. */ - -/* - * Digest type and selection. - */ - -/* bitmask of supported algorithms */ -#define MDTYPE_MICROSOFT_V2 0x1 -#define MDTYPE_MICROSOFT 0x2 -#define MDTYPE_MD5 0x4 - -#ifdef CHAPMS -#define MDTYPE_ALL (MDTYPE_MICROSOFT_V2 | MDTYPE_MICROSOFT | MDTYPE_MD5) -#else -#define MDTYPE_ALL (MDTYPE_MD5) -#endif -#define MDTYPE_NONE 0 - -/* Return the digest alg. ID for the most preferred digest type. */ -#define CHAP_DIGEST(mdtype) \ - ((mdtype) & MDTYPE_MICROSOFT_V2)? CHAP_MICROSOFT_V2: \ - ((mdtype) & MDTYPE_MICROSOFT)? CHAP_MICROSOFT: \ - ((mdtype) & MDTYPE_MD5)? CHAP_DIGEST_MD5: \ - 0 - -/* Return the bit flag (lsb set) for our most preferred digest type. */ -#define CHAP_MDTYPE(mdtype) ((mdtype) ^ ((mdtype) - 1)) & (mdtype) - -/* Return the bit flag for a given digest algorithm ID. */ -#define CHAP_MDTYPE_D(digest) \ - ((digest) == CHAP_MICROSOFT_V2)? MDTYPE_MICROSOFT_V2: \ - ((digest) == CHAP_MICROSOFT)? MDTYPE_MICROSOFT: \ - ((digest) == CHAP_DIGEST_MD5)? MDTYPE_MD5: \ - 0 - -/* Can we do the requested digest? */ -#define CHAP_CANDIGEST(mdtype, digest) \ - ((digest) == CHAP_MICROSOFT_V2)? (mdtype) & MDTYPE_MICROSOFT_V2: \ - ((digest) == CHAP_MICROSOFT)? (mdtype) & MDTYPE_MICROSOFT: \ - ((digest) == CHAP_DIGEST_MD5)? (mdtype) & MDTYPE_MD5: \ - 0 - -#define CHAP_CHALLENGE 1 -#define CHAP_RESPONSE 2 -#define CHAP_SUCCESS 3 -#define CHAP_FAILURE 4 - -/* - * Challenge lengths (for challenges we send) and other limits. - */ -#define MIN_CHALLENGE_LENGTH 16 -#define MAX_CHALLENGE_LENGTH 24 /* sufficient for MS-CHAP Peer Chal. */ -#define MAX_RESPONSE_LENGTH 64 /* sufficient for MD5 or MS-CHAP */ -#define MS_AUTH_RESPONSE_LENGTH 40 /* MS-CHAPv2 authenticator response, */ - /* as ASCII */ - -/* - * Each interface is described by a chap structure. - */ - -typedef struct chap_state { - int unit; /* Interface unit number */ - int clientstate; /* Client state */ - int serverstate; /* Server state */ - u_char challenge[MAX_CHALLENGE_LENGTH]; /* last challenge string sent */ - u_char chal_len; /* challenge length */ - u_char chal_id; /* ID of last challenge */ - u_char chal_type; /* hash algorithm for challenges */ - u_char id; /* Current id */ - char *chal_name; /* Our name to use with challenge */ - int chal_interval; /* Time until we challenge peer again */ - int timeouttime; /* Timeout time in seconds */ - int max_transmits; /* Maximum # of challenge transmissions */ - int chal_transmits; /* Number of transmissions of challenge */ - int resp_transmits; /* Number of transmissions of response */ - u_char response[MAX_RESPONSE_LENGTH]; /* Response to send */ - char saresponse[MS_AUTH_RESPONSE_LENGTH+1]; /* Auth response to send */ - char earesponse[MS_AUTH_RESPONSE_LENGTH+1]; /* Auth response expected */ - /* +1 for null terminator */ - u_char resp_flags; /* flags from MS-CHAPv2 auth response */ - u_char resp_length; /* length of response */ - u_char resp_id; /* ID for response messages */ - u_char resp_type; /* hash algorithm for responses */ - char *resp_name; /* Our name to send with response */ -} chap_state; - -/* We need the declaration of chap_state to use this prototype */ -extern int (*chap_auth_hook) __P((char *user, u_char *remmd, - int remmd_len, chap_state *cstate)); - -/* - * Client (peer) states. - */ -#define CHAPCS_INITIAL 0 /* Lower layer down, not opened */ -#define CHAPCS_CLOSED 1 /* Lower layer up, not opened */ -#define CHAPCS_PENDING 2 /* Auth us to peer when lower up */ -#define CHAPCS_LISTEN 3 /* Listening for a challenge */ -#define CHAPCS_RESPONSE 4 /* Sent response, waiting for status */ -#define CHAPCS_OPEN 5 /* We've received Success */ - -/* - * Server (authenticator) states. - */ -#define CHAPSS_INITIAL 0 /* Lower layer down, not opened */ -#define CHAPSS_CLOSED 1 /* Lower layer up, not opened */ -#define CHAPSS_PENDING 2 /* Auth peer when lower up */ -#define CHAPSS_INITIAL_CHAL 3 /* We've sent the first challenge */ -#define CHAPSS_OPEN 4 /* We've sent a Success msg */ -#define CHAPSS_RECHALLENGE 5 /* We've sent another challenge */ -#define CHAPSS_BADAUTH 6 /* We've sent a Failure msg */ - -/* - * Timeouts. - */ -#define CHAP_DEFTIMEOUT 3 /* Timeout time in seconds */ -#define CHAP_DEFTRANSMITS 10 /* max # times to send challenge */ - -extern chap_state chap[]; - -void ChapAuthWithPeer __P((int, char *, int)); -void ChapAuthPeer __P((int, char *, int)); - -extern struct protent chap_protent; - -#define __CHAP_INCLUDE__ -#endif /* __CHAP_INCLUDE__ */ -- 2.39.2