ftp.nice.ch/pub/next/unix/communication/Alby.2.PPP.0.3.N.bs.tar.gz#/source/upap.c

This is upap.c in view mode; [Download] [Up]

/*
 * 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>

#ifdef STREAMS
#include <sys/socket.h>
#include <net/if.h>
#include <sys/stream.h>
#endif
#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));
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.