Subject: Re: PAP connection to NT RAS
To: None <current-users@NetBSD.ORG>
From: Christos Zoulas <christos@zoulas.com>
List: current-users
Date: 11/19/1997 12:06:46
In article <199711190545.AAAAA29276@hrothgar.gw.com> rnestor@metronet.com (Bob Nestor) writes:
>Joel Klecker <jk@espy.org> wrote:
>
>>NT-RAS also has MS's own slightly different version of CHAP, fortunately,
>>PPP 2.3.1 supports "MS-CHAP".
>
>Unfortunately it doesn't seem that MS-CHAP is supported without a custom 
>build of PPPD. That leads to a real rats nest of problems with the latest 
>sources:
>
>can't locate "des.h" if USE_CRYPT is undefined
>
>USE_CRYPT uses the non-exportable crypt routines
>
>chap_ms.c has missing includes for string.h, unistd.h
>
>chap_ms.c has a number of missing prototypes for internal routines
>
>chap_ms.c uses MD4 routines including a "reverse" function that's nowhere 
>to be found while the rest of PPPD uses MD5 routines. (Can these be 
>mixed? Should they be?)
>
>Has anyone successfully build PPP 2.3.1 with the MS_CHAP option?

I just committed changes to pppd that build it with CHAPMS and MSLANMAN by
default. I'd appreciate it if you could test them. Here are the diffs in
case you don't have access to 1.3A...

christos

Index: chap_ms.c
===================================================================
RCS file: /cvsroot/src/usr.sbin/pppd/pppd/chap_ms.c,v
retrieving revision 1.4
diff -c -r1.4 chap_ms.c
*** chap_ms.c	1997/09/26 19:52:37	1.4
--- chap_ms.c	1997/11/19 11:57:29
***************
*** 45,53 ****
--- 45,56 ----
  #ifdef CHAPMS
  
  #include <stdio.h>
+ #include <string.h>
+ #include <ctype.h>
  #include <sys/types.h>
  #include <sys/time.h>
  #include <syslog.h>
+ #include <unistd.h>
  
  #include "pppd.h"
  #include "chap.h"
***************
*** 67,74 ****
--- 70,83 ----
     in case this struct gets padded. */
  
  
+ static void	ChallengeResponse __P((u_char *, u_char *, u_char *));
  static void	DesEncrypt __P((u_char *, u_char *, u_char *));
  static void	MakeKey __P((u_char *, u_char *));
+ static u_char	Get7Bits __P((u_char *, int));
+ static void	ChapMS_NT __P((char *, int, char *, int, MS_ChapResponse *));
+ #ifdef MSLANMAN
+ static void	ChapMS_LANMan __P((char *, int, char *, int, MS_ChapResponse *));
+ #endif
  
  #ifdef USE_CRYPT
  static void	Expand __P((u_char *, u_char *));
***************
*** 84,90 ****
      char    ZPasswordHash[21];
  
      BZERO(ZPasswordHash, sizeof(ZPasswordHash));
!     BCOPY(pwHash, ZPasswordHash, 16);
  
  #if 0
      log_packet(ZPasswordHash, sizeof(ZPasswordHash), "ChallengeResponse - ZPasswordHash", LOG_DEBUG);
--- 93,99 ----
      char    ZPasswordHash[21];
  
      BZERO(ZPasswordHash, sizeof(ZPasswordHash));
!     BCOPY(pwHash, ZPasswordHash, MD4_SIGNATURE_SIZE);
  
  #if 0
      log_packet(ZPasswordHash, sizeof(ZPasswordHash), "ChallengeResponse - ZPasswordHash", LOG_DEBUG);
