[patch] functional mod_ntlm_winbind

Nicolas Dehaine nicko at stbernard.com
Thu Aug 5 19:31:43 GMT 2004


Hello everyone,

Here is a patch for Tim Potter's mod_ntlm_winbind which allows Apache to
interface with winbindd to authenticate users for browsers supporting
NTLM authentication.

The patch is against the latest version (mod_ntlm_winbind.c 1.10 and
ntlmssp.c 1.3), available from
http://cvs.samba.org/cgi-bin/cvsweb/mod_ntlm_winbind/ and should work
with:
- Apache 1.3.31
- Samba 3.0.2/3.0.5
- NTLM v1 (no support for v2)
- Tested on FreeBSD 4.x and 5.2
- Tested with IE 5.x 6.x on Windows 95,98,ME,NT4,2000,XP,2003
- Tested with Firefox 0.9.3 on XP

----------------------------------------------------
Nicolas Dehaine - RAPID Development Manager
St Bernard Software - San Diego, CA.
http://www.stbernard.com
-------------- next part --------------
Index: ntlmssp.c
===================================================================
RCS file: ntlmssp.c,v
*** ntlmssp.c	2002/10/23 17:53:12
--- ntlmssp.c	2004/08/05 16:22:44
***************
*** 23,35 ****
  #define RESP_LEN 24
  #define NONCE_LEN 8
  
  struct ntlm_msg1 {
      unsigned char protocol[8];
      unsigned char type;         /* 1 */
      unsigned char zero1[3];
!     unsigned char flags1;
!     unsigned char flags2;
!     unsigned char zero2[2];
  
      unsigned char dom_len[4];
      unsigned char dom_off[4];
--- 23,67 ----
  #define RESP_LEN 24
  #define NONCE_LEN 8
  
+ // ###### flags for msg 1, 2 & 3
+ #define UNICODE		0x00000001
+ #define ASCII		0x00000002
+ #define REQUEST_TARGET	0x00000004
+ #define UNKNOWN1	0x00000008
+ #define SIGN		0x00000010
+ #define SEAL		0x00000020
+ #define USE_DATAGRAM	0x00000040
+ #define USE_LM		0x00000080
+ #define USE_NETWARE	0x00000100
+ #define USE_NTLM	0x00000200
+ #define UNKNOWN2	0x00000400
+ #define UNKNOWN3	0x00000800
+ #define DOMAIN_SUPPLIED	0x00001000
+ #define WORKSTATION_SUPPLIED	0x00002000
+ #define LOCAL_CALL	0x00004000
+ #define ALWAYS_SIGN	0x00008000
+ #define TARGET_DOMAIN	0x00010000
+ #define TARGET_SERVER	0x00020000
+ #define TARGET_SHARE	0x00040000
+ #define NTLM2		0x00080000
+ #define INIT_RESPONSE	0x00100000
+ #define ACCEPT_RESPONSE	0x00200000
+ #define NON_NT_SESSION_KEY	0x00400000
+ #define TARGET_INFO	0x00800000
+ #define UNKNOWN4	0x01000000
+ #define UNKNOWN5	0x02000000
+ #define UNKNOWN6	0x04000000
+ #define UNKNOWN7	0x08000000
+ #define UNKNOWN8	0x10000000
+ #define NEGOTIATE_128	0x20000000
+ #define KEY_EXCHANGE	0x40000000
+ #define UNKNOWN9	0x80000000
+ 
  struct ntlm_msg1 {
      unsigned char protocol[8];
      unsigned char type;         /* 1 */
      unsigned char zero1[3];
!     unsigned char flags[4];
  
      unsigned char dom_len[4];
      unsigned char dom_off[4];
***************
*** 39,51 ****
  
  } __attribute__((packed));
  
! struct ntlm_msg2 {
      unsigned char protocol[8];
      unsigned char type;         /* 2 */
      unsigned char zero1[7];
      unsigned char msg_len[4];
!     unsigned char flags[2];
      unsigned char zero2[2];
  
      unsigned char nonce[8];
      unsigned char zero3[8];
--- 71,96 ----
  
  } __attribute__((packed));
  
! struct ntlm_msg2_bad {
      unsigned char protocol[8];
      unsigned char type;         /* 2 */
      unsigned char zero1[7];
      unsigned char msg_len[4];
!     unsigned char flags[4];
! 
!     unsigned char nonce[8];
!     unsigned char zero3[8];
! } __attribute__((packed));
! 
! struct ntlm_msg2 {
!     unsigned char protocol[8];
!     unsigned char type;         /* 2 */
!     unsigned char zero1[3];
!     unsigned char dom_len[2];
!     unsigned char dom_maxlen[2];
!     unsigned char dom_offset[2];
      unsigned char zero2[2];
+     unsigned char flags[4];
  
      unsigned char nonce[8];
      unsigned char zero3[8];
***************
*** 81,90 ****
      unsigned char domain[MAX_DOMLEN + 1];
      unsigned char lm[RESP_LEN];
      unsigned char nt[RESP_LEN];
  } ntlmssp_info_rec;
  
! #define little_endian_word(x) x[0] + (((unsigned)x[1]) << 8)
  #define set_little_endian_word(x,y) x[0]=(y&0xff);x[1]=(y>>8)
  
  static int 
  ntlm_msg_type(unsigned char *raw_msg, unsigned msglen)
--- 126,140 ----
      unsigned char domain[MAX_DOMLEN + 1];
      unsigned char lm[RESP_LEN];
      unsigned char nt[RESP_LEN];
+     int nt_resp_actual_len;
+     unsigned char msg1_flags[4];
  } ntlmssp_info_rec;
