This patch is generated from the ntlm_smbpasswd branch of HEAD in squid
Mon Jan 26 12:56:48 2004 GMT
See http://devel.squid-cache.org/

Index: squid/configure.in
diff -u squid/configure.in:1.48 squid/configure.in:1.47.2.2
--- squid/configure.in:1.48	Sat Mar 30 08:55:04 2002
+++ squid/configure.in	Mon Apr  1 03:18:00 2002
@@ -2170,6 +2170,7 @@
 	src/auth/ntlm/helpers/no_check/Makefile \
 	src/auth/ntlm/helpers/NTLMSSP/Makefile \
 	src/auth/ntlm/helpers/NTLMSSP/smbval/Makefile \
+	src/auth/ntlm/helpers/smbpasswd/Makefile \
 	contrib/Makefile \
 	snmplib/Makefile \
 	icons/Makefile \
Index: squid/src/auth/ntlm/auth_ntlm.c
diff -u squid/src/auth/ntlm/auth_ntlm.c:1.19 squid/src/auth/ntlm/auth_ntlm.c:1.19.2.1
--- squid/src/auth/ntlm/auth_ntlm.c:1.19	Mon Feb 18 15:43:12 2002
+++ squid/src/auth/ntlm/auth_ntlm.c	Tue Feb 26 03:37:41 2002
@@ -737,7 +737,7 @@
 		helperStatefulSubmit(ntlmauthenticators, NULL, authenticateNTLMHandleplaceholder, r, NULL);
 	    } else {
 		/* Server with invalid challenge */
-		snprintf(buf, 8192, "YR\n");
+		snprintf(buf, 8192, "YR %s\n", sent_string);
 		helperStatefulSubmit(ntlmauthenticators, buf, authenticateNTLMHandleReply, r, ntlm_request->authserver);
 	    }
 	} else {
Index: squid/src/auth/ntlm/helpers/smbpasswd/Makefile.am
diff -u /dev/null squid/src/auth/ntlm/helpers/smbpasswd/Makefile.am:1.1.2.1
--- /dev/null	Mon Jan 26 04:56:12 2004
+++ squid/src/auth/ntlm/helpers/smbpasswd/Makefile.am	Sat Feb 23 19:29:20 2002
@@ -0,0 +1,13 @@
+#
+#  Makefile for the Squid Object Cache server
+#
+#  $Id: squid-ntlm_smbpasswd-HEAD,v 1.1 2004/08/17 20:55:13 hno Exp $
+#
+#  Uncomment and customize the following to suit your needs:
+#
+
+libexec_PROGRAMS = ntlm_smbpasswd
+ntlm_smbpasswd_SOURCES	= ntlm_smbpasswd.c ntlm.c ntlm.h smbdes.c smbdes.h
+INCLUDES      = -I. -I$(top_builddir)/include -I$(top_srcdir)/include \
+		-I$(top_srcdir)/src/
+LDADD	= -L$(top_builddir)/lib -lmiscutil $(CRYPTLIB) $(XTRA_LIBS)
Index: squid/src/auth/ntlm/helpers/smbpasswd/README
diff -u /dev/null squid/src/auth/ntlm/helpers/smbpasswd/README:1.1.2.2
--- /dev/null	Mon Jan 26 04:56:12 2004
+++ squid/src/auth/ntlm/helpers/smbpasswd/README	Sat Dec  7 10:21:33 2002
@@ -0,0 +1,7 @@
+README for ntlm_smbpasswd
+
+ntlm_smbpasswd is a NTLM helper to Squid, allowing you to perform
+NTLM authentication to Samba like smbpasswd files.
+
+ntlm_smbpasswd is (C)2002 Henrik Nordstrom <hno@squid-cache.org>. It includes
+components copyrighted by others. See respective source file for details.
Index: squid/src/auth/ntlm/helpers/smbpasswd/ntlm.c
diff -u /dev/null squid/src/auth/ntlm/helpers/smbpasswd/ntlm.c:1.1.2.5
--- /dev/null	Mon Jan 26 04:56:12 2004
+++ squid/src/auth/ntlm/helpers/smbpasswd/ntlm.c	Mon Apr  1 03:16:53 2002
@@ -0,0 +1,389 @@
+/*
+ * AUTHOR: Henrik Nordstrom <hno@squid-cache.org>
+ *
+ * Loosely based on fakeauth by Robert Collins <rbtcollins@hotmail.com>
+ *
+ * NTLM authentication originally by ad@interlude.eu.org - 07/1999
+ */
+
+#include "config.h"
+#include "squid_types.h"
+
+#include "ntlm.h"
+#include "smbdes.h"
+#include "util.h"
+
+#if HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if HAVE_STRING_H
+#include <string.h>
+#endif
+
+
+#define ERR    "ERR\n"
+#define OK     "OK\n"
+
+static char *authenticate_ntlm_domain = "LIFELESSWKS";
+
+/*
+ * Generates a challenge request. The randomness of the 8 byte 
+ * challenge strings can be guarenteed to be poor at best.
+ * XXX FIX ME
+ */
+void
+ntlmMakeChallenge(ntlm_challenge *chal)
+{
+    static unsigned hash;
+    int r;
+    char *d;
+    int i;
+
+    memset(chal, 0, sizeof(*chal));
+    memcpy(chal->hdr.signature, "NTLMSSP", 8);
+    chal->flags = WSWAP(0x00018206);
+    chal->hdr.type = WSWAP(NTLMSSP_CHALLENGE);
+    //chal->unknown[6] = SSWAP(0x003a);
+
+    d = (char *) chal + 48;
+    i = 0;
+
+    /* XXX WHAT ABOUT THIS?? */
+    if (authenticate_ntlm_domain != NULL)
+	while (authenticate_ntlm_domain[i++]);
+
+    chal->target.offset = WSWAP(48);
+    chal->target.maxlen = SSWAP(i);
+    chal->target.len = chal->target.maxlen;
+
+    r = (int) rand();
+    r = (hash ^ r) + r;
+
+    for (i = 0; i < 8; i++) {
+	chal->challenge[i] = r;
+	r = (r >> 2) ^ r;
+    }
+
+    hash = r;
+}
+
+void ntlmNegotiateChallenge(const ntlm_negotiate *nego, ntlm_challenge *chal)
+{
+    int32_t flags = WSWAP(nego->flags);
+    ntlmMakeChallenge(chal);
+    flags &= (
+	    	NTLMSSP_NEGOTIATE_OEM | 
+		NTLMSSP_NEGOTIATE_LM |
+		NTLMSSP_NEGOTIATE_NTLM |
+#if 0 /* Documentation yet incomplete */
+		NTLMSSP_NEGOTIATE_NTLM2 |
+#endif
+		NTLMSSP_NEGOTIATE_ALWAYS_SIGN
+	    );
+    flags |= NTLMSSP_CHALLENGE_TARGET_IS_DOMAIN;
+    chal->flags = WSWAP(flags);
+}
+
+#if 0
+/*
+ * Returns the length of a string
+ */
+static int
+ntlmStringLength(strhdr *str)
+{
+    return SSWAP(str->len);
+}
+#endif
+
+/*
+ * Check the validity of a string. Return <0 on error.
+ */
+static int
+ntlmCheckString(const ntlmhdr * hdr, const strhdr *str, size_t size)
+{
+    int offset = WSWAP(str->offset);
+    int len = SSWAP(str->len);
+    int maxlen = SSWAP(str->maxlen);
+
+    if (len == 0)
+	return 0;
+
+    if (offset < sizeof(ntlmhdr)) {
+	fprintf(stderr, "ntlmCheckString: too low offset\n");
+	return -1;
+    }
+    if (offset > size || offset + len > size) {
+	/* both are required above to protect from integrer wrap */
+	fprintf(stderr, "ntlmCheckString: too high offset\n");
+	return -1;
+    }
+    if (len > maxlen) {
+	fprintf(stderr, "ntlmCheckString: too long\n");
+	return -1;
+    }
+    if (offset + maxlen > size) {
+	fprintf(stderr, "ntlmCheckString: too big\n");
+	return -1;
+    }
+    return 0;
+}
+
+/*
+ * Check the validity of a fixed length string. Return <0 on error.
+ */
+static int
+ntlmCheckStringLength(const ntlmhdr *hdr, const strhdr *str, size_t size, int len)
+{
+    if (SSWAP(str->len) && len != SSWAP(str->len)) {
+	fprintf(stderr, "ntlmCheckStringLength: invalid length %d (expected %d)\n", SSWAP(str->len), len);
+	return -1;
+    }
+    return ntlmCheckString(hdr, str, size);
+}
+
+/*
+ * Check the vailidity of a request. Return <0 on error.
+ */
+int
+ntlmCheckPacket(const ntlmhdr * hdr, int type, size_t size)
+{
+    /* 
+     * Must be the correct security package and request type. The
+     * 8 bytes compared includes the ASCII 'NUL'. 
+     */
+    if (memcmp(hdr->signature, "NTLMSSP", 8) != 0) {
+	fprintf(stderr, "ntlmCheckHeader: bad header signature\n");
+	return -1;
+    }
+    if (type != NTLMSSP_ANY && WSWAP(hdr->type) != type) {
+	fprintf(stderr, "ntlmCheckHeader: unexpected type %d (expected %d)\n", WSWAP(hdr->type), type);
+	return -1;
+    }
+    switch(WSWAP(hdr->type)) {
+    case NTLMSSP_NEGOTIATE: {
+	ntlm_negotiate * p = (ntlm_negotiate *) hdr;
+	uint32_t flags = WSWAP(p->flags);
+	if (flags & NTLMSSP_OEM_DOMAIN_SUPPLIED && ntlmCheckString(hdr, &p->domain, size) < 0) {
+	    fprintf(stderr, "ntlmCheckHeader: malformed negotiate packet (domain)\n");
+	    return -1;
+	}
+	if (flags & NTLMSSP_OEM_WORKSTATION_SUPPLIED && ntlmCheckString(hdr, &p->workstation, size) < 0) {
+	    fprintf(stderr, "ntlmCheckHeader: malformed negotiate packet (workstation)\n");
+	    return -1;
+	}
+	} break;
+    case NTLMSSP_CHALLENGE: {
+	ntlm_challenge *p = (ntlm_challenge *) hdr;
+	if (ntlmCheckString(hdr, &p->target, size) < 0) {
+	    fprintf(stderr, "ntlmCheckHeader: malformed challenge packet (target)\n");
+	    return -1;
+	}
+	} break;
+    case NTLMSSP_AUTHENTICATE: {
+	ntlm_authenticate *p = (ntlm_authenticate *) hdr;
+	if (ntlmCheckStringLength(hdr, &p->lmresponse, size, 24) < 0) {
+	    fprintf(stderr, "ntlmCheckHeader: malformed authenticate packet (lmresponse)\n");
+	    return -1;
+	}
+	if (ntlmCheckStringLength(hdr, &p->ntresponse, size, 24) < 0) {
+	    fprintf(stderr, "ntlmCheckHeader: malformed authenticate packet (ntresponse)\n");
+	    return -1;
+	}
+	if (ntlmCheckString(hdr, &p->domain, size) < 0) {
+	    fprintf(stderr, "ntlmCheckHeader: malformed authenticate packet (domain)\n");
+	    return -1;
+	}
+	if (ntlmCheckString(hdr, &p->user, size) < 0) {
+	    fprintf(stderr, "ntlmCheckHeader: malformed authenticate packet (user)\n");
+	    return -1;
+	}
+	if (ntlmCheckString(hdr, &p->workstation, size) < 0) {
+	    fprintf(stderr, "ntlmCheckHeader: malformed authenticate packet (workstation)\n");
+	    return -1;
+	}
+#if 0
+	if (ntlmCheckString(hdr, &p->sessionkey, size) < 0) {
+	    fprintf(stderr, "ntlmCheckHeader: malformed authenticate packet (sessionkey)\n");
+	    return -1;
+	}
+#endif
+	} break;
+    }
+    return 0;
+}
+
+/*
+ * Extract a string from an NTLM request and return as ASCII.
+ */
+unsigned char *
+ntlmGetString(const ntlmhdr * hdr, const strhdr * str, uint32_t flags)
+{
+    static unsigned char buf[512];
+    unsigned char *d;
+    int l, o;
+
+    l = SSWAP(str->len);
+    o = WSWAP(str->offset);
+
+    if (flags & NTLMSSP_NEGOTIATE_UNICODE) {
+	/* UNICODE string */
+	u_short *s = (u_short *) ((char *) hdr + o);
+	d = buf;
+	l = l >> 1; /* 16 bit characters */
+
+	if (l > sizeof(buf) - 1) {
+	    fprintf(stderr, "ntlmGetString: too large: %d\n", l);
+	    return NULL;
+	}
+	while (l--) {
+	    u_short c = SSWAP(*s++);
+	    if (c > 254 || c == '\0' || c < 32) {
+		fprintf(stderr, "ntlmGetString: bad uni char: %04x\n", c);
+		return NULL;
+	    }
+	    *d++ = c;
+	}
+	*d = 0;
+    } else {
+	/* ASCII string */
+	unsigned char *s = (unsigned char *) hdr + o;
+	d = buf;
+
+	if (l > sizeof(buf) - 1) {
+	    fprintf(stderr, "ntlmGetString: too large: %d\n", l);
+	    return NULL;
+	}
+	for (; l; l--) {
+	    unsigned char c = *s++;
+	    if (c == '\0' || c < 32) {
+		fprintf(stderr, "ntlmGetString: bad ascii: %02x\n", c);
+		return (NULL);
+	    }
+	    *d++ = c;
+	}
+
+	*d = 0;
+    }
+
+    return (buf);
+}
+
+/*
+ * Extract a binary string from an NTLM request
+ */
+static unsigned char *
+ntlmGetBinary(const ntlmhdr * hdr, const strhdr * str, size_t *lenp)
+{
+    static unsigned char buf[512];
+    unsigned char *d, *s;
+    int l, o;
+
+    l = SSWAP(str->len);
+    o = WSWAP(str->offset);
+
+    s = (unsigned char *) hdr + o;
+    d = buf;
+
+    if (l > sizeof(buf)) {
+	fprintf(stderr, "ntlmGetBinary: too large: %d\n", l);
+	return NULL;
+    }
+    if (lenp)
+	*lenp = l;
+    while (l--) {
+	*d++ = *s++;
+    }
+
+    return (buf);
+}
+
+/*
+ * Return the full username including domain
+ */
+int
+ntlmGetFullUserName(const ntlm_authenticate *auth, char *buf, size_t size)
+{
+    unsigned char *p;
+    int s;
+    uint32_t flags = WSWAP(auth->flags); /* XXX The flags field do not always exists */
+
+    if ((p = ntlmGetString(&auth->hdr, &auth->domain, flags)) == NULL)
+	p = authenticate_ntlm_domain;
+    if (!p)
+	return -1;
+    s = strlen(p);
+    if (s > size)
+	return -1;
+    strcpy(buf, p);
+    size -= s;
+    buf += s;
+
+    if (!size)
+	return -1;
+    *buf++ = '\\';		/* Using \ is more consistent with MS-proxy */
+    size--;
+
+    p = ntlmGetString(&auth->hdr, &auth->user, flags);
+    if (!p)
+	return -1;
+    s = strlen(p);
+    if (s > size)
+	return -1;
+    while (*p)
+    *buf++ = *p++;
+
+    *buf++ = '\0';
+    size -= s;
+
+    return 0;
+}
+
+void
+ntlmEncrypt(const unsigned char *pwhash, const unsigned char *key, unsigned char *out)
+{
+    unsigned char tmp[21];
+    memset(tmp, 0, sizeof(tmp));
+    memcpy(tmp, pwhash, 16);
+    E_P24(tmp, key, out);
+}
+
+/*
+ * Verify that the password supplied by the user matches
+ */
+int ntlmCheckAuth(const ntlm_authenticate *auth, const ntlm_challenge *challenge, const unsigned char *lmhash, const unsigned char *nthash)
+{
+    if (nthash) {
+	unsigned char *ntresp = ntlmGetBinary(&auth->hdr, &auth->ntresponse, NULL);
+	if (ntresp) {
+	    uint32_t flags = WSWAP(auth->flags);
+	    if (flags & NTLMSSP_NEGOTIATE_NTLM2) {
+		unsigned char local_response[24];
+		/* XXX This is not correct. Documentation is incomplete,
+		 * but there is some magic with the lmhash here..
+		 */
+		ntlmEncrypt(nthash, challenge->challenge, local_response);
+		if (memcmp(ntresp, local_response, 24) == 0)
+		    return 0;
+	    } else {
+		unsigned char local_response[24];
+		ntlmEncrypt(nthash, challenge->challenge, local_response);
+		if (memcmp(ntresp, local_response, 24) == 0)
+		    return 0;
+	    }
+	}
+    }
+    if (lmhash) {
+	unsigned char *lmresp = ntlmGetBinary(&auth->hdr, &auth->lmresponse, NULL);
+	if (lmresp) {
+	    unsigned char local_response[24];
+	    ntlmEncrypt(lmhash, challenge->challenge, local_response);
+	    if (memcmp(lmresp, local_response, 24) == 0)
+		return 0;
+	}
+    }
+    return -1;
+}
+
Index: squid/src/auth/ntlm/helpers/smbpasswd/ntlm.h
diff -u /dev/null squid/src/auth/ntlm/helpers/smbpasswd/ntlm.h:1.1.2.4
--- /dev/null	Mon Jan 26 04:56:12 2004
+++ squid/src/auth/ntlm/helpers/smbpasswd/ntlm.h	Sat Dec  7 10:21:33 2002
@@ -0,0 +1,139 @@
+/*
+ * $Id: squid-ntlm_smbpasswd-HEAD,v 1.1 2004/08/17 20:55:13 hno Exp $
+ *
+ * AUTHOR: Andrew Doran <ad@interlude.eu.org>
+ *
+ * SQUID Web Proxy Cache          http://www.squid-cache.org/
+ * ----------------------------------------------------------
+ *
+ *  Squid is the result of efforts by numerous individuals from
+ *  the Internet community; see the CONTRIBUTORS file for full
+ *  details.   Many organizations have provided support for Squid's
+ *  development; see the SPONSORS file for full details.  Squid is
+ *  Copyrighted (C) 2001 by the Regents of the University of
+ *  California; see the COPYRIGHT file for full details.  Squid
+ *  incorporates software developed and/or copyrighted by other
+ *  sources; see the CREDITS file for full details.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *  
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *  
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ *  
+ */
+
+#ifndef _NTLM_H_
+#define _NTLM_H_
+
+#include <sys/types.h>
+
+/* All of this cruft is little endian */
+#ifdef WORDS_BIGENDIAN
+#define SSWAP(x)	(bswap16((x)))
+#define WSWAP(x)	(bswap32((x)))
+#else
+#define SSWAP(x)	(x)
+#define WSWAP(x)	(x)
+#endif
+
+/* NTLM request types that we know about */
+#define NTLMSSP_NEGOTIATE		1
+#define NTLMSSP_CHALLENGE		2
+#define NTLMSSP_AUTHENTICATE		3
+#define NTLMSSP_ANY			0
+
+/* flags */
+#define NTLMSSP_NEGOTIATE_UNICODE			0x00000001  /* Text are in unicode */
+#define NTLMSSP_NEGOTIATE_OEM				0x00000002  /* Text are in OEM (???) */
+#define NTLMSSP_REQUEST_TARGET				0x00000004  /* Ask server to return its target/realm */
+#define NTLMSSP_NEGOTIATE_SIGN				0x00000010  /* Request signature capability */
+#define NTLMSSP_NEGOTIATE_SEAL				0x00000020  /* Request seal capability */
+#define NTLMSSP_NEGOTIATE_DATAGRAM_STYLE		0x00000040
+#define NTLMSSP_NEGOTIATE_LM				0x00000080  /* Client/Server supports LM key for sign/seal */
+#define NTLMSSP_NEGOTIATE_NETWARE			0x00000100  /* Client/Server supports Netware authentication (???) */
+#define NTLMSSP_NEGOTIATE_NTLM				0x00000200  /* Client/Server supports NTLM */
+#define NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED		0x00001000
+#define NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED	0x00002000
+#define NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL		0x00004000
+#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN			0x00008000
+#define NTLMSSP_NEGOTIATE_NTLM2				0x00080000  /* Client/Server supports NTLMv2 */
+#define NTLMSSP_NEGOTIATE_TARGET_INFO			0x00800000  /* ??? */
+#define NTLMSSP_NEGOTIATE_128				0x20000000  /* ??? */
+#define NTLMSSP_NEGOTIATE_KEY_EXCH			0x40000000  /* ??? */
+
+/* challenge TargetName is a XXX */
+#define NTLMSSP_CHALLENGE_TARGET_IS_DOMAIN		0x00010000  /* TargetName is a domain name */
+#define NTLMSSP_CHALLENGE_TARGET_IS_SERVER		0x00020000  /* TargetName is a server name */
+#define NTLMSSP_CHALLENGE_TARGET_IS_SHARE		0x00040000  /* TargetName is a share name */
+
+/* these NTLMSSP_are marked as "extra" fields */
+#define NTLMSSP_REQUEST_INIT_RESPONSE			0x00100000  /* request NT session key */
+#define NTLMSSP_REQUEST_ACCEPT_RESPONSE			0x00200000  /* request session key, LUID? */
+#define NTLMSSP_REQUEST_NON_NT_SESSION_KEY		0x00400000  /* request non-NT session key (LM?) */
+
+/* This is an header common to all signatures, it's used to discriminate
+ * among the different signature types. */
+typedef struct {
+    char signature[8];		/* "NTLMSSP" */
+    int32_t type;		/* One of the NTLM_* types above. */
+} ntlmhdr;
+
+/* String header. String data resides at the end of the request */
+typedef struct _strhdr {
+    int16_t len;		/* Length in bytes */
+    int16_t maxlen;		/* Allocated space in bytes */
+    int32_t offset;		/* Offset from start of request */
+} strhdr;
+
+/* Negotiation request sent by client */
+typedef struct {
+    ntlmhdr hdr;		/* NTLM header */
+    int32_t flags;		/* Request flags */
+    /* the rest is optional fields */
+    strhdr domain;		/* Domain we wish to authenticate in */
+    strhdr workstation;		/* Client workstation name */
+    char pad[256];		/* String data */
+} ntlm_negotiate;
+
+/* Challenge request sent by server. */
+typedef struct {
+    ntlmhdr hdr;		/* NTLM header */
+    strhdr target;		/* Authentication target (domain/server/share ...) */
+    int32_t flags;		/* Request flags */
+    u_char challenge[8];	/* Challenge string */
+    uint32_t ServerContextHandle[2];	/* Some sort of context data */
+    strhdr unknown2;		/* Some sort of context string data */
+    char pad[256];		/* String data */
+} ntlm_challenge;
+
+/* Authentication request sent by client in response to challenge */
+typedef struct {
+    ntlmhdr hdr;		/* NTLM header */
+    strhdr lmresponse;		/* LANMAN challenge response */
+    strhdr ntresponse;		/* NT challenge response */
+    strhdr domain;		/* Domain to authenticate against */
+    strhdr user;		/* Username */
+    strhdr workstation;		/* Workstation name */
+    strhdr sessionkey;		/* Session key for server's use */
+    int32_t flags;		/* Request flags */
+    char pad[256 * 6];		/* String data */
+} ntlm_authenticate;
+
+unsigned char *ntlmGetString(const ntlmhdr * hdr, const strhdr * str, u_int32_t flags);
+void ntlmMakeChallenge(ntlm_challenge *chal);
+int ntlmCheckPacket(const ntlmhdr * hdr, int type, size_t len);
+int ntlmGetFullUserName(const ntlm_authenticate *auth, char *buf, size_t size);
+int ntlmCheckAuth(const ntlm_authenticate *auth, const ntlm_challenge *challenge, const unsigned char *lmhash, const unsigned char *nthash);
+void ntlmNegotiateChallenge(const ntlm_negotiate *nego, ntlm_challenge *chal);
+void ntlm2MakeResponse(const char *nthash, const char *user, const char *challenge, char *response);
+
+#endif /* _NTLM_H_ */
Index: squid/src/auth/ntlm/helpers/smbpasswd/ntlm_smbpasswd.c
diff -u /dev/null squid/src/auth/ntlm/helpers/smbpasswd/ntlm_smbpasswd.c:1.1.2.6
--- /dev/null	Mon Jan 26 04:56:12 2004
+++ squid/src/auth/ntlm/helpers/smbpasswd/ntlm_smbpasswd.c	Mon Apr  1 03:16:53 2002
@@ -0,0 +1,133 @@
+/*
+ * AUTHOR: Henrik Nordstrom <hno@squid-cache.org>
+ *
+ * Loosely based on fakeauth by Robert Collins <rbtcollins@hotmail.com>
+ */
+
+#include "config.h"
+#include "squid_types.h"
+
+#include "ntlm.h"
+#include "util.h"
+#include <ctype.h>
+
+#if HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_STRING_H
+#include <string.h>
+#endif
+
+#define DEBUG(args...) fprintf(stderr, ## args)
+#define WARN(args...) fprintf(stderr, ## args)
+
+#ifndef DEBUG
+#define DEBUG(args...)
+#endif
+
+
+#ifdef DEBUG
+#include <stdarg.h>
+void send_result(const char *fmt, ...)
+{
+    char buf[8192];
+    va_list args;
+    va_start(args, fmt);
+    vsnprintf(buf, sizeof(buf), fmt, args);
+    fprintf(stderr, buf);
+    printf(buf);
+}
+#else
+#define send_result printf
+#endif
+
+#define ERR    "ERR\n"
+#define OK     "OK\n"
+
+/* test1234 */
+char lmhash[] = { 0x62, 0x4A, 0xAC, 0x41, 0x37, 0x95, 0xCD, 0xC1, 0xFF, 0x17, 0x36, 0x5F, 0xAF, 0x1F, 0xFE, 0x89 };
+//char nthash[] = { 0x3B, 0x1B, 0x47, 0xE4, 0x2E, 0x04, 0x63, 0x27, 0x6E, 0x3D, 0xED, 0x6C, 0xEF, 0x34, 0x9F, 0x93 };
+
+/* topsecret */
+//char lmhash[] = { 0x3E, 0x67, 0x37, 0xD0, 0xC0, 0xDC, 0x52, 0x3B, 0x9A, 0x0F, 0x5D, 0x12, 0xD8, 0xF6, 0x12, 0xD0 };
+char nthash[] = { 0x7C, 0x45, 0x18, 0x51, 0xEA, 0x87, 0xB6, 0x3E, 0xC7, 0x69, 0x21, 0x26, 0x41, 0x6D, 0x01, 0xEB };
+
+/* makes a null-terminated string lower-case. Changes CONTENTS! */
+static void
+lc(char *string)
+{
+    char *p = string, c;
+    while ((c = *p)) {
+	*p = tolower(c);
+	p++;
+    }
+}
+
+int
+main(int argc, char **argv)
+{
+    char buf[8192];
+    char user[256], *p;
+    ntlm_challenge chal;
+    int len;
+    char *data = NULL;
+
+    setbuf(stdout, NULL);
+    while (fgets(buf, 8192, stdin) != NULL) {
+	if ((p = strchr(buf, '\n')) != NULL)
+	    *p = '\0';		/* strip \n */
+#ifdef DEBUG
+	{
+	    char *p2 = base64_decode("AAA");
+	    memset(p2, '!', 4096);
+	}
+#endif
+	DEBUG("%s\n", buf);
+	if (strncasecmp(buf, "YR ", 3) == 0) {
+	    ntlm_negotiate *nego = (ntlm_negotiate *) base64_decode(buf + 3);
+	    len = strlen(buf + 3) * 3 / 4; /* approximation, in lack of base64_decode_bin */
+	    if (ntlmCheckPacket(&nego->hdr, NTLMSSP_NEGOTIATE, len) != 0) {
+		send_result("BH invalid NTLMSSP packet\n");
+		continue;
+	    }
+	    ntlmNegotiateChallenge(nego, &chal);
+	    len = (int)&((ntlm_challenge *)NULL)->pad
+		+ SSWAP(chal.target.maxlen);
+	    data = (char *) base64_encode_bin((char *) &chal, len);
+	    send_result("TT %s\n", data);
+	} else if (strncasecmp(buf, "YR", 2) == 0) {
+	    ntlmMakeChallenge(&chal);
+	    len = (int)&((ntlm_challenge *)NULL)->pad
+		+ SSWAP(chal.target.maxlen);
+	    data = (char *) base64_encode_bin((char *) &chal, len);
+	    send_result("TT %s\n", data);
+	} else if (strncasecmp(buf, "KK ", 3) == 0) {
+	    ntlm_authenticate *auth = (ntlm_authenticate *) base64_decode(buf + 3);
+	    len = strlen(buf + 3) * 3 / 4; /* approximation, in lack of base64_decode_bin */
+	    if (ntlmCheckPacket(&auth->hdr, NTLMSSP_AUTHENTICATE, len) != 0) {
+		send_result("BH invalid NTLMSSP packet\n");
+		continue;
+	    }
+	    if (ntlmGetFullUserName(auth, user, 256) == 0) {
+		lc(user);
+		if (ntlmCheckAuth(auth, &chal, lmhash, nthash) == 0) {
+		    send_result("AF %s\n", user);
+		} else {
+		    send_result("NA invalid credentials\n");
+		}
+	    } else {
+		send_result("NA invalid username\n");
+	    }
+	} else {
+	    WARN("ntlm_smbpass: Unknown input: %s\n", buf);
+	    send_result("BH unknown packet format!\n");
+	}
+    }
+    exit(0);
+}
Index: squid/src/auth/ntlm/helpers/smbpasswd/smbdes.c
diff -u /dev/null squid/src/auth/ntlm/helpers/smbpasswd/smbdes.c:1.1.2.3
--- /dev/null	Mon Jan 26 04:56:12 2004
+++ squid/src/auth/ntlm/helpers/smbpasswd/smbdes.c	Mon Feb 25 05:46:32 2002
@@ -0,0 +1,311 @@
+/* 
+   Unix SMB/Netbios implementation.
+   Version 1.9.
+
+   a partial implementation of DES designed for use in the 
+   SMB authentication protocol
+
+   Copyright (C) Andrew Tridgell 1998-2000
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/* NOTES: 
+
+   This code makes no attempt to be fast! In fact, it is a very
+   slow implementation 
+
+   This code is NOT a complete DES implementation. It implements only
+   the minimum necessary for SMB authentication, as used by all SMB
+   products (including every copy of Microsoft Windows95 ever sold)
+
+   In particular, it can only do a unchained forward DES pass. This
+   means it is not possible to use this code for encryption/decryption
+   of data, instead it is only useful as a "hash" algorithm.
+
+   There is no entry point into this code that allows normal DES operation.
+
+   I believe this means that this code does not come under ITAR
+   regulations but this is NOT a legal opinion. If you are concerned
+   about the applicability of ITAR regulations to this code then you
+   should confirm it for yourself (and maybe let me know if you come
+   up with a different answer to the one above)
+*/
+
+
+#define uchar unsigned char
+
+static uchar perm1[56] = {57, 49, 41, 33, 25, 17,  9,
+			 1, 58, 50, 42, 34, 26, 18,
+			10,  2, 59, 51, 43, 35, 27,
+			19, 11,  3, 60, 52, 44, 36,
+			63, 55, 47, 39, 31, 23, 15,
+			 7, 62, 54, 46, 38, 30, 22,
+			14,  6, 61, 53, 45, 37, 29,
+			21, 13,  5, 28, 20, 12,  4};
+
+static uchar perm2[48] = {14, 17, 11, 24,  1,  5,
+                         3, 28, 15,  6, 21, 10,
+                        23, 19, 12,  4, 26,  8,
+                        16,  7, 27, 20, 13,  2,
+                        41, 52, 31, 37, 47, 55,
+                        30, 40, 51, 45, 33, 48,
+                        44, 49, 39, 56, 34, 53,
+                        46, 42, 50, 36, 29, 32};
+
+static uchar perm3[64] = {58, 50, 42, 34, 26, 18, 10,  2,
+			60, 52, 44, 36, 28, 20, 12,  4,
+			62, 54, 46, 38, 30, 22, 14,  6,
+			64, 56, 48, 40, 32, 24, 16,  8,
+			57, 49, 41, 33, 25, 17,  9,  1,
+			59, 51, 43, 35, 27, 19, 11,  3,
+			61, 53, 45, 37, 29, 21, 13,  5,
+			63, 55, 47, 39, 31, 23, 15,  7};
+
+static uchar perm4[48] = {   32,  1,  2,  3,  4,  5,
+                            4,  5,  6,  7,  8,  9,
+                            8,  9, 10, 11, 12, 13,
+                           12, 13, 14, 15, 16, 17,
+                           16, 17, 18, 19, 20, 21,
+                           20, 21, 22, 23, 24, 25,
+                           24, 25, 26, 27, 28, 29,
+                           28, 29, 30, 31, 32,  1};
+
+static uchar perm5[32] = {      16,  7, 20, 21,
+                              29, 12, 28, 17,
+                               1, 15, 23, 26,
+                               5, 18, 31, 10,
+                               2,  8, 24, 14,
+                              32, 27,  3,  9,
+                              19, 13, 30,  6,
+                              22, 11,  4, 25};
+
+
+static uchar perm6[64] ={ 40,  8, 48, 16, 56, 24, 64, 32,
+                        39,  7, 47, 15, 55, 23, 63, 31,
+                        38,  6, 46, 14, 54, 22, 62, 30,
+                        37,  5, 45, 13, 53, 21, 61, 29,
+                        36,  4, 44, 12, 52, 20, 60, 28,
+                        35,  3, 43, 11, 51, 19, 59, 27,
+                        34,  2, 42, 10, 50, 18, 58, 26,
+                        33,  1, 41,  9, 49, 17, 57, 25};
+
+
+static uchar sc[16] = {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1};
+
+static uchar sbox[8][4][16] = {
+	{{14,  4, 13,  1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7},
+	 {0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3,  8},
+	 {4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5,  0},
+	 {15, 12,  8,  2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0,  6, 13}},
+
+	{{15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10},
+	 {3, 13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9, 11,  5},
+	 {0, 14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, 15},
+	 {13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5, 14,  9}},
+
+	{{10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8},
+	 {13,  7,  0,  9,  3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15,  1},
+	 {13,  6,  4,  9,  8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14,  7},
+	 {1, 10, 13,  0,  6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, 12}},
+
+	{{7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15},
+	 {13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,  9},
+	 {10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4},
+	 {3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14}},
+
+	{{2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9},
+	 {14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8,  6},
+	 {4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, 14},
+	 {11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5,  3}},
+
+	{{12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11},
+	 {10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8},
+	 {9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6},
+	 {4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13}},
+
+	{{4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1},
+	 {13,  0, 11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8,  6},
+	 {1,  4, 11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9,  2},
+	 {6, 11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, 12}},
+
+	{{13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7},
+	 {1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2},
+	 {7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8},
+	 {2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11}}};
+
+static void permute(char *out, char *in, uchar *p, int n)
+{
+	int i;
+	for (i=0;i<n;i++)
+		out[i] = in[p[i]-1];
+}
+
+static void lshift(char *d, int count, int n)
+{
+	char out[64];
+	int i;
+	for (i=0;i<n;i++)
+		out[i] = d[(i+count)%n];
+	for (i=0;i<n;i++)
+		d[i] = out[i];
+}
+
+static void concat(char *out, char *in1, char *in2, int l1, int l2)
+{
+	while (l1--)
+		*out++ = *in1++;
+	while (l2--)
+		*out++ = *in2++;
+}
+
+static void xor(char *out, char *in1, char *in2, int n)
+{
+	int i;
+	for (i=0;i<n;i++)
+		out[i] = in1[i] ^ in2[i];
+}
+
+static void dohash(char *out, char *in, char *key, int forw)
+{
+	int i, j, k;
+	char pk1[56];
+	char c[28];
+	char d[28];
+	char cd[56];
+	char ki[16][48];
+	char pd1[64];
+	char l[32], r[32];
+	char rl[64];
+
+	permute(pk1, key, perm1, 56);
+
+	for (i=0;i<28;i++)
+		c[i] = pk1[i];
+	for (i=0;i<28;i++)
+		d[i] = pk1[i+28];
+
+	for (i=0;i<16;i++) {
+		lshift(c, sc[i], 28);
+		lshift(d, sc[i], 28);
+
+		concat(cd, c, d, 28, 28); 
+		permute(ki[i], cd, perm2, 48); 
+	}
+
+	permute(pd1, in, perm3, 64);
+
+	for (j=0;j<32;j++) {
+		l[j] = pd1[j];
+		r[j] = pd1[j+32];
+	}
+
+	for (i=0;i<16;i++) {
+		char er[48];
+		char erk[48];
+		char b[8][6];
+		char cb[32];
+		char pcb[32];
+		char r2[32];
+
+		permute(er, r, perm4, 48);
+
+		xor(erk, er, ki[forw ? i : 15 - i], 48);
+
+		for (j=0;j<8;j++)
+			for (k=0;k<6;k++)
+				b[j][k] = erk[j*6 + k];
+
+		for (j=0;j<8;j++) {
+			int m, n;
+			m = (b[j][0]<<1) | b[j][5];
+
+			n = (b[j][1]<<3) | (b[j][2]<<2) | (b[j][3]<<1) | b[j][4]; 
+
+			for (k=0;k<4;k++) 
+				b[j][k] = (sbox[j][m][n] & (1<<(3-k)))?1:0; 
+		}
+
+		for (j=0;j<8;j++)
+			for (k=0;k<4;k++)
+				cb[j*4+k] = b[j][k];
+		permute(pcb, cb, perm5, 32);
+
+		xor(r2, l, pcb, 32);
+
+		for (j=0;j<32;j++)
+			l[j] = r[j];
+
+		for (j=0;j<32;j++)
+			r[j] = r2[j];
+	}
+
+	concat(rl, r, l, 32, 32);
+
+	permute(out, rl, perm6, 64);
+}
+
+static void str_to_key(const uchar *str, uchar *key)
+{
+	int i;
+
+	key[0] = str[0]>>1;
+	key[1] = ((str[0]&0x01)<<6) | (str[1]>>2);
+	key[2] = ((str[1]&0x03)<<5) | (str[2]>>3);
+	key[3] = ((str[2]&0x07)<<4) | (str[3]>>4);
+	key[4] = ((str[3]&0x0F)<<3) | (str[4]>>5);
+	key[5] = ((str[4]&0x1F)<<2) | (str[5]>>6);
+	key[6] = ((str[5]&0x3F)<<1) | (str[6]>>7);
+	key[7] = str[6]&0x7F;
+	for (i=0;i<8;i++) {
+		key[i] = (key[i]<<1);
+	}
+}
+
+
+static void smbhash(uchar *out, const uchar *in, const uchar *key, int forw)
+{
+	int i;
+	char outb[64];
+	char inb[64];
+	char keyb[64];
+	uchar key2[8];
+
+	str_to_key(key, key2);
+
+	for (i=0;i<64;i++) {
+		inb[i] = (in[i/8] & (1<<(7-(i%8)))) ? 1 : 0;
+		keyb[i] = (key2[i/8] & (1<<(7-(i%8)))) ? 1 : 0;
+		outb[i] = 0;
+	}
+
+	dohash(outb, inb, keyb, forw);
+
+	for (i=0;i<8;i++) {
+		out[i] = 0;
+	}
+
+	for (i=0;i<64;i++) {
+		if (outb[i])
+			out[i/8] |= (1<<(7-(i%8)));
+	}
+}
+
+void E_P24(const uchar *p21, const uchar *c8, uchar *p24)
+{
+	smbhash(p24, c8, p21, 1);
+	smbhash(p24+8, c8, p21+7, 1);
+	smbhash(p24+16, c8, p21+14, 1);
+}
Index: squid/src/auth/ntlm/helpers/smbpasswd/smbdes.h
diff -u /dev/null squid/src/auth/ntlm/helpers/smbpasswd/smbdes.h:1.1.2.3
--- /dev/null	Mon Jan 26 04:56:12 2004
+++ squid/src/auth/ntlm/helpers/smbpasswd/smbdes.h	Mon Feb 25 05:46:32 2002
@@ -0,0 +1 @@
+void E_P24(const unsigned char *p21, const unsigned char *c8, unsigned char *p24);
Index: squid/src/auth/ntlm/helpers/smbpasswd/std-defines.h
diff -u /dev/null squid/src/auth/ntlm/helpers/smbpasswd/std-defines.h:1.1.2.1
--- /dev/null	Mon Jan 26 04:56:12 2004
+++ squid/src/auth/ntlm/helpers/smbpasswd/std-defines.h	Sat Feb 23 19:29:20 2002
@@ -0,0 +1,49 @@
+#ifndef __STD_DEFINES__
+#define __STD_DEFINES__
+
+/* RFCNB Standard includes ... */
+/*
+ * 
+ * SMBlib Standard Includes
+ * 
+ * Copyright (C) 1996, Richard Sharpe
+ * 
+ * One day we will conditionalize these on OS types ... */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "squid_types.h"
+#define BOOL int16_t
+#define int16 int16_t
+#define uint16 u_int16_t
+#define int32 int32_t
+#define uint32 u_int32_t
+
+#include <netdb.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <signal.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <strings.h>
+
+#define TRUE 1
+#define FALSE 0
+
+#endif /* __STD_DEFINES__ */
Index: squid/src/auth/ntlm/helpers/smbpasswd/std-includes.h
diff -u /dev/null squid/src/auth/ntlm/helpers/smbpasswd/std-includes.h:1.1.2.1
--- /dev/null	Mon Jan 26 04:56:12 2004
+++ squid/src/auth/ntlm/helpers/smbpasswd/std-includes.h	Sat Feb 23 19:29:20 2002
@@ -0,0 +1,47 @@
+/* RFCNB Standard includes ... */
+/*
+ * 
+ * RFCNB Standard Includes
+ * 
+ * Copyright (C) 1996, Richard Sharpe
+ * 
+ * One day we will conditionalize these on OS types ... */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* the types are provided by squid's configure preocess */
+#include "squid_types.h"
+#define BOOL int16_t
+#define int16 int16_t
+
+#include <netdb.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <signal.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#define TRUE 1
+#define FALSE 0
+
+/* Pick up define for INADDR_NONE */
+
+#ifndef INADDR_NONE
+#define INADDR_NONE -1
+#endif
squid-ntlm_smbpasswd-HEAD.new squid-ntlm_smbpasswd-HEAD differ: char 73, line 2