--------------------- PatchSet 4055 Date: 2002/04/21 20:35:06 Author: serassio Branch: nt-2_5 Tag: (none) Log: Added WIN32 native NTLM authenticator Members: port/win32/squid.dsw:1.1.2.9->1.1.2.10 port/win32/update.cmd:1.1.2.4->1.1.2.5 port/win32/include/autoconf.h:1.1.2.6->1.1.2.7 port/win32/ntlm_win32_auth/.cvsignore:1.1->1.1.2.1 port/win32/ntlm_win32_auth/ntlm_win32_auth.dsp:1.1->1.1.2.1 src/auth/ntlm/helpers/NTLMSSP-WIN32/.cvsignore:1.1->1.1.2.1 src/auth/ntlm/helpers/NTLMSSP-WIN32/Makefile.am:1.1->1.1.2.1 src/auth/ntlm/helpers/NTLMSSP-WIN32/libntlmssp.c:1.1->1.1.2.1 src/auth/ntlm/helpers/NTLMSSP-WIN32/libsspwin32.c:1.1->1.1.2.1 src/auth/ntlm/helpers/NTLMSSP-WIN32/ntlm.h:1.1->1.1.2.1 src/auth/ntlm/helpers/NTLMSSP-WIN32/ntlm_auth.c:1.1->1.1.2.1 Index: squid/port/win32/squid.dsw =================================================================== RCS file: /cvsroot/squid-sf//squid/port/win32/Attic/squid.dsw,v retrieving revision 1.1.2.9 retrieving revision 1.1.2.10 diff -u -r1.1.2.9 -r1.1.2.10 --- squid/port/win32/squid.dsw 13 Apr 2002 17:11:41 -0000 1.1.2.9 +++ squid/port/win32/squid.dsw 21 Apr 2002 20:37:34 -0000 1.1.2.10 @@ -264,6 +264,24 @@ ############################################################################### +Project: "ntlm_win32_auth"=".\ntlm_win32_auth\ntlm_win32_auth.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name libntlmauth + End Project Dependency + Begin Project Dependency + Project_Dep_Name libmiscutil + End Project Dependency +}}} + +############################################################################### + Project: "pinger"=".\pinger\pinger.dsp" - Package Owner=<4> Package=<5> @@ -356,6 +374,9 @@ Begin Project Dependency Project_Dep_Name NCSA_auth End Project Dependency + Begin Project Dependency + Project_Dep_Name ntlm_win32_auth + End Project Dependency }}} ############################################################################### Index: squid/port/win32/update.cmd =================================================================== RCS file: /cvsroot/squid-sf//squid/port/win32/Attic/update.cmd,v retrieving revision 1.1.2.4 retrieving revision 1.1.2.5 diff -u -r1.1.2.4 -r1.1.2.5 --- squid/port/win32/update.cmd 13 Apr 2002 17:11:41 -0000 1.1.2.4 +++ squid/port/win32/update.cmd 21 Apr 2002 20:37:34 -0000 1.1.2.5 @@ -8,6 +8,7 @@ copy %0\..\fake_auth\%1\fake_auth.exe %2\libexec\fake_auth.exe copy %0\..\nt_auth\%1\nt_auth.exe %2\libexec\nt_auth.exe copy %0\..\ncsa_auth\%1\ncsa_auth.exe %2\libexec\ncsa_auth.exe +copy %0\..\ntlm_win32_auth\%1\ntlm_win32_auth.exe %2\libexec\ntlm_win32_auth.exe copy %0\..\ldap_auth\%1\ldap_auth.exe %2\libexec\ldap_auth.exe rem copy %0\..\..\contrib\htpasswd\%1\htpasswd.exe %2\htpasswd.exe copy %0\..\cachemgr\%1\cachemgr.exe %2\libexec\cachemgr.exe Index: squid/port/win32/include/autoconf.h =================================================================== RCS file: /cvsroot/squid-sf//squid/port/win32/include/Attic/autoconf.h,v retrieving revision 1.1.2.6 retrieving revision 1.1.2.7 diff -u -r1.1.2.6 -r1.1.2.7 --- squid/port/win32/include/autoconf.h 9 Apr 2002 19:04:42 -0000 1.1.2.6 +++ squid/port/win32/include/autoconf.h 21 Apr 2002 20:37:34 -0000 1.1.2.7 @@ -22,7 +22,7 @@ * */ -/* $Id: autoconf.h,v 1.1.2.6 2002/04/09 19:04:42 serassio Exp $ */ +/* $Id: autoconf.h,v 1.1.2.7 2002/04/21 20:37:34 serassio Exp $ */ /* * configure command line used to configure Squid @@ -907,7 +907,7 @@ #define STDC_HEADERS 1 /* Version number of package */ -#define VERSION "2.5.PRE5-CVS" +#define VERSION "2.5.PRE6-CVS" /* Define if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel and VAX). */ --- /dev/null Wed Feb 14 00:55:47 2007 +++ squid/port/win32/ntlm_win32_auth/.cvsignore Wed Feb 14 00:58:16 2007 @@ -0,0 +1,3 @@ +.cvsignore +Debug +Release --- /dev/null Wed Feb 14 00:55:47 2007 +++ squid/port/win32/ntlm_win32_auth/ntlm_win32_auth.dsp Wed Feb 14 00:58:16 2007 @@ -0,0 +1,112 @@ +# Microsoft Developer Studio Project File - Name="ntlm_win32_auth" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=ntlm_win32_auth - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ntlm_win32_auth.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ntlm_win32_auth.mak" CFG="ntlm_win32_auth - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ntlm_win32_auth - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "ntlm_win32_auth - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ntlm_win32_auth - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../../include" /I "../../../src" /I "../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x410 /d "NDEBUG" +# ADD RSC /l 0x410 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "ntlm_win32_auth - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../../include" /I "../../../src" /I "../include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x410 /d "_DEBUG" +# ADD RSC /l 0x410 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "ntlm_win32_auth - Win32 Release" +# Name "ntlm_win32_auth - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE="..\..\..\src\auth\ntlm\helpers\NTLMSSP-WIN32\libntlmssp.c" +# End Source File +# Begin Source File + +SOURCE="..\..\..\src\auth\ntlm\helpers\NTLMSSP-WIN32\libsspwin32.c" +# End Source File +# Begin Source File + +SOURCE="..\..\..\src\auth\ntlm\helpers\NTLMSSP-WIN32\ntlm_auth.c" +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE="..\..\..\src\auth\ntlm\helpers\NTLMSSP-WIN32\ntlm.h" +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project --- /dev/null Wed Feb 14 00:55:47 2007 +++ squid/src/auth/ntlm/helpers/NTLMSSP-WIN32/.cvsignore Wed Feb 14 00:58:16 2007 @@ -0,0 +1,2 @@ +.cvsignore +Makefile.in --- /dev/null Wed Feb 14 00:55:47 2007 +++ squid/src/auth/ntlm/helpers/NTLMSSP-WIN32/Makefile.am Wed Feb 14 00:58:16 2007 @@ -0,0 +1,14 @@ +# +# Makefile for the Squid Object Cache server +# +# $Id: Makefile.am,v 1.1.2.1 2002/04/21 20:35:06 serassio Exp $ +# + +SUBDIRS = smbval + +libexec_PROGRAMS = ntlm_auth +ntlm_auth_SOURCES = libntlmssp.c ntlm_auth.c ntlm.h +INCLUDES = -I. -I$(top_builddir)/include -I$(top_srcdir)/include \ + -I$(top_srcdir)/src/ -I$(srcdir)/smbval +LDADD = smbval/libsmbvalid.a -L$(top_builddir)/lib -lntlmauth \ + -lmiscutil $(CRYPTLIB) $(XTRA_LIBS) --- /dev/null Wed Feb 14 00:55:47 2007 +++ squid/src/auth/ntlm/helpers/NTLMSSP-WIN32/libntlmssp.c Wed Feb 14 00:58:16 2007 @@ -0,0 +1,213 @@ +/* + * (C) 2000 Francesco Chemolli + * 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" + +#ifdef DEBUG +#define debug_dump_ntlmssp_flags dump_ntlmssp_flags +#else /* DEBUG */ +#define debug_dump_ntlmssp_flags(X) /* empty */ +#endif /* DEBUG */ + +static char REGKEY[256]="SYSTEM\\CurrentControlSet\\Services\\Netlogon\\JoinDomain"; +#define DOMAINNAME "DomainName" + +extern SECURITY_STATUS ss; + +#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 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 * GetDomainName(void) + +{ + HKEY hndKey; + static char * DomainName; + + safe_free(DomainName); + if (RegOpenKey(HKEY_LOCAL_MACHINE, REGKEY, &hndKey) == ERROR_SUCCESS) { + DWORD Type = 0; + DWORD Size = 0; + LONG Result; + Result = + RegQueryValueEx(hndKey, DOMAINNAME, NULL, &Type, NULL, &Size); + if (Result == ERROR_SUCCESS && Size) { + DomainName = xmalloc(Size); + RegQueryValueEx(hndKey, DOMAINNAME, NULL, &Type, DomainName, &Size); + } else + return NULL; + } else + return NULL; + 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. */ + + debug("credentials: %s\n", credentials); + return credentials; +} --- /dev/null Wed Feb 14 00:55:47 2007 +++ squid/src/auth/ntlm/helpers/NTLMSSP-WIN32/libsspwin32.c Wed Feb 14 00:58:16 2007 @@ -0,0 +1,454 @@ + /////////////////////////////////////////////////////////////////////////////// + // + // SSPI Authentication Sample + // + // This program demonstrates how to use SSPI to authenticate user credentials. + // + // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF + // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED + // TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A + // PARTICULAR PURPOSE. + // + // Copyright (C) 2001. Microsoft Corporation. All rights reserved. + /////////////////////////////////////////////////////////////////////////////// + +#include "squid.h" +#include "ntlm.h" +#include + +typedef struct _AUTH_SEQ { + BOOL fInitialized; + BOOL fHaveCredHandle; + BOOL fHaveCtxtHandle; + CredHandle hcred; + struct _SecHandle hctxt; +} AUTH_SEQ, *PAUTH_SEQ; + +static HMODULE hModule = NULL; +SECURITY_STATUS ss = SEC_E_OK; + +// Function pointers +ACCEPT_SECURITY_CONTEXT_FN _AcceptSecurityContext = NULL; +ACQUIRE_CREDENTIALS_HANDLE_FN _AcquireCredentialsHandle = NULL; +COMPLETE_AUTH_TOKEN_FN _CompleteAuthToken = NULL; +DELETE_SECURITY_CONTEXT_FN _DeleteSecurityContext = NULL; +FREE_CONTEXT_BUFFER_FN _FreeContextBuffer = NULL; +FREE_CREDENTIALS_HANDLE_FN _FreeCredentialsHandle = NULL; +INITIALIZE_SECURITY_CONTEXT_FN _InitializeSecurityContext = NULL; +QUERY_SECURITY_PACKAGE_INFO_FN _QuerySecurityPackageInfo = NULL; + +/////////////////////////////////////////////////////////////////////////////// + +void UnloadSecurityDll(void) +{ + if (hModule) + FreeLibrary(hModule); + + _AcceptSecurityContext = NULL; + _AcquireCredentialsHandle = NULL; + _CompleteAuthToken = NULL; + _DeleteSecurityContext = NULL; + _FreeContextBuffer = NULL; + _FreeCredentialsHandle = NULL; + _InitializeSecurityContext = NULL; + _QuerySecurityPackageInfo = NULL; + hModule = NULL; +} + +/////////////////////////////////////////////////////////////////////////////// + +HMODULE LoadSecurityDll(void) +{ + BOOL fAllFunctionsLoaded = FALSE; + TCHAR lpszDLL[MAX_PATH]; + OSVERSIONINFO VerInfo; + + // + // Find out which security DLL to use, depending on + // whether we are on NT or Win95 or 2000 or XP or .NET Server + // We have to use security.dll on Windows NT 4.0. + // All other operating systems, we have to use Secur32.dll + // + VerInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); + if (!GetVersionEx (&VerInfo)) // If this fails, something has gone wrong + { + return FALSE; + } + + if (VerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT && + VerInfo.dwMajorVersion == 4 && + VerInfo.dwMinorVersion == 0) + { + lstrcpy (lpszDLL, _T(WINNT_SECURITY_DLL)); + } + else + { + lstrcpy (lpszDLL, _T(WIN9X_SECURITY_DLL)); + } + + hModule = LoadLibrary(lpszDLL); + if (!hModule) + return hModule; + + __try { + + _AcceptSecurityContext = (ACCEPT_SECURITY_CONTEXT_FN) + GetProcAddress(hModule, "AcceptSecurityContext"); + if (!_AcceptSecurityContext) + __leave; + +#ifdef UNICODE + _AcquireCredentialsHandle = (ACQUIRE_CREDENTIALS_HANDLE_FN) + GetProcAddress(hModule, "AcquireCredentialsHandleW"); +#else + _AcquireCredentialsHandle = (ACQUIRE_CREDENTIALS_HANDLE_FN) + GetProcAddress(hModule, "AcquireCredentialsHandleA"); +#endif + if (!_AcquireCredentialsHandle) + __leave; + + // CompleteAuthToken is not present on Windows 9x Secur32.dll + // Do not check for the availablity of the function if it is NULL; + _CompleteAuthToken = (COMPLETE_AUTH_TOKEN_FN) + GetProcAddress(hModule, "CompleteAuthToken"); + + _DeleteSecurityContext = (DELETE_SECURITY_CONTEXT_FN) + GetProcAddress(hModule, "DeleteSecurityContext"); + if (!_DeleteSecurityContext) + __leave; + + _FreeContextBuffer = (FREE_CONTEXT_BUFFER_FN) + GetProcAddress(hModule, "FreeContextBuffer"); + if (!_FreeContextBuffer) + __leave; + + _FreeCredentialsHandle = (FREE_CREDENTIALS_HANDLE_FN) + GetProcAddress(hModule, "FreeCredentialsHandle"); + if (!_FreeCredentialsHandle) + __leave; + +#ifdef UNICODE + _InitializeSecurityContext = (INITIALIZE_SECURITY_CONTEXT_FN) + GetProcAddress(hModule, "InitializeSecurityContextW"); +#else + _InitializeSecurityContext = (INITIALIZE_SECURITY_CONTEXT_FN) + GetProcAddress(hModule, "InitializeSecurityContextA"); +#endif + if (!_InitializeSecurityContext) + __leave; + +#ifdef UNICODE + _QuerySecurityPackageInfo = (QUERY_SECURITY_PACKAGE_INFO_FN) + GetProcAddress(hModule, "QuerySecurityPackageInfoW"); +#else + _QuerySecurityPackageInfo = (QUERY_SECURITY_PACKAGE_INFO_FN) + GetProcAddress(hModule, "QuerySecurityPackageInfoA"); +#endif + if (!_QuerySecurityPackageInfo) + __leave; + + fAllFunctionsLoaded = TRUE; + + } __finally { + + if (!fAllFunctionsLoaded) { + UnloadSecurityDll(); + hModule = NULL; + } + + } + return hModule; +} + + /////////////////////////////////////////////////////////////////////////////// + +BOOL GenClientContext(PAUTH_SEQ pAS, PSEC_WINNT_AUTH_IDENTITY pAuthIdentity, + PVOID pIn, DWORD cbIn, PVOID pOut, PDWORD pcbOut, PBOOL pfDone) { + + /*++ + + Routine Description: + + Optionally takes an input buffer coming from the server and returns + a buffer of information to send back to the server. Also returns + an indication of whether or not the context is complete. + + Return Value: + + Returns TRUE if successful; otherwise FALSE. + + --*/ + + TimeStamp tsExpiry; + SecBufferDesc sbdOut; + SecBuffer sbOut; + SecBufferDesc sbdIn; + SecBuffer sbIn; + ULONG fContextAttr; + + if (!pAS->fInitialized) { + + ss = _AcquireCredentialsHandle(NULL, _T(NTLM_PACKAGE_NAME), + SECPKG_CRED_OUTBOUND, NULL, NULL, NULL, NULL, + &pAS->hcred, &tsExpiry); + if (ss < 0) { + fprintf(stderr, "AcquireCredentialsHandle failed with %08X\n", ss); + return FALSE; + } + + pAS->fHaveCredHandle = TRUE; + } + + // Prepare output buffer + sbdOut.ulVersion = 0; + sbdOut.cBuffers = 1; + sbdOut.pBuffers = &sbOut; + + sbOut.cbBuffer = *pcbOut; + sbOut.BufferType = SECBUFFER_TOKEN; + sbOut.pvBuffer = pOut; + + // Prepare input buffer + if (pAS->fInitialized) { + sbdIn.ulVersion = 0; + sbdIn.cBuffers = 1; + sbdIn.pBuffers = &sbIn; + + sbIn.cbBuffer = cbIn; + sbIn.BufferType = SECBUFFER_TOKEN; + sbIn.pvBuffer = pIn; + } + + ss = _InitializeSecurityContext(&pAS->hcred, + pAS->fInitialized ? &pAS->hctxt : NULL, NULL, 0, 0, + SECURITY_NATIVE_DREP, pAS->fInitialized ? &sbdIn : NULL, + 0, &pAS->hctxt, &sbdOut, &fContextAttr, &tsExpiry); + if (ss < 0) { + // + fprintf(stderr, "InitializeSecurityContext failed with %08X\n", ss); + return FALSE; + } + + pAS->fHaveCtxtHandle = TRUE; + + // If necessary, complete token + if (ss == SEC_I_COMPLETE_NEEDED || ss == SEC_I_COMPLETE_AND_CONTINUE) { + + if (_CompleteAuthToken) { + ss = _CompleteAuthToken(&pAS->hctxt, &sbdOut); + if (ss < 0) { + fprintf(stderr, "CompleteAuthToken failed with %08X\n", ss); + return FALSE; + } + } + else { + fprintf (stderr, "CompleteAuthToken not supported.\n"); + return FALSE; + } + } + + *pcbOut = sbOut.cbBuffer; + + if (!pAS->fInitialized) + pAS->fInitialized = TRUE; + + *pfDone = !(ss == SEC_I_CONTINUE_NEEDED + || ss == SEC_I_COMPLETE_AND_CONTINUE ); + + return TRUE; + } + + /////////////////////////////////////////////////////////////////////////////// + + BOOL GenServerContext(PAUTH_SEQ pAS, PVOID pIn, DWORD cbIn, PVOID pOut, + PDWORD pcbOut, PBOOL pfDone) { + + /*++ + + Routine Description: + + Takes an input buffer coming from the client and returns a buffer + to be sent to the client. Also returns an indication of whether or + not the context is complete. + + Return Value: + + Returns TRUE if successful; otherwise FALSE. + + --*/ + + TimeStamp tsExpiry; + SecBufferDesc sbdOut; + SecBuffer sbOut; + SecBufferDesc sbdIn; + SecBuffer sbIn; + ULONG fContextAttr; + + if (!pAS->fInitialized) { + + ss = _AcquireCredentialsHandle(NULL, _T("NTLM"), + SECPKG_CRED_INBOUND, NULL, NULL, NULL, NULL, &pAS->hcred, + &tsExpiry); + if (ss < 0) { + fprintf(stderr, "AcquireCredentialsHandle failed with %08X\n", ss); + return FALSE; + } + + pAS->fHaveCredHandle = TRUE; + } + + // Prepare output buffer + sbdOut.ulVersion = 0; + sbdOut.cBuffers = 1; + sbdOut.pBuffers = &sbOut; + + sbOut.cbBuffer = *pcbOut; + sbOut.BufferType = SECBUFFER_TOKEN; + sbOut.pvBuffer = pOut; + + // Prepare input buffer + sbdIn.ulVersion = 0; + sbdIn.cBuffers = 1; + sbdIn.pBuffers = &sbIn; + + sbIn.cbBuffer = cbIn; + sbIn.BufferType = SECBUFFER_TOKEN; + sbIn.pvBuffer = pIn; + + ss = _AcceptSecurityContext(&pAS->hcred, + pAS->fInitialized ? &pAS->hctxt : NULL, &sbdIn, ASC_REQ_DELEGATE, + SECURITY_NATIVE_DREP, &pAS->hctxt, &sbdOut, &fContextAttr, + &tsExpiry); + if (ss < 0) { + fprintf(stderr, "AcceptSecurityContext failed with %08X\n", ss); + return FALSE; + } + + pAS->fHaveCtxtHandle = TRUE; + + // If necessary, complete token + if (ss == SEC_I_COMPLETE_NEEDED || ss == SEC_I_COMPLETE_AND_CONTINUE) { + + if (_CompleteAuthToken) { + ss = _CompleteAuthToken(&pAS->hctxt, &sbdOut); + if (ss < 0) { + fprintf(stderr, "CompleteAuthToken failed with %08X\n", ss); + return FALSE; + } + } + else { + fprintf (stderr, "CompleteAuthToken not supported.\n"); + return FALSE; + } + } + + *pcbOut = sbOut.cbBuffer; + + if (!pAS->fInitialized) + pAS->fInitialized = TRUE; + + *pfDone = !(ss = SEC_I_CONTINUE_NEEDED + || ss == SEC_I_COMPLETE_AND_CONTINUE); + + return TRUE; + } + + +BOOL WINAPI SSPLogonUser(PTSTR szUser, PTSTR szPassword, PTSTR szDomain) +{ + AUTH_SEQ asServer = {0}; + AUTH_SEQ asClient = {0}; + BOOL fDone = FALSE; + BOOL fResult = FALSE; + DWORD cbOut = 0; + DWORD cbIn = 0; + DWORD cbMaxToken = 0; + PVOID pClientBuf = NULL; + PVOID pServerBuf = NULL; + PSecPkgInfo pSPI = NULL; + + SEC_WINNT_AUTH_IDENTITY ai; + + __try { + if (!hModule) + __leave; + + // Get max token size + _QuerySecurityPackageInfo(_T("NTLM"), &pSPI); + cbMaxToken = pSPI->cbMaxToken; + _FreeContextBuffer(pSPI); + + // Allocate buffers for client and server messages + pClientBuf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbMaxToken); + pServerBuf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbMaxToken); + + // Initialize auth identity structure + ZeroMemory(&ai, sizeof(ai)); + ai.Domain = szDomain; + ai.DomainLength = lstrlen(szDomain); + ai.User = szUser; + ai.UserLength = lstrlen(szUser); + ai.Password = szPassword; + ai.PasswordLength = lstrlen(szPassword); +#if defined(UNICODE) || defined(_UNICODE) + ai.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; +#else + ai.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; +#endif + + // Prepare client message (negotiate) . + cbOut = cbMaxToken; + if (!GenClientContext(&asClient, &ai, NULL, 0, pClientBuf, &cbOut, &fDone)) + __leave; + + // Prepare server message (challenge) . + cbIn = cbOut; + cbOut = cbMaxToken; + if (!GenServerContext(&asServer, pClientBuf, cbIn, pServerBuf, &cbOut, + &fDone)) + __leave; + // Most likely failure: AcceptServerContext fails with SEC_E_LOGON_DENIED + // in the case of bad szUser or szPassword. + // Unexpected Result: Logon will succeed if you pass in a bad szUser and + // the guest account is enabled in the specified domain. + + // Prepare client message (authenticate) . + cbIn = cbOut; + cbOut = cbMaxToken; + if (!GenClientContext(&asClient, &ai, pServerBuf, cbIn, pClientBuf, &cbOut, + &fDone)) + __leave; + + // Prepare server message (authentication) . + cbIn = cbOut; + cbOut = cbMaxToken; + if (!GenServerContext(&asServer, pClientBuf, cbIn, pServerBuf, &cbOut, + &fDone)) + __leave; + + fResult = TRUE; + + } __finally { + + // Clean up resources + if (asClient.fHaveCtxtHandle) + _DeleteSecurityContext(&asClient.hctxt); + + if (asClient.fHaveCredHandle) + _FreeCredentialsHandle(&asClient.hcred); + + if (asServer.fHaveCtxtHandle) + _DeleteSecurityContext(&asServer.hctxt); + + if (asServer.fHaveCredHandle) + _FreeCredentialsHandle(&asServer.hcred); + + + HeapFree(GetProcessHeap(), 0, pClientBuf); + HeapFree(GetProcessHeap(), 0, pServerBuf); + + } + + return fResult; + } + --- /dev/null Wed Feb 14 00:55:47 2007 +++ squid/src/auth/ntlm/helpers/NTLMSSP-WIN32/ntlm.h Wed Feb 14 00:58:16 2007 @@ -0,0 +1,113 @@ +/* + * (C) 2000 Francesco Chemolli , + * inspired by previous work by 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_ +#define SECURITY_WIN32 +#define NTLM_PACKAGE_NAME "NTLM" + +#include +#include +#include +#include "ntlmauth.h" + +#undef debug + +/************* CONFIGURATION ***************/ +/* + * define this if you want debugging + */ +#ifndef DEBUG +#define DEBUG +#endif + +#define DEAD_DC_RETRY_INTERVAL 30 + +/************* END CONFIGURATION ***************/ + +#include + +#define WINNT_SECURITY_DLL "security.dll" +#define WIN9X_SECURITY_DLL "secur32.dll" + + +/* 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 _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 +} + +#endif + + +/* 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 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 + +HMODULE LoadSecurityDll(void); +void UnloadSecurityDll(void); +BOOL WINAPI SSPLogonUser(PTSTR, PTSTR, PTSTR); + +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 00:55:47 2007 +++ squid/src/auth/ntlm/helpers/NTLMSSP-WIN32/ntlm_auth.c Wed Feb 14 00:58:16 2007 @@ -0,0 +1,352 @@ +/* + * (C) 2000 Francesco Chemolli + * 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; + + + + +/* 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: + * -b try load-balancing the domain-controllers + * -f fail-over to another DC if DC connection fails. + * DEPRECATED and VERBOSELY IGNORED. This is on by default now. + * -l last-ditch-mode + * domain\controller ... + */ +char *my_program_name = NULL; + +void +usage() +{ + fprintf(stderr, + "%s usage:\n%s [-d] -A UserGroup [-D UserGroup]\n" + "-d enables debugging statements if DEBUG was defined at build-time.\n" + "-l if specified, changes behavior on failures to last-ditch.\n" + "-A specify the Windows Local Group name allowed to authenticate.\n" + "-D can specify aWindows 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; + while (-1 != (opt = getopt(argc, argv, "dlA:D:"))) { + switch (opt) { + case 'A': + safe_free(NTAllowedGroup); + NTAllowedGroup=xstrdup(optarg); + 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 'd': + 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) { + fprintf(stderr, "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 the DC */ + plen = strlen(buf) * 3 / 4; /* we only need it here. Optimization */ + cred = ntlm_check_auth((ntlm_authenticate *) decoded, plen); + if (cred == NULL) { +// int smblib_err, smb_errorclass, smb_errorcode, nb_error; + if (ntlm_errno == NTLM_LOGON_ERROR) { /* hackish */ + SEND("NA Logon Failure"); + return; + } + else { + SEND("NA SSPI Error"); + return; + } + /* there was an error. We have two errno's to look at. + * libntlmssp's erno is insufficient, we'll have to look at + * the actual SMB library error codes, to acually figure + * out what's happening. The thing has braindamaged interfacess..*/ +// smblib_err = SMB_Get_Last_Error(); +// smb_errorclass = SMBlib_Error_Class(SMB_Get_Last_SMB_Err()); +// smb_errorcode = SMBlib_Error_Code(SMB_Get_Last_SMB_Err()); +// nb_error = RFCNB_Get_Last_Error(); +// debug("No creds. SMBlib error %d, SMB error class %d, SMB error code %d, NB error %d\n", +// smblib_err, smb_errorclass, smb_errorcode, nb_error); + /* Should I use smblib_err? Actually it seems I can do as well + * without it.. */ +// if (nb_error != 0) { /* netbios-level error */ +// send_bh_or_ld("NetBios error!", +// (ntlm_authenticate *) decoded, plen); +// fprintf(stderr, "NetBios error code %d (%s)\n", nb_error, +// RFCNB_Error_Strings[abs(nb_error)]); +// return; +// } +// switch (smb_errorclass) { +// case SMBC_SUCCESS: +// debug("Huh? Got a SMB success code but could check auth.."); +// SEND("NA Authentication failed"); + /* + * send_bh_or_ld("SMB success, but no creds. Internal error?", + * (ntlm_authenticate *) decoded, plen); + */ +// return; +// case SMBC_ERRDOS: + /*this is the most important one for errors */ +// debug("DOS error\n"); +// switch (smb_errorcode) { + /* two categories matter to us: those which could be + * server errors, and those which are auth errors */ +// case SMBD_noaccess: /* 5 */ +// SEND("NA Access denied"); +// return; +// case SMBD_badformat: +// SEND("NA bad format in authentication packet"); +// return; +// case SMBD_badaccess: +// SEND("NA Bad access request"); +// return; +// case SMBD_baddata: +// SEND("NA Bad Data"); +// return; +// default: +// send_bh_or_ld("DOS Error", +// (ntlm_authenticate *) decoded, plen); +// return; +// } +// case SMBC_ERRSRV: /* server errors */ +// debug("Server error"); +// switch (smb_errorcode) { +// /* mostly same as above */ +// case SMBV_badpw: +// SEND("NA Bad password"); +// return; +// case SMBV_access: +// SEND("NA Server access error"); +// return; +// default: +// send_bh_or_ld("Server Error", +// (ntlm_authenticate *) decoded, plen); +// return; +// } +// case SMBC_ERRHRD: /* hardware errors don't really matter */ +// send_bh_or_ld("Domain Controller Hardware error", +// (ntlm_authenticate *) decoded, plen); +// return; +// case SMBC_ERRCMD: +// send_bh_or_ld("Domain Controller Command Error", +// (ntlm_authenticate *) decoded, plen); +// 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() == 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; +}