+ 
+ void dump_flags(request_rec *r, char *p);
  
! #define little_endian_word(x) (x[0] + (((unsigned)x[1]) << 8))
  #define set_little_endian_word(x,y) x[0]=(y&0xff);x[1]=(y>>8)
+ #define set_little_endian_dword(x,y) x[0]=(char)((y)&0xff);x[1]=(char)(((y)>>8)&0xff);x[2]=(char)(((y)>>16)&0xff);x[3]=(char)(((y)>>24)&0xff)
  
  static int 
  ntlm_msg_type(unsigned char *raw_msg, unsigned msglen)
***************
*** 99,104 ****
--- 149,162 ----
  }
  
  static int 
+ ntlm_extract_dword(request_rec * r, char *raw_msg, int msg_len, int offset, int *result)
+ {
+   if ( msg_len < offset + 1 )
+ 	return 1;
+   *result = raw_msg[offset] + (raw_msg[offset+1] << 8);
+   return 0;
+ }
+ 
  ntlm_extract_mem(request_rec * r, unsigned char *dst,
                   unsigned char *src, unsigned srclen,
                   unsigned char *off, unsigned char *len,
***************
*** 126,131 ****
--- 184,190 ----
  {
      unsigned o = little_endian_word(off);
      unsigned l = little_endian_word(len);
+     ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r, "ntlm_extract_string(): srclen (%u), off (0x%02x%02x), len (0x%02x%02x), l (%u), max (%u)", srclen, off[1], off[0], len[1], len[0], l, max);
      if (l > max)
          return -1;
      if (o >= srclen)
***************
*** 140,145 ****
--- 199,213 ----
  }
  
  static int 
+ ntlm_encode_unicode(char *str, char *result)
+ {
+     int i;
+     bzero(result, strlen(str) * 2);
+     for (i=0; i<strlen(str); i++)
+         result[i*2] = str[i];
+ }
+ 
+ static int 
  ntlm_extract_unicode(request_rec * r, unsigned char *dst,
                       unsigned char *src, unsigned srclen,
                       unsigned char *off, unsigned char *len,
***************
*** 147,166 ****
  {
      unsigned o = little_endian_word(off);
      unsigned l = little_endian_word(len) / 2;   /* Unicode! */
!     if (l > max)
          return -1;
!     if (o >= srclen)
          return -1;
!     if (o + l > srclen)
          return -1;
      src += o;
      while (l > 0) {
          /* Unicode to ASCII */
          *dst++ = *src;
          src += 2;
!         l -= 2;
      }
      *dst = 0;
      return 0;
  }
  
--- 215,246 ----
  {
      unsigned o = little_endian_word(off);
      unsigned l = little_endian_word(len) / 2;   /* Unicode! */
! 
!     /* debug
!     ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r, "ntlm_extract_unicode(): srclen (%u), off (0x%02x%02x), len (0x%02x%02x), l (%u), max (%u)", srclen, off[1], off[0], len[1], len[0], l, max);
!     */
! 
!     if (l > max) {
!         ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r, "ntlm_extract_unicode(): length (%u) > max (%u)", l, max);
          return -1;
!     }
!     if (o >= srclen) {
!         ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r, "ntlm_extract_unicode(): offset (%u) >= source length (%u)", o, srclen);
          return -1;
!     }
!     if (o + l > srclen) {
!         ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r, "ntlm_extract_unicode(): offset (%u) + length (%u) > source length (%u)", o, l, srclen);
          return -1;
