1 /* Copyright (C) 2005 Juan Lang
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 * This file implements the schannel provider, or, the SSL/TLS implementations.
18 * FIXME: It should be rather obvious that this file is empty of any
26 #include "secur32_priv.h"
27 #include "wine/debug.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(secur32);
31 static SECURITY_STATUS schan_QueryCredentialsAttributes(
32 PCredHandle phCredential, ULONG ulAttribute, const VOID *pBuffer)
38 case SECPKG_ATTR_SUPPORTED_ALGS:
41 /* FIXME: get from CryptoAPI */
42 FIXME("SECPKG_ATTR_SUPPORTED_ALGS: stub\n");
43 ret = SEC_E_UNSUPPORTED_FUNCTION;
46 ret = SEC_E_INTERNAL_ERROR;
48 case SECPKG_ATTR_CIPHER_STRENGTHS:
51 SecPkgCred_CipherStrengths *r = (SecPkgCred_CipherStrengths*)pBuffer;
53 /* FIXME: get from CryptoAPI */
54 FIXME("SECPKG_ATTR_CIPHER_STRENGTHS: semi-stub\n");
55 r->dwMinimumCipherStrength = 40;
56 r->dwMaximumCipherStrength = 168;
60 ret = SEC_E_INTERNAL_ERROR;
62 case SECPKG_ATTR_SUPPORTED_PROTOCOLS:
65 /* FIXME: get from OpenSSL? */
66 FIXME("SECPKG_ATTR_SUPPORTED_PROTOCOLS: stub\n");
67 ret = SEC_E_UNSUPPORTED_FUNCTION;
70 ret = SEC_E_INTERNAL_ERROR;
73 ret = SEC_E_UNSUPPORTED_FUNCTION;
78 static SECURITY_STATUS SEC_ENTRY schan_QueryCredentialsAttributesA(
79 PCredHandle phCredential, ULONG ulAttribute, PVOID pBuffer)
83 TRACE("(%p, %d, %p)\n", phCredential, ulAttribute, pBuffer);
87 case SECPKG_CRED_ATTR_NAMES:
88 FIXME("SECPKG_CRED_ATTR_NAMES: stub\n");
89 ret = SEC_E_UNSUPPORTED_FUNCTION;
92 ret = schan_QueryCredentialsAttributes(phCredential, ulAttribute,
98 static SECURITY_STATUS SEC_ENTRY schan_QueryCredentialsAttributesW(
99 PCredHandle phCredential, ULONG ulAttribute, PVOID pBuffer)
103 TRACE("(%p, %d, %p)\n", phCredential, ulAttribute, pBuffer);
107 case SECPKG_CRED_ATTR_NAMES:
108 FIXME("SECPKG_CRED_ATTR_NAMES: stub\n");
109 ret = SEC_E_UNSUPPORTED_FUNCTION;
112 ret = schan_QueryCredentialsAttributes(phCredential, ulAttribute,
118 static SECURITY_STATUS schan_CheckCreds(const SCHANNEL_CRED *schanCred)
122 switch (schanCred->dwVersion)
125 case SCHANNEL_CRED_VERSION:
128 return SEC_E_INTERNAL_ERROR;
131 if (schanCred->cCreds == 0)
132 st = SEC_E_NO_CREDENTIALS;
133 else if (schanCred->cCreds > 1)
134 st = SEC_E_UNKNOWN_CREDENTIALS;
141 ret = CryptAcquireCertificatePrivateKey(schanCred->paCred[0],
142 0, /* FIXME: what flags to use? */ NULL,
143 &csp, &keySpec, &freeCSP);
148 CryptReleaseContext(csp, 0);
151 st = SEC_E_UNKNOWN_CREDENTIALS;
156 static SECURITY_STATUS schan_AcquireClientCredentials(const SCHANNEL_CRED *schanCred,
157 PCredHandle phCredential, PTimeStamp ptsExpiry)
159 SECURITY_STATUS st = SEC_E_OK;
163 st = schan_CheckCreds(schanCred);
164 if (st == SEC_E_NO_CREDENTIALS)
168 /* For now, the only thing I'm interested in is the direction of the
169 * connection, so just store it.
173 phCredential->dwUpper = SECPKG_CRED_OUTBOUND;
174 /* Outbound credentials have no expiry */
177 ptsExpiry->LowPart = 0;
178 ptsExpiry->HighPart = 0;
184 static SECURITY_STATUS schan_AcquireServerCredentials(const SCHANNEL_CRED *schanCred,
185 PCredHandle phCredential, PTimeStamp ptsExpiry)
189 if (!schanCred) return SEC_E_NO_CREDENTIALS;
191 st = schan_CheckCreds(schanCred);
194 phCredential->dwUpper = SECPKG_CRED_INBOUND;
195 /* FIXME: get expiry from cert */
200 static SECURITY_STATUS schan_AcquireCredentialsHandle(ULONG fCredentialUse,
201 const SCHANNEL_CRED *schanCred, PCredHandle phCredential, PTimeStamp ptsExpiry)
205 if (fCredentialUse == SECPKG_CRED_OUTBOUND)
206 ret = schan_AcquireClientCredentials(schanCred, phCredential,
209 ret = schan_AcquireServerCredentials(schanCred, phCredential,
214 static SECURITY_STATUS SEC_ENTRY schan_AcquireCredentialsHandleA(
215 SEC_CHAR *pszPrincipal, SEC_CHAR *pszPackage, ULONG fCredentialUse,
216 PLUID pLogonID, PVOID pAuthData, SEC_GET_KEY_FN pGetKeyFn,
217 PVOID pGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
219 TRACE("(%s, %s, 0x%08x, %p, %p, %p, %p, %p, %p)\n",
220 debugstr_a(pszPrincipal), debugstr_a(pszPackage), fCredentialUse,
221 pLogonID, pAuthData, pGetKeyFn, pGetKeyArgument, phCredential, ptsExpiry);
222 return schan_AcquireCredentialsHandle(fCredentialUse,
223 (PSCHANNEL_CRED)pAuthData, phCredential, ptsExpiry);
226 static SECURITY_STATUS SEC_ENTRY schan_AcquireCredentialsHandleW(
227 SEC_WCHAR *pszPrincipal, SEC_WCHAR *pszPackage, ULONG fCredentialUse,
228 PLUID pLogonID, PVOID pAuthData, SEC_GET_KEY_FN pGetKeyFn,
229 PVOID pGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
231 TRACE("(%s, %s, 0x%08x, %p, %p, %p, %p, %p, %p)\n",
232 debugstr_w(pszPrincipal), debugstr_w(pszPackage), fCredentialUse,
233 pLogonID, pAuthData, pGetKeyFn, pGetKeyArgument, phCredential, ptsExpiry);
234 return schan_AcquireCredentialsHandle(fCredentialUse,
235 (PSCHANNEL_CRED)pAuthData, phCredential, ptsExpiry);
238 static SECURITY_STATUS SEC_ENTRY schan_FreeCredentialsHandle(
239 PCredHandle phCredential)
241 FIXME("(%p): stub\n", phCredential);
245 /***********************************************************************
246 * InitializeSecurityContextA
248 static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextA(
249 PCredHandle phCredential, PCtxtHandle phContext, SEC_CHAR *pszTargetName,
250 ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
251 PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext,
252 PSecBufferDesc pOutput, ULONG *pfContextAttr, PTimeStamp ptsExpiry)
256 TRACE("%p %p %s %d %d %d %p %d %p %p %p %p\n", phCredential, phContext,
257 debugstr_a(pszTargetName), fContextReq, Reserved1, TargetDataRep, pInput,
258 Reserved1, phNewContext, pOutput, pfContextAttr, ptsExpiry);
262 ret = SEC_E_UNSUPPORTED_FUNCTION;
266 ret = SEC_E_INVALID_HANDLE;
271 /***********************************************************************
272 * InitializeSecurityContextW
274 static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW(
275 PCredHandle phCredential, PCtxtHandle phContext, SEC_WCHAR *pszTargetName,
276 ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
277 PSecBufferDesc pInput,ULONG Reserved2, PCtxtHandle phNewContext,
278 PSecBufferDesc pOutput, ULONG *pfContextAttr, PTimeStamp ptsExpiry)
282 TRACE("%p %p %s %d %d %d %p %d %p %p %p %p\n", phCredential, phContext,
283 debugstr_w(pszTargetName), fContextReq, Reserved1, TargetDataRep, pInput,
284 Reserved1, phNewContext, pOutput, pfContextAttr, ptsExpiry);
288 ret = SEC_E_UNSUPPORTED_FUNCTION;
292 ret = SEC_E_INVALID_HANDLE;
297 static const SecurityFunctionTableA schanTableA = {
299 NULL, /* EnumerateSecurityPackagesA */
300 schan_QueryCredentialsAttributesA,
301 schan_AcquireCredentialsHandleA,
302 schan_FreeCredentialsHandle,
303 NULL, /* Reserved2 */
304 schan_InitializeSecurityContextA,
305 NULL, /* AcceptSecurityContext */
306 NULL, /* CompleteAuthToken */
307 NULL, /* DeleteSecurityContext */
308 NULL, /* ApplyControlToken */
309 NULL, /* QueryContextAttributesA */
310 NULL, /* ImpersonateSecurityContext */
311 NULL, /* RevertSecurityContext */
312 NULL, /* MakeSignature */
313 NULL, /* VerifySignature */
315 NULL, /* QuerySecurityPackageInfoA */
316 NULL, /* Reserved3 */
317 NULL, /* Reserved4 */
318 NULL, /* ExportSecurityContext */
319 NULL, /* ImportSecurityContextA */
320 NULL, /* AddCredentialsA */
321 NULL, /* Reserved8 */
322 NULL, /* QuerySecurityContextToken */
323 NULL, /* EncryptMessage */
324 NULL, /* DecryptMessage */
325 NULL, /* SetContextAttributesA */
328 static const SecurityFunctionTableW schanTableW = {
330 NULL, /* EnumerateSecurityPackagesW */
331 schan_QueryCredentialsAttributesW,
332 schan_AcquireCredentialsHandleW,
333 schan_FreeCredentialsHandle,
334 NULL, /* Reserved2 */
335 schan_InitializeSecurityContextW,
336 NULL, /* AcceptSecurityContext */
337 NULL, /* CompleteAuthToken */
338 NULL, /* DeleteSecurityContext */
339 NULL, /* ApplyControlToken */
340 NULL, /* QueryContextAttributesW */
341 NULL, /* ImpersonateSecurityContext */
342 NULL, /* RevertSecurityContext */
343 NULL, /* MakeSignature */
344 NULL, /* VerifySignature */
346 NULL, /* QuerySecurityPackageInfoW */
347 NULL, /* Reserved3 */
348 NULL, /* Reserved4 */
349 NULL, /* ExportSecurityContext */
350 NULL, /* ImportSecurityContextW */
351 NULL, /* AddCredentialsW */
352 NULL, /* Reserved8 */
353 NULL, /* QuerySecurityContextToken */
354 NULL, /* EncryptMessage */
355 NULL, /* DecryptMessage */
356 NULL, /* SetContextAttributesW */
359 static const WCHAR schannelComment[] = { 'S','c','h','a','n','n','e','l',' ',
360 'S','e','c','u','r','i','t','y',' ','P','a','c','k','a','g','e',0 };
362 void SECUR32_initSchannelSP(void)
364 SecureProvider *provider = SECUR32_addProvider(&schanTableA, &schanTableW,
369 /* This is what Windows reports. This shouldn't break any applications
370 * even though the functions are missing, because the wrapper will
371 * return SEC_E_UNSUPPORTED_FUNCTION if our function is NULL.
373 static const long caps =
374 SECPKG_FLAG_INTEGRITY |
375 SECPKG_FLAG_PRIVACY |
376 SECPKG_FLAG_CONNECTION |
377 SECPKG_FLAG_MULTI_REQUIRED |
378 SECPKG_FLAG_EXTENDED_ERROR |
379 SECPKG_FLAG_IMPERSONATION |
380 SECPKG_FLAG_ACCEPT_WIN32_NAME |
382 static const short version = 1;
383 static const long maxToken = 16384;
384 SEC_WCHAR *uniSPName = (SEC_WCHAR *)UNISP_NAME_W,
385 *schannel = (SEC_WCHAR *)SCHANNEL_NAME_W;
387 const SecPkgInfoW info[] = {
388 { caps, version, UNISP_RPC_ID, maxToken, uniSPName, uniSPName },
389 { caps, version, UNISP_RPC_ID, maxToken, schannel,
390 (SEC_WCHAR *)schannelComment },
393 SECUR32_addPackages(provider, sizeof(info) / sizeof(info[0]), NULL,