--------------------- PatchSet 5920 Date: 2003/09/07 17:17:35 Author: serassio Branch: nt-2_5 Tag: (none) Log: Rewrite of Win32 native NTLM authentication helper, now it should be a real NTLM authenticator Members: helpers/basic_auth/win32_locallogon/valid.c:1.1.4.2->1.1.4.3 helpers/ntlm_auth/NTLMSSP-WIN32/libntlmssp.c:1.1.4.2->1.1.4.3 helpers/ntlm_auth/NTLMSSP-WIN32/ntlm.h:1.1.4.3->1.1.4.4 helpers/ntlm_auth/NTLMSSP-WIN32/ntlm_auth.c:1.1.4.5->1.1.4.6 helpers/ntlm_auth/NTLMSSP-WIN32/readme.txt:1.1.4.3->1.1.4.4 lib/sspwin32.c:1.1.4.2->1.1.4.3 Index: squid/helpers/basic_auth/win32_locallogon/valid.c =================================================================== RCS file: /cvsroot/squid-sf//squid/helpers/basic_auth/win32_locallogon/Attic/valid.c,v retrieving revision 1.1.4.2 retrieving revision 1.1.4.3 diff -u -r1.1.4.2 -r1.1.4.3 --- squid/helpers/basic_auth/win32_locallogon/valid.c 22 Sep 2002 11:40:25 -0000 1.1.4.2 +++ squid/helpers/basic_auth/win32_locallogon/valid.c 7 Sep 2003 17:17:35 -0000 1.1.4.3 @@ -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: squid/helpers/ntlm_auth/NTLMSSP-WIN32/libntlmssp.c =================================================================== RCS file: /cvsroot/squid-sf//squid/helpers/ntlm_auth/NTLMSSP-WIN32/Attic/libntlmssp.c,v retrieving revision 1.1.4.2 retrieving revision 1.1.4.3 diff -u -r1.1.4.2 -r1.1.4.3 --- squid/helpers/ntlm_auth/NTLMSSP-WIN32/libntlmssp.c 22 Sep 2002 11:40:25 -0000 1.1.4.2 +++ squid/helpers/ntlm_auth/NTLMSSP-WIN32/libntlmssp.c 7 Sep 2003 17:17:35 -0000 1.1.4.3 @@ -21,17 +21,6 @@ #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) @@ -100,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) { @@ -139,6 +111,7 @@ return target; } + char * GetDomainName(void) { @@ -227,50 +200,9 @@ 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) @@ -282,75 +214,50 @@ 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"); */ + 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_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; + 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'; } - - 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!!!!! */ - + strcpy(credentials, domain); + strcat(credentials, "\\"); + strcat(credentials, user); - - debug("checking domain: '%s', user: '%s', pass='%s'\n", domain, user, pass); - rv = SSPLogonUser(user, pass, domain); + debug("checking domain: '%s', user: '%s'\n", domain, user); + rv = SSP_ValidateCredentials(auth, auth_length); debug("Login attempt had result %d\n", rv); @@ -358,7 +265,6 @@ ntlm_errno = ss; return NULL; } - *(user - 1) = '\\'; /* hack. Performing, but ugly. */ if (UseAllowedGroup) { if (!Valid_Group(credentials, NTAllowedGroup)) { @@ -378,3 +284,82 @@ debug("credentials: %s\n", credentials); return credentials; } + + +const char * +ntlm_make_negotiate(void) +{ + ntlm_negotiate ne; + int pl = 0; + const char *encoded; + memset(&ne, 0, sizeof(ntlm_negotiate)); /* reset */ + memcpy(ne.signature, "NTLMSSP", 8); /* set the signature */ + ne.type = WSWAP(NTLM_NEGOTIATE); /* this is a challenge */ + ne.flags = WSWAP( + NEGOTIATE_ALWAYS_SIGN | + NEGOTIATE_USE_NTLM | + NEGOTIATE_USE_LM | + NEGOTIATE_ASCII | + 0 + ); + encoded = base64_encode_bin((char *) &ne, NEGOTIATE_LEGTH); + 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: squid/helpers/ntlm_auth/NTLMSSP-WIN32/ntlm.h =================================================================== RCS file: /cvsroot/squid-sf//squid/helpers/ntlm_auth/NTLMSSP-WIN32/Attic/ntlm.h,v retrieving revision 1.1.4.3 retrieving revision 1.1.4.4 diff -u -r1.1.4.3 -r1.1.4.4 --- squid/helpers/ntlm_auth/NTLMSSP-WIN32/ntlm.h 21 Jul 2002 09:07:11 -0000 1.1.4.3 +++ squid/helpers/ntlm_auth/NTLMSSP-WIN32/ntlm.h 7 Sep 2003 17:17:35 -0000 1.1.4.4 @@ -66,7 +66,6 @@ va_start(args,format); fprintf(stderr, "ntlm-auth[%d]: ",getpid()); vfprintf(stderr, format, args); - fprintf(stderr, "\n"); va_end(args); } #endif /* _SQUID_MSWIN_ */ @@ -99,10 +98,12 @@ #define NTLM_NOT_CONNECTED SEC_E_SECPKG_NOT_FOUND #define NTLM_BAD_NTGROUP -1 +#define NEGOTIATE_LEGTH 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); +extern void hex_dump(void *, int); #endif /* _NTLM_H_ */ Index: squid/helpers/ntlm_auth/NTLMSSP-WIN32/ntlm_auth.c =================================================================== RCS file: /cvsroot/squid-sf//squid/helpers/ntlm_auth/NTLMSSP-WIN32/Attic/ntlm_auth.c,v retrieving revision 1.1.4.5 retrieving revision 1.1.4.6 diff -u -r1.1.4.5 -r1.1.4.6 --- squid/helpers/ntlm_auth/NTLMSSP-WIN32/ntlm_auth.c 28 May 2003 17:37:25 -0000 1.1.4.5 +++ squid/helpers/ntlm_auth/NTLMSSP-WIN32/ntlm_auth.c 7 Sep 2003 17:17:35 -0000 1.1.4.6 @@ -1,22 +1,45 @@ /* - * $Id: ntlm_auth.c,v 1.1.4.5 2003/05/28 17:37:25 serassio Exp $ + * ntlm_auth: helper for NTLM Authentication for Squid Cache * - * This is a helper for NTLM Authentication for Squid Cache - * Copyright (C) 2002 Guido Serassio - * Based on previous work of Francesco Chemolli and Robert Collins + * (C)2002,2003 Guido Serassio - Acme Consulting S.r.l. * - * Distributed freely under the terms of the GNU General Public License, - * version 2. See the file COPYING for licensing details + * Authors: + * Guido Serassio + * Acme Consulting S.r.l., Italy + * + * With contributions from others mentioned in the change history section + * below. + * + * Based on previous work of Francesco Chemolli and Robert Collins. + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * + * History: + * + * Version 1.10 + * 07-09-2003 Guido Serassio + * Now is true NTLM authenticator + * More debug info. + * Updated documentation. + * Version 1.0 + * 29-06-2002 Guido Serassio + * First release + * + * */ @@ -25,6 +48,7 @@ #define BUFFER_SIZE 10240 +#define FAKE_NEGOTIATE 1 #ifdef DEBUG char error_messages_buffer[BUFFER_SIZE]; @@ -36,6 +60,7 @@ #endif char debug_enabled=0; +static int have_challenge; char * NTAllowedGroup; @@ -107,18 +132,18 @@ { fprintf(stderr, #ifdef NTLM_FAIL_OPEN - "%s usage:\n%s [-v] [-a UserGroup] [-d UserGroup] [-l] [-h]\n" + "Usage: %s [-d] [-A|D LocalUserGroup] [-l] [-h]\n" #else - "%s usage:\n%s [-v] [-a UserGroup] [-d UserGroup] [-h]\n" + "Usage: %s [-d] [-A|D LocalUserGroup] [-h]\n" #endif - "-v enables verbose debugging.\n" + " -d enable 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" + " -h this message\n\n", + my_program_name); } @@ -129,17 +154,17 @@ opterr =0; #ifdef NTLM_FAIL_OPEN - while (-1 != (opt = getopt(argc, argv, "hvla:d:"))) { + while (-1 != (opt = getopt(argc, argv, "hdlA:D:"))) { #else - while (-1 != (opt = getopt(argc, argv, "hva:d:"))) { + while (-1 != (opt = getopt(argc, argv, "hdA:D:"))) { #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; @@ -149,7 +174,7 @@ last_ditch_enabled = 1; break; #endif - case 'v': + case 'd': debug_enabled=1; break; case 'h': @@ -169,13 +194,12 @@ } 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 */ @@ -189,6 +213,7 @@ { ntlmhdr *fast_header; char buf[BUFFER_SIZE]; + char helper_command[3]; char *c, *decoded, *cred; int plen; int oversized = 0; @@ -212,15 +237,77 @@ oversized = 1; goto try_again; } - - debug("Got '%s' from Squid\n", buf); - + if (strlen(buf) > 3) { + decoded = base64_decode(buf + 3); + strncpy(helper_command, buf, 2); + debug("Got '%s'\n", helper_command); + hex_dump(decoded, ((strlen(buf) - 3) * 3) / 4); + debug("from Squid\n"); + } else + debug("Got '%s' from Squid\n", buf); +#if FAKE_NEGOTIATE if (memcmp(buf, "YR", 2) == 0) { /* refresh-request */ - c = (char *) obtain_challenge(); - SEND2("TT %s", c); + decoded = base64_decode(ntlm_make_negotiate()); +#else + if (memcmp(buf, "YR ", 3) == 0) { /* refresh-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. + */ +#endif + 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: + /* Obtain challenge against SSPI */ +#if FAKE_NEGOTIATE + plen = NEGOTIATE_LEGTH; +#else + plen = (strlen(buf) - 3) * 3 / 4; /* we only need it here. Optimization */ +#endif + if ((c = (char *) obtain_challenge((ntlm_negotiate *) decoded, plen)) != NULL ) + { + decoded = base64_decode(c); + debug("sending 'TT'\n"); + hex_dump(decoded, (strlen(c) * 3) / 4); + debug("to squid\n"); + printf("TT %s\n",c); + have_challenge = 1; + } else + helperfail("can't obtain challenge"); + return; + /* notreached */ + case NTLM_CHALLENGE: + SEND + ("NA Got a challenge. We refuse to have our authority disputed"); + return; + /* notreached */ + case NTLM_AUTHENTICATE: + SEND("NA Got authentication request instead of negotiate request"); + return; + /* notreached */ + default: + helperfail("unknown refresh-request packet type"); + return; + } return; } if (memcmp(buf, "KK ", 3) == 0) { /* authenticate-request */ + if (!have_challenge) { + helperfail("invalid challenge"); + return; + } /* figure out what we got */ decoded = base64_decode(buf + 3); /* Note: we don't need to manage memory at this point, since @@ -251,7 +338,7 @@ /* 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); if (cred == NULL) { switch (ntlm_errno) { @@ -271,6 +358,7 @@ } lc(cred); /* let's lowercase them for our convenience */ SEND2("AF %s", cred); + have_challenge = 0; return; default: helperfail("unknown authentication packet type"); @@ -290,12 +378,12 @@ 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"); + + debug("%s build " __DATE__ ", " __TIME__ " starting up...\n", my_program_name); + srand( (unsigned)time( NULL ) ); if (LoadSecurityDll(SSP_NTLM) == NULL) { Index: squid/helpers/ntlm_auth/NTLMSSP-WIN32/readme.txt =================================================================== RCS file: /cvsroot/squid-sf//squid/helpers/ntlm_auth/NTLMSSP-WIN32/Attic/readme.txt,v retrieving revision 1.1.4.3 retrieving revision 1.1.4.4 diff -u -r1.1.4.3 -r1.1.4.4 --- squid/helpers/ntlm_auth/NTLMSSP-WIN32/readme.txt 14 Jun 2003 10:36:49 -0000 1.1.4.3 +++ squid/helpers/ntlm_auth/NTLMSSP-WIN32/readme.txt 7 Sep 2003 17:17:35 -0000 1.1.4.4 @@ -6,12 +6,13 @@ Usage ===== -ntlm_auth [-v] [-a UserGroup] [-d UserGroup] [-l] +ntlm_auth [-d] [-A|D LocalUserGroup] [-l] [-h] --v enables debugging statements. +-d enables debugging statements. -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. +-h print program usage This is released under the GNU General Public License Index: squid/lib/sspwin32.c =================================================================== RCS file: /cvsroot/squid-sf//squid/lib/sspwin32.c,v retrieving revision 1.1.4.2 retrieving revision 1.1.4.3 diff -u -r1.1.4.2 -r1.1.4.3 --- squid/lib/sspwin32.c 22 Sep 2002 11:39:41 -0000 1.1.4.2 +++ squid/lib/sspwin32.c 7 Sep 2003 17:18:41 -0000 1.1.4.3 @@ -16,6 +16,7 @@ */ #include "squid.h" +#include "ntlmauth.h" #include "sspwin32.h" typedef struct _AUTH_SEQ { @@ -23,13 +24,23 @@ 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; +static DWORD cbMaxToken = 0; +static PVOID pClientBuf = NULL; +static PVOID pServerBuf = NULL; + +static AUTH_SEQ NTLM_asServer = {0}; + +BOOL Use_Unicode = FALSE; + /* Function pointers */ ACCEPT_SECURITY_CONTEXT_FN _AcceptSecurityContext = NULL; ACQUIRE_CREDENTIALS_HANDLE_FN _AcquireCredentialsHandle = NULL; @@ -45,6 +56,10 @@ { if (hModule) FreeLibrary(hModule); + + xfree(pClientBuf); + xfree(pServerBuf); + _AcceptSecurityContext = NULL; _AcquireCredentialsHandle = NULL; _CompleteAuthToken = NULL; @@ -53,6 +68,7 @@ _FreeCredentialsHandle = NULL; _InitializeSecurityContext = NULL; _QuerySecurityPackageInfo = NULL; + hModule = NULL; } @@ -61,7 +77,9 @@ { 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 * We have to use security.dll on Windows NT 4.0. @@ -154,6 +172,16 @@ 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; } @@ -254,7 +282,6 @@ * Returns TRUE if successful; otherwise FALSE. */ - TimeStamp tsExpiry; SecBufferDesc sbdOut; SecBuffer sbOut; SecBufferDesc sbdIn; @@ -264,7 +291,7 @@ if (!pAS->fInitialized) { ss = _AcquireCredentialsHandle(NULL, _T("NTLM"), SECPKG_CRED_INBOUND, NULL, NULL, NULL, NULL, &pAS->hcred, - &tsExpiry); + &pAS->hcredLifeTime); if (ss < 0) { fprintf(stderr, "AcquireCredentialsHandle failed with %08lX\n", ss); return FALSE; @@ -290,7 +317,7 @@ ss = _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); + &pAS->hctxtLifeTime); if (ss < 0) { fprintf(stderr, "AcceptSecurityContext failed with %08lX\n", ss); return FALSE; @@ -319,7 +346,7 @@ } -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}; @@ -327,26 +354,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(_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); @@ -402,8 +417,93 @@ _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); + + 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)) + break; + fResult = pServerBuf; + } while(0); + if (fResult != NULL) { + challenge = (ntlm_challenge *) fResult; + Use_Unicode = NEGOTIATE_UNICODE & challenge->flags; + encoded = base64_encode_bin((char *) fResult, cbOut); + } + return encoded; +} + + +BOOL WINAPI SSP_ValidateCredentials(PVOID PAutenticateBuf, int AutenticateLen) +{ + 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)) + break; + fResult = TRUE; + } while(0); + + return fResult; +} + + +BOOL WINAPI SSP_VerifyChallenge(void) +{ + BOOL fResult = FALSE; + FILETIME SysTime; + ULARGE_INTEGER Now; + + GetSystemTimeAsFileTime(&SysTime); + memcpy(&Now, &SysTime, sizeof(Now)); + if ((Now.QuadPart >= (unsigned) NTLM_asServer.hctxtLifeTime.QuadPart ) && + (Now.QuadPart >= (unsigned) NTLM_asServer.hcredLifeTime.QuadPart)) + fResult = TRUE; + + fprintf(stderr,"hctxtLifeTime: %LLu\n",(unsigned) NTLM_asServer.hctxtLifeTime.QuadPart); + fprintf(stderr,"hcredLifeTime: %LLu\n",(unsigned) NTLM_asServer.hcredLifeTime.QuadPart); + fprintf(stderr,"SystemTime: %LLu\n",Now.QuadPart); + return fResult; }