+     }
      src += o;
      while (l > 0) {
          /* Unicode to ASCII */
          *dst++ = *src;
          src += 2;
!         l -= 1; /* was 2, back when the little_endian_word macro above was broken... */
      }
      *dst = 0;
+ 
      return 0;
  }
  
***************
*** 172,178 ****
      if (ntlm_extract_string(r, hostname, (char *) msg, msglen,
                              msg->host_off, msg->host_len, MAX_HOSTLEN))
          return 1;
!     ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r, "got hostname %s", hostname);
      return 0;
  }
  
--- 252,258 ----
      if (ntlm_extract_string(r, hostname, (char *) msg, msglen,
                              msg->host_off, msg->host_len, MAX_HOSTLEN))
          return 1;
!     ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r, "got hostname '%s'", hostname);
      return 0;
  }
  
***************
*** 185,195 ****
                              msglen, msg->dom_off, msg->dom_len, MAX_DOMLEN))
          return 2;
  
!     ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r, "got domainname %s", domainname);
      return 0;
  }
  
  static int 
  ntlm_msg3_getlm(request_rec * r, unsigned char *raw_msg, unsigned msglen,
                  unsigned char *lm)
  {
--- 265,304 ----
                              msglen, msg->dom_off, msg->dom_len, MAX_DOMLEN))
          return 2;
  
!     ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r, "got domainname '%s'", domainname);
      return 0;
  }
  
  static int 
+ ntlm_msg1_getflags(request_rec * r, unsigned char *raw_msg,
+                         unsigned msglen, unsigned char *flags)
+ {
+     struct ntlm_msg1 *msg = (struct ntlm_msg1 *) raw_msg;
+ 
+     memcpy(flags, msg->flags, 4);
+ 
+     ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r, "got flags '%02x%02x%02x%02x'",
+ 				flags[3], flags[2], flags[1], flags[0]);
+     dump_flags(r, flags);
+ 
+     return 0;
+ }
+ 
+ /* debug for next two */
+ void
+ dump_mem_hex(request_rec * r, unsigned char *srcp, unsigned cnt) {
+     int i;
+     int outsize=cnt*2+1;
+     char out[outsize];
+     char * outp = out;
+     for (i=0; i<cnt; i++) {
+ 	snprintf(outp, 3, "%02x", srcp[i]);
+ 	outp+=2;
+     }
+     ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r, "   mem: %s", out);
+ }
+ 
+ static int 
  ntlm_msg3_getlm(request_rec * r, unsigned char *raw_msg, unsigned msglen,
                  unsigned char *lm)
  {
***************
*** 199,204 ****
--- 308,314 ----
          return 4;
  
      ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r, "Getting lm hash");
+     dump_mem_hex(r, lm, little_endian_word(msg->lm_len));
      return 0;
  }
  
***************
*** 209,217 ****
      struct ntlm_msg3 *msg = (struct ntlm_msg3 *) raw_msg;
      if (ntlm_extract_mem(r, nt, (char *) msg, msglen, msg->nt_off,
                           msg->nt_len, RESP_LEN))
!         return 8;
  
!     ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r, "Getting nt hash");
      return 0;
  }
  
--- 319,329 ----
      struct ntlm_msg3 *msg = (struct ntlm_msg3 *) raw_msg;
      if (ntlm_extract_mem(r, nt, (char *) msg, msglen, msg->nt_off,
                           msg->nt_len, RESP_LEN))
!         return 0;
!         // return 8;
  
