📄 chap.c
字号:
#if CHAPME_DEBUG
Printu("\r\nChapInput\r\n");
#endif
/*
* Parse header (code, id and length).
* If packet too short, drop it.
*/
inp = inpacket;
if (packet_len < CHAP_HEADERLEN)
{
// ConPrintf("ChapInput: rcvd short header.");
return;
}
code = *inp++;
id = *inp++;
len = ppp_getshort(inp);
inp += 2;
if (len < CHAP_HEADERLEN)
{
//ConPrintf("ChapInput: rcvd illegal length.");
return;
}
if (len > packet_len)
{
// ConPrintf("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, id);
break;
case CHAP_SUCCESS:
ChapReceiveSuccess(cstate, id,inpacket,len+CHAP_HEADERLEN);
break;
default: /* Need code reject? */
//ConPrintf("Unknown CHAP code (%d) received.", code);
break;
}
}
/* FUNCTION: ChapReceiveChallenge()
*
* ChapReceiveChallenge - Receive Challenge and send Response.
*
*
* PARAM1: chap_state *cstate
* PARAM2: u_char *inp
* PARAM3: int id
* PARAM4: int len
*
* RETURNS:
*/
static void
ChapReceiveChallenge(chap_state * cstate,
u_char * inp,
int id,
int len)
{
int rchallenge_len;
u_char * rchallenge;
int secret_len;
char secret[MAXSECRETLEN];
char rhostname[MAXSECRETLEN];
MD5_CTX mdContext;
// ConPrintf("ChapReceiveChallenge: link %lx Rcvd id %d.", cstate->mppp, id);
#if CHAPME_DEBUG
Printu("ChapReceiveChallenge: link %lx Rcvd id %d.\r\n", cstate->mppp, id);
#endif
if (cstate->clientstate == CHAPCS_CLOSED ||
cstate->clientstate == CHAPCS_PENDING)
{
//ConPrintf("ChapReceiveChallenge: in state %d",
// cstate->clientstate);
#if CHAPME_DEBUG
Printu("ChapReceiveChallenge: in state %d",
cstate->clientstate);
#endif
return;
}
if (len < 2)
{
// ConPrintf("ChapReceiveChallenge: rcvd short packet.");
#if CHAPME_DEBUG
Printu("ChapReceiveChallenge: rcvd short packet.\r\n");
#endif
return;
}
rchallenge_len = *inp++;
len -= sizeof (u_char) + rchallenge_len; /* now name field length */
if (len < 0)
{
//ConPrintf("ChapReceiveChallenge: rcvd short packet.");
#if CHAPME_DEBUG
Printu("ChapReceiveChallenge: rcvd short packet.\r\n");
#endif
return;
}
rchallenge = inp;
inp += rchallenge_len;
if (len >= sizeof(rhostname))
len = sizeof(rhostname) - 1;
MEMCPY(rhostname, inp, len);
rhostname[len] = '\000';
//ConPrintf("ChapReceiveChallenge: received name field: %s",
// rhostname);
#if CHAPME_DEBUG
Printu("ChapReceiveChallenge: received name field:Len:%x\t %s",len,
rhostname);
#endif
/* get secret for authenticating ourselves with the specified host */
if (!get_secret(cstate->mppp, cstate->resp_name, rhostname,
secret, &secret_len, 0))
{
secret_len = 0; /* assume null secret if can't find one */
//ConPrintf("No CHAP secret found for authenticating us to %s",
// rhostname);
#if CHAPME_DEBUG
Printu("No CHAP secret found for authenticating us to %s",
rhostname);
#endif
}
/* cancel response send timeout if necessary */
if (cstate->clientstate == CHAPCS_RESPONSE)
ppp_cleartimer(cstate->mppp);
cstate->resp_id = (u_char)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 */
#ifdef DEBUGCHAP
//ConPrintf("MD5ing; id:%d, secret:%s, chal_len:%u\n",
//cstate->resp_id, secret, rchallenge_len);
#endif
MD5Init(&mdContext);
MD5Update(&mdContext, &cstate->resp_id, 1);
MD5Update(&mdContext, (u_char*)secret, (unsigned)secret_len);
MD5Update(&mdContext, rchallenge, rchallenge_len);
MD5Final(&mdContext);
MEMCPY(cstate->response, mdContext.digest, MD5_SIGNATURE_SIZE);
cstate->resp_length = MD5_SIGNATURE_SIZE;
break;
#ifdef MSCHAP_SUPPORT
case CHAP_DIGEST_MSCHAP:
{
#ifdef DEBUGCHAP
//ConPrintf("MS-CHAPping; id:%d, secret:%s, chal_len:%u\n",
//cstate->resp_id, secret, rchallenge_len);
#endif
MSChapChallenge( rchallenge, rchallenge_len, cstate->response, secret );
cstate->resp_length = MSCHAP_SIGNATURE_SIZE;
break;
}
#endif
default:
//ConPrintf("unknown digest type %d", cstate->resp_type);
return;
}
ChapSendResponse(cstate);
}
/* FUNCTION: ChapReceiveResponse()
*
* ChapReceiveResponse - Receive and process response.
*
* PARAM1: chap_state *cstate
* PARAM2: u_char *inp
* PARAM3: int id
* PARAM4: int len
*
* RETURNS:
*/
static void
ChapReceiveResponse(chap_state * cstate,
u_char * inp,
int id,
int len)
{
u_char * remmd, remmd_len;
int secret_len, old_state;
int code;
MD5_CTX mdContext;
char secret[MAXSECRETLEN];
char rhostname[MAXSECRETLEN];
//ConPrintf("ChapReceiveResponse: link: %lx Rcvd id %d.", cstate->mppp, id);
if (cstate->serverstate == CHAPSS_CLOSED ||
cstate->serverstate == CHAPSS_PENDING)
{
//ConPrintf("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)
{
//ConPrintf("ChapReceiveResponse: rcvd short packet.");
return;
}
remmd_len = *inp++; /* get length of MD */
remmd = inp; /* get pointer to MD */
inp += remmd_len;
len -= sizeof (u_char) + remmd_len;
if (len < 0)
{
//ConPrintf("ChapReceiveResponse: rcvd short packet.");
return;
}
ppp_cleartimer(cstate->mppp);
if (len >= sizeof(rhostname))
len = sizeof(rhostname) - 1;
MEMCPY(rhostname, inp, len);
rhostname[len] = '\000';
// ConPrintf("ChapReceiveResponse: received name field: %s",
// rhostname);
/*
* Get secret for authenticating them with us,
* do the hash ourselves, and compare the result.
*/
code = CHAP_FAILURE;
if (!get_secret(cstate->mppp, rhostname, cstate->chal_name,
secret, &secret_len, 1))
{
//ConPrintf("No CHAP secret found for authenticating %s",
//rhostname);
}
else
{
/* generate MD based on negotiated type */
switch (cstate->chal_type)
{
case CHAP_DIGEST_MD5: /* only MD5 is defined for now */
if (remmd_len != MD5_SIGNATURE_SIZE)
break; /* it's not even the right length */
#ifdef DEBUGCHAP
// ConPrintf("MD5ing; id:%d, secret:%s, chal_len:%u\n",
//cstate->chal_id, secret, cstate->chal_len);
#endif
MD5Init(&mdContext);
MD5Update(&mdContext, &cstate->chal_id, 1);
MD5Update(&mdContext, (u_char*)secret, (unsigned)secret_len);
MD5Update(&mdContext, cstate->challenge, cstate->chal_len);
MD5Final(&mdContext);
/* compare local and remote MDs and send the appropriate status */
if (MEMCMP(mdContext.digest, remmd, MD5_SIGNATURE_SIZE) == 0)
code = CHAP_SUCCESS; /* they are the same! */
break;
#ifdef MSCHAP_SUPPORT
case CHAP_DIGEST_MSCHAP:
{
unsigned char response[MAX_RESPONSE_LENGTH];
if (remmd_len != MSCHAP_SIGNATURE_SIZE)
break; /* it's not even the right length */
MSChapChallenge( cstate->challenge, cstate->chal_len, response, secret );
/* compare local and remote MDs and send the appropriate status */
/* If byte 48 of the remote MD is ZERO then we are using a LanMangler */
/* style challenge/response, and must compare the first 24 bytes. */
/* If byte 48 is ONE then we are using an NT style challenge/response */
/* and must compare the second 24 bytes. */
if ( remmd[48] )
{
/* NT style */
if (MEMCMP(response+24, remmd+24, 24) == 0)
code = CHAP_SUCCESS; /* they are the same! */
#ifdef DEBUGCHAP
//ConPrintf("Authentication %s using NT version of MS-CHAP\n", code == CHAP_SUCCESS ? "OK" : "FAILED" );
#endif
}
else
{
/* Lan Manager style */
if (MEMCMP(response, remmd, 24) == 0)
code = CHAP_SUCCESS; /* they are the same! */
#ifdef DEBUGCHAP
//ConPrintf("Authentication %s using Lan Manager version of MS-CHAP\n", code == CHAP_SUCCESS ? "OK" : "FAILED" );
#endif
}
if ( code != CHAP_SUCCESS )
{
/* MSCHAP allows retries (boo, hiss)
*/
if ( ++cstate->mschap_failures < cstate->max_transmits )
{
#ifdef DEBUGCHAP
// ConPrintf("MS-CHAP Authentication failure. Allowing retry. New ID is %d\n", cstate->chal_id + 1 );
#endif
/* Send out the failure message for this
* response...
*/
ChapSendStatus(cstate, code);
/* Bump the challenge ID & the challenge value
*/
cstate->chal_id++;
cstate->challenge[0] += 23;
return;
}
}
break;
}
#endif /* MSCHAP_SUPPORT */
default:
;
//ConPrintf("unknown digest type %d", cstate->chal_type);
}
}
ChapSendStatus(cstate, code);
if (code == CHAP_SUCCESS)
{
old_state = cstate->serverstate;
cstate->serverstate = CHAPSS_OPEN;
if (old_state == CHAPSS_INITIAL_CHAL)
{
/* bring up IPCP layer */
ppp_lowerup(cstate->mppp, IPCP_STATE);
/* If we're server then do the open too. */
if(cstate->mppp->pppflags & PPP_SERVER)
ppp_open(cstate->mppp, IPCP_STATE);
}
if (cstate->chal_interval != 0)
{
ppp_settimer(cstate->mppp, ChapRechallenge,
cstate->chal_interval, 0);
}
}
else
{
// ConPrintf("CHAP peer authentication failed");
cstate->serverstate = CHAPSS_BADAUTH;
ppp_auth_failed(cstate->mppp, 1);
}
}
/* FUNCTION: ChapReceiveSuccess()
*
* ChapReceiveSuccess - Receive Success
*
* PARAM1: chap_state *cstate
* PARAM2: u_char *inp
* PARAM3: u_char id
* PARAM4: int len
*
* RETURNS:
*/
static u_char sendbuf[]={0xc2,0x23,0x3,0x01,0x00,0x04};
static void
ChapReceiveSuccess(chap_state * cstate, int id,u_char *inp,int len)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -