Fix the rechallenge behaviour. Previously, once it sent a rechallenge,
authorPaul Mackerras <paulus@samba.org>
Sun, 10 Jul 2005 07:31:26 +0000 (07:31 +0000)
committerPaul Mackerras <paulus@samba.org>
Sun, 10 Jul 2005 07:31:26 +0000 (07:31 +0000)
it would ignore the response (except to send a reply with a bogus
message) and retransmit the rechallenge every 3 seconds until it
eventually timed out and took down the link.

pppd/chap-new.c

index b09fa3e3ce9623e883bac253da86796166e87a0c..e5fe16106d85ad80508d5ad070fe4c983dce8856 100644 (file)
@@ -28,7 +28,7 @@
  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#define RCSID  "$Id: chap-new.c,v 1.6 2004/11/04 10:02:26 paulus Exp $"
+#define RCSID  "$Id: chap-new.c,v 1.7 2005/07/10 07:31:26 paulus Exp $"
 
 #include <stdlib.h>
 #include <string.h>
@@ -96,6 +96,7 @@ static struct chap_server_state {
        int challenge_xmits;
        int challenge_pktlen;
        unsigned char challenge[CHAL_MAX_PKTLEN];
+       char message[256];
 } server;
 
 /* Values for flags in chap_client_state and chap_server_state */
@@ -310,15 +311,12 @@ chap_handle_response(struct chap_server_state *ss, int id,
        int (*verifier)(char *, char *, int, struct chap_digest_type *,
                unsigned char *, unsigned char *, char *, int);
        char rname[MAXNAMELEN+1];
-       char message[256];
 
        if ((ss->flags & LOWERUP) == 0)
                return;
        if (id != ss->challenge[PPP_HDRLEN+1] || len < 2)
                return;
-       if ((ss->flags & AUTH_DONE) == 0) {
-               if ((ss->flags & CHALLENGE_VALID) == 0)
-                       return;
+       if (ss->flags & CHALLENGE_VALID) {
                response = pkt;
                GETCHAR(response_len, pkt);
                len -= response_len + 1;        /* length of name */
@@ -326,7 +324,6 @@ chap_handle_response(struct chap_server_state *ss, int id,
                if (len < 0)
                        return;
 
-               ss->flags &= ~CHALLENGE_VALID;
                if (ss->flags & TIMEOUT_PENDING) {
                        ss->flags &= ~TIMEOUT_PENDING;
                        UNTIMEOUT(chap_timeout, ss);
@@ -346,39 +343,43 @@ chap_handle_response(struct chap_server_state *ss, int id,
                        verifier = chap_verify_response;
                ok = (*verifier)(name, ss->name, id, ss->digest,
                                 ss->challenge + PPP_HDRLEN + CHAP_HDRLEN,
-                                response, message, sizeof(message));
+                                response, ss->message, sizeof(ss->message));
                if (!ok || !auth_number()) {
                        ss->flags |= AUTH_FAILED;
                        warn("Peer %q failed CHAP authentication", name);
                }
-       }
+       } else if ((ss->flags & AUTH_DONE) == 0)
+               return;
 
        /* send the response */
        p = outpacket_buf;
        MAKEHEADER(p, PPP_CHAP);
-       mlen = strlen(message);
+       mlen = strlen(ss->message);
        len = CHAP_HDRLEN + mlen;
        p[0] = (ss->flags & AUTH_FAILED)? CHAP_FAILURE: CHAP_SUCCESS;
        p[1] = id;
        p[2] = len >> 8;
        p[3] = len;
        if (mlen > 0)
-               memcpy(p + CHAP_HDRLEN, message, mlen);
+               memcpy(p + CHAP_HDRLEN, ss->message, mlen);
        output(0, outpacket_buf, PPP_HDRLEN + len);
 
-       if ((ss->flags & AUTH_DONE) == 0) {
-               ss->flags |= AUTH_DONE;
+       if (ss->flags & CHALLENGE_VALID) {
+               ss->flags &= ~CHALLENGE_VALID;
                if (ss->flags & AUTH_FAILED) {
                        auth_peer_fail(0, PPP_CHAP);
                } else {
-                       auth_peer_success(0, PPP_CHAP, ss->digest->code,
-                                         name, strlen(name));
+                       if ((ss->flags & AUTH_DONE) == 0)
+                               auth_peer_success(0, PPP_CHAP,
+                                                 ss->digest->code,
+                                                 name, strlen(name));
                        if (chap_rechallenge_time) {
                                ss->flags |= TIMEOUT_PENDING;
                                TIMEOUT(chap_timeout, ss,
                                        chap_rechallenge_time);
                        }
                }
+               ss->flags |= AUTH_DONE;
        }
 }