!     ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r, "Getting nt hash:");
!     dump_mem_hex(r, nt, little_endian_word(msg->nt_len));
      return 0;
  }
  
***************
*** 229,234 ****
--- 341,357 ----
  }
  
  static int 
+ ntlm_msg3_getntlen(request_rec * r, unsigned char *raw_msg,
+                       unsigned msglen, int *ntlen)
+ {
+     if (ntlm_extract_dword(r, raw_msg, msglen, 20, ntlen))
+         return 32;
+     
+     ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r, "got nt len %d", *ntlen);
+     return 0;
+ }
+ 
+ static int 
  ntlm_msg3_gethostname(request_rec * r, unsigned char *raw_msg, unsigned msglen,
                        unsigned char *hostname)
  {
***************
*** 237,242 ****
--- 360,367 ----
                               msg->host_off, msg->host_len, MAX_HOSTLEN))
          return 0;  /* this one FAILS, but since the value is not used,
                      * we just pretend it was ok. */
+ 
+     ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r, "got hostname %s", hostname);
      return 0;
  }
  
***************
*** 248,286 ****
      if (ntlm_extract_unicode(r, domainname, (char *) msg, msglen,
                               msg->dom_off, msg->dom_len, MAX_DOMLEN))
          return 64;
      return 0;
  }
  
  static int 
  ntlm_decode_msg(request_rec * r, struct ntlmssp_info *info,
                  unsigned char *raw_msg, unsigned msglen)
  {
!         ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r, 
!                       "Decoding auth message type %d", 
!                       ntlm_msg_type(raw_msg, msglen));
  
!     switch (info->msg_type = ntlm_msg_type(raw_msg, msglen)) {
        case 1:
!           return ntlm_msg1_gethostname(r, raw_msg, msglen, info->host)
!               + ntlm_msg1_getdomainname(r, raw_msg, msglen, info->domain);
        case 3:
!           return ntlm_msg3_getlm(r, raw_msg, msglen, info->lm)
                + ntlm_msg3_getnt(r, raw_msg, msglen, info->nt)
                + ntlm_msg3_getusername(r, raw_msg, msglen, info->user)
                + ntlm_msg3_gethostname(r, raw_msg, msglen, info->host)
                + ntlm_msg3_getdomainname(r, raw_msg, msglen, info->domain);
      }
      return -1;
  }
  
  static int 
! ntlm_encode_msg2(unsigned char *nonce, struct ntlm_msg2 *msg)
  {
      memset(msg, 0, sizeof(struct ntlm_msg2));
      strcpy(msg->protocol, "NTLMSSP");
      msg->type = 0x02;
!     set_little_endian_word(msg->msg_len, sizeof(struct ntlm_msg2));
!     set_little_endian_word(msg->flags, 0x8201);
      memcpy(msg->nonce, nonce, sizeof(msg->nonce));
      return 0;
  }
--- 373,495 ----
      if (ntlm_extract_unicode(r, domainname, (char *) msg, msglen,
                               msg->dom_off, msg->dom_len, MAX_DOMLEN))
          return 64;
+ 
+     ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r, "got domainname %s", domainname);
+     return 0;
+ }
+ 
+ static int 
+ ntlm_msg3_getusername_ascii(request_rec * r, unsigned char *raw_msg,
+                       unsigned msglen, unsigned char *username)
+ {
+     struct ntlm_msg3 *msg = (struct ntlm_msg3 *) raw_msg;
+     if (ntlm_extract_string(r, username, (char *) msg, msglen,
+                              msg->user_off, msg->user_len, MAX_USERLEN))
+         return 16;
+     
+     ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r, "got username %s", username);
+     return 0;
+ }
+ 
+ static int 
+ ntlm_msg3_gethostname_ascii(request_rec * r, unsigned char *raw_msg, unsigned msglen,
+                       unsigned char *hostname)
+ {
+     struct ntlm_msg3 *msg = (struct ntlm_msg3 *) raw_msg;
+     if (ntlm_extract_string(r, hostname, (char *) msg, msglen,
+                              msg->host_off, msg->host_len, MAX_HOSTLEN))
+         return 0;  /* this one FAILS, but since the value is not used,
+                     * we just pretend it was ok. */
+ 
+     ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r, "got hostname %s", hostname);
+     return 0;
+ }
+ 
+ static int 
+ ntlm_msg3_getdomainname_ascii(request_rec * r, unsigned char *raw_msg,
+                         unsigned msglen, unsigned char *domainname)
+ {
+     struct ntlm_msg3 *msg = (struct ntlm_msg3 *) raw_msg;
+     if (ntlm_extract_string(r, domainname, (char *) msg, msglen,
+                              msg->dom_off, msg->dom_len, MAX_DOMLEN))
+         return 64;
+ 
+     ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r, "got domainname %s", domainname);
      return 0;
  }
  
