--------------------- PatchSet 973 Date: 2004/01/03 16:20:44 Author: serassio Branch: nt Tag: (none) Log: Updated Windows native helpers with new release from nt-2_5 Members: helpers/basic_auth/win32_locallogon/README.txt:1.2.18.1->1.2.18.2 helpers/basic_auth/win32_locallogon/valid.c:1.2.18.1->1.2.18.2 helpers/ntlm_auth/NTLMSSP-WIN32/libntlmssp.c:1.2.18.2->1.2.18.3 helpers/ntlm_auth/NTLMSSP-WIN32/ntlm.h:1.2.18.1->1.2.18.2 helpers/ntlm_auth/NTLMSSP-WIN32/ntlm_auth.c:1.2.18.2->1.2.18.3 helpers/ntlm_auth/NTLMSSP-WIN32/readme.txt:1.2.18.2->1.2.18.3 include/sspwin32.h:1.2.18.3->1.2.18.4 lib/sspwin32.c:1.2.18.3->1.2.18.4 Index: squid3/helpers/basic_auth/win32_locallogon/README.txt =================================================================== RCS file: /cvsroot/squid-sf//squid3/helpers/basic_auth/win32_locallogon/Attic/README.txt,v retrieving revision 1.2.18.1 retrieving revision 1.2.18.2 diff -u -r1.2.18.1 -r1.2.18.2 --- squid3/helpers/basic_auth/win32_locallogon/README.txt 25 Feb 2003 02:48:20 -0000 1.2.18.1 +++ squid3/helpers/basic_auth/win32_locallogon/README.txt 3 Jan 2004 16:20:44 -0000 1.2.18.2 @@ -18,8 +18,7 @@ -d can specify a Windows Local Group name not allowed to authenticate. -D can specify the default Domain against to authenticate. -This is released under the GNU General Public License and -is available from http://www.serassio.it. +This is released under the GNU General Public License. ============== @@ -41,12 +40,17 @@ Type 'make', then 'make install', then 'make clean'. -The default is to install 'nt_auth' into /usr/local/squid/libexec. +On Cygwin the default is to install 'nt_auth' into /usr/local/squid/libexec, +with other environment into c:/squid/libexec. Refer to Squid documentation for the required changes to squid.conf. You will need to set the following line to enable the authenticator: -authenticate_program /usr/local/squid/bin/NT_auth +auth_param basic program /usr/local/squid/libexec/nt_auth [options] + +or + +auth_param basic program c:/squid/libexec/nt_auth [options] You will need to set the following lines to enable authentication for your access list - @@ -54,9 +58,9 @@ acl proxy_auth REQUIRED http_access allow -You will need to specify the absolute path to NT_auth in the -authenticate_program directive, and check the authenticate_children -and authenticate_ttl. +You will need to specify the absolute path to nt_auth in the +'auth_param basic program' directive, and check the 'auth_param basic children' +and 'auth_param basic credentialsttl'. ================== @@ -64,7 +68,8 @@ ================== The Makefile assumes that GCC is in the current PATH. -NT_auth compile ONLY on CygWin Environment or MS VC++. +NT_auth compile ONLY on Cygwin Environment, MinGW + MSYS Environment +or MS VC++. ======= @@ -91,5 +96,5 @@ 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. +To contact the maintainer of this package, e-mail on squidnt@acmeconsulting.it. + Index: squid3/helpers/basic_auth/win32_locallogon/valid.c =================================================================== RCS file: /cvsroot/squid-sf//squid3/helpers/basic_auth/win32_locallogon/Attic/valid.c,v retrieving revision 1.2.18.1 retrieving revision 1.2.18.2 diff -u -r1.2.18.1 -r1.2.18.2 --- squid3/helpers/basic_auth/win32_locallogon/valid.c 25 Feb 2003 02:48:21 -0000 1.2.18.1 +++ squid3/helpers/basic_auth/win32_locallogon/valid.c 3 Jan 2004 16:20:44 -0000 1.2.18.2 @@ -26,7 +26,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. */ -#include "config.h" +#include "util.h" /* Check if we try to compile on a Windows Platform */ #if defined(_SQUID_CYGWIN_) || defined(_SQUID_MSWIN_) @@ -133,7 +133,7 @@ domain_qualify[0] = '\0'; } /* Log the client on to the local computer. */ - if (!SSPLogonUser(User, Password, NTDomain)) { + if (!SSP_LogonUser(User, Password, NTDomain)) { result = NTV_LOGON_ERROR; } else { result = NTV_NO_ERROR; Index: squid3/helpers/ntlm_auth/NTLMSSP-WIN32/libntlmssp.c =================================================================== RCS file: /cvsroot/squid-sf//squid3/helpers/ntlm_auth/NTLMSSP-WIN32/Attic/libntlmssp.c,v retrieving revision 1.2.18.2 retrieving revision 1.2.18.3 diff -u -r1.2.18.2 -r1.2.18.3 --- squid3/helpers/ntlm_auth/NTLMSSP-WIN32/libntlmssp.c 2 May 2003 14:02:41 -0000 1.2.18.2 +++ squid3/helpers/ntlm_auth/NTLMSSP-WIN32/libntlmssp.c 3 Jan 2004 16:20:44 -0000 1.2.18.3 @@ -1,50 +1,26 @@ /* - * (C)2002,2003 Guido Serassio - Acme Consulting S.r.l. - * - * Authors: - * Guido Serassio - * Acme Consulting S.r.l., Italy - * + * (C) 2002 Guido Serassio * Based on previous work of Francesco Chemolli and Robert Collins - * - * Dependencies: Microsoft Windows NT 4.0 SP4 and later. - * - * 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. + * 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 "config.h" -#include #include "util.h" #include "ntlm.h" #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) @@ -113,23 +89,6 @@ 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) { @@ -152,6 +111,7 @@ return target; } + char * GetDomainName(void) { @@ -240,51 +200,10 @@ 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. @@ -295,83 +214,58 @@ ntlm_check_auth(ntlm_authenticate * auth, int auth_length) { int rv; - char pass[25] /*, encrypted_pass[40] */; - char *domain = credentials; - char *user; + char domain[256]; + char user[256]; + static char credentials[1024]; /* we can afford to waste */ + 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'; + if (!NTLM_LocalCall) { - - /* 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 + tmp = ntlm_fetch_string((char *) auth, auth_length, &auth->domain); - /* TODO: check against empty password!!!!! */ - + if (tmp.str == NULL || tmp.l == 0) { + debug("No domain supplied. Returning no-auth\n"); + ntlm_errno = NTLM_BAD_REQUEST; + return NULL; + } + if (Use_Unicode) { + /* copy unicode buffer */ + WideCharToMultiByte(CP_ACP, 0, (LPCWSTR) tmp.str, tmp.l, domain, 256, NULL, NULL ); + /* add null termination */ + domain[tmp.l / sizeof(WCHAR)] = '\0'; + } else { + memcpy(domain, tmp.str, tmp.l); + domain[tmp.l] = '\0'; + } + 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_BAD_REQUEST; + return NULL; + } + if (Use_Unicode) { + /* copy unicode buffer */ + WideCharToMultiByte(CP_ACP, 0, (LPCWSTR) tmp.str, tmp.l, user, 256, NULL, NULL ); + /* add null termination */ + user[tmp.l / sizeof(WCHAR)] = '\0'; + } else { + memcpy(user, tmp.str, tmp.l); + user[tmp.l] = '\0'; + } + debug("checking domain: '%s', user: '%s'\n", domain, user); + } else + debug("checking local user\n"); - debug("checking domain: '%s', user: '%s', pass='%s'\n", domain, user, pass); - rv = SSPLogonUser(user, pass, domain); + rv = SSP_ValidateCredentials(auth, auth_length, credentials); debug("Login attempt had result %d\n", rv); if (!rv) { /* failed */ - ntlm_errno = ss; + ntlm_errno = NTLM_SSPI_ERROR; return NULL; } - *(user - 1) = '\\'; /* hack. Performing, but ugly. */ if (UseAllowedGroup) { if (!Valid_Group(credentials, NTAllowedGroup)) { @@ -391,3 +285,81 @@ debug("credentials: %s\n", credentials); return credentials; } + + +const char * +ntlm_make_negotiate(void) +{ + ntlm_negotiate ne; + const char *encoded; + memset(&ne, 0, sizeof(ntlm_negotiate)); /* reset */ + memcpy(ne.signature, "NTLMSSP", 8); /* set the signature */ + ne.type = htole32(NTLM_NEGOTIATE); /* this is a challenge */ + ne.flags = htole32( + NEGOTIATE_ALWAYS_SIGN | + NEGOTIATE_USE_NTLM | + NEGOTIATE_USE_LM | + NEGOTIATE_ASCII | + 0 + ); + encoded = base64_encode_bin((char *) &ne, NEGOTIATE_LENGTH); + return encoded; +} + + +void hex_dump(void *data, int size) +{ + /* dumps size bytes of *data to stdout. Looks like: + * [0000] 75 6E 6B 6E 6F 77 6E 20 + * 30 FF 00 00 00 00 39 00 unknown 0.....9. + * (in a single line of course) + */ + + if (debug_enabled) { + unsigned char *p = data; + unsigned char c; + int n; + char bytestr[4] = {0}; + char addrstr[10] = {0}; + char hexstr[ 16*3 + 5] = {0}; + char charstr[16*1 + 5] = {0}; + for(n=1;n<=size;n++) { + if (n%16 == 1) { + /* store address for this line */ + snprintf(addrstr, sizeof(addrstr), "%.4x", + ((unsigned int)p-(unsigned int)data) ); + } + + c = *p; + if (isalnum(c) == 0) { + c = '.'; + } + + /* store hex str (for left side) */ + snprintf(bytestr, sizeof(bytestr), "%02X ", *p); + strncat(hexstr, bytestr, sizeof(hexstr)-strlen(hexstr)-1); + + /* store char str (for right side) */ + snprintf(bytestr, sizeof(bytestr), "%c", c); + strncat(charstr, bytestr, sizeof(charstr)-strlen(charstr)-1); + + if(n%16 == 0) { + /* line completed */ + fprintf(stderr, "[%4.4s] %-50.50s %s\n", addrstr, hexstr, charstr); + hexstr[0] = 0; + charstr[0] = 0; + } else if(n%8 == 0) { + /* half line: add whitespaces */ + strncat(hexstr, " ", sizeof(hexstr)-strlen(hexstr)-1); + strncat(charstr, " ", sizeof(charstr)-strlen(charstr)-1); + } + p++; /* next byte */ + } + + if (strlen(hexstr) > 0) { + /* print rest of buffer if not empty */ + fprintf(stderr, "[%4.4s] %-50.50s %s\n", addrstr, hexstr, charstr); + } + } +} + Index: squid3/helpers/ntlm_auth/NTLMSSP-WIN32/ntlm.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/helpers/ntlm_auth/NTLMSSP-WIN32/Attic/ntlm.h,v retrieving revision 1.2.18.1 retrieving revision 1.2.18.2 diff -u -r1.2.18.1 -r1.2.18.2 --- squid3/helpers/ntlm_auth/NTLMSSP-WIN32/ntlm.h 25 Feb 2003 02:48:28 -0000 1.2.18.1 +++ squid3/helpers/ntlm_auth/NTLMSSP-WIN32/ntlm.h 3 Jan 2004 16:20:44 -0000 1.2.18.2 @@ -33,10 +33,17 @@ #define DEBUG #endif +#define FAIL_DEBUG 0 + /************* END CONFIGURATION ***************/ #include +extern int debug_enabled; +#ifdef FAIL_DEBUG +extern int fail_debug_enabled; +#endif + /* Debugging stuff */ #ifdef __GNUC__ /* this is really a gcc-ism */ @@ -44,7 +51,6 @@ #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),\ @@ -54,26 +60,28 @@ #define debug(X...) /* */ #endif /* DEBUG */ #else /* __GNUC__ */ -extern char debug_enabled; static void debug(char *format,...) { #ifdef DEBUG #ifdef _SQUID_MSWIN_ - if (debug_enabled) { + if (debug_enabled || fail_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); +#ifdef FAIL_DEBUG + fail_debug_enabled = 0; +#endif } #endif /* _SQUID_MSWIN_ */ #endif /* DEBUG */ } #endif /* __GNUC__ */ +#define safe_free(x) if (x) { free(x); x = NULL; } /* A couple of harmless helper macros */ #define SEND(X) debug("sending '%s' to squid\n",X); printf(X "\n"); @@ -90,21 +98,17 @@ 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 +#define NTLM_NO_ERROR 0 +#define NTLM_SSPI_ERROR 1 +#define NTLM_BAD_NTGROUP 2 +#define NTLM_BAD_REQUEST 3 + +#define NEGOTIATE_LENGTH 16 extern void uc(char *); -const char *make_challenge(void); +extern const char * ntlm_make_negotiate(void); extern char *ntlm_check_auth(ntlm_authenticate * auth, int auth_length); -extern char *fetch_credentials(ntlm_authenticate * auth, int auth_length); - -#define safe_free(x) if (x) { free(x); x = NULL; } +extern void hex_dump(void *, int); #endif /* _NTLM_H_ */ Index: squid3/helpers/ntlm_auth/NTLMSSP-WIN32/ntlm_auth.c =================================================================== RCS file: /cvsroot/squid-sf//squid3/helpers/ntlm_auth/NTLMSSP-WIN32/Attic/ntlm_auth.c,v retrieving revision 1.2.18.2 retrieving revision 1.2.18.3 diff -u -r1.2.18.2 -r1.2.18.3 --- squid3/helpers/ntlm_auth/NTLMSSP-WIN32/ntlm_auth.c 2 May 2003 14:02:43 -0000 1.2.18.2 +++ squid3/helpers/ntlm_auth/NTLMSSP-WIN32/ntlm_auth.c 3 Jan 2004 16:20:44 -0000 1.2.18.3 @@ -1,5 +1,5 @@ /* - * ntlm_win32_auth: NTLM authenticator in a Windows NT/2000 domain + * ntlm_auth: helper for NTLM Authentication for Squid Cache * * (C)2002,2003 Guido Serassio - Acme Consulting S.r.l. * @@ -10,9 +10,9 @@ * With contributions from others mentioned in the change history section * below. * - * Based on previous work of Francesco Chemolli and Robert Collins + * Based on previous work of Francesco Chemolli and Robert Collins. * - * Dependencies: Microsoft Windows NT 4.0 SP4 and later. + * Dependencies: Windows NT4 SP4 and later. * * 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 @@ -30,62 +30,50 @@ * * History: * - * Version 1.02 - * 21-07-2002 Guido Serassio - * Bugfixes in options processing - * New usage message and -h option - * Fixed a potential Squid DoS issue if oversized auth - * requests is sent to the helpers - * Version 1.01 - * 26-04-2002 Guido Serassio - * Added Group membership check + * Version 1.20 + * 30-11-2003 Guido Serassio + * Added support for NTLM local calls. + Added control of use of NTLM NEGOTIATE packet from + command line. + * Updated documentation. + * Version 1.10 + * 07-09-2003 Guido Serassio + * Now is true NTLM authenticator. + * More debug info. + * Updated documentation. * Version 1.0 - * 21-04-2002 Guido Serassio - * Using the main function from wb_ntlm_auth and sections - * from ntlm_auth wrote ntlm_win32_auth + * 29-06-2002 Guido Serassio + * First release. + * * - * This is a helper for NTLM Authentication for Squid Cache - * */ -#include "config.h" -#if HAVE_STDLIB_H -#include -#endif -#if HAVE_STDIO_H -#include -#endif -#if HAVE_CTYPE_H -#include -#endif -#if HAVE_ERRNO_H -#include -#endif -#if HAVE_GETOPT_H -#include -#endif #include "util.h" +#include "getopt.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; +int last_ditch_enabled = 0; #endif -char debug_enabled=0; +int debug_enabled = 0; +int NTLM_packet_debug_enabled = 0; +static int have_challenge; char * NTAllowedGroup; char * NTDisAllowedGroup; int UseDisallowedGroup = 0; int UseAllowedGroup = 0; +int UseNtlmNegotiate = 0; +#ifdef FAIL_DEBUG +int fail_debug_enabled = 0; +#endif + +char YR_String[4] = "YR"; +int YR_Length = 2; /* makes a null-terminated string upper-case. Changes CONTENTS! */ void @@ -112,37 +100,20 @@ void helperfail(const char *reason) { - SEND2("BH %s", reason); -} - -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 - } +#ifdef FAIL_DEBUG + fail_debug_enabled =1; #endif + SEND2("BH %s", reason); } /* - * 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 ... + options: + -d enable debugging. + -v enable verbose NTLM packet debugging. + -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. + -N enable use of NTLM NEGOTIATE packet */ char *my_program_name = NULL; @@ -151,18 +122,20 @@ { fprintf(stderr, #ifdef NTLM_FAIL_OPEN - "%s usage:\n%s [-v] [-a UserGroup] [-d UserGroup] [-l] [-h]\n" + "Usage: %s [-d] [-v] [-N] [-A|D LocalUserGroup] [-l] [-h]\n" #else - "%s usage:\n%s [-v] [-a UserGroup] [-d UserGroup] [-h]\n" + "Usage: %s [-d] [-v] [-N] [-A|D LocalUserGroup] [-h]\n" #endif - "-v enables verbose debugging.\n" + " -d enable debugging.\n" + " -v enable verbose NTLM packet debugging.\n" #ifdef NTLM_FAIL_OPEN - "-l if specified, changes behavior on failures to last-ditch\n" + " -l if specified, changes behavior on failures to last-ditch\n" #endif - "-a specify a Windows Local Group name allowed to authenticate\n" - "-d specify a Windows Local Group name not allowed to authenticate\n" - "-h this message\n\n", - my_program_name, my_program_name); + " -A specify a Windows Local Group name allowed to authenticate\n" + " -D specify a Windows Local Group name not allowed to authenticate\n" + " -N enable use of NTLM NEGOTIATE packet\n" + " -h this message\n\n", + my_program_name); } @@ -173,28 +146,37 @@ opterr =0; #ifdef NTLM_FAIL_OPEN - while (-1 != (opt = getopt(argc, argv, "hvla:d:"))) { + while (-1 != (opt = getopt(argc, argv, "hdvlA:D:N"))) { #else - while (-1 != (opt = getopt(argc, argv, "hva:d:"))) { + while (-1 != (opt = getopt(argc, argv, "hdvA:D:N"))) { #endif switch (opt) { - case 'a': + case 'A': safe_free(NTAllowedGroup); NTAllowedGroup=xstrdup(optarg); UseAllowedGroup = 1; break; - case 'd': + case 'D': safe_free(NTDisAllowedGroup); NTDisAllowedGroup=xstrdup(optarg); UseDisallowedGroup = 1; break; + case 'N': + UseNtlmNegotiate = 1; + strcpy(YR_String, "YR "); + YR_Length = 3; + break; #ifdef NTLM_FAIL_OPEN case 'l': last_ditch_enabled = 1; break; #endif + case 'd': + debug_enabled = 1; + break; case 'v': - debug_enabled=1; + debug_enabled = 1; + NTLM_packet_debug_enabled = 1; break; case 'h': usage(); @@ -212,17 +194,14 @@ exit(1); } -/* tries connecting to the domain controllers in the "controllers" ring, - * with failover if the adequate option is specified. - */ + const char * -obtain_challenge() +obtain_challenge(ntlm_negotiate * nego, int nego_length) { const char *ch = NULL; - debug("attempting challenge retrieval\n"); - ch = make_challenge(); - debug("make_challenge returned %p\n", ch); + debug("attempting SSPI challenge retrieval\n"); + ch = SSP_MakeChallenge(nego, nego_length); if (ch) { debug("Got it\n"); return ch; /* All went OK, returning */ @@ -231,27 +210,27 @@ } -void +int manage_request() { ntlmhdr *fast_header; char buf[BUFFER_SIZE]; + char helper_command[3]; char *c, *decoded, *cred; int plen; int oversized = 0; + char * ErrorMessage; try_again: - if (fgets(buf, BUFFER_SIZE, stdin) == NULL) { - debug("fgets() failed! dying..... errno=%d (%s)\n", errno, - strerror(errno)); - exit(1); /* BIIG buffer */ - } + if (fgets(buf, BUFFER_SIZE, stdin) == NULL) + return 0; + c = memchr(buf, '\n', BUFFER_SIZE); /* safer against overrun than strchr */ if (c) { if (oversized) { helperfail("illegal request received"); fprintf(stderr, "Illegal request received: '%s'\n", buf); - return; + return 1; } *c = '\0'; } else { @@ -259,15 +238,78 @@ oversized = 1; goto try_again; } + if ((strlen(buf) > 3) && NTLM_packet_debug_enabled) { + decoded = base64_decode(buf + 3); + strncpy(helper_command, buf, 2); + debug("Got '%s' from Squid with data:\n", helper_command); + hex_dump(decoded, ((strlen(buf) - 3) * 3) / 4); + } else + debug("Got '%s' from Squid\n", buf); + if (memcmp(buf, YR_String, YR_Length) == 0) { /* refresh-request */ + /* figure out what we got */ + if (UseNtlmNegotiate) + decoded = base64_decode(buf + 3); + else + decoded = base64_decode(ntlm_make_negotiate()); + /* 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 1; + } + /* fast-track-decode request type. */ + fast_header = (struct _ntlmhdr *) decoded; - debug("Got '%s' from Squid\n", buf); - - if (memcmp(buf, "YR", 2) == 0) { /* refresh-request */ - c = (char *) obtain_challenge(); - SEND2("TT %s", c); - return; + /* sanity-check: it IS a NTLMSSP packet, isn't it? */ + if (memcmp(fast_header->signature, "NTLMSSP", 8) != 0) { + SEND("NA Broken authentication packet"); + return 1; + } + switch (fast_header->type) { + case NTLM_NEGOTIATE: + /* Obtain challenge against SSPI */ + if (UseNtlmNegotiate) + plen = (strlen(buf) - 3) * 3 / 4; /* we only need it here. Optimization */ + else + plen = NEGOTIATE_LENGTH; + if ((c = (char *) obtain_challenge((ntlm_negotiate *) decoded, plen)) != NULL ) + { + if (NTLM_packet_debug_enabled) { + printf("TT %s\n",c); + decoded = base64_decode(c); + debug("sending 'TT' to squid with data:\n"); + hex_dump(decoded, (strlen(c) * 3) / 4); + if (NTLM_LocalCall) + debug("NTLM Local Call detected\n"); + } else { + SEND2("TT %s", c); + } + have_challenge = 1; + } else + helperfail("can't obtain challenge"); + return 1; + /* notreached */ + case NTLM_CHALLENGE: + SEND + ("NA Got a challenge. We refuse to have our authority disputed"); + return 1; + /* notreached */ + case NTLM_AUTHENTICATE: + SEND("NA Got authentication request instead of negotiate request"); + return 1; + /* notreached */ + default: + helperfail("unknown refresh-request packet type"); + return 1; + } + return 1; } if (memcmp(buf, "KK ", 3) == 0) { /* authenticate-request */ + if (!have_challenge) { + helperfail("invalid challenge"); + return 1; + } /* figure out what we got */ decoded = base64_decode(buf + 3); /* Note: we don't need to manage memory at this point, since @@ -276,7 +318,7 @@ if (!decoded) { /* decoding failure, return error */ SEND("NA Packet format error, couldn't base64-decode"); - return; + return 1; } /* fast-track-decode request type. */ fast_header = (struct _ntlmhdr *) decoded; @@ -284,67 +326,84 @@ /* sanity-check: it IS a NTLMSSP packet, isn't it? */ if (memcmp(fast_header->signature, "NTLMSSP", 8) != 0) { SEND("NA Broken authentication packet"); - return; + return 1; } switch (fast_header->type) { case NTLM_NEGOTIATE: SEND("NA Invalid negotiation request received"); - return; + return 1; /* notreached */ case NTLM_CHALLENGE: SEND ("NA Got a challenge. We refuse to have our authority disputed"); - return; + return 1; /* notreached */ case NTLM_AUTHENTICATE: /* check against SSPI */ - plen = strlen(buf) * 3 / 4; /* we only need it here. Optimization */ + plen = (strlen(buf) - 3) * 3 / 4; /* we only need it here. Optimization */ cred = ntlm_check_auth((ntlm_authenticate *) decoded, plen); + have_challenge = 0; if (cred == NULL) { +#ifdef FAIL_DEBUG + fail_debug_enabled =1; +#endif 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; + return 1; + case NTLM_BAD_REQUEST: + SEND("NA Incorrect Request Format"); + return 1; + case NTLM_SSPI_ERROR: + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &ErrorMessage, + 0, + NULL); + if (ErrorMessage[strlen(ErrorMessage) - 1] == '\n') + ErrorMessage[strlen(ErrorMessage) - 1] = '\0'; + if (ErrorMessage[strlen(ErrorMessage) - 1] == '\r') + ErrorMessage[strlen(ErrorMessage) - 1] = '\0'; + SEND2("NA %s", ErrorMessage); + LocalFree(ErrorMessage); + return 1; default: - SEND("NA SSPI Error"); - return; + SEND("NA Unknown Error"); + return 1; } } lc(cred); /* let's lowercase them for our convenience */ SEND2("AF %s", cred); - return; + return 1; default: helperfail("unknown authentication packet type"); - return; + return 1; } - return; - } else { /* not an auth-request */ + return 1; + } else { /* not an auth-request */ helperfail("illegal request received"); fprintf(stderr, "Illegal request received: '%s'\n", buf); - return; + return 1; } helperfail("detected protocol error"); - return; + return 1; /********* 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 ) ); + debug("%s build " __DATE__ ", " __TIME__ " starting up...\n", my_program_name); + if (LoadSecurityDll(SSP_NTLM) == NULL) { fprintf(stderr, "FATAL, can't initialize SSPI, exiting.\n"); exit(1); @@ -357,8 +416,8 @@ setbuf(stdout, NULL); setbuf(stderr, NULL); - while (1) { - manage_request(); + while (manage_request()) { + /* everything is done within manage_request */ } - return 0; + exit(0); } Index: squid3/helpers/ntlm_auth/NTLMSSP-WIN32/readme.txt =================================================================== RCS file: /cvsroot/squid-sf//squid3/helpers/ntlm_auth/NTLMSSP-WIN32/Attic/readme.txt,v retrieving revision 1.2.18.2 retrieving revision 1.2.18.3 diff -u -r1.2.18.2 -r1.2.18.3 --- squid3/helpers/ntlm_auth/NTLMSSP-WIN32/readme.txt 2 May 2003 14:02:43 -0000 1.2.18.2 +++ squid3/helpers/ntlm_auth/NTLMSSP-WIN32/readme.txt 3 Jan 2004 16:20:44 -0000 1.2.18.3 @@ -1,17 +1,20 @@ ntlm_auth.exe -Native Windows NTLM authenticator for Squid 2.5 +Native Windows NTLM/NTLMv2 authenticator for Squid 3.0. ===== Usage ===== -ntlm_auth [-v] [-a UserGroup] [-d UserGroup] [-l] +ntlm_auth [-d] [-v] [-N] [-A|D LocalUserGroup] [-l] [-h] --v enables debugging statements. +-d enables debugging. +-v enables verbose NTLM packet debugging. -l if specified, changes behavior on failures to last-ditch. --a specify a Windows Local Group name allowed to authenticate. --d specify a Windows Local Group name not allowed to authenticate. +-A specify a Windows Local Group name allowed to authenticate. +-D specify a Windows Local Group name not allowed to authenticate. +-N enable use of NTLM NEGOTIATE packet. +-h print program usage This is released under the GNU General Public License @@ -20,17 +23,49 @@ ============== 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. +User Rights "logon from the network". +Optionally the authenticator can verify the NT LOCAL group membership of +the user against the User Group 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, it works only with MACHINE +Local Groups, not Domain Local Groups. +Better group checking is available with External Acl, see win32_check_group +documentation. + +The use of NTLM NEGOTIATE packet allow full NTLM/NTLMv2 support, but +Squid too must be configured to use NTLM NEGOTIATE, see squid.conf. + +Squid.conf typical minimal required changes: + +auth_param ntlm program c:/squid/libexec/ntlm_auth.exe -N +auth_param ntlm children 5 +auth_param ntlm max_challenge_reuses 0 +auth_param ntlm max_challenge_lifetime 2 minutes +auth_param ntlm use_ntlm_negotiate on <== needs (or needed by) -N option + +acl password proxy_auth REQUIRED + +http_access allow password +http_access deny all + +When using -N option, "use_ntlm_negotiate on" is MANDATORY and +max_challenge_reuses and max_challenge_lifetime parameters must be specified +but they are are ignored. + +Refer to Squid documentation for more details. + +Currently Internet Explorer has some problems with ftp:// URLs when handling +internal Squid FTP icons. The following squid.conf ACL works around this: + +acl internal_icons urlpath_regex -i /squid-internal-static/icons/ + +http_access allow our_networks internal_icons <== BEFORE authentication ACL !!! -Refer to Squid documentation for the required changes to squid.conf: -http://www.squid-cache.org/Doc/FAQ/FAQ-23.html#ss23.5 =============== Contact details =============== -To contact the maintainer of this package, e-mail on guido.serassio@acmeconsulting.it. -The latest version may be found on http://www.serassio.it/SquidNT.htm. +To contact the maintainer of this package, e-mail on squidnt@acmeconsulting.it. +The latest version may be found on http://www.acmeconsulting.it/SquidNT.htm. Index: squid3/include/sspwin32.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/include/sspwin32.h,v retrieving revision 1.2.18.3 retrieving revision 1.2.18.4 diff -u -r1.2.18.3 -r1.2.18.4 --- squid3/include/sspwin32.h 10 Aug 2003 16:02:02 -0000 1.2.18.3 +++ squid3/include/sspwin32.h 3 Jan 2004 16:22:57 -0000 1.2.18.4 @@ -31,26 +31,17 @@ #include #define WINNT_SECURITY_DLL "security.dll" -#define WIN9X_SECURITY_DLL "secur32.dll" +#define WIN2K_SECURITY_DLL "secur32.dll" #define SSP_BASIC 1 #define SSP_NTLM 2 -typedef struct _AUTH_SEQ { - BOOL fInitialized; - BOOL fHaveCredHandle; - BOOL fHaveCtxtHandle; - CredHandle hcred; - struct _SecHandle hctxt; -} AUTH_SEQ, *PAUTH_SEQ; - -BOOL WINAPI SSPLogonUser(PTSTR, PTSTR, PTSTR); -BOOL GenClientContext(PAUTH_SEQ, PSEC_WINNT_AUTH_IDENTITY, PVOID, DWORD, PVOID, PDWORD, PBOOL); -BOOL GenServerContext(PAUTH_SEQ, PVOID, DWORD, PVOID, PDWORD, PBOOL); - HMODULE LoadSecurityDll(int); void UnloadSecurityDll(void); +BOOL WINAPI SSP_LogonUser(PTSTR, PTSTR, PTSTR); +BOOL WINAPI SSP_ValidateCredentials(PVOID, int, char *); +const char * WINAPI SSP_MakeChallenge(PVOID, int); -extern SECURITY_STATUS ss; - +extern BOOL Use_Unicode; +extern BOOL NTLM_LocalCall; #endif /* LIBSSPWIN32_H_ */ Index: squid3/lib/sspwin32.c =================================================================== RCS file: /cvsroot/squid-sf//squid3/lib/sspwin32.c,v retrieving revision 1.2.18.3 retrieving revision 1.2.18.4 diff -u -r1.2.18.3 -r1.2.18.4 --- squid3/lib/sspwin32.c 10 Aug 2003 16:02:02 -0000 1.2.18.3 +++ squid3/lib/sspwin32.c 3 Jan 2004 16:21:08 -0000 1.2.18.4 @@ -15,14 +15,33 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. */ -#include "config.h" -#include #include "util.h" + +#include "ntlmauth.h" #include "sspwin32.h" +typedef struct _AUTH_SEQ { + BOOL fInitialized; + BOOL fHaveCredHandle; + BOOL fHaveCtxtHandle; + CredHandle hcred; + TimeStamp hcredLifeTime; + struct _SecHandle hctxt; + TimeStamp hctxtLifeTime; +} AUTH_SEQ, *PAUTH_SEQ; + static HMODULE hModule; static int NTLM_mode = SSP_BASIC; -SECURITY_STATUS ss = SEC_E_OK; +SECURITY_STATUS SecurityStatus = SEC_E_OK; + +static DWORD cbMaxToken = 0; +static PVOID pClientBuf = NULL; +static PVOID pServerBuf = NULL; + +static AUTH_SEQ NTLM_asServer = {0}; + +BOOL Use_Unicode = FALSE; +BOOL NTLM_LocalCall = FALSE; /* Function pointers */ ACCEPT_SECURITY_CONTEXT_FN _AcceptSecurityContext = NULL; @@ -33,12 +52,25 @@ FREE_CREDENTIALS_HANDLE_FN _FreeCredentialsHandle = NULL; INITIALIZE_SECURITY_CONTEXT_FN _InitializeSecurityContext = NULL; QUERY_SECURITY_PACKAGE_INFO_FN _QuerySecurityPackageInfo = NULL; - +#ifdef UNICODE +QUERY_CONTEXT_ATTRIBUTES_FN_W _QueryContextAttributes = NULL; +#else +QUERY_CONTEXT_ATTRIBUTES_FN_A _QueryContextAttributes = NULL; +#endif void UnloadSecurityDll(void) { + if (NTLM_asServer.fHaveCtxtHandle) + _DeleteSecurityContext(&NTLM_asServer.hctxt); + if (NTLM_asServer.fHaveCredHandle) + _FreeCredentialsHandle(&NTLM_asServer.hcred); + if (hModule) FreeLibrary(hModule); + + xfree(pClientBuf); + xfree(pServerBuf); + _AcceptSecurityContext = NULL; _AcquireCredentialsHandle = NULL; _CompleteAuthToken = NULL; @@ -47,6 +79,8 @@ _FreeCredentialsHandle = NULL; _InitializeSecurityContext = NULL; _QuerySecurityPackageInfo = NULL; + _QueryContextAttributes = NULL; + hModule = NULL; } @@ -55,9 +89,11 @@ { TCHAR lpszDLL[MAX_PATH]; OSVERSIONINFO VerInfo; -/* + PSecPkgInfo pSPI = NULL; + + /* * Find out which security DLL to use, depending on - * whether we are on NT or Win95 or 2000 or XP or .NET Server + * whether we are on NT or 2000 or XP or 2003 Server * We have to use security.dll on Windows NT 4.0. * All other operating systems, we have to use Secur32.dll */ @@ -75,7 +111,7 @@ { lstrcpy (lpszDLL, _T(WINNT_SECURITY_DLL)); } else { - lstrcpy (lpszDLL, _T(WIN9X_SECURITY_DLL)); + lstrcpy (lpszDLL, _T(WIN2K_SECURITY_DLL)); } hModule = LoadLibrary(lpszDLL); if (!hModule) @@ -99,11 +135,13 @@ hModule = NULL; return hModule; } -/* 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"); + if (!_CompleteAuthToken) { + UnloadSecurityDll(); + hModule = NULL; + return hModule; + } _DeleteSecurityContext = (DELETE_SECURITY_CONTEXT_FN) GetProcAddress(hModule, "DeleteSecurityContext"); if (!_DeleteSecurityContext) { @@ -148,6 +186,28 @@ UnloadSecurityDll(); hModule = NULL; } + +#ifdef UNICODE + _QueryContextAttributes = (QUERY_CONTEXT_ATTRIBUTES_FN_W) + GetProcAddress(hModule, "QueryContextAttributesW"); +#else + _QueryContextAttributes = (QUERY_CONTEXT_ATTRIBUTES_FN_A) + GetProcAddress(hModule, "QueryContextAttributesA"); +#endif + if (!_QueryContextAttributes) { + UnloadSecurityDll(); + hModule = NULL; + } + + /* Get max token size */ + _QuerySecurityPackageInfo(_T("NTLM"), &pSPI); + cbMaxToken = pSPI->cbMaxToken; + _FreeContextBuffer(pSPI); + + /* Allocate buffers for client and server messages */ + pClientBuf = xcalloc(cbMaxToken, sizeof(char)); + pServerBuf = xcalloc(cbMaxToken, sizeof(char)); + return hModule; } @@ -173,13 +233,11 @@ ULONG fContextAttr; if (!pAS->fInitialized) { - ss = _AcquireCredentialsHandle(NULL, (SEC_CHAR *)_T(NTLM_PACKAGE_NAME), + SecurityStatus = _AcquireCredentialsHandle(NULL, _T(NTLM_PACKAGE_NAME), SECPKG_CRED_OUTBOUND, NULL, (NTLM_mode == SSP_NTLM) ? NULL : pAuthIdentity, NULL, NULL, &pAS->hcred, &tsExpiry); - if (ss < 0) { - fprintf(stderr, "AcquireCredentialsHandle failed with %08lX\n", ss); + if (SecurityStatus < 0) return FALSE; - } pAS->fHaveCredHandle = TRUE; } @@ -200,41 +258,31 @@ sbIn.BufferType = SECBUFFER_TOKEN; sbIn.pvBuffer = pIn; } - ss = _InitializeSecurityContext(&pAS->hcred, + SecurityStatus = _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 %08lX\n", ss); + if (SecurityStatus < 0) 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 %08lX\n", ss); - return FALSE; - } - } else { - fprintf (stderr, "CompleteAuthToken not supported.\n"); + if (SecurityStatus == SEC_I_COMPLETE_NEEDED || SecurityStatus == SEC_I_COMPLETE_AND_CONTINUE) { + SecurityStatus = _CompleteAuthToken(&pAS->hctxt, &sbdOut); + if (SecurityStatus < 0) return FALSE; - } } *pcbOut = sbOut.cbBuffer; if (!pAS->fInitialized) pAS->fInitialized = TRUE; - *pfDone = !(ss == SEC_I_CONTINUE_NEEDED - || ss == SEC_I_COMPLETE_AND_CONTINUE ); + *pfDone = !(SecurityStatus == SEC_I_CONTINUE_NEEDED + || SecurityStatus == SEC_I_COMPLETE_AND_CONTINUE ); return TRUE; } BOOL GenServerContext(PAUTH_SEQ pAS, PVOID pIn, DWORD cbIn, PVOID pOut, - PDWORD pcbOut, PBOOL pfDone) + PDWORD pcbOut, PBOOL pfDone, char * credentials) { /* * Routine Description: @@ -248,21 +296,19 @@ * Returns TRUE if successful; otherwise FALSE. */ - TimeStamp tsExpiry; SecBufferDesc sbdOut; SecBuffer sbOut; SecBufferDesc sbdIn; SecBuffer sbIn; ULONG fContextAttr; + SecPkgContext_Names namebuffer; if (!pAS->fInitialized) { - ss = _AcquireCredentialsHandle(NULL, (SEC_CHAR *)_T("NTLM"), + SecurityStatus = _AcquireCredentialsHandle(NULL, _T("NTLM"), SECPKG_CRED_INBOUND, NULL, NULL, NULL, NULL, &pAS->hcred, - &tsExpiry); - if (ss < 0) { - fprintf(stderr, "AcquireCredentialsHandle failed with %08lX\n", ss); + &pAS->hcredLifeTime); + if (SecurityStatus < 0) return FALSE; - } pAS->fHaveCredHandle = TRUE; } @@ -281,39 +327,38 @@ sbIn.cbBuffer = cbIn; sbIn.BufferType = SECBUFFER_TOKEN; sbIn.pvBuffer = pIn; - ss = _AcceptSecurityContext(&pAS->hcred, + SecurityStatus = _AcceptSecurityContext(&pAS->hcred, pAS->fInitialized ? &pAS->hctxt : NULL, &sbdIn, (NTLM_mode == SSP_NTLM) ? ASC_REQ_DELEGATE : 0, SECURITY_NATIVE_DREP, &pAS->hctxt, &sbdOut, &fContextAttr, - &tsExpiry); - if (ss < 0) { - fprintf(stderr, "AcceptSecurityContext failed with %08lX\n", ss); + &pAS->hctxtLifeTime); + if (SecurityStatus < 0) 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 %08lX\n", ss); - return FALSE; - } - } else { - fprintf (stderr, "CompleteAuthToken not supported.\n"); + if (SecurityStatus == SEC_I_COMPLETE_NEEDED || SecurityStatus == SEC_I_COMPLETE_AND_CONTINUE) { + SecurityStatus = _CompleteAuthToken(&pAS->hctxt, &sbdOut); + if (SecurityStatus < 0) + return FALSE; + } + + if (credentials != NULL) { + SecurityStatus = _QueryContextAttributes(&pAS->hctxt, SECPKG_ATTR_NAMES, &namebuffer); + if (SecurityStatus < 0) return FALSE; - } + strcpy(credentials, namebuffer.sUserName); } + *pcbOut = sbOut.cbBuffer; if (!pAS->fInitialized) pAS->fInitialized = TRUE; - *pfDone = !(ss = SEC_I_CONTINUE_NEEDED - || ss == SEC_I_COMPLETE_AND_CONTINUE); + *pfDone = !(SecurityStatus = SEC_I_CONTINUE_NEEDED + || SecurityStatus == SEC_I_COMPLETE_AND_CONTINUE); return TRUE; } -BOOL WINAPI SSPLogonUser(PTSTR szUser, PTSTR szPassword, PTSTR szDomain) +BOOL WINAPI SSP_LogonUser(PTSTR szUser, PTSTR szPassword, PTSTR szDomain) { AUTH_SEQ asServer = {0}; AUTH_SEQ asClient = {0}; @@ -321,26 +366,14 @@ 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; do { if (!hModule) break; - /* Get max token size */ - _QuerySecurityPackageInfo((SEC_CHAR *)_T("NTLM"), &pSPI); - cbMaxToken = pSPI->cbMaxToken; - _FreeContextBuffer(pSPI); - - /* Allocate buffers for client and server messages */ - pClientBuf = xcalloc(cbMaxToken, sizeof(char)); - pServerBuf = xcalloc(cbMaxToken, sizeof(char)); - /* Initialize auth identity structure */ + /* Initialize auth identity structure */ ZeroMemory(&ai, sizeof(ai)); ai.Domain = szDomain; ai.DomainLength = lstrlen(szDomain); @@ -363,7 +396,7 @@ cbIn = cbOut; cbOut = cbMaxToken; if (!GenServerContext(&asServer, pClientBuf, cbIn, pServerBuf, &cbOut, - &fDone)) + &fDone, NULL)) break; /* Most likely failure: AcceptServerContext fails with SEC_E_LOGON_DENIED * in the case of bad szUser or szPassword. @@ -382,7 +415,7 @@ cbIn = cbOut; cbOut = cbMaxToken; if (!GenServerContext(&asServer, pClientBuf, cbIn, pServerBuf, &cbOut, - &fDone)) + &fDone, NULL)) break; fResult = TRUE; } while(0); @@ -396,8 +429,73 @@ _DeleteSecurityContext(&asServer.hctxt); if (asServer.fHaveCredHandle) _FreeCredentialsHandle(&asServer.hcred); - xfree(pClientBuf); - xfree(pServerBuf); + + return fResult; +} + + +const char * WINAPI SSP_MakeChallenge(PVOID PNegotiateBuf, int NegotiateLen) +{ + BOOL fDone = FALSE; + PVOID fResult = NULL; + DWORD cbOut = 0; + DWORD cbIn = 0; + ntlm_challenge * challenge; + const char * encoded = NULL; + + if (NTLM_asServer.fHaveCtxtHandle) + _DeleteSecurityContext(&NTLM_asServer.hctxt); + if (NTLM_asServer.fHaveCredHandle) + _FreeCredentialsHandle(&NTLM_asServer.hcred); + + NTLM_LocalCall = FALSE; + Use_Unicode = FALSE; + memcpy(pClientBuf, PNegotiateBuf, NegotiateLen); + ZeroMemory(pServerBuf, cbMaxToken); + ZeroMemory(&NTLM_asServer, sizeof(NTLM_asServer)); + do { + if (!hModule) + break; + + /* Prepare server message (challenge) */ + cbIn = NegotiateLen; + cbOut = cbMaxToken; + if (!GenServerContext(&NTLM_asServer, pClientBuf, cbIn, pServerBuf, &cbOut, + &fDone, NULL)) + break; + fResult = pServerBuf; + } while(0); + if (fResult != NULL) { + challenge = (ntlm_challenge *) fResult; + Use_Unicode = NEGOTIATE_UNICODE & challenge->flags; + NTLM_LocalCall = NEGOTIATE_THIS_IS_LOCAL_CALL & challenge->flags; + encoded = base64_encode_bin((char *) fResult, cbOut); + } + return encoded; +} + + +BOOL WINAPI SSP_ValidateCredentials(PVOID PAutenticateBuf, int AutenticateLen, char * credentials) +{ + BOOL fDone = FALSE; + BOOL fResult = FALSE; + DWORD cbOut = 0; + DWORD cbIn = 0; + + memcpy(pClientBuf, PAutenticateBuf, AutenticateLen); + ZeroMemory(pServerBuf, cbMaxToken); + do { + if (!hModule) + break; + + /* Prepare server message (authentication) */ + cbIn = AutenticateLen; + cbOut = cbMaxToken; + if (!GenServerContext(&NTLM_asServer, pClientBuf, cbIn, pServerBuf, &cbOut, + &fDone, credentials)) + break; + fResult = TRUE; + } while(0); return fResult; }