/*
*
* Copyright (c) 2000 by Sun Microsystems, Inc.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, provided that the above copyright
* notice appears in all copies.
*
* SUN MAKES NO REPRESENTATION OR WARRANTIES ABOUT THE SUITABILITY OF
* THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES
*
* 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.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h>
#include <string.h>
#include "pppd.h"
#include "upap.h"
#endif
/*
* Command-line options.
*/
"Don't output passwords to log", 1 },
"Show password string in debug log messages", 0 },
"Set retransmit timeout for PAP" },
"Max number of PAP Authenticate-Request sent" },
"Max allowable PAP Authenticate-Request received" },
"Set time limit for peer PAP authentication" },
{ NULL }
};
/*
* Protocol entry points.
*/
static void upap_lowerup __P((int));
static void upap_lowerdown __P((int));
static void upap_protrej __P((int));
void (*) __P((void *, const char *, ...)), void *));
NULL,
NULL,
NULL,
1,
"PAP",
NULL,
NULL,
NULL,
};
static void upap_timeout __P((void *));
static void upap_reqtimeout __P((void *));
static const char *
int clientstate;
{
return ((const char *)buf);
}
return (cstate[clientstate]);
}
static const char *
int serverstate;
{
return ((const char *)buf);
}
return (sstate[serverstate]);
}
/*
* upap_init - Initialize a UPAP unit.
*/
static void
int unit;
{
u->us_userlen = 0;
u->us_clientstate = UPAPCS_INITIAL;
u->us_serverstate = UPAPSS_INITIAL;
u->us_id = 0;
u->us_maxtransmits = 10;
u->us_reqtimeout = UPAP_DEFREQTIME;
u->us_maxreceives = 3;
u->us_msg = "";
u->us_msglen = 0;
}
/*
* upap_authwithpeer - Authenticate us with our peer (start client).
*
* Set new state and send authenticate's.
*/
void
int unit;
{
/* Save the username and password we're given */
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 */
}
/*
* upap_authpeer - Authenticate our peer (start server).
*
* Set new state.
*/
void
int unit;
{
/* 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;
u->us_receives = 0;
if (u->us_reqtimeout > 0)
}
/*
* upap_timeout - Retransmission timer for sending auth-reqs expired.
*/
static void
void *arg;
{
if (u->us_clientstate != UPAPCS_AUTHREQ)
return;
if (u->us_transmits >= u->us_maxtransmits) {
/* give up in disgust */
u->us_clientstate = UPAPCS_BADAUTH;
return;
}
upap_sauthreq(u); /* Send Authenticate-Request */
}
/*
* upap_reqtimeout - Give up waiting for the peer to send a valid auth-req.
*/
static void
void *arg;
{
if (u->us_serverstate != UPAPSS_LISTEN)
return; /* huh?? */
u->us_serverstate = UPAPSS_BADAUTH;
}
/*
* upap_lowerup - The lower layer is up.
*
* Start authenticating if pending.
*/
static void
int unit;
{
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)
}
}
/*
* upap_lowerdown - The lower layer is down.
*
* Cancel all timeouts.
*/
static void
int unit;
{
/* Cancel timeouts */
UNTIMEOUT(upap_timeout, u);
UNTIMEOUT(upap_reqtimeout, u);
u->us_clientstate = UPAPCS_INITIAL;
u->us_serverstate = UPAPSS_INITIAL;
}
/*
* upap_protrej - Peer doesn't speak this protocol.
*
* This shouldn't happen. In any case, pretend lower layer went down.
*/
static void
int unit;
{
if (u->us_clientstate == UPAPCS_AUTHREQ) {
error("PAP authentication failed due to protocol-reject");
}
if (u->us_serverstate == UPAPSS_LISTEN) {
error("PAP authentication of peer failed (protocol-reject)");
}
}
/*
* upap_input - Input UPAP packet.
*/
static void
int unit;
int l;
{
int len;
/*
* Parse header (code, id and length).
* If packet too short, drop it.
*/
if (l < UPAP_HEADERLEN) {
return;
}
UPAP_HEADERLEN, l);
return;
}
len -= UPAP_HEADERLEN;
/*
* Action depends on code.
*/
switch (code) {
case UPAP_AUTHREQ:
break;
case UPAP_AUTHACK:
break;
case UPAP_AUTHNAK:
break;
default:
break;
}
}
/*
* upap_rauth - Receive Authenticate.
*/
static void
upap_state *u;
int id;
int len;
{
int retcode;
char *msg;
int msglen;
if (u->us_serverstate < UPAPSS_LISTEN) {
info("PAP: discarded Authenticate-Request in state %s",
pap_sstate(u->us_serverstate));
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) {
/* return auth-ack */
return;
}
if (u->us_serverstate == UPAPSS_BADAUTH) {
/* return auth-nak */
return;
}
/*
*/
if (len < 1) {
error("PAP: rcvd short packet; no data");
return;
}
if (len < 0) {
error("PAP: rcvd short packet; peer name missing");
return;
}
if (len < rpasswdlen) {
return;
}
/*
* Check the username and password given.
*/
rpasswdlen, &msg);
if (msglen > 255)
msglen = 255;
if (retcode == UPAP_AUTHACK) {
u->us_serverstate = UPAPSS_OPEN;
} else if (++u->us_receives >= u->us_maxreceives) {
u->us_serverstate = UPAPSS_BADAUTH;
} else {
/* Just wait for a good one to arrive, or for time-out. */
return;
}
if (u->us_reqtimeout > 0)
UNTIMEOUT(upap_reqtimeout, u);
}
/*
* upap_rauthack - Receive Authenticate-Ack.
*/
/*ARGSUSED*/
static void
upap_state *u;
int id;
int len;
{
char *msg;
if (u->us_clientstate != UPAPCS_AUTHREQ) {
info("PAP: discarded Authenticate-Ack in state %s",
pap_cstate(u->us_clientstate));
return;
}
dbglog("PAP: discard Authenticate-Ack; ID %d != %d",
return;
}
if (u->us_timeouttime > 0)
UNTIMEOUT(upap_timeout, u);
/*
* Parse message.
*/
if (len < 1) {
info("PAP: Ignoring missing ack msg-length octet");
} else {
if (msglen > 0) {
return;
}
}
}
u->us_clientstate = UPAPCS_OPEN;
}
/*
* upap_rauthnak - Receive Authenticate-Nakk.
*/
/*ARGSUSED*/
static void
upap_state *u;
int id;
int len;
{
char *msg;
if (u->us_clientstate != UPAPCS_AUTHREQ) {
info("PAP: discarded Authenticate-Nak in state %s",
pap_cstate(u->us_clientstate));
return;
}
dbglog("PAP: discard Authenticate-Ack; ID %d != %d",
return;
}
if (u->us_timeouttime > 0)
UNTIMEOUT(upap_timeout, u);
/*
* Parse message.
*/
if (len < 1) {
error("PAP: ignoring missing nak msg-length octet");
} else {
if (msglen > 0) {
return;
}
}
}
/* Try to get a new password from the plugin. */
if (pap_passwd_hook != NULL) {
if (u->us_transmits < u->us_maxtransmits) {
upap_sauthreq(u);
return;
}
} else {
/* Tell plug-in that we're giving up. */
}
}
u->us_clientstate = UPAPCS_BADAUTH;
error("PAP authentication failed");
}
/*
* upap_sauthreq - Send an Authenticate-Request.
*/
static void
upap_state *u;
{
int pwlen;
int outlen;
if (pwlen > 0xFF)
pwlen = 0xFF;
if (u->us_timeouttime > 0)
++u->us_transmits;
u->us_clientstate = UPAPCS_AUTHREQ;
}
/*
* upap_sresp - Send a response (ack or nak).
*/
static void
upap_state *u;
char *msg;
int msglen;
{
int outlen;
}
/*
* upap_printpkt - print the contents of a PAP packet.
*/
static char *upap_codenames[] = {
"AuthReq", "AuthAck", "AuthNak"
};
static int
u_char *p;
int plen;
void *arg;
{
if (plen < UPAP_HEADERLEN)
return (0);
pstart = p;
return (0);
else
len -= UPAP_HEADERLEN;
switch (code) {
case UPAP_AUTHREQ:
if (len < 1)
break;
ulen = p[0];
break;
break;
user = (char *) (p + 1);
if (!hide_password)
else
break;
case UPAP_AUTHACK:
case UPAP_AUTHNAK:
if (len < 1)
break;
mlen = p[0];
break;
msg = (char *) (p + 1);
p += mlen + 1;
break;
}
/* print the rest of the bytes in the packet */
}
return (p - pstart);
}