+ unsigned long
+ test_flags(unsigned long test, char *flags)
+ {
+   return ( test & (flags[0] + (flags[1]<<8) + (flags[2]<<16) + (flags[3]<<24)));
+ }
+ 
  static int 
  ntlm_decode_msg(request_rec * r, struct ntlmssp_info *info,
                  unsigned char *raw_msg, unsigned msglen)
  {
!     int type = ntlm_msg_type(raw_msg, msglen);
! 
!     info->msg_type = type;
  
!     switch (info->msg_type) {
        case 1:
! 	   return
!              ntlm_msg1_gethostname(r, raw_msg, msglen, info->host)
!            + ntlm_msg1_getdomainname(r, raw_msg, msglen, info->domain)
!            + ntlm_msg1_getflags(r, raw_msg, msglen, info->msg1_flags);
        case 3:
! 	ntlm_msg3_getntlen(r, raw_msg, msglen, &(info->nt_resp_actual_len));
! 	dump_flags(r, info->msg1_flags);
! 	return 
! 	        ntlm_msg3_getlm(r, raw_msg, msglen, info->lm)
                + ntlm_msg3_getnt(r, raw_msg, msglen, info->nt)
+               + ntlm_msg3_getusername_ascii(r, raw_msg, msglen, info->user)
+               + ntlm_msg3_gethostname_ascii(r, raw_msg, msglen, info->host)
+               + ntlm_msg3_getdomainname_ascii(r, raw_msg, msglen, info->domain);
+               // ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r, "LEN %d NTH %s LMH %s", info->nt_resp_actual_len, info->nt , info->lm);
+ 	  /* This is broken if the browser is only able to send UNICODE (need to keep some state from msg2) */
+           /* return
+ 	       ntlm_msg3_getlm(r, raw_msg, msglen, info->lm)
+               + ntlm_msg3_getnt(r, raw_msg, msglen, info->nt)
                + ntlm_msg3_getusername(r, raw_msg, msglen, info->user)
                + ntlm_msg3_gethostname(r, raw_msg, msglen, info->host)
                + ntlm_msg3_getdomainname(r, raw_msg, msglen, info->domain);
+           */
      }
      return -1;
  }
  
+ void
+ dump_flags(request_rec *r, char *flags)
+ {
+   unsigned long ulflags = flags[0] + (flags[1]<<8) + (flags[2]<<16) + (flags[3]<<24);
+   ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r, "raw ul flags: %08lx", ulflags);
+   ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r, "%sUNICODE", ulflags & UNICODE ? "" : "NO_");
+   ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r, "%sASCII", ulflags & ASCII ? "" : "NO_");
+   ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r, "%sREQUEST_TARGET", ulflags & REQUEST_TARGET ? "" : "NO_");
+   ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r, "%sUSE_LM", ulflags & USE_LM ? "" : "NO_");
+   ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r, "%sUSE_NTLM", ulflags & USE_NTLM ? "" : "NO_");
+   ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r, "%sDOMAIN_SUPPLIED", ulflags & DOMAIN_SUPPLIED ? "" : "NO_");
+   ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r, "%sWORKSTATION_SUPPLIED", ulflags & WORKSTATION_SUPPLIED ? "" : "NO_");
+   ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r, "%sALWAYS_SIGN", ulflags & ALWAYS_SIGN ? "" : "NO_");
+   ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r, "%sNTLM2", ulflags & NTLM2 ? "" : "NO_");
+   ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r, "%sNON_NT_SESSION_KEY", ulflags & NON_NT_SESSION_KEY ? "" : "NO_");
+   ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r, "%sHIGHEST_BIT", ulflags & UNKNOWN9 ? "" : "NO_");
+ }
+ 
  static int 
