diff --git a/dlls/secur32/Makefile.in b/dlls/secur32/Makefile.in index b9761817016..eb7cd555e78 100644 --- a/dlls/secur32/Makefile.in +++ b/dlls/secur32/Makefile.in @@ -8,6 +8,7 @@ IMPORTS = user32 advapi32 kernel32 ntdll C_SRCS = \ negotiate.c \ + ntlm.c \ schannel.c \ secur32.c \ thunks.c \ diff --git a/dlls/secur32/ntlm.c b/dlls/secur32/ntlm.c new file mode 100644 index 00000000000..4bad3e8c002 --- /dev/null +++ b/dlls/secur32/ntlm.c @@ -0,0 +1,470 @@ +/* + * Copyright 2005 Kai Blin + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This file implements the NTLM security provider. + * FIXME: So far, this beast doesn't do anything. + */ +#include +#include +#include "windef.h" +#include "winbase.h" +#include "sspi.h" +#include "secur32_priv.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(secur32); + +static char ntlm_name_A[] = "NTLM"; +static WCHAR ntlm_name_W[] = {'N', 'T', 'L', 'M', 0}; + + +/*********************************************************************** + * QueryCredentialsAttributesA + */ +static SECURITY_STATUS SEC_ENTRY ntlm_QueryCredentialsAttributesA( + PCredHandle phCredential, ULONG ulAttribute, PVOID pBuffer) +{ + SECURITY_STATUS ret; + + TRACE("(%p, %ld, %p)\n", phCredential, ulAttribute, pBuffer); + + if(ulAttribute == SECPKG_ATTR_NAMES) + { + FIXME("SECPKG_CRED_ATTR_NAMES: stub\n"); + ret = SEC_E_UNSUPPORTED_FUNCTION; + } + else + ret = SEC_E_UNSUPPORTED_FUNCTION; + + return ret; +} + +/*********************************************************************** + * QueryCredentialsAttributesW + */ +static SECURITY_STATUS SEC_ENTRY ntlm_QueryCredentialsAttributesW( + PCredHandle phCredential, ULONG ulAttribute, PVOID pBuffer) +{ + SECURITY_STATUS ret; + + TRACE("(%p, %ld, %p)\n", phCredential, ulAttribute, pBuffer); + + if(ulAttribute == SECPKG_ATTR_NAMES) + { + FIXME("SECPKG_CRED_ATTR_NAMES: stub\n"); + ret = SEC_E_UNSUPPORTED_FUNCTION; + } + else + ret = SEC_E_UNSUPPORTED_FUNCTION; + + return ret; +} + +static SECURITY_STATUS ntlm_AcquireCredentialsHandle(ULONG fCredentialsUse, + PCredHandle phCredential, PTimeStamp ptsExpiry) +{ + SECURITY_STATUS ret; + + if(fCredentialsUse == SECPKG_CRED_BOTH) + { + ret = SEC_E_NO_CREDENTIALS; + } + else + { + /* Ok, just store the direction like schannel does for now. + * FIXME: This should probably do something useful later on + */ + phCredential->dwUpper = fCredentialsUse; + phCredential->dwLower = 0; + /* Same here, shamelessly stolen from schannel.c */ + if (ptsExpiry) + ptsExpiry->QuadPart = 0; + ret = SEC_E_OK; + } + return ret; +} + +/*********************************************************************** + * AcquireCredentialsHandleA + */ +static SECURITY_STATUS SEC_ENTRY ntlm_AcquireCredentialsHandleA( + SEC_CHAR *pszPrincipal, SEC_CHAR *pszPackage, ULONG fCredentialUse, + PLUID pLogonID, PVOID pAuthData, SEC_GET_KEY_FN pGetKeyFn, + PVOID pGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) +{ + TRACE("(%s, %s, 0x%08lx, %p, %p, %p, %p, %p, %p)\n", + debugstr_a(pszPrincipal), debugstr_a(pszPackage), fCredentialUse, + pLogonID, pAuthData, pGetKeyFn, pGetKeyArgument, phCredential, ptsExpiry); + return ntlm_AcquireCredentialsHandle(fCredentialUse, phCredential, + ptsExpiry); +} + +/*********************************************************************** + * AcquireCredentialsHandleW + */ +static SECURITY_STATUS SEC_ENTRY ntlm_AcquireCredentialsHandleW( + SEC_WCHAR *pszPrincipal, SEC_WCHAR *pszPackage, ULONG fCredentialUse, + PLUID pLogonID, PVOID pAuthData, SEC_GET_KEY_FN pGetKeyFn, + PVOID pGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) +{ + TRACE("(%s, %s, 0x%08lx, %p, %p, %p, %p, %p, %p)\n", + debugstr_w(pszPrincipal), debugstr_w(pszPackage), fCredentialUse, + pLogonID, pAuthData, pGetKeyFn, pGetKeyArgument, phCredential, ptsExpiry); + return ntlm_AcquireCredentialsHandle(fCredentialUse, phCredential, + ptsExpiry); +} + +/*********************************************************************** + * InitializeSecurityContextA + */ +static SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextA( + PCredHandle phCredential, PCtxtHandle phContext, SEC_CHAR *pszTargetName, + ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, + PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, + PSecBufferDesc pOutput, ULONG *pfContextAttr, PTimeStamp ptsExpiry) +{ + SECURITY_STATUS ret; + + TRACE("%p %p %s %ld %ld %ld %p %ld %p %p %p %p\n", phCredential, phContext, + debugstr_a(pszTargetName), fContextReq, Reserved1, TargetDataRep, pInput, + Reserved1, phNewContext, pOutput, pfContextAttr, ptsExpiry); + if(phCredential){ + ret = SEC_E_UNSUPPORTED_FUNCTION; + } + else + { + ret = SEC_E_INVALID_HANDLE; + } + return ret; +} + +/*********************************************************************** + * InitializeSecurityContextW + */ +static SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW( + PCredHandle phCredential, PCtxtHandle phContext, SEC_WCHAR *pszTargetName, + ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, + PSecBufferDesc pInput,ULONG Reserved2, PCtxtHandle phNewContext, + PSecBufferDesc pOutput, ULONG *pfContextAttr, PTimeStamp ptsExpiry) +{ + SECURITY_STATUS ret; + + TRACE("%p %p %s %ld %ld %ld %p %ld %p %p %p %p\n", phCredential, phContext, + debugstr_w(pszTargetName), fContextReq, Reserved1, TargetDataRep, pInput, + Reserved1, phNewContext, pOutput, pfContextAttr, ptsExpiry); + if (phCredential) + { + ret = SEC_E_UNSUPPORTED_FUNCTION; + } + else + { + ret = SEC_E_INVALID_HANDLE; + } + return ret; +} + +/*********************************************************************** + * AcceptSecurityContext + */ +static SECURITY_STATUS SEC_ENTRY ntlm_AcceptSecurityContext( + PCredHandle phCredential, PCtxtHandle phContext, PSecBufferDesc pInput, + ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext, + PSecBufferDesc pOutput, ULONG *pfContextAttr, PTimeStamp ptsExpiry) +{ + SECURITY_STATUS ret; + + TRACE("%p %p %p %ld %ld %p %p %p %p\n", phCredential, phContext, pInput, + fContextReq, TargetDataRep, phNewContext, pOutput, pfContextAttr, + ptsExpiry); + if (phCredential) + { + ret = SEC_E_UNSUPPORTED_FUNCTION; + } + else + { + ret = SEC_E_INVALID_HANDLE; + } + return ret; +} + +/*********************************************************************** + * CompleteAuthToken + */ +static SECURITY_STATUS SEC_ENTRY ntlm_CompleteAuthToken(PCtxtHandle phContext, + PSecBufferDesc pToken) +{ + SECURITY_STATUS ret; + + TRACE("%p %p\n", phContext, pToken); + if (phContext) + { + ret = SEC_E_UNSUPPORTED_FUNCTION; + } + else + { + ret = SEC_E_INVALID_HANDLE; + } + return ret; +} + +/*********************************************************************** + * DeleteSecurityContext + */ +static SECURITY_STATUS SEC_ENTRY ntlm_DeleteSecurityContext(PCtxtHandle phContext) +{ + SECURITY_STATUS ret; + + TRACE("%p\n", phContext); + if (phContext) + { + ret = SEC_E_UNSUPPORTED_FUNCTION; + } + else + { + ret = SEC_E_INVALID_HANDLE; + } + return ret; +} + +/*********************************************************************** + * ApplyControlToken + */ +static SECURITY_STATUS SEC_ENTRY ntlm_ApplyControlToken(PCtxtHandle phContext, + PSecBufferDesc pInput) +{ + SECURITY_STATUS ret; + + TRACE("%p %p\n", phContext, pInput); + if (phContext) + { + ret = SEC_E_UNSUPPORTED_FUNCTION; + } + else + { + ret = SEC_E_INVALID_HANDLE; + } + return ret; +} + +/*********************************************************************** + * QueryContextAttributesW + */ +static SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesW(PCtxtHandle phContext, + unsigned long ulAttribute, void *pBuffer) +{ + SECURITY_STATUS ret; + + /* FIXME: From reading wrapper.h, I think the dwUpper part of a context is + * the SecurePackage part and the dwLower part is the actual context + * handle. It should be easy to extract the context attributes from that. + */ + TRACE("%p %ld %p\n", phContext, ulAttribute, pBuffer); + if (phContext) + { + ret = SEC_E_UNSUPPORTED_FUNCTION; + } + else + { + ret = SEC_E_INVALID_HANDLE; + } + return ret; +} + +/*********************************************************************** + * QueryContextAttributesA + */ +static SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesA(PCtxtHandle phContext, + unsigned long ulAttribute, void *pBuffer) +{ + return ntlm_QueryContextAttributesW(phContext, ulAttribute, pBuffer); +} + +/*********************************************************************** + * ImpersonateSecurityContext + */ +static SECURITY_STATUS SEC_ENTRY ntlm_ImpersonateSecurityContext(PCtxtHandle phContext) +{ + SECURITY_STATUS ret; + + TRACE("%p\n", phContext); + if (phContext) + { + ret = SEC_E_UNSUPPORTED_FUNCTION; + } + else + { + ret = SEC_E_INVALID_HANDLE; + } + return ret; +} + +/*********************************************************************** + * RevertSecurityContext + */ +static SECURITY_STATUS SEC_ENTRY ntlm_RevertSecurityContext(PCtxtHandle phContext) +{ + SECURITY_STATUS ret; + + TRACE("%p\n", phContext); + if (phContext) + { + ret = SEC_E_UNSUPPORTED_FUNCTION; + } + else + { + ret = SEC_E_INVALID_HANDLE; + } + return ret; +} + +/*********************************************************************** + * MakeSignature + */ +static SECURITY_STATUS SEC_ENTRY ntlm_MakeSignature(PCtxtHandle phContext, ULONG fQOP, + PSecBufferDesc pMessage, ULONG MessageSeqNo) +{ + SECURITY_STATUS ret; + + TRACE("%p %ld %p %ld\n", phContext, fQOP, pMessage, MessageSeqNo); + if (phContext) + { + ret = SEC_E_UNSUPPORTED_FUNCTION; + } + else + { + ret = SEC_E_INVALID_HANDLE; + } + return ret; +} + +/*********************************************************************** + * VerifySignature + */ +static SECURITY_STATUS SEC_ENTRY ntlm_VerifySignature(PCtxtHandle phContext, + PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP) +{ + SECURITY_STATUS ret; + + TRACE("%p %p %ld %p\n", phContext, pMessage, MessageSeqNo, pfQOP); + if (phContext) + { + ret = SEC_E_UNSUPPORTED_FUNCTION; + } + else + { + ret = SEC_E_INVALID_HANDLE; + } + return ret; +} + + + +static SecurityFunctionTableA negoTableA = { + 1, + NULL, /* EnumerateSecurityPackagesA */ + ntlm_QueryCredentialsAttributesA, /* QueryCredentialsAttributesA */ + ntlm_AcquireCredentialsHandleA, /* AcquireCredentialsHandleA */ + FreeCredentialsHandle, /* FreeCredentialsHandle */ + NULL, /* Reserved2 */ + ntlm_InitializeSecurityContextA, /* InitializeSecurityContextA */ + ntlm_AcceptSecurityContext, /* AcceptSecurityContext */ + ntlm_CompleteAuthToken, /* CompleteAuthToken */ + ntlm_DeleteSecurityContext, /* DeleteSecurityContext */ + ntlm_ApplyControlToken, /* ApplyControlToken */ + ntlm_QueryContextAttributesA, /* QueryContextAttributesA */ + ntlm_ImpersonateSecurityContext, /* ImpersonateSecurityContext */ + ntlm_RevertSecurityContext, /* RevertSecurityContext */ + ntlm_MakeSignature, /* MakeSignature */ + ntlm_VerifySignature, /* VerifySignature */ + FreeContextBuffer, /* FreeContextBuffer */ + NULL, /* QuerySecurityPackageInfoA */ + NULL, /* Reserved3 */ + NULL, /* Reserved4 */ + NULL, /* ExportSecurityContext */ + NULL, /* ImportSecurityContextA */ + NULL, /* AddCredentialsA */ + NULL, /* Reserved8 */ + NULL, /* QuerySecurityContextToken */ + NULL, /* EncryptMessage */ + NULL, /* DecryptMessage */ + NULL, /* SetContextAttributesA */ +}; + +static SecurityFunctionTableW negoTableW = { + 1, + NULL, /* EnumerateSecurityPackagesW */ + ntlm_QueryCredentialsAttributesW, /* QueryCredentialsAttributesW */ + ntlm_AcquireCredentialsHandleW, /* AcquireCredentialsHandleW */ + FreeCredentialsHandle, /* FreeCredentialsHandle */ + NULL, /* Reserved2 */ + ntlm_InitializeSecurityContextW, /* InitializeSecurityContextW */ + ntlm_AcceptSecurityContext, /* AcceptSecurityContext */ + ntlm_CompleteAuthToken, /* CompleteAuthToken */ + ntlm_DeleteSecurityContext, /* DeleteSecurityContext */ + ntlm_ApplyControlToken, /* ApplyControlToken */ + ntlm_QueryContextAttributesW, /* QueryContextAttributesW */ + ntlm_ImpersonateSecurityContext, /* ImpersonateSecurityContext */ + ntlm_RevertSecurityContext, /* RevertSecurityContext */ + ntlm_MakeSignature, /* MakeSignature */ + ntlm_VerifySignature, /* VerifySignature */ + FreeContextBuffer, /* FreeContextBuffer */ + NULL, /* QuerySecurityPackageInfoW */ + NULL, /* Reserved3 */ + NULL, /* Reserved4 */ + NULL, /* ExportSecurityContext */ + NULL, /* ImportSecurityContextW */ + NULL, /* AddCredentialsW */ + NULL, /* Reserved8 */ + NULL, /* QuerySecurityContextToken */ + NULL, /* EncryptMessage */ + NULL, /* DecryptMessage */ + NULL, /* SetContextAttributesW */ +}; + +static WCHAR ntlm_comment_W[] = { 'N', 'T', 'L', 'M', ' ', 'S', 'e', + 'c', 'u', 'r', 'i', 't', 'y', ' ', 'P', 'a', 'c', 'k', 'a', 'g', 'e',0}; + +static CHAR ntlm_comment_A[] = "NTLM Security Package"; + +void SECUR32_initNTLMSP(void) +{ + SecureProvider *provider = SECUR32_addProvider(&negoTableA, &negoTableW, + NULL); + /* According to Windows, NTLM has the following capabilities. + */ + + static const LONG caps = + SECPKG_FLAG_INTEGRITY | + SECPKG_FLAG_PRIVACY | + SECPKG_FLAG_TOKEN_ONLY | + SECPKG_FLAG_CONNECTION | + SECPKG_FLAG_MULTI_REQUIRED | + SECPKG_FLAG_IMPERSONATION | + SECPKG_FLAG_ACCEPT_WIN32_NAME | + SECPKG_FLAG_READONLY_WITH_CHECKSUM; + + static const USHORT version = 1; + static const USHORT rpcid = 10; + static const ULONG max_token = 12000; + const SecPkgInfoW infoW = { caps, version, rpcid, max_token, ntlm_name_W, + ntlm_comment_W}; + const SecPkgInfoA infoA = { caps, version, rpcid, max_token, ntlm_name_A, + ntlm_comment_A}; + + SECUR32_addPackages(provider, 1L, &infoA, &infoW); + +} diff --git a/dlls/secur32/secur32.c b/dlls/secur32/secur32.c index 1018605abbc..eadfefeafb1 100644 --- a/dlls/secur32/secur32.c +++ b/dlls/secur32/secur32.c @@ -611,6 +611,7 @@ static void SECUR32_initializeProviders(void) /* First load built-in providers */ SECUR32_initSchannelSP(); SECUR32_initNegotiateSP(); + SECUR32_initNTLMSP(); /* Now load providers from registry */ apiRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, securityProvidersKeyW, 0, KEY_READ, &key); diff --git a/dlls/secur32/secur32_priv.h b/dlls/secur32/secur32_priv.h index ba21a4c01bd..36a1d2e13ac 100644 --- a/dlls/secur32/secur32_priv.h +++ b/dlls/secur32/secur32_priv.h @@ -80,5 +80,6 @@ PSTR SECUR32_AllocMultiByteFromWide(PCWSTR str); /* Initialization functions for built-in providers */ void SECUR32_initSchannelSP(void); void SECUR32_initNegotiateSP(void); +void SECUR32_initNTLMSP(void); #endif /* ndef __SECUR32_PRIV_H__ */