***************
*** 250,256 ****
      MS_ChapResponse    *response;
  {
      int			i;
!     MDstruct		md4Context;
      u_char		unicodePassword[MAX_NT_PASSWORD * 2];
      static int		low_byte_first = -1;
  
--- 259,266 ----
      MS_ChapResponse    *response;
  {
      int			i;
!     MD4_CTX		md4Context;
!     u_short		hash[MD4_SIGNATURE_SIZE/sizeof(u_short)];
      u_char		unicodePassword[MAX_NT_PASSWORD * 2];
      static int		low_byte_first = -1;
  
***************
*** 260,282 ****
      for (i = 0; i < secret_len; i++)
  	unicodePassword[i * 2] = (u_char)secret[i];
  
!     MDbegin(&md4Context);
!     MDupdate(&md4Context, unicodePassword, secret_len * 2 * 8);	/* Unicode is 2 bytes/char, *8 for bit count */
  
      if (low_byte_first == -1)
  	low_byte_first = (htons((unsigned short int)1) != 1);
!     if (low_byte_first == 0)
! 	MDreverse(&md4Context);  /*  sfb 961105 */
  
!     MDupdate(&md4Context, NULL, 0);	/* Tell MD4 we're done */
! 
!     ChallengeResponse(rchallenge, (char *)md4Context.buffer, response->NTResp);
  }
  
  #ifdef MSLANMAN
  static u_char *StdText = (u_char *)"KGS!@#$%"; /* key from rasapi32.dll */
  
! static ChapMS_LANMan(rchallenge, rchallenge_len, secret, secret_len, response)
      char *rchallenge;
      int rchallenge_len;
      char *secret;
--- 270,295 ----
      for (i = 0; i < secret_len; i++)
  	unicodePassword[i * 2] = (u_char)secret[i];
  
!     MD4Init(&md4Context);
!     MD4Update(&md4Context, unicodePassword, secret_len * 2 * 8);	/* Unicode is 2 bytes/char, *8 for bit count */
! 
!     MD4Final((u_char *) hash, &md4Context); 	/* Tell MD4 we're done */
  
      if (low_byte_first == -1)
  	low_byte_first = (htons((unsigned short int)1) != 1);
!     if (low_byte_first == 0) {
! 	for (i = 0; i < MD4_SIGNATURE_SIZE; i += sizeof(u_short))
! 		hash[i] = htons(hash[i]);
!     }
  
!     ChallengeResponse(rchallenge, (u_char *)hash, response->NTResp);
  }
  
  #ifdef MSLANMAN
  static u_char *StdText = (u_char *)"KGS!@#$%"; /* key from rasapi32.dll */
  
! static void
! ChapMS_LANMan(rchallenge, rchallenge_len, secret, secret_len, response)
      char *rchallenge;
      int rchallenge_len;
      char *secret;
***************
*** 285,291 ****
  {
      int			i;
      u_char		UcasePassword[MAX_NT_PASSWORD]; /* max is actually 14 */
!     u_char		PasswordHash[16];
  
      /* LANMan password is case insensitive */
      BZERO(UcasePassword, sizeof(UcasePassword));
--- 298,304 ----
  {
      int			i;
      u_char		UcasePassword[MAX_NT_PASSWORD]; /* max is actually 14 */
!     u_char		PasswordHash[MD4_SIGNATURE_SIZE];
  
      /* LANMan password is case insensitive */
      BZERO(UcasePassword, sizeof(UcasePassword));
Index: chap_ms.h
===================================================================
RCS file: /cvsroot/src/usr.sbin/pppd/pppd/chap_ms.h,v
retrieving revision 1.3
diff -c -r1.3 chap_ms.h
*** chap_ms.h	1997/09/26 19:52:38	1.3
--- chap_ms.h	1997/11/19 11:57:29
***************
*** 26,31 ****
--- 26,32 ----
  
  #ifndef __CHAPMS_INCLUDE__
  
+ #define MD4_SIGNATURE_SIZE	16	/* 16 bytes in a MD4 message digest */
  #define MAX_NT_PASSWORD	256	/* Maximum number of (Unicode) chars in an NT password */
  
  void ChapMS __P((chap_state *, char *, int, char *, int));
Index: options.c
===================================================================
RCS file: /cvsroot/src/usr.sbin/pppd/pppd/options.c,v
retrieving revision 1.21
diff -c -r1.21 options.c
*** options.c	1997/10/20 08:08:37	1.21
--- options.c	1997/11/19 11:57:29
***************
*** 258,264 ****
  #endif /* IPX_CHANGE */
  
  #ifdef MSLANMAN
! static int setmslanman __P((void));
  #endif
  
  static int number_option __P((char *, u_int32_t *, int));
--- 258,264 ----
  #endif /* IPX_CHANGE */
  
  #ifdef MSLANMAN
! static int setmslanman __P((char **));
  #endif
  
  static int number_option __P((char *, u_int32_t *, int));
***************
*** 2564,2570 ****
  
  #ifdef MSLANMAN
  static int
! setmslanman()
  {
      ms_lanman = 1;
      return (1);
--- 2564,2571 ----
  
  #ifdef MSLANMAN
  static int
! setmslanman(argv)
!     char **argv;
  {
      ms_lanman = 1;
      return (1);

Index: Makefile
===================================================================
RCS file: /cvsroot/src/usr.sbin/pppd/pppd/Makefile,v
*** Makefile	1997/10/25 06:58:30	1.22
--- Makefile	1997/11/19 11:59:58	1.23
***************
*** 14,18 ****
--- 14,19 ----
  LDADD=	-lpcap -lcrypt -lutil
  DPADD=	${LIBPCAP} ${LIBCRYPT} ${LIBUTIL}
  CPPFLAGS+= -I. -DHAVE_PATHS_H -I${PCAPDIR} -DPPP_FILTER -DCBCP_SUPPORT
+ CPPFLAGS+= -DCHAPMS -DUSE_CRYPT -DMSLANMAN
  
  .include <bsd.prog.mk>