! ntlm_encode_msg2(request_rec *r, unsigned char *nonce, struct ntlm_msg2 *msg, ntlmssp_info_rec *ntlmssp)
  {
      memset(msg, 0, sizeof(struct ntlm_msg2));
      strcpy(msg->protocol, "NTLMSSP");
      msg->type = 0x02;
!     set_little_endian_word(msg->dom_len, 0);
!     set_little_endian_word(msg->dom_maxlen, 0);
!     set_little_endian_word(msg->dom_offset, 0);
! 
!     set_little_endian_dword(msg->flags,ASCII|USE_LM|USE_NTLM|ALWAYS_SIGN|TARGET_DOMAIN|REQUEST_TARGET); // 0x00018286
! 
      memcpy(msg->nonce, nonce, sizeof(msg->nonce));
      return 0;
  }
Index: mod_ntlm_winbind.c
===================================================================
RCS file: /usr/cvsroot/source/packages/www/mod_ntlm_winbind/D/mod_ntlm_winbind.c,v
*** mod_ntlm_winbind.c	2002/10/23 17:53:12
--- mod_ntlm_winbind.c	2004/08/05 15:53:48
***************
*** 138,143 ****
--- 138,160 ----
      { NULL }
  };
  
+ void
+ dump_ntlmssp_rec(request_rec *r, ntlmssp_info_rec *info)
+ {
+     ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r,
+                   "dump_ntlmssp_rec(): info struct\t%d", info);
+     ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r,
+                   "dump_ntlmssp_rec(): type\t%d", info->msg_type);   
+     ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r,
+                   "dump_ntlmssp_rec(): user\t%s", info->user);
+     ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r,
+                   "dump_ntlmssp_rec(): host\t%s", info->host);
+     ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r,
+                   "dump_ntlmssp_rec(): domain\t%s", info->domain);
+     ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r,
+                   "dump_ntlmssp_rec(): actual nt len\t%d", info->nt_resp_actual_len);
+ } 
+ 
  /* Base 64 encode/decode wrapper functions */
  
  static void *
***************
*** 179,188 ****
  
      line = ap_pstrdup(r->pool, NTLM_AUTH_NAME);
  
- #ifdef WIN9X_TEST
-     ap_table_set(r->err_headers_out, "WWW-Authenticate", "Negotiate");
- #endif
- 
      ap_table_add(r->err_headers_out,
                   r->proxyreq ? "Proxy-Authenticate" : "WWW-Authenticate",
                   line);
--- 196,201 ----
***************
*** 213,219 ****
  #define RANDOM_DEV "/dev/urandom"
  
  static int 
! send_ntlm_challenge(request_rec * r, ntlm_config_rec * crec)
  {
      struct ntlm_msg2 msg;
      unsigned char *challenge;
--- 226,232 ----
  #define RANDOM_DEV "/dev/urandom"
  
  static int 
! send_ntlm_challenge(request_rec * r, ntlm_config_rec * crec, ntlmssp_info_rec *ntlmssp)
  {
      struct ntlm_msg2 msg;
      unsigned char *challenge;
***************
*** 255,263 ****
  
      /* Encode and send message */
  
!     ntlm_encode_msg2(ntlm_connection->nonce, &msg);
  
      challenge = uuencode_binary(r->pool, (unsigned char *) &msg, sizeof(msg));
  
      ap_table_setn(r->err_headers_out,
                    r->proxyreq ? "Proxy-Authenticate" : "WWW-Authenticate",
--- 268,278 ----
  
      /* Encode and send message */
  
!     ntlm_encode_msg2(r, ntlm_connection->nonce, &msg, ntlmssp);
  
      challenge = uuencode_binary(r->pool, (unsigned char *) &msg, sizeof(msg));
+     ap_table_setn(r->err_headers_out,
+                   "Content-Length" , "0");
  
      ap_table_setn(r->err_headers_out,
                    r->proxyreq ? "Proxy-Authenticate" : "WWW-Authenticate",
***************
*** 296,301 ****
--- 311,319 ----
                        foo);
          return NULL;
      }
+     ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r,
+                       "get_ntlm_header(): type: %d, host: \"%s\", user: \"%s\", domain: \"%s\"",
+                       ntlmssp->msg_type, ntlmssp->host, ntlmssp->user, ntlmssp->domain);
  
      return ntlmssp;
  }
