#include "windef.h"
#include "winbase.h"
#include "winnls.h"
+#include "wincred.h"
#include "rpc.h"
#include "sspi.h"
#include "lm.h"
#include "secur32_priv.h"
#include "hmac_md5.h"
+#include "wine/unicode.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(ntlm);
static CHAR ntlm_auth[] = "ntlm_auth";
+typedef struct _NtlmCredentials
+{
+ HelperMode mode;
+
+ /* these are all in the Unix codepage */
+ char *username_arg;
+ char *domain_arg;
+ char *password; /* not nul-terminated */
+ int pwlen;
+} NtlmCredentials, *PNtlmCredentials;
+
/***********************************************************************
* QueryCredentialsAttributesA
*/
return ret;
}
+static char *ntlm_GetUsernameArg(LPCWSTR userW, INT userW_length)
+{
+ static const char username_arg[] = "--username=";
+ char *user;
+ int unixcp_size;
+
+ unixcp_size = WideCharToMultiByte(CP_UNIXCP, WC_NO_BEST_FIT_CHARS,
+ userW, userW_length, NULL, 0, NULL, NULL) + sizeof(username_arg);
+ user = HeapAlloc(GetProcessHeap(), 0, unixcp_size);
+ if (!user) return NULL;
+ memcpy(user, username_arg, sizeof(username_arg) - 1);
+ WideCharToMultiByte(CP_UNIXCP, WC_NO_BEST_FIT_CHARS, userW, userW_length,
+ user + sizeof(username_arg) - 1,
+ unixcp_size - sizeof(username_arg) + 1, NULL, NULL);
+ user[unixcp_size - 1] = '\0';
+ return user;
+}
+
+static char *ntlm_GetDomainArg(LPCWSTR domainW, INT domainW_length)
+{
+ static const char domain_arg[] = "--domain=";
+ char *domain;
+ int unixcp_size;
+
+ unixcp_size = WideCharToMultiByte(CP_UNIXCP, WC_NO_BEST_FIT_CHARS,
+ domainW, domainW_length, NULL, 0, NULL, NULL) + sizeof(domain_arg);
+ domain = HeapAlloc(GetProcessHeap(), 0, unixcp_size);
+ if (!domain) return NULL;
+ memcpy(domain, domain_arg, sizeof(domain_arg) - 1);
+ WideCharToMultiByte(CP_UNIXCP, WC_NO_BEST_FIT_CHARS, domainW,
+ domainW_length, domain + sizeof(domain_arg) - 1,
+ unixcp_size - sizeof(domain) + 1, NULL, NULL);
+ domain[unixcp_size - 1] = '\0';
+ return domain;
+}
+
/***********************************************************************
* AcquireCredentialsHandleW
*/
PVOID pGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
{
SECURITY_STATUS ret;
- PNegoHelper helper = NULL;
- static CHAR server_helper_protocol[] = "--helper-protocol=squid-2.5-ntlmssp",
- credentials_argv[] = "--use-cached-creds";
-
- SEC_CHAR *client_user_arg = NULL;
- SEC_CHAR *client_domain_arg = NULL;
+ PNtlmCredentials ntlm_cred = NULL;
SEC_WCHAR *username = NULL, *domain = NULL;
- SEC_CHAR *client_argv[6];
- SEC_CHAR *server_argv[] = { ntlm_auth,
- server_helper_protocol,
- NULL };
-
TRACE("(%s, %s, 0x%08x, %p, %p, %p, %p, %p, %p)\n",
debugstr_w(pszPrincipal), debugstr_w(pszPackage), fCredentialUse,
pLogonID, pAuthData, pGetKeyFn, pGetKeyArgument, phCredential, ptsExpiry);
-
switch(fCredentialUse)
{
case SECPKG_CRED_INBOUND:
- if( (ret = fork_helper(&helper, ntlm_auth, server_argv)) !=
- SEC_E_OK)
- {
- phCredential = NULL;
- break;
- }
+ ntlm_cred = HeapAlloc(GetProcessHeap(), 0, sizeof(*ntlm_cred));
+ if (!ntlm_cred)
+ ret = SEC_E_INSUFFICIENT_MEMORY;
else
{
- helper->mode = NTLM_SERVER;
+ ntlm_cred->mode = NTLM_SERVER;
+ ntlm_cred->username_arg = NULL;
+ ntlm_cred->domain_arg = NULL;
+ ntlm_cred->password = NULL;
+ ntlm_cred->pwlen = 0;
phCredential->dwUpper = fCredentialUse;
- phCredential->dwLower = (ULONG_PTR)helper;
+ phCredential->dwLower = (ULONG_PTR)ntlm_cred;
+ ret = SEC_E_OK;
}
- ret = SEC_E_OK;
break;
case SECPKG_CRED_OUTBOUND:
{
- static const char username_arg[] = "--username=";
- static const char domain_arg[] = "--domain=";
- static char helper_protocol[] = "--helper-protocol=ntlmssp-client-1";
- int unixcp_size;
-
- if(pAuthData == NULL)
- {
- LPWKSTA_USER_INFO_1 ui = NULL;
- NET_API_STATUS status;
-
- status = NetWkstaUserGetInfo(NULL, 1, (LPBYTE *)&ui);
- if (status != NERR_Success || ui == NULL)
- {
- ret = SEC_E_NO_CREDENTIALS;
- phCredential = NULL;
- break;
- }
-
- username = HeapAlloc(GetProcessHeap(), 0,
- (lstrlenW(ui->wkui1_username)+1) *
- sizeof(SEC_WCHAR));
- lstrcpyW(username, ui->wkui1_username);
-
- /* same for the domain */
- domain = HeapAlloc(GetProcessHeap(), 0,
- (lstrlenW(ui->wkui1_logon_domain)+1) *
- sizeof(SEC_WCHAR));
- lstrcpyW(domain, ui->wkui1_logon_domain);
- NetApiBufferFree(ui);
- }
- else
+ ntlm_cred = HeapAlloc(GetProcessHeap(), 0, sizeof(*ntlm_cred));
+ if (!ntlm_cred)
{
- PSEC_WINNT_AUTH_IDENTITY_W auth_data =
- (PSEC_WINNT_AUTH_IDENTITY_W)pAuthData;
-
- /* Get username and domain from pAuthData */
- username = HeapAlloc(GetProcessHeap(), 0,
- (auth_data->UserLength + 1) * sizeof(SEC_WCHAR));
- memcpy(username, auth_data->User,
- auth_data->UserLength * sizeof(SEC_WCHAR));
- username[auth_data->UserLength] = '\0';
-
- domain = HeapAlloc(GetProcessHeap(), 0,
- (auth_data->DomainLength + 1) * sizeof(SEC_WCHAR));
- memcpy(domain, auth_data->Domain,
- auth_data->DomainLength * sizeof(SEC_WCHAR));
- domain[auth_data->DomainLength] = '\0';
- }
- TRACE("Username is %s\n", debugstr_w(username));
- unixcp_size = WideCharToMultiByte(CP_UNIXCP, WC_NO_BEST_FIT_CHARS,
- username, -1, NULL, 0, NULL, NULL) + sizeof(username_arg);
- client_user_arg = HeapAlloc(GetProcessHeap(), 0, unixcp_size);
- lstrcpyA(client_user_arg, username_arg);
- WideCharToMultiByte(CP_UNIXCP, WC_NO_BEST_FIT_CHARS, username, -1,
- client_user_arg + sizeof(username_arg) - 1,
- unixcp_size - sizeof(username_arg) + 1, NULL, NULL);
-
- TRACE("Domain name is %s\n", debugstr_w(domain));
- unixcp_size = WideCharToMultiByte(CP_UNIXCP, WC_NO_BEST_FIT_CHARS,
- domain, -1, NULL, 0, NULL, NULL) + sizeof(domain_arg);
- client_domain_arg = HeapAlloc(GetProcessHeap(), 0, unixcp_size);
- lstrcpyA(client_domain_arg, domain_arg);
- WideCharToMultiByte(CP_UNIXCP, WC_NO_BEST_FIT_CHARS, domain,
- -1, client_domain_arg + sizeof(domain_arg) - 1,
- unixcp_size - sizeof(domain) + 1, NULL, NULL);
-
- client_argv[0] = ntlm_auth;
- client_argv[1] = helper_protocol;
- client_argv[2] = client_user_arg;
- client_argv[3] = client_domain_arg;
- client_argv[4] = credentials_argv;
- client_argv[5] = NULL;
-
- if((ret = fork_helper(&helper, ntlm_auth, client_argv)) !=
- SEC_E_OK)
- {
- phCredential = NULL;
+ ret = SEC_E_INSUFFICIENT_MEMORY;
break;
}
- else
+ ntlm_cred->mode = NTLM_CLIENT;
+ ntlm_cred->username_arg = NULL;
+ ntlm_cred->domain_arg = NULL;
+ ntlm_cred->password = NULL;
+ ntlm_cred->pwlen = 0;
+
+ if(pAuthData != NULL)
{
- helper->mode = NTLM_CLIENT;
+ PSEC_WINNT_AUTH_IDENTITY_W auth_data = pAuthData;
- if(pAuthData != NULL)
+ TRACE("Username is %s\n", debugstr_wn(auth_data->User, auth_data->UserLength));
+ TRACE("Domain name is %s\n", debugstr_wn(auth_data->Domain, auth_data->DomainLength));
+
+ ntlm_cred->username_arg = ntlm_GetUsernameArg(auth_data->User, auth_data->UserLength);
+ ntlm_cred->domain_arg = ntlm_GetDomainArg(auth_data->Domain, auth_data->DomainLength);
+
+ if(auth_data->PasswordLength != 0)
{
- PSEC_WINNT_AUTH_IDENTITY_W auth_data =
- (PSEC_WINNT_AUTH_IDENTITY_W)pAuthData;
-
- if(auth_data->PasswordLength != 0)
- {
- helper->pwlen = WideCharToMultiByte(CP_UNIXCP,
- WC_NO_BEST_FIT_CHARS, auth_data->Password,
- auth_data->PasswordLength, NULL, 0, NULL,
- NULL);
-
- helper->password = HeapAlloc(GetProcessHeap(), 0,
- helper->pwlen);
-
- WideCharToMultiByte(CP_UNIXCP, WC_NO_BEST_FIT_CHARS,
- auth_data->Password, auth_data->PasswordLength,
- helper->password, helper->pwlen, NULL, NULL);
- }
- }
+ ntlm_cred->pwlen = WideCharToMultiByte(CP_UNIXCP,
+ WC_NO_BEST_FIT_CHARS, auth_data->Password,
+ auth_data->PasswordLength, NULL, 0, NULL,
+ NULL);
+
+ ntlm_cred->password = HeapAlloc(GetProcessHeap(), 0,
+ ntlm_cred->pwlen);
- phCredential->dwUpper = fCredentialUse;
- phCredential->dwLower = (ULONG_PTR)helper;
- TRACE("ACH phCredential->dwUpper: 0x%08lx, dwLower: 0x%08lx\n",
- phCredential->dwUpper, phCredential->dwLower);
+ WideCharToMultiByte(CP_UNIXCP, WC_NO_BEST_FIT_CHARS,
+ auth_data->Password, auth_data->PasswordLength,
+ ntlm_cred->password, ntlm_cred->pwlen, NULL, NULL);
+ }
}
+
+ phCredential->dwUpper = fCredentialUse;
+ phCredential->dwLower = (ULONG_PTR)ntlm_cred;
+ TRACE("ACH phCredential->dwUpper: 0x%08lx, dwLower: 0x%08lx\n",
+ phCredential->dwUpper, phCredential->dwLower);
ret = SEC_E_OK;
break;
}
phCredential = NULL;
ret = SEC_E_UNKNOWN_CREDENTIALS;
}
-
- HeapFree(GetProcessHeap(), 0, client_user_arg);
- HeapFree(GetProcessHeap(), 0, client_domain_arg);
HeapFree(GetProcessHeap(), 0, username);
HeapFree(GetProcessHeap(), 0, domain);
if(pAuthData != NULL)
{
- identity = (PSEC_WINNT_AUTH_IDENTITY_A)pAuthData;
-
+ identity = pAuthData;
+
if(identity->Flags == SEC_WINNT_AUTH_IDENTITY_ANSI)
{
pAuthDataW = HeapAlloc(GetProcessHeap(), 0,
return ret;
}
+/*************************************************************************
+ * ntlm_GetTokenBufferIndex
+ * Calculates the index of the secbuffer with BufferType == SECBUFFER_TOKEN
+ * Returns index if found or -1 if not found.
+ */
+static int ntlm_GetTokenBufferIndex(PSecBufferDesc pMessage)
+{
+ UINT i;
+
+ TRACE("%p\n", pMessage);
+
+ for( i = 0; i < pMessage->cBuffers; ++i )
+ {
+ if(pMessage->pBuffers[i].BufferType == SECBUFFER_TOKEN)
+ return i;
+ }
+
+ return -1;
+}
+
+/*************************************************************************
+ * ntlm_GetDataBufferIndex
+ * Calculates the index of the first secbuffer with BufferType == SECBUFFER_DATA
+ * Returns index if found or -1 if not found.
+ */
+static int ntlm_GetDataBufferIndex(PSecBufferDesc pMessage)
+{
+ UINT i;
+
+ TRACE("%p\n", pMessage);
+
+ for( i = 0; i < pMessage->cBuffers; ++i )
+ {
+ if(pMessage->pBuffers[i].BufferType == SECBUFFER_DATA)
+ return i;
+ }
+
+ return -1;
+}
+
+static BOOL ntlm_GetCachedCredential(const SEC_WCHAR *pszTargetName, PCREDENTIALW *cred)
+{
+ LPCWSTR p;
+ LPCWSTR pszHost;
+ LPWSTR pszHostOnly;
+ BOOL ret;
+
+ if (!pszTargetName)
+ return FALSE;
+
+ /* try to get the start of the hostname from service principal name (SPN) */
+ pszHost = strchrW(pszTargetName, '/');
+ if (pszHost)
+ {
+ /* skip slash character */
+ pszHost++;
+
+ /* find end of host by detecting start of instance port or start of referrer */
+ p = strchrW(pszHost, ':');
+ if (!p)
+ p = strchrW(pszHost, '/');
+ if (!p)
+ p = pszHost + strlenW(pszHost);
+ }
+ else /* otherwise not an SPN, just a host */
+ {
+ pszHost = pszTargetName;
+ p = pszHost + strlenW(pszHost);
+ }
+
+ pszHostOnly = HeapAlloc(GetProcessHeap(), 0, (p - pszHost + 1) * sizeof(WCHAR));
+ if (!pszHostOnly)
+ return FALSE;
+
+ memcpy(pszHostOnly, pszHost, (p - pszHost) * sizeof(WCHAR));
+ pszHostOnly[p - pszHost] = '\0';
+
+ ret = CredReadW(pszHostOnly, CRED_TYPE_DOMAIN_PASSWORD, 0, cred);
+
+ HeapFree(GetProcessHeap(), 0, pszHostOnly);
+ return ret;
+}
+
/***********************************************************************
* InitializeSecurityContextW
*/
PSecBufferDesc pOutput, ULONG *pfContextAttr, PTimeStamp ptsExpiry)
{
SECURITY_STATUS ret;
- PNegoHelper helper;
+ PNtlmCredentials ntlm_cred = NULL;
+ PNegoHelper helper = NULL;
ULONG ctxt_attr = 0;
char* buffer, *want_flags = NULL;
PBYTE bin;
int buffer_len, bin_len, max_len = NTLM_MAX_BUF;
+ int token_idx;
+ SEC_CHAR *username = NULL;
+ SEC_CHAR *domain = NULL;
+ SEC_CHAR *password = NULL;
- TRACE("%p %p %s %d %d %d %p %d %p %p %p %p\n", phCredential, phContext,
+ TRACE("%p %p %s 0x%08x %d %d %p %d %p %p %p %p\n", phCredential, phContext,
debugstr_w(pszTargetName), fContextReq, Reserved1, TargetDataRep, pInput,
Reserved1, phNewContext, pOutput, pfContextAttr, ptsExpiry);
*/
/* The squid cache size is 2010 chars, and that's what ntlm_auth uses */
- if (pszTargetName)
- {
- TRACE("According to a MS whitepaper pszTargetName is ignored.\n");
- }
-
if(TargetDataRep == SECURITY_NETWORK_DREP){
TRACE("Setting SECURITY_NETWORK_DREP\n");
}
if((phContext == NULL) && (pInput == NULL))
{
+ static char helper_protocol[] = "--helper-protocol=ntlmssp-client-1";
+ static CHAR credentials_argv[] = "--use-cached-creds";
+ SEC_CHAR *client_argv[5];
+ int pwlen = 0;
+
TRACE("First time in ISC()\n");
if(!phCredential)
- return SEC_E_INVALID_HANDLE;
+ {
+ ret = SEC_E_INVALID_HANDLE;
+ goto isc_end;
+ }
/* As the server side of sspi never calls this, make sure that
* the handler is a client handler.
*/
- helper = (PNegoHelper)phCredential->dwLower;
- if(helper->mode != NTLM_CLIENT)
+ ntlm_cred = (PNtlmCredentials)phCredential->dwLower;
+ if(ntlm_cred->mode != NTLM_CLIENT)
{
- TRACE("Helper mode = %d\n", helper->mode);
- return SEC_E_INVALID_HANDLE;
+ TRACE("Cred mode = %d\n", ntlm_cred->mode);
+ ret = SEC_E_INVALID_HANDLE;
+ goto isc_end;
+ }
+
+ client_argv[0] = ntlm_auth;
+ client_argv[1] = helper_protocol;
+ if (!ntlm_cred->username_arg && !ntlm_cred->domain_arg)
+ {
+ LPWKSTA_USER_INFO_1 ui = NULL;
+ NET_API_STATUS status;
+ PCREDENTIALW cred;
+
+ if (ntlm_GetCachedCredential(pszTargetName, &cred))
+ {
+ LPWSTR p;
+ p = strchrW(cred->UserName, '\\');
+ if (p)
+ {
+ domain = ntlm_GetDomainArg(cred->UserName, p - cred->UserName);
+ p++;
+ }
+ else
+ {
+ domain = ntlm_GetDomainArg(NULL, 0);
+ p = cred->UserName;
+ }
+
+ username = ntlm_GetUsernameArg(p, -1);
+
+ if(cred->CredentialBlobSize != 0)
+ {
+ pwlen = WideCharToMultiByte(CP_UNIXCP,
+ WC_NO_BEST_FIT_CHARS, (LPWSTR)cred->CredentialBlob,
+ cred->CredentialBlobSize / sizeof(WCHAR), NULL, 0,
+ NULL, NULL);
+
+ password = HeapAlloc(GetProcessHeap(), 0, pwlen);
+
+ WideCharToMultiByte(CP_UNIXCP, WC_NO_BEST_FIT_CHARS,
+ (LPWSTR)cred->CredentialBlob,
+ cred->CredentialBlobSize / sizeof(WCHAR),
+ password, pwlen, NULL, NULL);
+ }
+
+ CredFree(cred);
+
+ client_argv[2] = username;
+ client_argv[3] = domain;
+ client_argv[4] = NULL;
+ }
+ else
+ {
+ status = NetWkstaUserGetInfo(NULL, 1, (LPBYTE *)&ui);
+ if (status != NERR_Success || ui == NULL)
+ {
+ ret = SEC_E_NO_CREDENTIALS;
+ goto isc_end;
+ }
+ username = ntlm_GetUsernameArg(ui->wkui1_username, -1);
+ NetApiBufferFree(ui);
+
+ TRACE("using cached credentials\n");
+
+ client_argv[2] = username;
+ client_argv[3] = credentials_argv;
+ client_argv[4] = NULL;
+ }
+ }
+ else
+ {
+ client_argv[2] = ntlm_cred->username_arg;
+ client_argv[3] = ntlm_cred->domain_arg;
+ client_argv[4] = NULL;
+ }
+
+ if((ret = fork_helper(&helper, ntlm_auth, client_argv)) != SEC_E_OK)
+ goto isc_end;
+
+ helper->mode = NTLM_CLIENT;
+ helper->session_key = HeapAlloc(GetProcessHeap(), 0, 16);
+ if (!helper->session_key)
+ {
+ cleanup_helper(helper);
+ ret = SEC_E_INSUFFICIENT_MEMORY;
+ goto isc_end;
}
- /* Allocate space for a maximal string of
+ /* Generate the dummy session key = MD4(MD4(password))*/
+ if(password || ntlm_cred->password)
+ {
+ SEC_WCHAR *unicode_password;
+ int passwd_lenW;
+
+ TRACE("Converting password to unicode.\n");
+ passwd_lenW = MultiByteToWideChar(CP_ACP, 0,
+ password ? password : ntlm_cred->password,
+ password ? pwlen : ntlm_cred->pwlen,
+ NULL, 0);
+ unicode_password = HeapAlloc(GetProcessHeap(), 0,
+ passwd_lenW * sizeof(SEC_WCHAR));
+ MultiByteToWideChar(CP_ACP, 0, password ? password : ntlm_cred->password,
+ password ? pwlen : ntlm_cred->pwlen, unicode_password, passwd_lenW);
+
+ SECUR32_CreateNTLM1SessionKey((PBYTE)unicode_password,
+ passwd_lenW * sizeof(SEC_WCHAR), helper->session_key);
+
+ HeapFree(GetProcessHeap(), 0, unicode_password);
+ }
+ else
+ memset(helper->session_key, 0, 16);
+
+ /* Allocate space for a maximal string of
* "SF NTLMSSP_FEATURE_SIGN NTLMSSP_FEATURE_SEAL
* NTLMSSP_FEATURE_SESSION_KEY"
*/
want_flags = HeapAlloc(GetProcessHeap(), 0, 73);
if(want_flags == NULL)
{
+ cleanup_helper(helper);
ret = SEC_E_INSUFFICIENT_MEMORY;
goto isc_end;
}
lstrcpyA(want_flags, "SF");
if(fContextReq & ISC_REQ_CONFIDENTIALITY)
{
- char *ptr;
- if((ptr = strstr(want_flags, "NTLMSSP_FEATURE_SEAL")) == NULL)
+ if(strstr(want_flags, "NTLMSSP_FEATURE_SEAL") == NULL)
lstrcatA(want_flags, " NTLMSSP_FEATURE_SEAL");
}
if(fContextReq & ISC_REQ_CONNECTION)
ctxt_attr |= ISC_RET_EXTENDED_ERROR;
if(fContextReq & ISC_REQ_INTEGRITY)
{
- char *ptr;
- if((ptr = strstr(want_flags, "NTLMSSP_FEATURE_SIGN")) == NULL)
+ if(strstr(want_flags, "NTLMSSP_FEATURE_SIGN") == NULL)
lstrcatA(want_flags, " NTLMSSP_FEATURE_SIGN");
}
if(fContextReq & ISC_REQ_MUTUAL_AUTH)
ctxt_attr |= ISC_RET_MUTUAL_AUTH;
if(fContextReq & ISC_REQ_REPLAY_DETECT)
{
- char *ptr;
- if((ptr = strstr(want_flags, "NTLMSSP_FEATURE_SIGN")) == NULL)
+ if(strstr(want_flags, "NTLMSSP_FEATURE_SIGN") == NULL)
lstrcatA(want_flags, " NTLMSSP_FEATURE_SIGN");
}
if(fContextReq & ISC_REQ_SEQUENCE_DETECT)
{
- char *ptr;
- if((ptr = strstr(want_flags, "NTLMSSP_FEATURE_SIGN")) == NULL)
+ if(strstr(want_flags, "NTLMSSP_FEATURE_SIGN") == NULL)
lstrcatA(want_flags, " NTLMSSP_FEATURE_SIGN");
}
if(fContextReq & ISC_REQ_STREAM)
/* If no password is given, try to use cached credentials. Fall back to an empty
* password if this failed. */
- if(helper->password == NULL)
+ if(!password && !ntlm_cred->password)
{
lstrcpynA(buffer, "OK", max_len-1);
if((ret = run_helper(helper, buffer, max_len, &buffer_len)) != SEC_E_OK)
+ {
+ cleanup_helper(helper);
goto isc_end;
+ }
/* If the helper replied with "PW", using cached credentials failed */
if(!strncmp(buffer, "PW", 2))
{
- TRACE("Using cached credentials failed. Using empty password.\n");
+ TRACE("Using cached credentials failed.\n");
lstrcpynA(buffer, "PW AA==", max_len-1);
}
else /* Just do a noop on the next run */
else
{
lstrcpynA(buffer, "PW ", max_len-1);
- if((ret = encodeBase64((unsigned char*)helper->password,
- helper->pwlen, buffer+3,
+ if((ret = encodeBase64(password ? (unsigned char *)password : (unsigned char *)ntlm_cred->password,
+ password ? pwlen : ntlm_cred->pwlen, buffer+3,
max_len-3, &buffer_len)) != SEC_E_OK)
{
- TRACE("Deleting password!\n");
- memset(helper->password, 0, helper->pwlen);
- HeapFree(GetProcessHeap(), 0, helper->password);
+ cleanup_helper(helper);
goto isc_end;
}
TRACE("Sending to helper: %s\n", debugstr_a(buffer));
if((ret = run_helper(helper, buffer, max_len, &buffer_len)) != SEC_E_OK)
+ {
+ cleanup_helper(helper);
goto isc_end;
+ }
TRACE("Helper returned %s\n", debugstr_a(buffer));
lstrcpynA(buffer, "YR", max_len-1);
if((ret = run_helper(helper, buffer, max_len, &buffer_len)) != SEC_E_OK)
+ {
+ cleanup_helper(helper);
goto isc_end;
+ }
TRACE("%s\n", buffer);
/* Something borked */
TRACE("Helper returned %c%c\n", buffer[0], buffer[1]);
ret = SEC_E_INTERNAL_ERROR;
+ cleanup_helper(helper);
goto isc_end;
}
if((ret = decodeBase64(buffer+3, buffer_len-3, bin,
max_len-1, &bin_len)) != SEC_E_OK)
+ {
+ cleanup_helper(helper);
goto isc_end;
+ }
/* put the decoded client blob into the out buffer */
}
else
{
+ int input_token_idx;
+
/* handle second call here */
/* encode server data to base64 */
- if (!pInput || !pInput->cBuffers)
+ if (!pInput || ((input_token_idx = ntlm_GetTokenBufferIndex(pInput)) == -1))
{
- ret = SEC_E_INCOMPLETE_MESSAGE;
+ ret = SEC_E_INVALID_TOKEN;
goto isc_end;
}
if(!phContext)
- return SEC_E_INVALID_HANDLE;
+ {
+ ret = SEC_E_INVALID_HANDLE;
+ goto isc_end;
+ }
/* As the server side of sspi never calls this, make sure that
* the handler is a client handler.
if(helper->mode != NTLM_CLIENT)
{
TRACE("Helper mode = %d\n", helper->mode);
- return SEC_E_INVALID_HANDLE;
+ ret = SEC_E_INVALID_HANDLE;
+ goto isc_end;
}
- if (!pInput->pBuffers[0].pvBuffer)
+ if (!pInput->pBuffers[input_token_idx].pvBuffer)
{
ret = SEC_E_INTERNAL_ERROR;
goto isc_end;
}
- if(pInput->pBuffers[0].cbBuffer > max_len)
+ if(pInput->pBuffers[input_token_idx].cbBuffer > max_len)
{
- TRACE("pInput->pBuffers[0].cbBuffer is: %ld\n",
- pInput->pBuffers[0].cbBuffer);
+ TRACE("pInput->pBuffers[%d].cbBuffer is: %d\n",
+ input_token_idx,
+ pInput->pBuffers[input_token_idx].cbBuffer);
ret = SEC_E_INVALID_TOKEN;
goto isc_end;
}
else
- bin_len = pInput->pBuffers[0].cbBuffer;
+ bin_len = pInput->pBuffers[input_token_idx].cbBuffer;
- memcpy(bin, pInput->pBuffers[0].pvBuffer, bin_len);
+ memcpy(bin, pInput->pBuffers[input_token_idx].pvBuffer, bin_len);
lstrcpynA(buffer, "TT ", max_len-1);
/* put the decoded client blob into the out buffer */
- if (fContextReq & ISC_REQ_ALLOCATE_MEMORY)
+ if (!pOutput || ((token_idx = ntlm_GetTokenBufferIndex(pOutput)) == -1))
{
- if (pOutput)
+ TRACE("no SECBUFFER_TOKEN buffer could be found\n");
+ ret = SEC_E_BUFFER_TOO_SMALL;
+ if ((phContext == NULL) && (pInput == NULL))
{
- pOutput->cBuffers = 1;
- pOutput->pBuffers[0].pvBuffer = SECUR32_ALLOC(bin_len);
- pOutput->pBuffers[0].cbBuffer = bin_len;
+ HeapFree(GetProcessHeap(), 0, helper->session_key);
+ cleanup_helper(helper);
+ phNewContext->dwUpper = 0;
+ phNewContext->dwLower = 0;
}
+ goto isc_end;
}
- if (!pOutput || !pOutput->cBuffers || pOutput->pBuffers[0].cbBuffer < bin_len)
+ if (fContextReq & ISC_REQ_ALLOCATE_MEMORY)
+ {
+ pOutput->pBuffers[token_idx].pvBuffer = HeapAlloc(GetProcessHeap(), 0, bin_len);
+ pOutput->pBuffers[token_idx].cbBuffer = bin_len;
+ }
+ else if (pOutput->pBuffers[token_idx].cbBuffer < bin_len)
{
TRACE("out buffer is NULL or has not enough space\n");
ret = SEC_E_BUFFER_TOO_SMALL;
+ if ((phContext == NULL) && (pInput == NULL))
+ {
+ HeapFree(GetProcessHeap(), 0, helper->session_key);
+ cleanup_helper(helper);
+ phNewContext->dwUpper = 0;
+ phNewContext->dwLower = 0;
+ }
goto isc_end;
}
- if (!pOutput->pBuffers[0].pvBuffer)
+ if (!pOutput->pBuffers[token_idx].pvBuffer)
{
TRACE("out buffer is NULL\n");
ret = SEC_E_INTERNAL_ERROR;
+ if ((phContext == NULL) && (pInput == NULL))
+ {
+ HeapFree(GetProcessHeap(), 0, helper->session_key);
+ cleanup_helper(helper);
+ phNewContext->dwUpper = 0;
+ phNewContext->dwLower = 0;
+ }
goto isc_end;
}
- pOutput->pBuffers[0].cbBuffer = bin_len;
- memcpy(pOutput->pBuffers[0].pvBuffer, bin, bin_len);
+ pOutput->pBuffers[token_idx].cbBuffer = bin_len;
+ memcpy(pOutput->pBuffers[token_idx].pvBuffer, bin, bin_len);
if(ret == SEC_E_OK)
{
else
{
TRACE("Negotiated %s\n", debugstr_a(buffer));
- sscanf(buffer + 3, "%lx", &(helper->neg_flags));
- TRACE("Stored 0x%08lx as flags\n", helper->neg_flags);
+ sscanf(buffer + 3, "%x", &(helper->neg_flags));
+ TRACE("Stored 0x%08x as flags\n", helper->neg_flags);
}
TRACE("Getting session key\n");
goto isc_end;
if(strncmp(buffer, "BH", 2) == 0)
- {
TRACE("No key negotiated.\n");
- helper->valid_session_key = FALSE;
- helper->session_key = HeapAlloc(GetProcessHeap(), 0, 16);
- /*Generate the dummy session key = MD4(MD4(password))*/
- if(helper->password)
- {
- SEC_WCHAR *unicode_password;
- int passwd_lenW;
-
- TRACE("Converting password to unicode.\n");
- passwd_lenW = MultiByteToWideChar(CP_ACP, 0,
- (LPCSTR)helper->password, helper->pwlen,
- NULL, 0);
- unicode_password = HeapAlloc(GetProcessHeap(), 0,
- passwd_lenW * sizeof(SEC_WCHAR));
- MultiByteToWideChar(CP_ACP, 0, (LPCSTR)helper->password,
- helper->pwlen, unicode_password, passwd_lenW);
-
- SECUR32_CreateNTLMv1SessionKey((PBYTE)unicode_password,
- passwd_lenW * sizeof(SEC_WCHAR), helper->session_key);
-
- HeapFree(GetProcessHeap(), 0, unicode_password);
- }
- else
- memset(helper->session_key, 0, 16);
- }
else if(strncmp(buffer, "GK ", 3) == 0)
{
if((ret = decodeBase64(buffer+3, buffer_len-3, bin, max_len,
TRACE("Failed to decode session key\n");
}
TRACE("Session key is %s\n", debugstr_a(buffer+3));
- helper->valid_session_key = TRUE;
+ HeapFree(GetProcessHeap(), 0, helper->session_key);
helper->session_key = HeapAlloc(GetProcessHeap(), 0, bin_len);
if(!helper->session_key)
{
helper->crypt.ntlm.a4i = SECUR32_arc4Alloc();
SECUR32_arc4Init(helper->crypt.ntlm.a4i, helper->session_key, 16);
helper->crypt.ntlm.seq_num = 0l;
- SECUR32_CreateNTLMv2SubKeys(helper);
+ SECUR32_CreateNTLM2SubKeys(helper);
helper->crypt.ntlm2.send_a4i = SECUR32_arc4Alloc();
helper->crypt.ntlm2.recv_a4i = SECUR32_arc4Alloc();
SECUR32_arc4Init(helper->crypt.ntlm2.send_a4i,
- (BYTE *)helper->crypt.ntlm2.send_seal_key, 16);
+ helper->crypt.ntlm2.send_seal_key, 16);
SECUR32_arc4Init(helper->crypt.ntlm2.recv_a4i,
- (BYTE *)helper->crypt.ntlm2.recv_seal_key, 16);
+ helper->crypt.ntlm2.recv_seal_key, 16);
helper->crypt.ntlm2.send_seq_no = 0l;
helper->crypt.ntlm2.recv_seq_no = 0l;
}
- if(ret != SEC_I_CONTINUE_NEEDED)
- {
- TRACE("Deleting password!\n");
- if(helper->password)
- memset(helper->password, 0, helper->pwlen);
- HeapFree(GetProcessHeap(), 0, helper->password);
- }
isc_end:
+ HeapFree(GetProcessHeap(), 0, username);
+ HeapFree(GetProcessHeap(), 0, domain);
+ HeapFree(GetProcessHeap(), 0, password);
HeapFree(GetProcessHeap(), 0, want_flags);
HeapFree(GetProcessHeap(), 0, buffer);
HeapFree(GetProcessHeap(), 0, bin);
int buffer_len, bin_len, max_len = NTLM_MAX_BUF;
ULONG ctxt_attr = 0;
PNegoHelper helper;
+ PNtlmCredentials ntlm_cred;
TRACE("%p %p %p %d %d %p %p %p %p\n", phCredential, phContext, pInput,
fContextReq, TargetDataRep, phNewContext, pOutput, pfContextAttr,
ptsExpiry);
- if (!phCredential)
- return SEC_E_INVALID_HANDLE;
-
- helper = (PNegoHelper)phCredential->dwLower;
-
buffer = HeapAlloc(GetProcessHeap(), 0, sizeof(char) * NTLM_MAX_BUF);
bin = HeapAlloc(GetProcessHeap(),0, sizeof(BYTE) * NTLM_MAX_BUF);
- if(helper->mode != NTLM_SERVER)
- {
- ret = SEC_E_INVALID_HANDLE;
- goto asc_end;
- }
-
if(TargetDataRep == SECURITY_NETWORK_DREP){
TRACE("Using SECURITY_NETWORK_DREP\n");
}
if(phContext == NULL)
{
+ static CHAR server_helper_protocol[] = "--helper-protocol=squid-2.5-ntlmssp";
+ SEC_CHAR *server_argv[] = { ntlm_auth,
+ server_helper_protocol,
+ NULL };
+
+ if (!phCredential)
+ {
+ ret = SEC_E_INVALID_HANDLE;
+ goto asc_end;
+ }
+
+ ntlm_cred = (PNtlmCredentials)phCredential->dwLower;
+
+ if(ntlm_cred->mode != NTLM_SERVER)
+ {
+ ret = SEC_E_INVALID_HANDLE;
+ goto asc_end;
+ }
+
/* This is the first call to AcceptSecurityHandle */
if(pInput == NULL)
{
else
bin_len = pInput->pBuffers[0].cbBuffer;
+ if( (ret = fork_helper(&helper, ntlm_auth, server_argv)) !=
+ SEC_E_OK)
+ {
+ ret = SEC_E_INTERNAL_ERROR;
+ goto asc_end;
+ }
+ helper->mode = NTLM_SERVER;
+
/* Handle all the flags */
want_flags = HeapAlloc(GetProcessHeap(), 0, 73);
if(want_flags == NULL)
{
TRACE("Failed to allocate memory for the want_flags!\n");
ret = SEC_E_INSUFFICIENT_MEMORY;
+ cleanup_helper(helper);
goto asc_end;
}
lstrcpyA(want_flags, "SF");
lstrcpynA(buffer, want_flags, max_len - 1);
if((ret = run_helper(helper, buffer, max_len, &buffer_len)) !=
SEC_E_OK)
+ {
+ cleanup_helper(helper);
goto asc_end;
+ }
if(!strncmp(buffer, "BH", 2))
TRACE("Helper doesn't understand new command set\n");
}
if((ret = encodeBase64(bin, bin_len, buffer+3, max_len-3,
&buffer_len)) != SEC_E_OK)
{
+ cleanup_helper(helper);
goto asc_end;
}
if((ret = run_helper(helper, buffer, max_len, &buffer_len)) !=
SEC_E_OK)
{
+ cleanup_helper(helper);
goto asc_end;
}
if(strncmp(buffer, "TT ", 3) != 0)
{
ret = SEC_E_INTERNAL_ERROR;
+ cleanup_helper(helper);
goto asc_end;
}
if((ret = decodeBase64(buffer+3, buffer_len-3, bin, max_len,
&bin_len)) != SEC_E_OK)
{
+ cleanup_helper(helper);
goto asc_end;
}
if(pOutput == NULL)
{
ret = SEC_E_INSUFFICIENT_MEMORY;
+ cleanup_helper(helper);
goto asc_end;
}
if(pOutput->cBuffers < 1)
{
ret = SEC_E_INSUFFICIENT_MEMORY;
+ cleanup_helper(helper);
goto asc_end;
}
goto asc_end;
}
+ if(!phContext)
+ {
+ ret = SEC_E_INVALID_HANDLE;
+ goto asc_end;
+ }
+
+ helper = (PNegoHelper)phContext->dwLower;
+
+ if(helper->mode != NTLM_SERVER)
+ {
+ ret = SEC_E_INVALID_HANDLE;
+ goto asc_end;
+ }
+
if(pInput->pBuffers[0].cbBuffer > max_len)
{
ret = SEC_E_INVALID_TOKEN;
TRACE("Reply from ntlm_auth: %s\n", debugstr_a(buffer));
+ /* At this point, we get a NA if the user didn't authenticate, but a BH
+ * if ntlm_auth could not connect to winbindd. Apart from running Wine
+ * as root, there is no way to fix this for now, so just handle this as
+ * a failed login. */
if(strncmp(buffer, "AF ", 3) != 0)
{
if(strncmp(buffer, "NA ", 3) == 0)
}
else
{
- ret = SEC_E_INTERNAL_ERROR;
+ size_t ntlm_pipe_err_len = strlen("BH NT_STATUS_ACCESS_DENIED");
+
+ if( (buffer_len >= ntlm_pipe_err_len) &&
+ (strncmp(buffer, "BH NT_STATUS_ACCESS_DENIED",
+ ntlm_pipe_err_len) == 0))
+ {
+ TRACE("Connection to winbindd failed\n");
+ ret = SEC_E_LOGON_DENIED;
+ }
+ else
+ ret = SEC_E_INTERNAL_ERROR;
+
goto asc_end;
}
}
else
{
TRACE("Negotiated %s\n", debugstr_a(buffer));
- sscanf(buffer + 3, "%lx", &(helper->neg_flags));
- TRACE("Stored 0x%08lx as flags\n", helper->neg_flags);
+ sscanf(buffer + 3, "%x", &(helper->neg_flags));
+ TRACE("Stored 0x%08x as flags\n", helper->neg_flags);
}
TRACE("Getting session key\n");
if(strncmp(buffer, "BH ", 3) == 0)
{
TRACE("Helper sent %s\n", debugstr_a(buffer+3));
- helper->valid_session_key = FALSE;
helper->session_key = HeapAlloc(GetProcessHeap(), 0, 16);
/*FIXME: Generate the dummy session key = MD4(MD4(password))*/
memset(helper->session_key, 0 , 16);
TRACE("Failed to decode session key\n");
}
TRACE("Session key is %s\n", debugstr_a(buffer+3));
- helper->valid_session_key = TRUE;
helper->session_key = HeapAlloc(GetProcessHeap(), 0, 16);
if(!helper->session_key)
{
SECUR32_arc4Cleanup(helper->crypt.ntlm.a4i);
HeapFree(GetProcessHeap(), 0, helper->session_key);
- helper->valid_session_key = FALSE;
SECUR32_arc4Cleanup(helper->crypt.ntlm2.send_a4i);
SECUR32_arc4Cleanup(helper->crypt.ntlm2.recv_a4i);
HeapFree(GetProcessHeap(), 0, helper->crypt.ntlm2.send_sign_key);
HeapFree(GetProcessHeap(), 0, helper->crypt.ntlm2.recv_sign_key);
HeapFree(GetProcessHeap(), 0, helper->crypt.ntlm2.recv_seal_key);
+ cleanup_helper(helper);
+
return SEC_E_OK;
}
return ret;
}
-/*************************************************************************
- * ntlm_GetTokenBufferIndex
- * Calculates the index of the secbuffer with BufferType == SECBUFFER_TOKEN
- * Returns index if found or -1 if not found.
- */
-static int ntlm_GetTokenBufferIndex(PSecBufferDesc pMessage)
-{
- UINT i;
-
- TRACE("%p\n", pMessage);
-
- for( i = 0; i < pMessage->cBuffers; ++i )
- {
- if(pMessage->pBuffers[i].BufferType == SECBUFFER_TOKEN)
- return i;
- }
-
- return -1;
-}
-
/***********************************************************************
* ntlm_CreateSignature
* As both MakeSignature and VerifySignature need this, but different keys
- * are needed for NTLMv2, the logic goes into a helper function.
+ * are needed for NTLM2, the logic goes into a helper function.
* To ensure maximal reusability, we can specify the direction as NTLM_SEND for
* signing/encrypting and NTLM_RECV for verfying/decrypting. When encrypting,
* the signature is encrypted after the message was encrypted, so
for( i = 0; i < pMessage->cBuffers; ++i )
{
if(pMessage->pBuffers[i].BufferType & SECBUFFER_DATA)
- HMACMD5Update(&hmac_md5_ctx, (BYTE *)pMessage->pBuffers[i].pvBuffer,
+ HMACMD5Update(&hmac_md5_ctx, pMessage->pBuffers[i].pvBuffer,
pMessage->pBuffers[i].cbBuffer);
}
return SEC_E_BUFFER_TOO_SMALL;
helper = (PNegoHelper)phContext->dwLower;
- TRACE("Negotiated flags are: 0x%08lx\n", helper->neg_flags);
+ TRACE("Negotiated flags are: 0x%08x\n", helper->neg_flags);
return ntlm_CreateSignature(helper, pMessage, token_idx, NTLM_SEND, TRUE);
}
FIXME("Ignoring MessageSeqNo\n");
helper = (PNegoHelper)phContext->dwLower;
- TRACE("Negotiated flags: 0x%08lx\n", helper->neg_flags);
+ TRACE("Negotiated flags: 0x%08x\n", helper->neg_flags);
local_buff = HeapAlloc(GetProcessHeap(), 0, pMessage->cBuffers * sizeof(SecBuffer));
SECURITY_STATUS ret;
if(phCredential){
- PNegoHelper helper = (PNegoHelper) phCredential->dwLower;
+ PNtlmCredentials ntlm_cred = (PNtlmCredentials) phCredential->dwLower;
phCredential->dwUpper = 0;
phCredential->dwLower = 0;
- cleanup_helper(helper);
+ if (ntlm_cred->password)
+ memset(ntlm_cred->password, 0, ntlm_cred->pwlen);
+ HeapFree(GetProcessHeap(), 0, ntlm_cred->password);
+ HeapFree(GetProcessHeap(), 0, ntlm_cred->username_arg);
+ HeapFree(GetProcessHeap(), 0, ntlm_cred->domain_arg);
+ HeapFree(GetProcessHeap(), 0, ntlm_cred);
ret = SEC_E_OK;
}
else
ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo)
{
PNegoHelper helper;
- int token_idx;
+ int token_idx, data_idx;
TRACE("(%p %d %p %d)\n", phContext, fQOP, pMessage, MessageSeqNo);
if((token_idx = ntlm_GetTokenBufferIndex(pMessage)) == -1)
return SEC_E_INVALID_TOKEN;
+ if((data_idx = ntlm_GetDataBufferIndex(pMessage)) ==-1 )
+ return SEC_E_INVALID_TOKEN;
+
if(pMessage->pBuffers[token_idx].cbBuffer < 16)
return SEC_E_BUFFER_TOO_SMALL;
{
ntlm_CreateSignature(helper, pMessage, token_idx, NTLM_SEND, FALSE);
SECUR32_arc4Process(helper->crypt.ntlm2.send_a4i,
- (BYTE *)pMessage->pBuffers[1].pvBuffer,
- pMessage->pBuffers[1].cbBuffer);
+ pMessage->pBuffers[data_idx].pvBuffer,
+ pMessage->pBuffers[data_idx].cbBuffer);
if(helper->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCHANGE)
SECUR32_arc4Process(helper->crypt.ntlm2.send_a4i,
sig = pMessage->pBuffers[token_idx].pvBuffer;
- SECUR32_arc4Process(helper->crypt.ntlm.a4i, pMessage->pBuffers[1].pvBuffer,
- pMessage->pBuffers[1].cbBuffer);
+ SECUR32_arc4Process(helper->crypt.ntlm.a4i,
+ pMessage->pBuffers[data_idx].pvBuffer,
+ pMessage->pBuffers[data_idx].cbBuffer);
SECUR32_arc4Process(helper->crypt.ntlm.a4i, sig+4, 12);
if(helper->neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN || helper->neg_flags == 0)
SECURITY_STATUS ret;
ULONG ntlmssp_flags_save;
PNegoHelper helper;
- int token_idx;
+ int token_idx, data_idx;
TRACE("(%p %p %d %p)\n", phContext, pMessage, MessageSeqNo, pfQOP);
if(!phContext)
if((token_idx = ntlm_GetTokenBufferIndex(pMessage)) == -1)
return SEC_E_INVALID_TOKEN;
+ if((data_idx = ntlm_GetDataBufferIndex(pMessage)) ==-1)
+ return SEC_E_INVALID_TOKEN;
+
if(pMessage->pBuffers[token_idx].cbBuffer < 16)
return SEC_E_BUFFER_TOO_SMALL;
if(helper->neg_flags & NTLMSSP_NEGOTIATE_NTLM2 && helper->neg_flags & NTLMSSP_NEGOTIATE_SEAL)
{
SECUR32_arc4Process(helper->crypt.ntlm2.recv_a4i,
- pMessage->pBuffers[1].pvBuffer, pMessage->pBuffers[1].cbBuffer);
+ pMessage->pBuffers[data_idx].pvBuffer,
+ pMessage->pBuffers[data_idx].cbBuffer);
}
else
{
SECUR32_arc4Process(helper->crypt.ntlm.a4i,
- pMessage->pBuffers[1].pvBuffer, pMessage->pBuffers[1].cbBuffer);
+ pMessage->pBuffers[data_idx].pvBuffer,
+ pMessage->pBuffers[data_idx].cbBuffer);
}
/* Make sure we use a session key for the signature check, EncryptMessage
ntlm_comment_A
};
+#define NEGO_COMMENT { 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', ' ', \
+ 'P', 'a', 'c', 'k', 'a', 'g', 'e', ' ', \
+ 'N', 'e', 'g', 'o', 't', 'i', 'a', 't', 'o', 'r', 0};
+
+static CHAR nego_comment_A[] = NEGO_COMMENT;
+static WCHAR nego_comment_W[] = NEGO_COMMENT;
+
+#define NEGO_NAME {'N', 'e', 'g', 'o', 't', 'i', 'a', 't', 'e', 0}
+
+static CHAR nego_name_A[] = NEGO_NAME;
+static WCHAR nego_name_W[] = NEGO_NAME;
+
+#define NEGO_CAPS (\
+ SECPKG_FLAG_INTEGRITY | \
+ SECPKG_FLAG_PRIVACY | \
+ SECPKG_FLAG_CONNECTION | \
+ SECPKG_FLAG_MULTI_REQUIRED | \
+ SECPKG_FLAG_EXTENDED_ERROR | \
+ SECPKG_FLAG_IMPERSONATION | \
+ SECPKG_FLAG_ACCEPT_WIN32_NAME | \
+ SECPKG_FLAG_READONLY_WITH_CHECKSUM )
+
+/* Not used for now, just kept here for completeness sake. We need to use the
+ * NTLM_MAX_BUF value. If the hack works, we might want to refactor the code a
+ * bit. */
+#define NEGO_MAX_TOKEN 12000
+
+static const SecPkgInfoW nego_infoW = {
+ NEGO_CAPS,
+ 1,
+ RPC_C_AUTHN_GSS_NEGOTIATE,
+ NTLM_MAX_BUF,
+ nego_name_W,
+ nego_comment_W
+};
+
+static const SecPkgInfoA nego_infoA = {
+ NEGO_CAPS,
+ 1,
+ RPC_C_AUTHN_GSS_NEGOTIATE,
+ NTLM_MAX_BUF,
+ nego_name_A,
+ nego_comment_A
+};
+
void SECUR32_initNTLMSP(void)
{
- SECURITY_STATUS ret;
PNegoHelper helper;
static CHAR version[] = "--version";
version,
NULL };
- if((ret = fork_helper(&helper, ntlm_auth, args)) != SEC_E_OK)
+ if(fork_helper(&helper, ntlm_auth, args) != SEC_E_OK)
{
/* Cheat and allocate a helper anyway, so cleanup later will work. */
- helper = HeapAlloc(GetProcessHeap(),0, sizeof(PNegoHelper));
+ helper = HeapAlloc(GetProcessHeap(),0, sizeof(NegoHelper));
helper->major = helper->minor = helper->micro = -1;
+ helper->pipe_in = helper->pipe_out = -1;
}
else
check_version(helper);
helper->micro >= MIN_NTLM_AUTH_MICRO_VERSION) )
{
SecureProvider *provider = SECUR32_addProvider(&ntlmTableA, &ntlmTableW, NULL);
+ SecureProvider *nego_provider = SECUR32_addProvider(&ntlmTableA, &ntlmTableW, NULL);
+
SECUR32_addPackages(provider, 1L, &infoA, &infoW);
+ /* HACK: Also pretend this is the Negotiate provider */
+ SECUR32_addPackages(nego_provider, 1L, &nego_infoA, &nego_infoW);
}
else
{
MIN_NTLM_AUTH_MAJOR_VERSION,
MIN_NTLM_AUTH_MINOR_VERSION,
MIN_NTLM_AUTH_MICRO_VERSION);
+ ERR("Usually, you can find it in the winbind package of your "
+ "distribution.\n");
+
}
cleanup_helper(helper);
}