--------------------- PatchSet 4498 Date: 2002/07/16 09:07:00 Author: serassio Branch: cygwin-svc-2_5 Tag: (none) Log: Added WIN32 native NTLM authenticator Members: helpers/ntlm_auth/Makefile.am:1.2.16.1->1.2.16.2 helpers/ntlm_auth/NTLMSSP-WIN32/.cvsignore:1.1->1.1.6.1 helpers/ntlm_auth/NTLMSSP-WIN32/Makefile.am:1.1->1.1.6.1 helpers/ntlm_auth/NTLMSSP-WIN32/libntlmssp.c:1.1->1.1.6.1 helpers/ntlm_auth/NTLMSSP-WIN32/ntlm.h:1.1->1.1.6.1 helpers/ntlm_auth/NTLMSSP-WIN32/ntlm_auth.c:1.1->1.1.6.1 helpers/ntlm_auth/NTLMSSP-WIN32/readme.txt:1.1->1.1.6.1 Index: squid/helpers/ntlm_auth/Makefile.am =================================================================== RCS file: /cvsroot/squid-sf//squid/helpers/ntlm_auth/Makefile.am,v retrieving revision 1.2.16.1 retrieving revision 1.2.16.2 diff -u -r1.2.16.1 -r1.2.16.2 --- squid/helpers/ntlm_auth/Makefile.am 13 Jul 2002 20:08:19 -0000 1.2.16.1 +++ squid/helpers/ntlm_auth/Makefile.am 16 Jul 2002 09:07:00 -0000 1.2.16.2 @@ -1,7 +1,7 @@ # Makefile for storage modules in the Squid Object Cache server # -# $Id: Makefile.am,v 1.2.16.1 2002/07/13 20:08:19 serassio Exp $ +# $Id: Makefile.am,v 1.2.16.2 2002/07/16 09:07:00 serassio Exp $ # -DIST_SUBDIRS = fakeauth no_check SMB winbind +DIST_SUBDIRS = fakeauth no_check SMB winbind NTLMSSP-WIN32 SUBDIRS = @NTLM_AUTH_HELPERS@ --- /dev/null Wed Feb 14 01:00:00 2007 +++ squid/helpers/ntlm_auth/NTLMSSP-WIN32/.cvsignore Wed Feb 14 01:00:02 2007 @@ -0,0 +1,2 @@ +.cvsignore +Makefile.in --- /dev/null Wed Feb 14 01:00:00 2007 +++ squid/helpers/ntlm_auth/NTLMSSP-WIN32/Makefile.am Wed Feb 14 01:00:02 2007 @@ -0,0 +1,14 @@ +# +# Makefile for the Squid Object Cache server +# +# $Id: Makefile.am,v 1.1.6.1 2002/07/16 09:07:00 serassio Exp $ +# + +libexec_PROGRAMS = ntlm_auth + +ntlm_auth_SOURCES = libntlmssp.c ntlm_auth.c ntlm.h + +INCLUDES = -I. -I$(top_srcdir)/include -I$(top_srcdir)/src + +LDADD = -L$(top_builddir)/lib -lntlmauth -lsspwin32 -lnetapi32 \ + -ladvapi32 -lmiscutil $(CRYPTLIB) $(XTRA_LIBS) --- /dev/null Wed Feb 14 01:00:00 2007 +++ squid/helpers/ntlm_auth/NTLMSSP-WIN32/libntlmssp.c Wed Feb 14 01:00:02 2007 @@ -0,0 +1,382 @@ +/* + * (C) 2002 Guido Serassio + * Based on previous work of Francesco Chemolli and Robert Collins + * Distributed freely under the terms of the GNU General Public License, + * version 2. See the file COPYING for licensing details + * + * 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. + */ + +typedef unsigned char uchar; + +#include "squid.h" +#include "ntlm.h" +#include +#include +#include + +#ifdef DEBUG +#define debug_dump_ntlmssp_flags dump_ntlmssp_flags +#else /* DEBUG */ +#define debug_dump_ntlmssp_flags(X) /* empty */ +#endif /* DEBUG */ + +#define ENCODED_PASS_LEN 24 +static char challenge[NONCE_LEN]; +static char lmencoded_empty_pass[ENCODED_PASS_LEN], + ntencoded_empty_pass[ENCODED_PASS_LEN]; + +/* returns 1 on success, 0 on failure */ +int +Valid_Group(char *UserName, char *Group) +{ + int result = FALSE; + WCHAR wszUserName[256]; // Unicode user name + WCHAR wszGroup[256]; // Unicode Group + + LPLOCALGROUP_USERS_INFO_0 pBuf = NULL; + LPLOCALGROUP_USERS_INFO_0 pTmpBuf; + DWORD dwLevel = 0; + DWORD dwFlags = LG_INCLUDE_INDIRECT; + DWORD dwPrefMaxLen = -1; + DWORD dwEntriesRead = 0; + DWORD dwTotalEntries = 0; + NET_API_STATUS nStatus; + DWORD i; + DWORD dwTotalCount = 0; + +/* Convert ANSI User Name and Group to Unicode */ + + MultiByteToWideChar(CP_ACP, 0, UserName, + strlen(UserName) + 1, wszUserName, + sizeof(wszUserName) / sizeof(wszUserName[0])); + MultiByteToWideChar(CP_ACP, 0, Group, + strlen(Group) + 1, wszGroup, sizeof(wszGroup) / sizeof(wszGroup[0])); + + /* + * Call the NetUserGetLocalGroups function + * specifying information level 0. + * + * The LG_INCLUDE_INDIRECT flag specifies that the + * function should also return the names of the local + * groups in which the user is indirectly a member. + */ + nStatus = NetUserGetLocalGroups(NULL, + wszUserName, + dwLevel, + dwFlags, + (LPBYTE *) & pBuf, dwPrefMaxLen, &dwEntriesRead, &dwTotalEntries); + /* + * If the call succeeds, + */ + if (nStatus == NERR_Success) { + if ((pTmpBuf = pBuf) != NULL) { + for (i = 0; i < dwEntriesRead; i++) { + assert(pTmpBuf != NULL); + if (pTmpBuf == NULL) { + result = FALSE; + break; + } + if (wcscmp(pTmpBuf->lgrui0_name, wszGroup) == 0) { + result = TRUE; + break; + } + pTmpBuf++; + dwTotalCount++; + } + } + } else + result = FALSE; +/* + * Free the allocated memory. + */ + if (pBuf != NULL) + NetApiBufferFree(pBuf); + return result; +} + +/* returns 0 on success, > 0 on failure */ +static int +init_challenge(void) +{ + static unsigned hash; + int r; + int i; + + r = (int) rand(); + r = (hash ^ r) + r; + for (i = 0; i < NONCE_LEN; i++) { + challenge[i] = r; + r = (r >> 2) ^ r; + } + hash = r; + return 0; +} + +char * AllocStrFromLSAStr(LSA_UNICODE_STRING LsaStr) +{ + size_t len; + static char * target; + + len = LsaStr.Length/sizeof(WCHAR) + 1; + + /* allocate buffer for str + null termination */ + safe_free(target); + target = (char *)xmalloc(len); + if (target == NULL) + return NULL; + + /* copy unicode buffer */ + WideCharToMultiByte(CP_ACP, 0, LsaStr.Buffer, LsaStr.Length, target, len, NULL, NULL ); + + /* add null termination */ + target[len-1] = '\0'; + return target; +} + +char * GetDomainName(void) + +{ + LSA_HANDLE PolicyHandle; + LSA_OBJECT_ATTRIBUTES ObjectAttributes; + NTSTATUS status; + PPOLICY_PRIMARY_DOMAIN_INFO ppdiDomainInfo; + PWKSTA_INFO_100 pwkiWorkstationInfo; + DWORD netret; + char * DomainName = NULL; + + /* + * Always initialize the object attributes to all zeroes. + */ + memset(&ObjectAttributes, '\0', sizeof(ObjectAttributes)); + + /* + * You need the local workstation name. Use NetWkstaGetInfo at level + * 100 to retrieve a WKSTA_INFO_100 structure. + * + * The wki100_computername field contains a pointer to a UNICODE + * string containing the local computer name. + */ + netret = NetWkstaGetInfo(NULL, 100, (LPBYTE *)&pwkiWorkstationInfo); + if (netret == NERR_Success) { + /* + * We have the workstation name in: + * pwkiWorkstationInfo->wki100_computername + * + * Next, open the policy object for the local system using + * the LsaOpenPolicy function. + */ + status = LsaOpenPolicy( + NULL, + &ObjectAttributes, + GENERIC_READ | POLICY_VIEW_LOCAL_INFORMATION, + &PolicyHandle + ); + + /* + * Error checking. + */ + if (status) { + debug("OpenPolicy Error: %d\n", status); + } else { + + /* + * You have a handle to the policy object. Now, get the + * domain information using LsaQueryInformationPolicy. + */ + status = LsaQueryInformationPolicy(PolicyHandle, + PolicyPrimaryDomainInformation, + &ppdiDomainInfo); + if (status) { + debug("LsaQueryInformationPolicy Error: %d\n", status); + } else { + + /* Get name in useable format */ + DomainName = AllocStrFromLSAStr(ppdiDomainInfo->Name); + + /* + * Check the Sid pointer, if it is null, the + * workstation is either a stand-alone computer + * or a member of a workgroup. + */ + if (ppdiDomainInfo->Sid) { + + /* + * Member of a domain. Display it in debug mode. + */ + debug("Member of Domain %s\n",DomainName); + } else { + DomainName = NULL; + } + } + } + + /* + * Clean up all the memory buffers created by the LSA and + * Net* APIs. + */ + NetApiBufferFree(pwkiWorkstationInfo); + LsaFreeMemory((LPVOID)ppdiDomainInfo); + } else + debug("NetWkstaGetInfo Error: %d\n", netret); + return DomainName; +} + +const char * +make_challenge(void) +{ + static char ComputerName[MAX_COMPUTERNAME_LENGTH + 1]; + static char * DomainName; + DWORD CNsize = MAX_COMPUTERNAME_LENGTH + 1; + + GetComputerName(ComputerName, &CNsize); + uc(ComputerName); + if ((DomainName=GetDomainName()) == NULL) + return NULL; + uc(DomainName); + debug("ComputerName:%s DomainName: %s",ComputerName,DomainName); + if (init_challenge() > 0) + return NULL; + return ntlm_make_challenge(DomainName, ComputerName, challenge, NONCE_LEN); +} + +int ntlm_errno; +static char credentials[1024]; /* we can afford to waste */ + + +/* Fetches the user's credentials from the challenge. + * Returns NULL if domain or user is not defined + * No identity control is performed. + * WARNING! The result is static storage, shared with ntlm_check_auth + */ +char * +fetch_credentials(ntlm_authenticate * auth, int auth_length) +{ + char *p = credentials; + lstring tmp; + tmp = ntlm_fetch_string((char *) auth, auth_length, &auth->domain); + if (tmp.str == NULL) + return NULL; + memcpy(p, tmp.str, tmp.l); + p += tmp.l; + *p++ = '\\'; + tmp = ntlm_fetch_string((char *) auth, auth_length, &auth->user); + if (tmp.str == NULL) + return NULL; + *(p + tmp.l) = '\0'; + return credentials; +} + +/* returns NULL on failure, or a pointer to + * the user's credentials (domain\\username) + * upon success. WARNING. It's pointing to static storage. + * In case of problem sets as side-effect ntlm_errno to one of the + * codes defined in ntlm.h + */ +char * +ntlm_check_auth(ntlm_authenticate * auth, int auth_length) +{ + int rv; + char pass[25] /*, encrypted_pass[40] */; + char *domain = credentials; + char *user; + lstring tmp; + +/* debug("fetching domain\n"); */ + tmp = ntlm_fetch_string((char *) auth, auth_length, &auth->domain); + if (tmp.str == NULL || tmp.l == 0) { + debug("No domain supplied. Returning no-auth\n"); + ntlm_errno = NTLM_LOGON_ERROR; + return NULL; + } + memcpy(domain, tmp.str, tmp.l); + user = domain + tmp.l; + *user++ = '\0'; + +/* debug("fetching user name\n"); */ + tmp = ntlm_fetch_string((char *) auth, auth_length, &auth->user); + if (tmp.str == NULL || tmp.l == 0) { + debug("No username supplied. Returning no-auth\n"); + ntlm_errno = NTLM_LOGON_ERROR; + return NULL; + } + memcpy(user, tmp.str, tmp.l); + *(user + tmp.l) = '\0'; + + + /* Authenticating against the NT response doesn't seem to work... */ + tmp = ntlm_fetch_string((char *) auth, auth_length, &auth->lmresponse); + if (tmp.str == NULL || tmp.l == 0) { + fprintf(stderr, "No auth at all. Returning no-auth\n"); + ntlm_errno = NTLM_LOGON_ERROR; + return NULL; + } + + memcpy(pass, tmp.str, tmp.l); + pass[25] = '\0'; + +#if 1 + debug ("Empty LM pass detection: user: '%s', ours:'%s', his: '%s'" + "(length: %d)\n", + user,lmencoded_empty_pass,tmp.str,tmp.l); + if (memcmp(tmp.str,lmencoded_empty_pass,ENCODED_PASS_LEN)==0) { + fprintf(stderr,"Empty LM password supplied for user %s\\%s. " + "No-auth\n",domain,user); + ntlm_errno=NTLM_LOGON_ERROR; + return NULL; + } + + tmp = ntlm_fetch_string ((char *) auth, auth_length, &auth->ntresponse); + if (tmp.str != NULL && tmp.l != 0) { + debug ("Empty NT pass detection: user: '%s', ours:'%s', his: '%s'" + "(length: %d)\n", + user,ntencoded_empty_pass,tmp.str,tmp.l); + if (memcmp(tmp.str,lmencoded_empty_pass,ENCODED_PASS_LEN)==0) { + fprintf(stderr,"Empty NT password supplied for user %s\\%s. " + "No-auth\n",domain,user); + ntlm_errno=NTLM_LOGON_ERROR; + return NULL; + } + } +#endif + + /* TODO: check against empty password!!!!! */ + + + + debug("checking domain: '%s', user: '%s', pass='%s'\n", domain, user, pass); + rv = SSPLogonUser(user, pass, domain); + + debug("Login attempt had result %d\n", rv); + + if (!rv) { /* failed */ + ntlm_errno = ss; + return NULL; + } + *(user - 1) = '\\'; /* hack. Performing, but ugly. */ + + if (UseAllowedGroup) { + if (!Valid_Group(credentials, NTAllowedGroup)) { + ntlm_errno = NTLM_BAD_NTGROUP; + debug("User %s not in allowed Group %s\n", credentials, NTAllowedGroup); + return NULL; + } + } + if (UseDisallowedGroup) { + if (Valid_Group(credentials, NTDisAllowedGroup)) { + ntlm_errno = NTLM_BAD_NTGROUP; + debug("User %s is in denied Group %s\n", credentials, NTDisAllowedGroup); + return NULL; + } + } + + debug("credentials: %s\n", credentials); + return credentials; +} --- /dev/null Wed Feb 14 01:00:00 2007 +++ squid/helpers/ntlm_auth/NTLMSSP-WIN32/ntlm.h Wed Feb 14 01:00:02 2007 @@ -0,0 +1,116 @@ +/* + * (C) 2002 Guido Serassio + * Based on previous work of Francesco Chemolli, Robert Collins and Andrew Doran + * + * Distributed freely under the terms of the GNU General Public License, + * version 2. See the file COPYING for licensing details + * + * 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 "sspwin32.h" +#include +#include +#include +#include "ntlmauth.h" +#undef debug + +/************* CONFIGURATION ***************/ +/* + * define this if you want debugging + */ +#ifdef _SQUID_MSWIN_ +#ifdef _DEBUG +#define DEBUG +#endif +#else +#ifndef DEBUG +#define DEBUG +#endif +#endif + +#define DEAD_DC_RETRY_INTERVAL 30 + +/************* END CONFIGURATION ***************/ + +#include + +/* Debugging stuff */ + +#ifdef __GNUC__ /* this is really a gcc-ism */ +#ifdef DEBUG +#include +#include +static char *__foo; +extern char debug_enabled; +#define debug(X...) if (debug_enabled) { \ + fprintf(stderr,"ntlm-auth[%d](%s:%d): ", getpid(), \ + ((__foo=strrchr(__FILE__,'/'))==NULL?__FILE__:__foo+1),\ + __LINE__);\ + fprintf(stderr,X); } +#else /* DEBUG */ +#define debug(X...) /* */ +#endif /* DEBUG */ +#else /* __GNUC__ */ +extern char debug_enabled; +static void +debug(char *format,...) +{ +#ifdef DEBUG +#ifdef _SQUID_MSWIN_ + if (debug_enabled) { + va_list args; + + va_start(args,format); + fprintf(stderr, "ntlm-auth[%d]: ",getpid()); + vfprintf(stderr, format, args); + fprintf(stderr, "\n"); + va_end(args); + } +#endif /* _SQUID_MSWIN_ */ +#endif /* DEBUG */ +} +#endif /* __GNUC__ */ + + +/* A couple of harmless helper macros */ +#define SEND(X) debug("sending '%s' to squid\n",X); printf(X "\n"); +#ifdef __GNUC__ +#define SEND2(X,Y...) debug("sending '" X "' to squid\n",Y); printf(X "\n",Y); +#else +/* no gcc, no debugging. varargs macros are a gcc extension */ +#define SEND2(X,Y) debug("sending '" X "' to squid\n",Y); printf(X "\n",Y); +#endif + +extern char * NTAllowedGroup; +extern char * NTDisAllowedGroup; +extern int UseDisallowedGroup; +extern int UseAllowedGroup; +extern int ntlm_errno; + +#define NTLM_NO_ERROR SEC_E_OK +#define NTLM_SERVER_ERROR SEC_E_NOT_SUPPORTED +#define NTLM_PROTOCOL_ERROR SEC_E_INCOMPLETE_MESSAGE +#define NTLM_LOGON_ERROR SEC_E_LOGON_DENIED +#define NTLM_UNTRUSTED_DOMAIN SEC_E_NO_AUTHENTICATING_AUTHORITY +#define NTLM_BAD_PROTOCOL SEC_E_BAD_PKGID +#define NTLM_NOT_CONNECTED SEC_E_SECPKG_NOT_FOUND +#define NTLM_BAD_NTGROUP -1 + +extern void uc(char *); + +const char *make_challenge(void); +extern char *ntlm_check_auth(ntlm_authenticate * auth, int auth_length); +extern char *fetch_credentials(ntlm_authenticate * auth, int auth_length); + +#endif /* _NTLM_H_ */ --- /dev/null Wed Feb 14 01:00:00 2007 +++ squid/helpers/ntlm_auth/NTLMSSP-WIN32/ntlm_auth.c Wed Feb 14 01:00:02 2007 @@ -0,0 +1,290 @@ +/* + * (C) 2002 Guido Serassio + * Based on previous work of Francesco Chemolli and Robert Collins + * Distributed freely under the terms of the GNU General Public License, + * version 2. See the file COPYING for licensing details + * + * 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. + * + */ + + +#include "squid.h" +#include "ntlm.h" + +#define BUFFER_SIZE 10240 + + +#ifdef DEBUG +char error_messages_buffer[BUFFER_SIZE]; +#endif + +char load_balance = 0, protocol_pedantic = 0; +#ifdef NTLM_FAIL_OPEN +char last_ditch_enabled = 0; +#endif + +char debug_enabled=0; + + +char * NTAllowedGroup; +char * NTDisAllowedGroup; +int UseDisallowedGroup = 0; +int UseAllowedGroup = 0; + +/* makes a null-terminated string upper-case. Changes CONTENTS! */ +void +uc(char *string) +{ + char *p = string, c; + while ((c = *p)) { + *p = toupper(c); + p++; + } +} + +/* 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++; + } +} + + +void +send_bh_or_ld(char *bhmessage, ntlm_authenticate * failedauth, int authlen) +{ +#ifdef NTLM_FAIL_OPEN + char *creds = NULL; + if (last_ditch_enabled) { + creds = fetch_credentials(failedauth, authlen); + if (creds) { + lc(creds); + SEND2("LD %s", creds); + } else { + SEND("NA last-ditch on, but no credentials"); + } + } else { +#endif + SEND2("BH %s", bhmessage); +#ifdef NTLM_FAIL_OPEN + } +#endif +} + +/* + * options: + * -v enables debugging statements if DEBUG was defined at build-time. + * -l if specified, changes behavior on failures to last-ditch. + * -a can specify a Windows Local Group name allowed to authenticate. + * -d can specify a Windows Local Group name not allowed to authenticate. + * domain\controller ... + */ +char *my_program_name = NULL; + +void +usage() +{ + fprintf(stderr, +#ifdef NTLM_FAIL_OPEN + "%s usage:\n%s [-v] [-a UserGroup] [-d UserGroup] [-l]\n" +#else + "%s usage:\n%s [-v] [-a UserGroup] [-d UserGroup]\n" +#endif + "-v enables verbose debugging statements if DEBUG was defined at build-time.\n" +#ifdef NTLM_FAIL_OPEN + "-l if specified, changes behavior on failures to last-ditch.\n" +#endif + "-a can specify a Windows Local Group name allowed to authenticate.\n" + "-d can specify a Windows Local Group name not allowed to authenticate.\n\n", + my_program_name, my_program_name); +} + + +void +process_options(int argc, char *argv[]) +{ + int opt, had_error = 0; +#ifdef NTLM_FAIL_OPEN + while (-1 != (opt = getopt(argc, argv, "vla:d:"))) { +#else + while (-1 != (opt = getopt(argc, argv, "va:d:"))) { +#endif + switch (opt) { + case 'a': + safe_free(NTAllowedGroup); + NTAllowedGroup=xstrdup(optarg); + UseAllowedGroup = 1; + break; + case 'd': + safe_free(NTDisAllowedGroup); + NTDisAllowedGroup=xstrdup(optarg); + UseDisallowedGroup = 1; + break; +#ifdef NTLM_FAIL_OPEN + case 'l': + last_ditch_enabled = 1; + break; +#endif + case 'v': + debug_enabled=1; + break; + default: + fprintf(stderr, "unknown option: -%c. Exiting\n", opt); + usage(); + had_error = 1; + } + } + if (had_error) + exit(1); +} + +/* tries connecting to the domain controllers in the "controllers" ring, + * with failover if the adequate option is specified. + */ +const char * +obtain_challenge() +{ + int j = 0; + const char *ch = NULL; + + debug("attempting challenge retrieval\n"); + ch = make_challenge(); + debug("make_challenge returned %p\n", ch); + if (ch) { + debug("Got it\n"); + return ch; /* All went OK, returning */ + } + return NULL; +} + + +void +manage_request() +{ + ntlmhdr *fast_header; + char buf[BUFFER_SIZE]; + const char *ch; + char *ch2, *decoded, *cred; + int plen; + + if (fgets(buf, BUFFER_SIZE, stdin) == NULL) { + debug("fgets() failed! dying..... errno=%d (%s)\n", errno, + strerror(errno)); + exit(1); /* BIIG buffer */ + } + debug("managing request\n"); + ch2 = memchr(buf, '\n', BUFFER_SIZE); /* safer against overrun than strchr */ + if (ch2) { + *ch2 = '\0'; /* terminate the string at newline. */ + ch = ch2; + } + debug("ntlm authenticator. Got '%s' from Squid\n", buf); + + if (memcmp(buf, "KK ", 3) == 0) { /* authenticate-request */ + /* figure out what we got */ + decoded = base64_decode(buf + 3); + /* Note: we don't need to manage memory at this point, since + * base64_decode returns a pointer to static storage. + */ + + if (!decoded) { /* decoding failure, return error */ + SEND("NA Packet format error, couldn't base64-decode"); + return; + } + /* fast-track-decode request type. */ + fast_header = (struct _ntlmhdr *) decoded; + + /* sanity-check: it IS a NTLMSSP packet, isn't it? */ + if (memcmp(fast_header->signature, "NTLMSSP", 8) != 0) { + SEND("NA Broken authentication packet"); + return; + } + switch (fast_header->type) { + case NTLM_NEGOTIATE: + SEND("NA Invalid negotiation request received"); + return; + /* notreached */ + case NTLM_CHALLENGE: + SEND + ("NA Got a challenge. We refuse to have our authority disputed"); + return; + /* notreached */ + case NTLM_AUTHENTICATE: + /* check against SSPI */ + plen = strlen(buf) * 3 / 4; /* we only need it here. Optimization */ + cred = ntlm_check_auth((ntlm_authenticate *) decoded, plen); + if (cred == NULL) { + switch (ntlm_errno) { + case NTLM_LOGON_ERROR: + SEND("NA Logon Failure"); + return; + case NTLM_BAD_NTGROUP: + SEND("NA Incorrect Group Membership"); + return; + case NTLM_UNTRUSTED_DOMAIN: + SEND("NA No authority could be contacted for authentication"); + return; + default: + SEND("NA SSPI Error"); + return; + } + } + lc(cred); /* let's lowercase them for our convenience */ + SEND2("AF %s", cred); + return; + default: + SEND("BH unknown authentication packet type"); + return; + } + return; + } + if (memcmp(buf, "YR", 2) == 0) { /* refresh-request */ + ch = obtain_challenge(); + SEND2("TT %s", ch); + return; + } + SEND("BH Helper detected protocol error"); + return; +/********* END ********/ +} + +int +main(int argc, char *argv[]) +{ + + debug("ntlm_auth build " __DATE__ ", " __TIME__ " starting up...\n"); + + my_program_name = argv[0]; + process_options(argc, argv); + debug("options processed OK\n"); + srand( (unsigned)time( NULL ) ); + + if (LoadSecurityDll(SSP_NTLM) == NULL) { + fprintf(stderr, "FATAL, can't initialize SSPI, exiting.\n"); + exit(1); + } + debug("SSPI initialized OK\n"); + + atexit(UnloadSecurityDll); + + /* initialize FDescs */ + setbuf(stdout, NULL); + setbuf(stderr, NULL); + + while (1) { + manage_request(); + } + return 0; +} --- /dev/null Wed Feb 14 01:00:00 2007 +++ squid/helpers/ntlm_auth/NTLMSSP-WIN32/readme.txt Wed Feb 14 01:00:02 2007 @@ -0,0 +1,31 @@ +ntlm_auth.exe + +Native Windows NTLM authenticator for Squid 2.5 + +Usage: + +ntlm_auth [-v] [-a UserGroup] [-d UserGroup] [-l] + +-v enables debugging statements if DEBUG was defined at build-time. +-l if specified, changes behavior on failures to last-ditch. +-a can specify a Windows Local Group name allowed to authenticate. +-d can specify a Windows Local Group name not allowed to authenticate. + +This is released under the GNU General Public License + + +Allowing Users + +Users that are allowed to access the web proxy must have the Windows NT +User Rights "logon from the network" and must be included in the NT LOCAL User Groups +specified in the Authenticator's command line. +This can be accomplished creating a local user group on the NT machine, grant the privilege, +and adding users to it. + +Refer to Squid documentation for the required changes to squid.conf. + + +Contact details - + +To contact the maintainer of this package, e-mail on squidnt@serassio.it. +The latest version may be found on http://www.serassio.it/SquidNT.htm.