***************
*** 303,309 ****
  /* Call winbind to authenticate a (user, domain, lm response, nt response)
     tuple. */
  
! static NSS_STATUS winbind_authenticate_ntlm(ntlmssp_info_rec *ntlmssp)
  {
      struct winbindd_request request;
      struct winbindd_response response;
--- 321,327 ----
  /* Call winbind to authenticate a (user, domain, lm response, nt response)
     tuple. */
  
! static NSS_STATUS winbind_authenticate_ntlm(ntlmssp_info_rec *ntlmssp, request_rec * r)
  {
      struct winbindd_request request;
      struct winbindd_response response;
***************
*** 312,331 ****
      ZERO_STRUCT(request);
      ZERO_STRUCT(response);
  
!     /* Fill request with DOMAIN\username, challenge and responses */
  
      ap_snprintf(request.data.auth_crap.user,
!                 sizeof(request.data.auth_crap.user) - 1, "%s\\%s",
!                 ntlmssp->domain, ntlmssp->user);
  
      memcpy(request.data.auth_crap.chal, ntlm_connection->nonce, 8);
  
      memcpy(request.data.auth_crap.lm_resp, ntlmssp->lm, RESP_LEN);
-     memcpy(request.data.auth_crap.nt_resp, ntlmssp->nt, RESP_LEN);
- 
      request.data.auth_crap.lm_resp_len = RESP_LEN;
-     request.data.auth_crap.nt_resp_len = RESP_LEN;
  
      /* Send request */
  
      return winbindd_request(WINBINDD_PAM_AUTH_CRAP, &request, &response);
--- 330,354 ----
      ZERO_STRUCT(request);
      ZERO_STRUCT(response);
  
!     /* Fill request with challenge and responses */
  
      ap_snprintf(request.data.auth_crap.user,
!                 sizeof(request.data.auth_crap.user) - 1, "%s", ntlmssp->user);
!     ap_snprintf(request.data.auth_crap.domain,
!                 sizeof(request.data.auth_crap.domain) - 1, "%s", ntlmssp->domain);
  
      memcpy(request.data.auth_crap.chal, ntlm_connection->nonce, 8);
  
      memcpy(request.data.auth_crap.lm_resp, ntlmssp->lm, RESP_LEN);
      request.data.auth_crap.lm_resp_len = RESP_LEN;
  
+     /* 9X doesn't send NT response hash */
+     if ( ntlmssp->nt_resp_actual_len ) {
+     	memcpy(request.data.auth_crap.nt_resp, ntlmssp->nt, ntlmssp->nt_resp_actual_len );
+     	request.data.auth_crap.nt_resp_len = ntlmssp->nt_resp_actual_len;
+     } else
+         request.data.auth_crap.nt_resp_len = 0;
+ 
      /* Send request */
  
      return winbindd_request(WINBINDD_PAM_AUTH_CRAP, &request, &response);
***************
*** 487,493 ****
      ZERO_STRUCT(response);
  
      ap_snprintf(request.data.username, sizeof(request.data.username) - 1,
!                 "%s\\%s", ntlm_connection->domain, ntlm_connection->user);
  
      result = winbindd_request(WINBINDD_GETGROUPS, &request, &response);
  
--- 510,518 ----
      ZERO_STRUCT(response);
  
      ap_snprintf(request.data.username, sizeof(request.data.username) - 1,
!                 "%s", ntlm_connection->user);
!     ap_snprintf(request.domain_name, sizeof(request.domain_name) - 1,
!                 "%s", ntlm_connection->domain);
  
      result = winbindd_request(WINBINDD_GETGROUPS, &request, &response);
  
***************
*** 537,544 ****
                            "silent reauthentication");            
  
              /* silently accept login with same credentials */
!             r->connection->user = ap_pstrdup(r->connection->pool,
!                                              ntlm_connection->user);
              r->connection->ap_auth_type = ap_pstrdup(r->connection->pool,
                                                       NTLM_AUTH_NAME);
              return OK;
--- 562,571 ----
                            "silent reauthentication");            
  
              /* silently accept login with same credentials */
