home *** CD-ROM | disk | FTP | other *** search
- /*
- * upap.c - User/Password Authentication Protocol.
- *
- * 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.
- */
-
- /*
- * TODO:
- */
-
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/time.h>
-
- #include "ppp.h"
- #include "upap.h"
-
-
- upap_state upap[NPPP]; /* UPAP state; one for each unit */
-
-
- void upap_timeout(), upap_rauth(), upap_rauthack(), upap_rauthnak();
- void upap_sauth(), upap_sresp();
-
-
- /*
- * upap_init - Initialize a UPAP unit.
- */
- void upap_init(unit)
- int unit;
- {
- upap_state *u = &upap[unit];
-
- u->us_unit = unit;
- u->us_user = NULL;
- u->us_userlen = 0;
- u->us_passwd = NULL;
- u->us_passwdlen = 0;
- u->us_clientstate = UPAPCS_CLOSED;
- u->us_serverstate = UPAPSS_CLOSED;
- u->us_flags = 0;
- u->us_id = 0;
- u->us_timeouttime = UPAP_DEFTIMEOUT;
- }
-
-
- /*
- * upap_authwithpeer - Authenticate us with our peer (start client).
- *
- * Set new state and send authenticate's.
- */
- void upap_authwithpeer(unit)
- int unit;
- {
- upap_state *u = &upap[unit];
-
- u->us_flags &= ~UPAPF_AWPPENDING; /* Clear pending flag */
-
- /* Protect against programming errors that compromise security */
- if (u->us_serverstate != UPAPSS_CLOSED ||
- u->us_flags & UPAPF_APPENDING) {
- UPAPDEBUG((stderr,
- "ppp: upap_authwithpeer: upap_authpeer already called!\n"));
- return;
- }
-
- /* Already authenticat{ed,ing}? */
- if (u->us_clientstate == UPAPCS_AUTHSENT ||
- u->us_clientstate == UPAPCS_OPEN)
- return;
-
- /* Lower layer up? */
- if (!(u->us_flags & UPAPF_LOWERUP)) {
- u->us_flags |= UPAPF_AWPPENDING; /* Wait */
- return;
- }
-
- /* User/passwd values valid? */
- if (!(u->us_flags & UPAPF_UPVALID)) {
- GETUSERPASSWD(unit); /* Start getting user and passwd */
- if (!(u->us_flags & UPAPF_UPVALID)) {
- u->us_flags |= UPAPF_UPPENDING; /* Wait */
- return;
- }
- }
-
- upap_sauth(u); /* Start protocol */
- TIMEOUT(upap_timeout, u, u->us_timeouttime);
- u->us_clientstate = UPAPCS_AUTHSENT;
- u->us_retransmits = 0;
- }
-
-
- /*
- * upap_authpeer - Authenticate our peer (start server).
- *
- * Set new state.
- */
- void upap_authpeer(unit)
- int unit;
- {
- upap_state *u = &upap[unit];
-
- u->us_flags &= ~UPAPF_APPENDING; /* Clear pending flag */
-
- /* Already authenticat{ed,ing}? */
- if (u->us_serverstate == UPAPSS_LISTEN ||
- u->us_serverstate == UPAPSS_OPEN)
- return;
-
- /* Lower layer up? */
- if (!(u->us_flags & UPAPF_LOWERUP)) {
- u->us_flags |= UPAPF_APPENDING; /* Wait for desired event */
- return;
- }
- u->us_serverstate = UPAPSS_LISTEN;
- }
-
-
- /*
- * upap_timeout - Timeout expired.
- */
- void upap_timeout(u)
- upap_state *u;
- {
- if (u->us_clientstate != UPAPCS_AUTHSENT)
- return;
-
- /* XXX Print warning after many retransmits? */
-
- upap_sauth(u); /* Send Configure-Request */
- TIMEOUT(upap_timeout, u, u->us_timeouttime);
- ++u->us_retransmits;
- }
-
-
- /*
- * upap_lowerup - The lower layer is up.
- *
- * Start authenticating if pending.
- */
- void upap_lowerup(unit)
- int unit;
- {
- upap_state *u = &upap[unit];
-
- u->us_flags |= UPAPF_LOWERUP;
- if (u->us_flags & UPAPF_AWPPENDING) /* Attempting authwithpeer? */
- upap_authwithpeer(unit); /* Try it now */
- if (u->us_flags & UPAPF_APPENDING) /* Attempting authpeer? */
- upap_authpeer(unit); /* Try it now */
- }
-
-
- /*
- * upap_lowerdown - The lower layer is down.
- *
- * Cancel all timeouts.
- */
- void upap_lowerdown(unit)
- int unit;
- {
- upap_state *u = &upap[unit];
-
- u->us_flags &= ~UPAPF_LOWERUP; /* XXX UPAP_UPVALID? */
-
- if (u->us_clientstate == UPAPCS_AUTHSENT) /* Timeout pending? */
- UNTIMEOUT(upap_timeout, u); /* Cancel timeout */
-
- if (u->us_serverstate == UPAPSS_OPEN) /* User logged in? */
- LOGOUT(unit);
- u->us_clientstate = UPAPCS_CLOSED;
- u->us_serverstate = UPAPSS_CLOSED;
- }
-
-
- /*
- * upap_protrej - Peer doesn't speak this protocol.
- *
- * This shouldn't happen. In any case, pretend lower layer went down.
- */
- void upap_protrej(unit)
- int unit;
- {
- upap_lowerdown(unit);
- }
-
-
- /*
- * upap_input - Input UPAP packet.
- */
- void upap_input(unit, inpacket, l)
- int unit;
- PACKET *inpacket;
- int l;
- {
- upap_state *u = &upap[unit];
- u_char *inp;
- u_char code, id;
- int len;
-
- /*
- * Parse header (code, id and length).
- * If packet too short, drop it.
- */
- inp = PACKET_DATA(inpacket);
- if (l < UPAP_HEADERLEN) {
- UPAPDEBUG((stderr, "ppp: upap_input: rcvd short header.\n"));
- goto freepacket;
- }
- GETCHAR(code, inp);
- GETCHAR(id, inp);
- GETSHORT(len, inp);
- if (len < UPAP_HEADERLEN) {
- UPAPDEBUG((stderr, "ppp: upap_input: rcvd illegal length.\n"));
- goto freepacket;
- }
- if (len > l) {
- UPAPDEBUG((stderr, "ppp: upap_input: rcvd short packet.\n"));
- goto freepacket;
- }
- len -= UPAP_HEADERLEN;
-
- /*
- * Action depends on code.
- */
- switch (code) {
- case UPAP_AUTH:
- upap_rauth(u, inp, id, len);
- break;
-
- case UPAP_AUTHACK:
- upap_rauthack(u, inp, id, len);
- break;
-
- case UPAP_AUTHNAK:
- upap_rauthnak(u, inp, id, len);
- break;
-
- default: /* XXX Need code reject */
- break;
- }
-
- freepacket:
- PACKET_FREE(inpacket);
- }
-
-
- /*
- * upap_rauth - Receive Authenticate.
- */
- void upap_rauth(u, inp, id, len)
- upap_state *u;
- u_char *inp;
- u_char id;
- int len;
- {
- u_char ruserlen, rpasswdlen;
- u_char *ruser, *rpasswd;
- u_char retcode;
- u_char *msg;
- int msglen;
-
- UPAPDEBUG((stderr, "ppp: upap_rauth: Rcvd id %d.\n", id));
- if (u->us_serverstate != UPAPSS_LISTEN) /* XXX Reset connection? */
- return;
-
- /*
- * Parse user/passwd.
- */
- if (len < sizeof (u_char)) {
- UPAPDEBUG((stderr, "ppp: upap_rauth: rcvd short packet.\n"));
- return;
- }
- GETCHAR(ruserlen, inp);
- len -= sizeof (u_char) + ruserlen + sizeof (u_char);;
- if (len < 0) {
- UPAPDEBUG((stderr, "ppp: upap_rauth: rcvd short packet.\n"));
- return;
- }
- ruser = inp;
- INCPTR(ruserlen, inp);
- GETCHAR(rpasswdlen, inp);
- if (len < rpasswdlen) {
- UPAPDEBUG((stderr, "ppp: upap_rauth: rcvd short packet.\n"));
- return;
- }
- rpasswd = inp;
-
- retcode = LOGIN(u->us_unit, ruser, ruserlen, rpasswd, rpasswdlen,
- &msg, &msglen);
-
- upap_sresp(u, retcode, id, msg, msglen);
- if (retcode == UPAP_AUTHACK) {
- u->us_serverstate = UPAPSS_OPEN;
- ipcp_activeopen(u->us_unit); /* Start IPCP */
- }
- }
-
-
- /*
- * upap_rauthack - Receive Authenticate-Ack.
- */
- void upap_rauthack(u, inp, id, len)
- upap_state *u;
- u_char *inp;
- u_char id;
- int len;
- {
- u_char msglen;
- u_char *msg;
-
- UPAPDEBUG((stderr, "ppp: upap_rauthack: Rcvd id %d.\n", id));
- if (u->us_clientstate != UPAPCS_AUTHSENT) /* XXX */
- return;
-
- /*
- * Parse message.
- */
- if (len < sizeof (u_char)) {
- UPAPDEBUG((stderr, "ppp: upap_rauthack: rcvd short packet.\n"));
- return;
- }
- GETCHAR(msglen, inp);
- len -= sizeof (u_char);
- if (len < msglen) {
- UPAPDEBUG((stderr, "ppp: upap_rauthack: rcvd short packet.\n"));
- return;
- }
- msg = inp;
- PRINTMSG(msg, msglen);
-
- u->us_clientstate = UPAPCS_OPEN;
- ipcp_activeopen(u->us_unit); /* Start IPCP */
- }
-
-
- /*
- * upap_rauthnak - Receive Authenticate-Nakk.
- */
- void upap_rauthnak(u, inp, id, len)
- upap_state *u;
- u_char *inp;
- u_char id;
- int len;
- {
- u_char msglen;
- u_char *msg;
-
- UPAPDEBUG((stderr, "ppp: upap_rauthnak: Rcvd id %d.\n", id));
- if (u->us_clientstate != UPAPCS_AUTHSENT) /* XXX */
- return;
-
- /*
- * Parse message.
- */
- if (len < sizeof (u_char)) {
- UPAPDEBUG((stderr, "ppp: upap_rauthnak: rcvd short packet.\n"));
- return;
- }
- GETCHAR(msglen, inp);
- len -= sizeof (u_char);
- if (len < msglen) {
- UPAPDEBUG((stderr, "ppp: upap_rauthnak: rcvd short packet.\n"));
- return;
- }
- msg = inp;
- PRINTMSG(msg, msglen);
-
- u->us_flags &= ~UPAPF_UPVALID; /* Clear valid flag */
- u->us_clientstate = UPAPCS_CLOSED; /* Pretend for a moment */
- upap_authwithpeer(u->us_unit); /* Restart */
- }
-
-
- /*
- * upap_sauth - Send an Authenticate.
- */
- void upap_sauth(u)
- upap_state *u;
- {
- PACKET *outpacket;
- u_char *outp;
- int outlen;
-
- outlen = UPAP_HEADERLEN + 2 * sizeof (u_char) +
- u->us_userlen + u->us_passwdlen;
- outpacket = PACKET_ALLOC(outlen);
- outp = PACKET_DATA(outpacket);
-
- PUTCHAR(UPAP_AUTH, outp);
- PUTCHAR(++u->us_id, outp);
- PUTSHORT(outlen, outp);
- PUTCHAR(u->us_userlen, outp);
- BCOPY(u->us_user, outp, u->us_userlen);
- INCPTR(u->us_userlen, outp);
- PUTCHAR(u->us_passwdlen, outp);
- BCOPY(u->us_passwd, outp, u->us_passwdlen);
- OUTPUT(u->us_unit, outpacket, outlen, UPAP);
-
- UPAPDEBUG((stderr, "ppp: upap_sauth: Sent id %d.\n", u->us_id));
- }
-
-
- /*
- * upap_sresp - Send a response (ack or nak).
- */
- void upap_sresp(u, code, id, msg, msglen)
- upap_state *u;
- u_char code, id;
- u_char *msg;
- int msglen;
- {
- PACKET *outpacket;
- u_char *outp;
- int outlen;
-
- outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen;
- outpacket = PACKET_ALLOC(outlen);
- outp = PACKET_DATA(outpacket);
-
- PUTCHAR(code, outp);
- PUTCHAR(id, outp);
- PUTSHORT(outlen, outp);
- PUTCHAR(msglen, outp);
- BCOPY(msg, outp, msglen);
- OUTPUT(u->us_unit, outpacket, outlen, UPAP);
-
- UPAPDEBUG((stderr, "ppp: upap_sresp: Sent code %d, id %d.\n", code, id));
- }
-