If CHAP authentication is required with the peer but this is never
completed (either because the server never sends the challenge or
because the client doesn't receive the outcome) then the client
will wait forever, relying on the server to terminate the connection.
There are options for server side retries but a client side timeout
option is required to prevent the client from getting stuck if the
server won't terminate the connection. This is defaulted to 60 seconds.
Signed-off-by: Simon Arlott <git@sa.me.uk>
/*
* Option variables.
*/
/*
* Option variables.
*/
-int chap_timeout_time = 3;
+int chap_server_timeout_time = 3;
int chap_max_transmits = 10;
int chap_rechallenge_time = 0;
int chap_max_transmits = 10;
int chap_rechallenge_time = 0;
+int chap_client_timeout_time = 60;
/*
* Command-line options.
*/
static option_t chap_option_list[] = {
/*
* Command-line options.
*/
static option_t chap_option_list[] = {
- { "chap-restart", o_int, &chap_timeout_time,
- "Set timeout for CHAP", OPT_PRIO },
+ { "chap-restart", o_int, &chap_server_timeout_time,
+ "Set timeout for CHAP (as server)", OPT_PRIO },
{ "chap-max-challenge", o_int, &chap_max_transmits,
"Set max #xmits for challenge", OPT_PRIO },
{ "chap-interval", o_int, &chap_rechallenge_time,
"Set interval for rechallenge", OPT_PRIO },
{ "chap-max-challenge", o_int, &chap_max_transmits,
"Set max #xmits for challenge", OPT_PRIO },
{ "chap-interval", o_int, &chap_rechallenge_time,
"Set interval for rechallenge", OPT_PRIO },
+ { "chap-timeout", o_int, &chap_client_timeout_time,
+ "Set timeout for CHAP (as client)", OPT_PRIO },
static void chap_init(int unit);
static void chap_lowerup(int unit);
static void chap_lowerdown(int unit);
static void chap_init(int unit);
static void chap_lowerup(int unit);
static void chap_lowerdown(int unit);
-static void chap_timeout(void *arg);
+static void chap_server_timeout(void *arg);
+static void chap_client_timeout(void *arg);
static void chap_generate_challenge(struct chap_server_state *ss);
static void chap_handle_response(struct chap_server_state *ss, int code,
unsigned char *pkt, int len);
static void chap_generate_challenge(struct chap_server_state *ss);
static void chap_handle_response(struct chap_server_state *ss, int code,
unsigned char *pkt, int len);
cs->flags |= LOWERUP;
ss->flags |= LOWERUP;
if (ss->flags & AUTH_STARTED)
cs->flags |= LOWERUP;
ss->flags |= LOWERUP;
if (ss->flags & AUTH_STARTED)
+ chap_server_timeout(ss);
struct chap_client_state *cs = &client;
struct chap_server_state *ss = &server;
struct chap_client_state *cs = &client;
struct chap_server_state *ss = &server;
+ if (cs->flags & TIMEOUT_PENDING)
+ UNTIMEOUT(chap_client_timeout, cs);
cs->flags = 0;
if (ss->flags & TIMEOUT_PENDING)
cs->flags = 0;
if (ss->flags & TIMEOUT_PENDING)
- UNTIMEOUT(chap_timeout, ss);
+ UNTIMEOUT(chap_server_timeout, ss);
ss->id = (unsigned char)(drand48() * 256);
ss->flags |= AUTH_STARTED;
if (ss->flags & LOWERUP)
ss->id = (unsigned char)(drand48() * 256);
ss->flags |= AUTH_STARTED;
if (ss->flags & LOWERUP)
+ chap_server_timeout(ss);
cs->digest = dp;
cs->name = our_name;
cs->digest = dp;
cs->name = our_name;
- cs->flags |= AUTH_STARTED;
+ cs->flags |= AUTH_STARTED | TIMEOUT_PENDING;
+ TIMEOUT(chap_client_timeout, cs, chap_client_timeout_time);
- * chap_timeout - It's time to send another challenge to the peer.
+ * chap_server_timeout - It's time to send another challenge to the peer.
* This could be either a retransmission of a previous challenge,
* or a new challenge to start re-authentication.
*/
static void
* This could be either a retransmission of a previous challenge,
* or a new challenge to start re-authentication.
*/
static void
+chap_server_timeout(void *arg)
{
struct chap_server_state *ss = arg;
{
struct chap_server_state *ss = arg;
output(0, ss->challenge, ss->challenge_pktlen);
++ss->challenge_xmits;
ss->flags |= TIMEOUT_PENDING;
output(0, ss->challenge, ss->challenge_pktlen);
++ss->challenge_xmits;
ss->flags |= TIMEOUT_PENDING;
- TIMEOUT(chap_timeout, arg, chap_timeout_time);
+ TIMEOUT(chap_server_timeout, arg, chap_server_timeout_time);
+}
+
+/* chap_client_timeout - Authentication with peer timed out. */
+static void
+chap_client_timeout(void *arg)
+{
+ struct chap_client_state *cs = arg;
+
+ cs->flags &= ~TIMEOUT_PENDING;
+ cs->flags |= AUTH_DONE | AUTH_FAILED;
+ error("CHAP authentication timed out");
+ auth_withpeer_fail(0, PPP_CHAP);
if (ss->flags & TIMEOUT_PENDING) {
ss->flags &= ~TIMEOUT_PENDING;
if (ss->flags & TIMEOUT_PENDING) {
ss->flags &= ~TIMEOUT_PENDING;
- UNTIMEOUT(chap_timeout, ss);
+ UNTIMEOUT(chap_server_timeout, ss);
name, strlen(name));
if (chap_rechallenge_time) {
ss->flags |= TIMEOUT_PENDING;
name, strlen(name));
if (chap_rechallenge_time) {
ss->flags |= TIMEOUT_PENDING;
- TIMEOUT(chap_timeout, ss,
+ TIMEOUT(chap_server_timeout, ss,
chap_rechallenge_time);
}
}
chap_rechallenge_time);
}
}
return;
cs->flags |= AUTH_DONE;
return;
cs->flags |= AUTH_DONE;
+ UNTIMEOUT(chap_client_timeout, cs);
+ cs->flags &= ~TIMEOUT_PENDING;
+
if (code == CHAP_SUCCESS) {
/* used for MS-CHAP v2 mutual auth, yuck */
if (cs->digest->check_success != NULL) {
if (code == CHAP_SUCCESS) {
/* used for MS-CHAP v2 mutual auth, yuck */
if (cs->digest->check_success != NULL) {
if (ss->flags & TIMEOUT_PENDING) {
ss->flags &= ~TIMEOUT_PENDING;
if (ss->flags & TIMEOUT_PENDING) {
ss->flags &= ~TIMEOUT_PENDING;
- UNTIMEOUT(chap_timeout, ss);
+ UNTIMEOUT(chap_server_timeout, ss);
}
if (ss->flags & AUTH_STARTED) {
ss->flags = 0;
}
if (ss->flags & AUTH_STARTED) {
ss->flags = 0;
Set the CHAP restart interval (retransmission timeout for challenges)
to \fIn\fR seconds (default 3).
.TP
Set the CHAP restart interval (retransmission timeout for challenges)
to \fIn\fR seconds (default 3).
.TP
+.B chap-timeout \fIn
+Set timeout for CHAP authentication by peer to \fIn\fR seconds (default 60).
+.TP
.B child\-timeout \fIn
When exiting, wait for up to \fIn\fR seconds for any child processes
(such as the command specified with the \fBpty\fR command) to exit
.B child\-timeout \fIn
When exiting, wait for up to \fIn\fR seconds for any child processes
(such as the command specified with the \fBpty\fR command) to exit