diff --git a/dlls/secur32/Makefile.in b/dlls/secur32/Makefile.in index 71907274feb..017816c9099 100644 --- a/dlls/secur32/Makefile.in +++ b/dlls/secur32/Makefile.in @@ -7,6 +7,7 @@ IMPORTLIB = libsecur32.$(IMPLIBEXT) IMPORTS = user32 advapi32 kernel32 ntdll C_SRCS = \ + schannel.c \ secur32.c \ thunks.c \ wrapper.c diff --git a/dlls/secur32/schannel.c b/dlls/secur32/schannel.c new file mode 100644 index 00000000000..c6f80bbed26 --- /dev/null +++ b/dlls/secur32/schannel.c @@ -0,0 +1,258 @@ +/* Copyright (C) 2005 Juan Lang + * + * 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 schannel provider, or, the SSL/TLS implementations. + * FIXME: It should be rather obvious that this file is empty of any + * implementation. + */ +#include +#include "windef.h" +#include "winbase.h" +#include "sspi.h" +#include "schannel.h" +#include "secur32_priv.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(secur32); + +static SECURITY_STATUS schan_QueryCredentialsAttributes( + PCredHandle phCredential, ULONG ulAttribute, PVOID pBuffer) +{ + SECURITY_STATUS ret; + + switch (ulAttribute) + { + case SECPKG_ATTR_SUPPORTED_ALGS: + if (pBuffer) + { + /* FIXME: get from CryptoAPI */ + FIXME("%ld: stub\n", ulAttribute); + ret = SEC_E_UNSUPPORTED_FUNCTION; + } + else + ret = SEC_E_INTERNAL_ERROR; + break; + case SECPKG_ATTR_CIPHER_STRENGTHS: + if (pBuffer) + { + /* FIXME: get from CryptoAPI */ + FIXME("%ld: stub\n", ulAttribute); + ret = SEC_E_UNSUPPORTED_FUNCTION; + } + else + ret = SEC_E_INTERNAL_ERROR; + break; + case SECPKG_ATTR_SUPPORTED_PROTOCOLS: + if (pBuffer) + { + /* FIXME: get from OpenSSL? */ + FIXME("%ld: stub\n", ulAttribute); + ret = SEC_E_UNSUPPORTED_FUNCTION; + } + else + ret = SEC_E_INTERNAL_ERROR; + break; + default: + ret = SEC_E_UNSUPPORTED_FUNCTION; + } + return ret; +} + +static SECURITY_STATUS SEC_ENTRY schan_QueryCredentialsAttributesA( + PCredHandle phCredential, ULONG ulAttribute, PVOID pBuffer) +{ + SECURITY_STATUS ret; + + TRACE("(%p, %ld, %p)\n", phCredential, ulAttribute, pBuffer); + + switch (ulAttribute) + { + case SECPKG_CRED_ATTR_NAMES: + FIXME("SECPKG_CRED_ATTR_NAMES: stub\n"); + ret = SEC_E_UNSUPPORTED_FUNCTION; + break; + default: + ret = schan_QueryCredentialsAttributes(phCredential, ulAttribute, + pBuffer); + } + return ret; +} + +static SECURITY_STATUS SEC_ENTRY schan_QueryCredentialsAttributesW( + PCredHandle phCredential, ULONG ulAttribute, PVOID pBuffer) +{ + SECURITY_STATUS ret; + + TRACE("(%p, %ld, %p)\n", phCredential, ulAttribute, pBuffer); + + switch (ulAttribute) + { + case SECPKG_CRED_ATTR_NAMES: + FIXME("SECPKG_CRED_ATTR_NAMES: stub\n"); + ret = SEC_E_UNSUPPORTED_FUNCTION; + break; + default: + ret = schan_QueryCredentialsAttributes(phCredential, ulAttribute, + pBuffer); + } + return ret; +} + +static SECURITY_STATUS schan_AcquireCredentialsHandle(ULONG fCredentialUse, + PCredHandle phCredential, PTimeStamp ptsExpiry) +{ + SECURITY_STATUS ret; + + if (fCredentialUse == SECPKG_CRED_BOTH) + ret = SEC_E_NO_CREDENTIALS; + else + { + /* For now, the only thing I'm interested in is the direction of the + * connection, so just store it. + */ + phCredential->dwUpper = fCredentialUse; + /* According to MSDN, all versions prior to XP do this */ + if (ptsExpiry) + ptsExpiry->QuadPart = 0; + ret = SEC_E_OK; + } + return ret; +} + +static SECURITY_STATUS SEC_ENTRY schan_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 schan_AcquireCredentialsHandle(fCredentialUse, phCredential, + ptsExpiry); +} + +static SECURITY_STATUS SEC_ENTRY schan_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 schan_AcquireCredentialsHandle(fCredentialUse, phCredential, + ptsExpiry); +} + +static SecurityFunctionTableA schanTableA = { + 1, + NULL, /* EnumerateSecurityPackagesA */ + schan_QueryCredentialsAttributesA, + schan_AcquireCredentialsHandleA, + NULL, /* FreeCredentialsHandle */ + NULL, /* Reserved2 */ + NULL, /* InitializeSecurityContextA */ + NULL, /* AcceptSecurityContext */ + NULL, /* CompleteAuthToken */ + NULL, /* DeleteSecurityContext */ + NULL, /* ApplyControlToken */ + NULL, /* QueryContextAttributesA */ + NULL, /* ImpersonateSecurityContext */ + NULL, /* RevertSecurityContext */ + NULL, /* MakeSignature */ + NULL, /* VerifySignature */ + 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 schanTableW = { + 1, + NULL, /* EnumerateSecurityPackagesW */ + schan_QueryCredentialsAttributesW, + schan_AcquireCredentialsHandleW, + NULL, /* FreeCredentialsHandle */ + NULL, /* Reserved2 */ + NULL, /* InitializeSecurityContextW */ + NULL, /* AcceptSecurityContext */ + NULL, /* CompleteAuthToken */ + NULL, /* DeleteSecurityContext */ + NULL, /* ApplyControlToken */ + NULL, /* QueryContextAttributesW */ + NULL, /* ImpersonateSecurityContext */ + NULL, /* RevertSecurityContext */ + NULL, /* MakeSignature */ + NULL, /* VerifySignature */ + FreeContextBuffer, + NULL, /* QuerySecurityPackageInfoW */ + NULL, /* Reserved3 */ + NULL, /* Reserved4 */ + NULL, /* ExportSecurityContext */ + NULL, /* ImportSecurityContextW */ + NULL, /* AddCredentialsW */ + NULL, /* Reserved8 */ + NULL, /* QuerySecurityContextToken */ + NULL, /* EncryptMessage */ + NULL, /* DecryptMessage */ + NULL, /* SetContextAttributesW */ +}; + +static const WCHAR schannelComment[] = { 'S','c','h','a','n','n','e','l',' ', + 'S','e','c','u','r','i','t','y',' ','P','a','c','k','a','g','e',0 }; + +void SECUR32_initSchannelSP(void) +{ + SecureProvider *provider = SECUR32_addProvider(&schanTableA, &schanTableW, + NULL); + + if (provider) + { + /* This is what Windows reports. This shouldn't break any applications + * even though the functions are missing, because the wrapper will + * return SEC_E_UNSUPPORTED_FUNCTION if our function is NULL. + */ + static const long 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_STREAM; + static const short version = 1; + static const long maxToken = 16384; + SEC_WCHAR *uniSPName = (SEC_WCHAR *)UNISP_NAME_W, + *schannel = (SEC_WCHAR *)SCHANNEL_NAME_W; + + const SecPkgInfoW info[] = { + { caps, version, UNISP_RPC_ID, maxToken, uniSPName, uniSPName }, + { caps, version, UNISP_RPC_ID, maxToken, schannel, + (SEC_WCHAR *)schannelComment }, + }; + + SECUR32_addPackages(provider, sizeof(info) / sizeof(info[0]), NULL, + info); + } +} diff --git a/dlls/secur32/secur32.c b/dlls/secur32/secur32.c index 1a286c46107..efe03c1e9ea 100644 --- a/dlls/secur32/secur32.c +++ b/dlls/secur32/secur32.c @@ -16,6 +16,7 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include #include "windef.h" #include "winbase.h" @@ -457,8 +458,8 @@ static void _makeFnTableW(PSecurityFunctionTableW fnTableW, } } -static void _copyPackageInfo(PSecPkgInfoW info, PSecPkgInfoA inInfoA, - PSecPkgInfoW inInfoW) +static void _copyPackageInfo(PSecPkgInfoW info, const SecPkgInfoA *inInfoA, + const SecPkgInfoW *inInfoW) { if (info && (inInfoA || inInfoW)) { @@ -479,6 +480,64 @@ static void _copyPackageInfo(PSecPkgInfoW info, PSecPkgInfoA inInfoA, } } +SecureProvider *SECUR32_addProvider(PSecurityFunctionTableA fnTableA, + PSecurityFunctionTableW fnTableW, PWSTR moduleName) +{ + SecureProvider *ret; + + EnterCriticalSection(&cs); + providerTable = _resizeProviderTable(providerTable, + providerTable ? providerTable->numProviders + 1 : 1); + if (providerTable) + { + ret = &providerTable->table[providerTable->numProviders++]; + ret->lib = NULL; + if (fnTableA || fnTableW) + { + _makeFnTableA(&ret->fnTableA, fnTableA, fnTableW); + _makeFnTableW(&ret->fnTableW, fnTableA, fnTableW); + ret->loaded = TRUE; + } + else + { + ret->moduleName = SECUR32_strdupW(moduleName); + ret->loaded = FALSE; + } + } + else + ret = NULL; + LeaveCriticalSection(&cs); + return ret; +} + +void SECUR32_addPackages(SecureProvider *provider, ULONG toAdd, + const SecPkgInfoA *infoA, const SecPkgInfoW *infoW) +{ + assert(provider); + assert(infoA || infoW); + + EnterCriticalSection(&cs); + packageTable = _resizePackageTable(packageTable, + packageTable ? packageTable->numPackages + toAdd : toAdd); + if (packageTable) + { + ULONG i; + + for (i = 0; i < toAdd; i++) + { + SecurePackage *package = + &packageTable->table[packageTable->numPackages + i]; + + package->provider = provider; + _copyPackageInfo(&package->infoW, + infoA ? &infoA[i] : NULL, + infoW ? &infoW[i] : NULL); + } + packageTable->numPackages += toAdd; + } + LeaveCriticalSection(&cs); +} + static void _tryLoadProvider(PWSTR moduleName) { HMODULE lib = LoadLibraryW(moduleName); @@ -514,33 +573,11 @@ static void _tryLoadProvider(PWSTR moduleName) ret = fnTableA->EnumerateSecurityPackagesA(&toAdd, &infoA); if (ret == SEC_E_OK && toAdd > 0 && (infoW || infoA)) { - providerTable = _resizeProviderTable(providerTable, - providerTable ? providerTable->numProviders + 1 : 1); - packageTable = _resizePackageTable(packageTable, - packageTable ? packageTable->numPackages + toAdd : toAdd); - if (providerTable && packageTable) - { - ULONG i; - SecureProvider *provider = - &providerTable->table[providerTable->numProviders]; + SecureProvider *provider = SECUR32_addProvider(NULL, NULL, + moduleName); - EnterCriticalSection(&cs); - provider->moduleName = SECUR32_strdupW(moduleName); - provider->lib = NULL; - for (i = 0; i < toAdd; i++) - { - SecurePackage *package = - &packageTable->table[packageTable->numPackages + i]; - - package->provider = provider; - _copyPackageInfo(&package->infoW, - infoA ? &infoA[i] : NULL, - infoW ? &infoW[i] : NULL); - } - packageTable->numPackages += toAdd; - providerTable->numProviders++; - LeaveCriticalSection(&cs); - } + if (provider) + SECUR32_addPackages(provider, toAdd, infoA, infoW); if (infoW) fnTableW->FreeContextBuffer(infoW); else @@ -569,6 +606,9 @@ static void SECUR32_initializeProviders(void) TRACE("\n"); InitializeCriticalSection(&cs); + /* First load built-in providers */ + SECUR32_initSchannelSP(); + /* Now load providers from registry */ apiRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, securityProvidersKeyW, 0, KEY_READ, &key); if (apiRet == ERROR_SUCCESS) @@ -605,7 +645,7 @@ static void SECUR32_initializeProviders(void) SecurePackage *SECUR32_findPackageW(PWSTR packageName) { - SecurePackage *ret; + SecurePackage *ret = NULL; if (packageTable && packageName) { @@ -614,7 +654,7 @@ SecurePackage *SECUR32_findPackageW(PWSTR packageName) for (i = 0, ret = NULL; !ret && i < packageTable->numPackages; i++) if (!lstrcmpiW(packageTable->table[i].infoW.Name, packageName)) ret = &packageTable->table[i]; - if (ret && ret->provider && !ret->provider->lib) + if (ret && ret->provider && !ret->provider->loaded) { ret->provider->lib = LoadLibraryW(ret->provider->moduleName); if (ret->provider->lib) @@ -634,13 +674,12 @@ SecurePackage *SECUR32_findPackageW(PWSTR packageName) fnTableW = pInitSecurityInterfaceW(); _makeFnTableA(&ret->provider->fnTableA, fnTableA, fnTableW); _makeFnTableW(&ret->provider->fnTableW, fnTableA, fnTableW); + ret->provider->loaded = TRUE; } else ret = NULL; } } - else - ret = NULL; return ret; } diff --git a/dlls/secur32/secur32_priv.h b/dlls/secur32/secur32_priv.h index 281cf46c2f5..74dad4691bb 100644 --- a/dlls/secur32/secur32_priv.h +++ b/dlls/secur32/secur32_priv.h @@ -34,6 +34,7 @@ typedef struct _SecureProvider { + BOOL loaded; PWSTR moduleName; HMODULE lib; SecurityFunctionTableA fnTableA; @@ -46,6 +47,21 @@ typedef struct _SecurePackage SecureProvider *provider; } SecurePackage; +/* Allocates space for and initializes a new provider. If fnTableA or fnTableW + * is non-NULL, assumes the provider is built-in (and is thus already loaded.) + * Otherwise moduleName must not be NULL. + * Returns a pointer to the stored provider entry, for use adding packages. + */ +SecureProvider *SECUR32_addProvider(PSecurityFunctionTableA fnTableA, + PSecurityFunctionTableW fnTableW, PWSTR moduleName); + +/* Allocates space for and adds toAdd packages with the given provider. + * provider must not be NULL, and either infoA or infoW may be NULL, but not + * both. + */ +void SECUR32_addPackages(SecureProvider *provider, ULONG toAdd, + const SecPkgInfoA *infoA, const SecPkgInfoW *infoW); + /* Tries to find the package named packageName. If it finds it, implicitly * loads the package if it isn't already loaded. */ @@ -61,4 +77,7 @@ PWSTR SECUR32_strdupW(PCWSTR str); PWSTR SECUR32_AllocWideFromMultiByte(PCSTR str); PSTR SECUR32_AllocMultiByteFromWide(PCWSTR str); +/* Initialization functions for built-in providers */ +void SECUR32_initSchannelSP(void); + #endif /* ndef __SECUR32_PRIV_H__ */