* upap.c - User/Password Authentication Protocol.
* Copyright (c) 1989 Carnegie Mellon University.
* 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.
upap_state upap
[NPPP
]; /* UPAP state; one for each unit */
static void upap_timeout
__ARGS((caddr_t
));
static void upap_rauth
__ARGS((upap_state
*, u_char
*, int, int));
static void upap_rauthack
__ARGS((upap_state
*, u_char
*, int, int));
static void upap_rauthnak
__ARGS((upap_state
*, u_char
*, int, int));
static void upap_sauth
__ARGS((upap_state
*));
static void upap_sresp
__ARGS((upap_state
*, int, int, u_char
*, int));
* upap_init - Initialize a UPAP unit.
upap_state
*u
= &upap
[unit
];
u
->us_clientstate
= UPAPCS_CLOSED
;
u
->us_serverstate
= UPAPSS_CLOSED
;
u
->us_timeouttime
= UPAP_DEFTIMEOUT
;
* upap_authwithpeer - Authenticate us with our peer (start client).
* Set new state and send authenticate's.
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
) {
"upap_authwithpeer: upap_authpeer already called!"))
/* Already authenticat{ed,ing}? */
if (u
->us_clientstate
== UPAPCS_AUTHSENT
||
u
->us_clientstate
== UPAPCS_OPEN
)
if (!(u
->us_flags
& UPAPF_LOWERUP
)) {
u
->us_flags
|= UPAPF_AWPPENDING
; /* Wait */
/* 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 */
upap_sauth(u
); /* Start protocol */
/* TIMEOUT(upap_timeout, (caddr_t) u, u->us_timeouttime);*/
u
->us_clientstate
= UPAPCS_AUTHSENT
;
* upap_authpeer - Authenticate our peer (start server).
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
)
if (!(u
->us_flags
& UPAPF_LOWERUP
)) {
u
->us_flags
|= UPAPF_APPENDING
; /* Wait for desired event */
u
->us_serverstate
= UPAPSS_LISTEN
;
* upap_timeout - Timeout expired.
upap_state
*u
= (upap_state
*) arg
;
if (u
->us_clientstate
!= UPAPCS_AUTHSENT
)
/* XXX Print warning after many retransmits? */
upap_sauth(u
); /* Send Configure-Request */
TIMEOUT(upap_timeout
, (caddr_t
) u
, u
->us_timeouttime
);
* upap_lowerup - The lower layer is up.
* Start authenticating if pending.
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.
upap_state
*u
= &upap
[unit
];
u
->us_flags
&= ~UPAPF_LOWERUP
; /* XXX UPAP_UPVALID? */
if (u
->us_clientstate
== UPAPCS_AUTHSENT
) /* Timeout pending? */
UNTIMEOUT(upap_timeout
, (caddr_t
) u
); /* Cancel timeout */
if (u
->us_serverstate
== UPAPSS_OPEN
) /* User logged in? */
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.
* upap_input - Input UPAP packet.
upap_input(unit
, inpacket
, l
)
upap_state
*u
= &upap
[unit
];
* Parse header (code, id and length).
* If packet too short, drop it.
if (l
< UPAP_HEADERLEN
) {
UPAPDEBUG((LOG_INFO
, "upap_input: rcvd short header."))
if (len
< UPAP_HEADERLEN
) {
UPAPDEBUG((LOG_INFO
, "upap_input: rcvd illegal length."))
UPAPDEBUG((LOG_INFO
, "upap_input: rcvd short packet."))
* Action depends on code.
upap_rauth(u
, inp
, id
, len
);
upap_rauthack(u
, inp
, id
, len
);
upap_rauthnak(u
, inp
, id
, len
);
default: /* XXX Need code reject */
* upap_rauth - Receive Authenticate.
upap_rauth(u
, inp
, id
, len
)
u_char ruserlen
, rpasswdlen
;
UPAPDEBUG((LOG_INFO
, "upap_rauth: Rcvd id %d.", id
))
if (u
->us_serverstate
!= UPAPSS_LISTEN
) /* XXX Reset connection? */
if (len
< sizeof (u_char
)) {
UPAPDEBUG((LOG_INFO
, "upap_rauth: rcvd short packet."))
len
-= sizeof (u_char
) + ruserlen
+ sizeof (u_char
);;
UPAPDEBUG((LOG_INFO
, "upap_rauth: rcvd short packet."))
GETCHAR(rpasswdlen
, inp
);
UPAPDEBUG((LOG_INFO
, "upap_rauth: rcvd short packet."))
retcode
= LOGIN(u
->us_unit
, (char *) ruser
, (int) ruserlen
, (char *) rpasswd
,
(int) rpasswdlen
, (char **) &msg
, &msglen
);
upap_sresp(u
, retcode
, id
, msg
, msglen
);
/* only crank up IPCP when either we aren't doing CHAP, or if we are, */
/* that it is in open state */
if (retcode
== UPAP_AUTHACK
) {
u
->us_serverstate
= UPAPSS_OPEN
;
if (!lcp_hisoptions
[u
->us_unit
].neg_chap
||
(lcp_hisoptions
[u
->us_unit
].neg_chap
&&
chap
[u
->us_unit
].serverstate
== CHAPSS_OPEN
))
ipcp_activeopen(u
->us_unit
); /* Start IPCP */
* upap_rauthack - Receive Authenticate-Ack.
upap_rauthack(u
, inp
, id
, len
)
UPAPDEBUG((LOG_INFO
, "upap_rauthack: Rcvd id %d.", id
))
if (u
->us_clientstate
!= UPAPCS_AUTHSENT
) /* XXX */
if (len
< sizeof (u_char
)) {
UPAPDEBUG((LOG_INFO
, "upap_rauthack: rcvd short packet."))
UPAPDEBUG((LOG_INFO
, "upap_rauthack: rcvd short packet."))
u
->us_clientstate
= UPAPCS_OPEN
;
/* only crank up IPCP when either we aren't doing CHAP, or if we are, */
/* that it is in open state */
if (!lcp_gotoptions
[u
->us_unit
].neg_chap
||
(lcp_gotoptions
[u
->us_unit
].neg_chap
&&
chap
[u
->us_unit
].clientstate
== CHAPCS_OPEN
))
ipcp_activeopen(u
->us_unit
); /* Start IPCP */
* upap_rauthnak - Receive Authenticate-Nakk.
upap_rauthnak(u
, inp
, id
, len
)
UPAPDEBUG((LOG_INFO
, "upap_rauthnak: Rcvd id %d.", id
))
if (u
->us_clientstate
!= UPAPCS_AUTHSENT
) /* XXX */
if (len
< sizeof (u_char
)) {
UPAPDEBUG((LOG_INFO
, "upap_rauthnak: rcvd short packet."))
UPAPDEBUG((LOG_INFO
, "upap_rauthnak: rcvd short packet."))
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.
outlen
= UPAP_HEADERLEN
+ 2 * sizeof (u_char
) +
u
->us_userlen
+ u
->us_passwdlen
;
PUTCHAR(UPAP_AUTH
, outp
);
PUTCHAR(++u
->us_id
, 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_buf
, outlen
+ DLLHEADERLEN
);
UPAPDEBUG((LOG_INFO
, "upap_sauth: Sent id %d.", u
->us_id
))
* upap_sresp - Send a response (ack or nak).
upap_sresp(u
, code
, id
, msg
, msglen
)
outlen
= UPAP_HEADERLEN
+ sizeof (u_char
) + msglen
;
BCOPY(msg
, outp
, msglen
);
output(u
->us_unit
, outpacket_buf
, outlen
+ DLLHEADERLEN
);
UPAPDEBUG((LOG_INFO
, "upap_sresp: Sent code %d, id %d.", code
, id
))