!             //r->connection->user = ap_pstrdup(r->connection->pool,
!             //                                 ntlm_connection->user);
!     r->connection->user = ap_psprintf(r->connection->pool,"%s\\%s",
!                                      ntlm_connection->domain,ntlm_connection->user);
              r->connection->ap_auth_type = ap_pstrdup(r->connection->pool,
                                                       NTLM_AUTH_NAME);
              return OK;
***************
*** 552,560 ****
      ntlm_connection->password = ap_pcalloc(r->connection->pool, RESP_LEN);
      memcpy(ntlm_connection->password, ntlmssp->nt, RESP_LEN);
  
!     /* Send authenication request to winbind */
  
!     result = winbind_authenticate_ntlm(ntlmssp);
  
      ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r, "winbind authenticate: %s", 
                    wb_error(result));
--- 579,587 ----
      ntlm_connection->password = ap_pcalloc(r->connection->pool, RESP_LEN);
      memcpy(ntlm_connection->password, ntlmssp->nt, RESP_LEN);
  
!     /* Send authentication request to winbind */
  
!     result = winbind_authenticate_ntlm(ntlmssp, r);
  
      ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r, "winbind authenticate: %s", 
                    wb_error(result));
***************
*** 572,578 ****
          return HTTP_UNAUTHORIZED;
      }
  
!     /* Now check user is authorised to use the service */
  
      result = winbind_authorise(r, crec, ntlmssp);
  
--- 599,605 ----
          return HTTP_UNAUTHORIZED;
      }
  
!     /* Now check user is authorised to use the service *
  
      result = winbind_authorise(r, crec, ntlmssp);
  
***************
*** 588,595 ****
  
      ntlm_connection->auth_ok = 1;
  
!     r->connection->user = ap_pstrdup(r->connection->pool,
!                                      ntlm_connection->user);
      r->connection->ap_auth_type = ap_pstrdup(r->connection->pool,
                                               NTLM_AUTH_NAME);
  
--- 615,624 ----
  
      ntlm_connection->auth_ok = 1;
  
!     //r->connection->user = ap_pstrdup(r->connection->pool,
!     //                                 ntlm_connection->user);
!     r->connection->user = ap_psprintf(r->connection->pool,"%s\\%s",
!                                      ntlm_connection->domain,ntlm_connection->user);
      r->connection->ap_auth_type = ap_pstrdup(r->connection->pool,
                                               NTLM_AUTH_NAME);
  
***************
*** 624,634 ****
          return HTTP_UNAUTHORIZED;
      }
  
      /* Handle message */
  
      switch (ntlmssp->msg_type) {
      case 1:
!         return send_ntlm_challenge(r, crec);
      case 3:
          return ntlm_check_response(r, crec, ntlmssp);
      }
--- 653,668 ----
          return HTTP_UNAUTHORIZED;
      }
  
+     if (ntlmssp->msg_type == 3 && ! ntlm_connection->sent_challenge ) {
+         ap_log_rerror(APLOG_MARK, NTLM_DEBUG, r, "BAD REQUEST [msg3 without msg1] %d %d", ntlmssp->msg_type, ntlm_connection);
+ 	return HTTP_BAD_REQUEST;
+     }
+ 
      /* Handle message */
  
      switch (ntlmssp->msg_type) {
      case 1:
!         return send_ntlm_challenge(r, crec, ntlmssp);
      case 3:
          return ntlm_check_response(r, crec, ntlmssp);
      }
***************
*** 795,801 ****
      /* Trust the authentication on an existing connection */
  
      if (ntlm_connection && ntlm_connection->auth_ok) {
!         r->connection->user = ntlm_connection->user;
          r->connection->ap_auth_type = "NTLM";
          return OK;
      }
--- 829,837 ----
      /* Trust the authentication on an existing connection */
  
      if (ntlm_connection && ntlm_connection->auth_ok) {
!         //r->connection->user = ntlm_connection->user;
!         r->connection->user = ap_psprintf(r->connection->pool,"%s\\%s",
!                                      ntlm_connection->domain,ntlm_connection->user);
          r->connection->ap_auth_type = "NTLM";
          return OK;
      }


More information about the samba-technical mailing list