📄 upap.c
字号:
/*
* FILENAME: upap.c
*
* Copyright 1997 - 2001 By InterNiche Technologies Inc. All rights reserved
*
* User/Password Authentication Protocol.
*
* MODULE: PPP
*
* ROUTINES: upap_init(), upap_authwithpeer(), upap_authpeer(),
* ROUTINES: upap_timeout(), upap_reqtimeout(), upap_lowerup(),
* ROUTINES: upap_lowerdown(), upap_protrej(), upap_input(), upap_rauthreq(),
* ROUTINES: upap_rauthack(), upap_rauthnak(), upap_sauthreq(), upap_sresp(),
*
* PORTABLE: yes
*/
/* Additional Copyrights: */
/* Portions Copyright 1996 by NetPort Software
* Portions Copyright (c) 1989 Carnegie Mellon University. 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 Carnegie Mellon University. The name of the
* University 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.
*/
#include "ppp_port.h"
#ifdef PAP_SUPPORT /* whole file can be ifdeffed out */
#include "mppp.h"
/* UPAP Header length - op + id + (short)len */
#define UPAP_HEADERLEN 4
static void upap_timeout (M_PPP mppp, long);
static void upap_reqtimeout (M_PPP mppp, long);
static void upap_rauthreq (upap_state *, u_char *, int id, unshort len);
static void upap_rauthack (upap_state *, u_char *, unshort len);
static void upap_rauthnak (upap_state *, u_char *, unshort len);
static void upap_sauthreq (upap_state *);
static void upap_sresp (upap_state *, int, int, char *, int);
auth_funcs upap_authtable =
{
upap_init,
upap_authwithpeer,
upap_authpeer,
upap_lowerup,
upap_lowerdown,
upap_input,
upap_protrej,
};
#ifndef NO_CONPRINTF
char * upap_code[] =
{
"foo",
"AUTHREQ",
"AUTHACK",
"AUTHNAK",
};
#endif
/* FUNCTION: upap_init()
*
* upap_init - Initialize a UPAP unit.
*
* PARAM1: M_PPP mppp
*
* RETURNS: void
*/
void
upap_init(M_PPP mppp)
{
upap_state * u = &mppp->upap;
u->mppp = mppp;
u->us_user = NULL;
u->us_userlen = 0;
u->us_passwd = NULL;
u->us_passwdlen = 0;
u->us_clientstate = UPAPCS_INITIAL;
u->us_serverstate = UPAPSS_INITIAL;
u->us_id = 0;
u->us_timeouttime = UPAP_DEFTIMEOUT;
u->us_maxtransmits = 10;
u->us_reqtimeout = UPAP_DEFREQTIME;
}
/* FUNCTION: upap_authwithpeer()
*
* Authenticate us with our peer (start client).
* Set new state and send authenticate's.
*
*
* PARAM1: M_PPP mppp
*
* RETURNS: void
*/
void
upap_authwithpeer(M_PPP mppp)
{
upap_state *u = &mppp->upap;
/* Save the username and password we're given */
u->us_user = mppp->username;
u->us_userlen = strlen(mppp->username);
u->us_passwd = mppp->password;
u->us_passwdlen = strlen(mppp->password);
u->us_transmits = 0;
/* Lower layer up yet? */
if (u->us_clientstate == UPAPCS_INITIAL ||
u->us_clientstate == UPAPCS_PENDING)
{
u->us_clientstate = UPAPCS_PENDING;
return;
}
upap_sauthreq(u); /* Start protocol */
}
/* FUNCTION: upap_authpeer()
*
* upap_authpeer - Authenticate our peer (start server). Sets new
* state.
*
*
* PARAM1: M_PPP mppp
*
* RETURNS:
*/
void
upap_authpeer(M_PPP mppp)
{
upap_state *u = &mppp->upap;
/* Lower layer up yet? */
if (u->us_serverstate == UPAPSS_INITIAL ||
u->us_serverstate == UPAPSS_PENDING)
{
u->us_serverstate = UPAPSS_PENDING;
return;
}
u->us_serverstate = UPAPSS_LISTEN;
if (u->us_reqtimeout > 0)
ppp_settimer(mppp, upap_reqtimeout, u->us_reqtimeout, 0);
}
/* FUNCTION: upap_timeout()
*
* Retransmission timer for sending auth-reqs expired.
*
* PARAM1: void * arg
*
* RETURNS: void
*/
static void
upap_timeout(M_PPP mppp, long arg)
{
upap_state *u = &mppp->upap;
USE_ARG(arg);
if (u->us_clientstate != UPAPCS_AUTHREQ)
return;
if (u->us_transmits >= u->us_maxtransmits)
{
/* give up in disgust */
//ConPrintf("link %lx: No response to PAP authenticate-requests", mppp);
u->us_clientstate = UPAPCS_BADAUTH;
ppp_auth_failed(mppp, 1);
return;
}
upap_sauthreq(u); /* Send Authenticate-Request */
}
/* FUNCTION: upap_reqtimeout()
*
* upap_reqtimeout - Give up waiting for the peer to send an auth-req.
*
* PARAM1: void * arg
*
* RETURNS: void
*/
static void
upap_reqtimeout(M_PPP mppp, long arg)
{
upap_state *u = &mppp->upap;
USE_ARG(arg);
if (u->us_serverstate != UPAPSS_LISTEN)
{
dtrap("upap 0\n");
return; /* huh?? */
}
ppp_auth_failed(mppp, 1);
u->us_serverstate = UPAPSS_BADAUTH;
}
/* FUNCTION: upap_lowerup()
*
* The lower layer is up. Start authenticating if pending.
*
*
* PARAM1: M_PPP mppp
*
* RETURNS:
*/
void
upap_lowerup(M_PPP mppp)
{
upap_state * u = &mppp->upap;
if (u->us_clientstate == UPAPCS_INITIAL)
u->us_clientstate = UPAPCS_CLOSED;
else if (u->us_clientstate == UPAPCS_PENDING)
{
upap_sauthreq(u); /* send an auth-request */
}
if (u->us_serverstate == UPAPSS_INITIAL)
u->us_serverstate = UPAPSS_CLOSED;
else if (u->us_serverstate == UPAPSS_PENDING)
{
u->us_serverstate = UPAPSS_LISTEN;
if (u->us_reqtimeout > 0)
ppp_settimer(mppp, upap_reqtimeout, u->us_reqtimeout, 0);
}
}
/* FUNCTION: upap_lowerdown()
*
* The lower layer is down. Cancel all timeouts.
*
*
* PARAM1: M_PPP mppp
*
* RETURNS: void
*/
void
upap_lowerdown(M_PPP mppp)
{
upap_state * u = &mppp->upap;
if((u->us_clientstate == UPAPCS_AUTHREQ) || /* Timeout pending? */
(u->us_serverstate == UPAPSS_LISTEN && u->us_reqtimeout > 0))
{
ppp_cleartimer(mppp); /* Cancel timeout */
}
u->us_clientstate = UPAPCS_INITIAL;
u->us_serverstate = UPAPSS_INITIAL;
}
/* FUNCTION: upap_protrej()
*
* upap_protrej - Peer doesn't speak this protocol. This shouldn't
* happen. In any case, pretend lower layer went down.
*
*
* PARAM1: M_PPP mppp
*
* RETURNS: void
*/
void
upap_protrej(M_PPP mppp)
{
upap_state *u = &mppp->upap;
if (u->us_clientstate == UPAPCS_AUTHREQ)
{
// ConPrintf("PAP authentication failed due to protocol-reject");
ppp_auth_failed(mppp, 0);
}
if (u->us_serverstate == UPAPSS_LISTEN)
{
//ConPrintf("PAP authentication of peer failed (protocol-reject)");
ppp_auth_failed(mppp, 1);
}
upap_lowerdown(mppp);
}
/* FUNCTION: upap_input()
*
* Input UPAP packet.
*
* PARAM1: M_PPP mppp - link
* PARAM2: u_char * inpacket - starts with opcode AFTER upap prot field
* PARAM3: int l - number of bytes in inpacket
*
* RETURNS:
*/
void
upap_input(M_PPP mppp, u_char * inpacket, int l)
{
upap_state * u = &mppp->upap;
u_char * inp;
u_char code, id;
unshort len;
/* Parse header (code, id and length). If packet too short, drop it. */
inp = inpacket;
if (l < UPAP_HEADERLEN)
{
// ConPrintf("upap_input: rcvd short header.");
return;
}
code = *inp++; /* get opcode (authreq, authack) */
id = *inp++;
len = ppp_getshort(inp);
inp += 2;
if (len < UPAP_HEADERLEN)
{
//ConPrintf("upap_input link %lx: runt, len: %d.",mppp, len);
return;
}
// ConPrintf("upap_input link %lx: code: %s, id %d, len %d\n",
// mppp, upap_code[code], id, len);
len -= 4; /* deduct the 4 bytes we advanced inp by */
if(code > UPAP_AUTHNAK)
{
/* Need code reject? */
//ConPrintf("upap_input: unknown code %d\n", code);
return;
}
/* Action depends on code. */
switch (code)
{
case UPAP_AUTHREQ:
upap_rauthreq(u, inp, id, len);
break;
case UPAP_AUTHACK:
upap_rauthack(u, inp, len);
break;
case UPAP_AUTHNAK:
upap_rauthnak(u, inp, len);
break;
}
return;
}
/* FUNCTION: upap_rauthreq()
*
* Receive Authenticate.
*
* PARAM1: upap_state *u
* PARAM2: u_char *inp
* PARAM3: int id
* PARAM4: int len
*
* RETURNS: void
*/
static void
upap_rauthreq(upap_state * u,
u_char * inp,
int id,
unshort len)
{
u_char ruserlen, rpasswdlen;
char * ruser, * rpasswd;
int retcode;
char * msg;
int msglen;
if (u->us_serverstate < UPAPSS_LISTEN)
return;
/* If we receive a duplicate authenticate-request, we are supposed
* to return the same status as for the first request.
*/
if (u->us_serverstate == UPAPSS_OPEN)
{
upap_sresp(u, UPAP_AUTHACK, id, "", 0); /* return auth-ack */
return;
}
if (u->us_serverstate == UPAPSS_BADAUTH)
{
upap_sresp(u, UPAP_AUTHNAK, id, "", 0); /* return auth-nak */
return;
}
/* Parse user/passwd. */
if (len < sizeof (u_char))
{
//ConPrintf("upap_rauth: rcvd short packet.");
return;
}
/* Subtract the length of the user name from the total length. */
ruserlen = *inp++;
len -= (unshort)ruserlen + 2; /* add size of 2 chars */
if (len & (unshort)0x8000) /* see if len tried to go negative */
{
//ConPrintf("upap_rauth: rcvd short packet.");
return;
}
ruser = (char *) inp;
inp += ruserlen;
rpasswdlen = *inp++;
if (len < rpasswdlen)
{
// ConPrintf("upap_rauth: rcvd short packet.");
return;
}
rpasswd = (char *) inp;
if (u->us_reqtimeout > 0) /* Don't need UPAP timer anymore */
ppp_cleartimer(u->mppp);
/* Check the username and password given. */
retcode = check_passwd(u->mppp, ruser, ruserlen, rpasswd,
rpasswdlen, &msg, &msglen);
upap_sresp(u, retcode, id, msg, msglen);
if (retcode == UPAP_AUTHACK)
{
ppp_lowerup(u->mppp, IPCP_STATE);
}
else
{
u->us_serverstate = UPAPSS_BADAUTH;
ppp_auth_failed(u->mppp, 1);
}
return;
}
/* FUNCTION: upap_rauthack()
*
* upap_rauthack - Receive Authenticate-Ack.
*
* PARAM1: upap_state *u
* PARAM2: u_char *inp
* PARAM3: int id
* PARAM4: int len
*
* RETURNS: void
*/
static void
upap_rauthack(upap_state * u,
u_char * inp,
unshort len)
{
u_char msglen;
char * msg;
if (u->us_clientstate != UPAPCS_AUTHREQ) /* XXX */
{
//ConPrintf("upap_rauthack: rx pkt in state %d\n", u->us_clientstate);
return;
}
/* Parse message. */
msglen = *inp++;
len -= sizeof (u_char);
if (len < (unshort)msglen)
{
//ConPrintf("upap_rauthack: runt, len: %d.", len);
return;
}
msg = (char *) inp;
//ConPrintf(msg);
u->us_clientstate = UPAPCS_OPEN;
if (u->us_reqtimeout > 0) /* Don't need UPAP timer anymore */
ppp_cleartimer(u->mppp);
ppp_lowerup(u->mppp, IPCP_STATE); /* let upper layer know auth OK */
return;
}
/* FUNCTION: upap_rauthnak()
*
* Receive Authenticate-Nakk.
*
* PARAM1: upap_state *u
* PARAM2: u_char *inp
* PARAM3: int id
* PARAM4: int len
*
* RETURNS:
*/
static void
upap_rauthnak(upap_state * u,
u_char * inp,
unshort len)
{
u_char msglen;
char * msg;
if (u->us_clientstate != UPAPCS_AUTHREQ) /* XXX */
{
dtrap("upap 1\n");
return;
}
/* Parse message. */
msglen = *inp++;
len -= sizeof (u_char);
if (len < msglen)
{
//ConPrintf("upap_rauthnak: runt, len %d\n", len);
return;
}
msg = (char *) inp;
//ConPrintf(msg);
u->us_clientstate = UPAPCS_BADAUTH;
//ConPrintf("Link %lx: PAP auth failed\n", u->mppp);
ppp_auth_failed(u->mppp, 0);
}
/* FUNCTION: upap_sauthreq()
*
* Send an Authenticate-Request.
*
* PARAM1: upap_state *u
*
* RETURNS:
*/
static void
upap_sauthreq(upap_state * u)
{
u_char * outp;
unshort outlen;
/* 2 len bytes + 2 prot bytes */
outlen = (unshort)(UPAP_HEADERLEN + 2 +
u->us_userlen + u->us_passwdlen);
if(outlen > MAX_CILEN)
panic("upap overflow 1");
outp = u->mppp->lastci;
/* build a UPAP header in the send buffer */
outp = ppp_putshort(outp, PPP_UPAP);
*outp++ = UPAP_AUTHREQ;
*outp++ = (++u->us_id);
outp = ppp_putshort(outp, outlen);
*outp++ = (u_char)u->us_userlen;
MEMCPY(outp, u->us_user, u->us_userlen);
outp += u->us_userlen;
*outp++ = (u_char)u->us_passwdlen;
MEMCPY(outp, u->us_passwd, u->us_passwdlen);
ppp_sendctl(u->mppp, AUTH_STATE, 0, u->mppp->lastci, outlen + 2, 0);
//ConPrintf("upap_sauth: Sent id %d.", u->us_id);
ppp_settimer(u->mppp, upap_timeout, u->us_timeouttime, 0);
++u->us_transmits;
u->us_clientstate = UPAPCS_AUTHREQ;
}
/* FUNCTION: upap_sresp()
*
* upap_sresp - Send a response (ack or nak).
*
* PARAM1: upap_state *u
* PARAM2: int code
* PARAM3: int id
* PARAM4: char *msg
* PARAM5: int msglen
*
* RETURNS:
*/
static void
upap_sresp(upap_state * u,
int code,
int id,
char * msg,
int msglen)
{
u_char * outp;
unshort outlen;
outlen = (unshort)(UPAP_HEADERLEN + 1 + msglen);
if(outlen > MAX_CILEN)
panic("upap overflow 1");
outp = u->mppp->lastci;
outp = ppp_putshort(outp, PPP_UPAP);
*outp++ = (u_char)code;
*outp++ = (u_char)id;
outp = ppp_putshort(outp, outlen);
*outp++ = (u_char)msglen;
MEMCPY(outp, msg, msglen);
ppp_sendctl(u->mppp, AUTH_STATE, 0, u->mppp->lastci, outlen + 2, 0);
//ConPrintf("upap_sresp: Sent code %d, id %d.", code, id);
}
#endif /* PAP_SUPPORT whole file can be ifdeffed out */
/* end of file upap.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -