📄 chap.c
字号:
/* chap.c - Crytographic Handshake Authentication Protocol *//* Copyright 1995 Wind River Systems, Inc. */#include "copyright_wrs.h"/* * 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. *//*modification history--------------------01e,30jun95,dzb removed floating point operation (srand48() and drand48()).01d,16jun95,dzb header file consolidation. changed [UN]TIMEOUT macros to PPP_[UN]TIMEOUT.01c,08jun95,dzb changed CHAP response messages to be more informative.01b,16jan95,dzb changed to use PPP specific md5 routines.01a,21dec94,dab VxWorks port - first WRS version. +dzb added: path for ppp header files, WRS copyright, NO_DRAND48.*/#include "vxWorks.h"#include "stdio.h"#include "string.h"#include "sys/types.h"#include "sys/times.h"#include "pppLib.h"static void ChapChallengeTimeout __ARGS((caddr_t));static void ChapResponseTimeout __ARGS((caddr_t));static void ChapReceiveChallenge __ARGS((chap_state *, u_char *, int, int));static void ChapReceiveResponse __ARGS((chap_state *, u_char *, int, int));static void ChapReceiveSuccess __ARGS((chap_state *, u_char *, int, int));static void ChapReceiveFailure __ARGS((chap_state *, u_char *, int, int));static void ChapSendStatus __ARGS((chap_state *, int));static void ChapSendChallenge __ARGS((chap_state *));static void ChapSendResponse __ARGS((chap_state *));static void ChapGenChallenge __ARGS((chap_state *));/* * ChapInit - Initialize a CHAP unit. */voidChapInit(unit) int unit;{ chap_state *cstate = &ppp_if[unit]->chap; BZERO((char *)cstate, sizeof(*cstate)); cstate->unit = unit; cstate->clientstate = CHAPCS_INITIAL; cstate->serverstate = CHAPSS_INITIAL; cstate->timeouttime = CHAP_DEFTIMEOUT; cstate->max_transmits = CHAP_DEFTRANSMITS; srandom((long) time(NULL)); /* joggle random number generator */}/* * ChapAuthWithPeer - Authenticate us with our peer (start client). * */voidChapAuthWithPeer(unit, our_name, digest) int unit; char *our_name; int digest;{ chap_state *cstate = &ppp_if[unit]->chap; 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;}/* * ChapAuthPeer - Authenticate our peer (start server). */voidChapAuthPeer(unit, our_name, digest) int unit; char *our_name; int digest;{ chap_state *cstate = &ppp_if[unit]->chap; 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 voidChapChallengeTimeout(arg) caddr_t 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 */ syslog(LOG_ERR, "Peer failed to respond to CHAP challenge"); cstate->serverstate = CHAPSS_BADAUTH; auth_peer_fail(cstate->unit, CHAP); return; } ChapSendChallenge(cstate); /* Re-send challenge */}/* * ChapResponseTimeout - Timeout expired on sending response. */static voidChapResponseTimeout(arg) caddr_t 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 voidChapRechallenge(arg) caddr_t 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; if (cstate->chal_interval != 0) PPP_TIMEOUT(ChapRechallenge, (caddr_t) cstate, cstate->chal_interval);}/* * ChapLowerUp - The lower layer is up. * * Start up if we have pending requests. */voidChapLowerUp(unit) int unit;{ chap_state *cstate = &ppp_if[unit]->chap; 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. */voidChapLowerDown(unit) int unit;{ chap_state *cstate = &ppp_if[unit]->chap; /* Timeout(s) pending? Cancel if so. */ if (cstate->serverstate == CHAPSS_INITIAL_CHAL || cstate->serverstate == CHAPSS_RECHALLENGE) PPP_UNTIMEOUT(ChapChallengeTimeout, (caddr_t) cstate); else if (cstate->serverstate == CHAPSS_OPEN && cstate->chal_interval != 0) PPP_UNTIMEOUT(ChapRechallenge, (caddr_t) cstate); if (cstate->clientstate == CHAPCS_RESPONSE) PPP_UNTIMEOUT(ChapResponseTimeout, (caddr_t) cstate); cstate->clientstate = CHAPCS_INITIAL; cstate->serverstate = CHAPSS_INITIAL;}/* * ChapProtocolReject - Peer doesn't grok CHAP. */voidChapProtocolReject(unit) int unit;{ chap_state *cstate = &ppp_if[unit]->chap; if (cstate->serverstate != CHAPSS_INITIAL && cstate->serverstate != CHAPSS_CLOSED) auth_peer_fail(unit, CHAP); if (cstate->clientstate != CHAPCS_INITIAL && cstate->clientstate != CHAPCS_CLOSED) auth_withpeer_fail(unit, CHAP); ChapLowerDown(unit); /* shutdown chap */}/* * ChapInput - Input CHAP packet. */voidChapInput(unit, inpacket, packet_len) int unit; u_char *inpacket; int packet_len;{ chap_state *cstate = &ppp_if[unit]->chap; 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((LOG_INFO, "ChapInput: rcvd short header.")); return; } GETCHAR(code, inp); GETCHAR(id, inp); GETSHORT(len, inp); if (len < CHAP_HEADERLEN) { CHAPDEBUG((LOG_INFO, "ChapInput: rcvd illegal length.")); return; } if (len > packet_len) { CHAPDEBUG((LOG_INFO, "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? */ syslog(LOG_WARNING, "Unknown CHAP code (%d) received.", code); break; }}/* * ChapReceiveChallenge - Receive Challenge and send Response. */static voidChapReceiveChallenge(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; CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: Rcvd id %d.", id)); if (cstate->clientstate == CHAPCS_CLOSED || cstate->clientstate == CHAPCS_PENDING) { CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: in state %d", cstate->clientstate)); return; } if (len < 2) { CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: rcvd short packet.")); return; } GETCHAR(rchallenge_len, inp); len -= sizeof (u_char) + rchallenge_len; /* now name field length */ if (len < 0) { CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: rcvd short packet.")); return; } rchallenge = inp; INCPTR(rchallenge_len, inp); if (len >= sizeof(rhostname)) len = sizeof(rhostname) - 1; BCOPY((char *)inp, rhostname, len); rhostname[len] = '\000'; CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: received name field: %s", 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 */ syslog(LOG_WARNING, "No CHAP secret found for authenticating us to %s", rhostname); } /* cancel response send timeout if necessary */ if (cstate->clientstate == CHAPCS_RESPONSE) PPP_UNTIMEOUT(ChapResponseTimeout, (caddr_t) cstate); cstate->resp_id = id; cstate->resp_transmits = 0; /* generate MD based on negotiated type */ switch (cstate->resp_type) { case CHAP_DIGEST_MD5: /* only MD5 is defined for now */ ppp_MD5Init(&mdContext); ppp_MD5Update(&mdContext, &cstate->resp_id, 1); ppp_MD5Update(&mdContext, (u_char *) secret, secret_len); ppp_MD5Update(&mdContext, rchallenge, rchallenge_len); ppp_MD5Final(&mdContext); BCOPY((char *)mdContext.digest, (char *)cstate->response, MD5_SIGNATURE_SIZE); cstate->resp_length = MD5_SIGNATURE_SIZE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -