$NetBSD: patch-bf,v 1.1.1.1 1999/10/08 04:34:43 dbj Exp $

--- pppd/chap.c.orig	Fri Aug 13 02:46:11 1999
+++ pppd/chap.c	Sat Sep 25 13:23:26 1999
@@ -47,6 +47,8 @@
 #include "pppd.h"
 #include "chap.h"
 #include "md5.h"
+#include "fsm.h"
+#include "lcp.h"
 #ifdef CHAPMS
 #include "chap_ms.h"
 #endif
@@ -113,7 +115,7 @@
 static void ChapSendStatus __P((chap_state *, int));
 static void ChapSendChallenge __P((chap_state *));
 static void ChapSendResponse __P((chap_state *));
-static void ChapGenChallenge __P((chap_state *));
+void ChapGenChallenge __P((chap_state *));
 
 extern double drand48 __P((void));
 extern void srand48 __P((long));
@@ -460,6 +462,7 @@
     switch (cstate->resp_type) { 
 
     case CHAP_DIGEST_MD5:
+	CHAPDEBUG(("ChapReceiveChallenge: rcvd type CHAP-DIGEST-MD5"));
 	MD5Init(&mdContext);
 	MD5Update(&mdContext, &cstate->resp_id, 1);
 	MD5Update(&mdContext, secret, secret_len);
@@ -471,8 +474,24 @@
 
 #ifdef CHAPMS
     case CHAP_MICROSOFT:
+	CHAPDEBUG(("ChapReceiveChallenge: rcvd type MS-CHAP-V1."));
+	if(rchallenge_len != 8)
+	{
+	    CHAPDEBUG(("Invalid challenge length for MS-CHAP-V1"));
+	    return;
+	}
 	ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len);
 	break;
+
+    case CHAP_MICROSOFT_V2:
+	CHAPDEBUG(("ChapReceiveChallenge: rcvd type MS-CHAP-V2."));
+	if(rchallenge_len != 16)
+	{
+	    CHAPDEBUG(("Invalid challenge length for MS-CHAP-V2"));
+	    return;
+	}
+	ChapMS_v2(cstate, rchallenge, rchallenge_len, secret, secret_len);
+	break;
 #endif
 
     default:
@@ -560,7 +579,8 @@
 	/*  generate MD based on negotiated type */
 	switch (cstate->chal_type) { 
 
-	case CHAP_DIGEST_MD5:		/* only MD5 is defined for now */
+	case CHAP_DIGEST_MD5:
+	    CHAPDEBUG(("ChapReceiveResponse: rcvd type CHAP-DIGEST-MD5"));
 	    if (remmd_len != MD5_SIGNATURE_SIZE)
 		break;			/* it's not even the right length */
 	    MD5Init(&mdContext);
@@ -574,6 +594,27 @@
 		code = CHAP_SUCCESS;	/* they are the same! */
 	    break;
 
+#ifdef CHAPMS
+	case CHAP_MICROSOFT:
+	    CHAPDEBUG(("ChapReceiveResponse: rcvd type MS-CHAP-V1"));
+	    if(remmd_len != MS_CHAP_RESPONSE_LEN)
+		break;
+	    if(ChapMS_Resp(cstate, secret, secret_len, remmd) == 0)
+		code = CHAP_SUCCESS;
+	    break;
+
+	case CHAP_MICROSOFT_V2:
+	    CHAPDEBUG(("ChapReceiveResponse: rcvd type MS-CHAP-V2"));
+	    if(remmd_len != MS_CHAP_RESPONSE_LEN)
+		break;
+	    if(ChapMS_v2_Resp(cstate,secret,secret_len,remmd,rhostname) == 0)
+	    {
+		code = CHAP_SUCCESS_R;
+		ChapMS_v2_Auth(cstate, secret, secret_len, remmd, rhostname);
+	    }
+	    break;
+#endif
+
 	default:
 	    CHAPDEBUG(("unknown digest type %d", cstate->chal_type));
 	}
@@ -582,7 +623,7 @@
     BZERO(secret, sizeof(secret));
     ChapSendStatus(cstate, code);
 
-    if (code == CHAP_SUCCESS) {
+    if ((code == CHAP_SUCCESS) || (code == CHAP_SUCCESS_R)) {
 	old_state = cstate->serverstate;
 	cstate->serverstate = CHAPSS_OPEN;
 	if (old_state == CHAPSS_INITIAL_CHAL) {
@@ -590,10 +631,43 @@
 	}
 	if (cstate->chal_interval != 0)
 	    TIMEOUT(ChapRechallenge, cstate, cstate->chal_interval);
-	notice("CHAP peer authentication succeeded for %q", rhostname);
-
+	switch (cstate->chal_type) { 
+	  case CHAP_DIGEST_MD5:
+	    notice("CHAP peer authentication succeeded for %q", rhostname);
+	    break;
+#ifdef CHAPMS
+	  case CHAP_MICROSOFT:
+	    notice("MSCHAP peer authentication succeeded for %q", rhostname);
+	    break;
+	  case CHAP_MICROSOFT_V2:
+	    notice("MSCHAP-v2 peer authentication succeeded for %q", rhostname);
+	    break;
+#endif
+	  default:
+	    notice("CHAP (unknown) peer authentication succeeded for %q", 
+		   rhostname);
+	    break;
+	}
     } else {
-	error("CHAP peer authentication failed for remote host %q", rhostname);
+	switch (cstate->chal_type) { 
+	  case CHAP_DIGEST_MD5:
+	    error("CHAP peer authentication failed for remote host %q", 
+		  rhostname);
+	    break;
+#ifdef CHAPMS
+	  case CHAP_MICROSOFT:
+	    error("MSCHAP peer authentication failed for remote host %q", 
+		  rhostname);
+	    break;
+	  case CHAP_MICROSOFT_V2:
+	    error("MSCHAP-v2 peer authentication failed for remote host %q", 
+		  rhostname);
+	    break;
+#endif
+	  default:
+	    error("CHAP (unknown) peer authentication failed for remote host %q", rhostname);
+	    break;
+	}
 	cstate->serverstate = CHAPSS_BADAUTH;
 	auth_peer_fail(cstate->unit, PPP_CHAP);
     }
@@ -712,6 +786,8 @@
 
     if (code == CHAP_SUCCESS)
 	slprintf(msg, sizeof(msg), "Welcome to %s.", hostname);
+    else if(code == CHAP_SUCCESS_R)
+	strcpy(msg, cstate->response);
     else
 	slprintf(msg, sizeof(msg), "I don't like you.  Go 'way.");
     msglen = strlen(msg);
@@ -721,7 +797,7 @@
 
     MAKEHEADER(outp, PPP_CHAP);	/* paste in a header */
   
-    PUTCHAR(code, outp);
+    PUTCHAR(code == CHAP_SUCCESS_R ? CHAP_SUCCESS : code, outp);
     PUTCHAR(cstate->chal_id, outp);
     PUTSHORT(outlen, outp);
     BCOPY(msg, outp, msglen);
@@ -735,7 +811,7 @@
  * *cstate are initialized.
  */
 
-static void
+void
 ChapGenChallenge(cstate)
     chap_state *cstate;
 {
@@ -743,6 +819,14 @@
     u_char *ptr = cstate->challenge;
     unsigned int i;
 
+#ifdef CHAPMS
+    if(cstate->chal_type == CHAP_MICROSOFT)
+	chal_len = 8;
+    else if(cstate->chal_type == CHAP_MICROSOFT_V2)
+	chal_len = 16;
+    else
+#endif
+
     /* pick a random challenge length between MIN_CHALLENGE_LENGTH and 
        MAX_CHALLENGE_LENGTH */  
     chal_len =  (unsigned) ((drand48() *
@@ -857,4 +941,14 @@
     }
 
     return len + CHAP_HEADERLEN;
+}
+
+int
+reqchap(argv)
+        char **argv;
+{
+    lcp_wantoptions[0].neg_chap = 1;
+    lcp_wantoptions[0].use_digest = 1;
+    auth_required = 1;
+    return 1;
 }
