wininet: Store WININETAPPINFOW pointer in WININETFTPSESSIONW.
[wine] / dlls / secur32 / schannel.c
1 /* Copyright (C) 2005 Juan Lang
2  *
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.
7  *
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.
12  *
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
16  *
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
19  * implementation.
20  */
21 #include <stdarg.h>
22 #include "windef.h"
23 #include "winbase.h"
24 #include "sspi.h"
25 #include "schannel.h"
26 #include "secur32_priv.h"
27 #include "wine/debug.h"
28
29 WINE_DEFAULT_DEBUG_CHANNEL(secur32);
30
31 static SECURITY_STATUS schan_QueryCredentialsAttributes(
32  PCredHandle phCredential, ULONG ulAttribute, PVOID pBuffer)
33 {
34     SECURITY_STATUS ret;
35
36     switch (ulAttribute)
37     {
38     case SECPKG_ATTR_SUPPORTED_ALGS:
39         if (pBuffer)
40         {
41             /* FIXME: get from CryptoAPI */
42             FIXME("%d: stub\n", ulAttribute);
43             ret = SEC_E_UNSUPPORTED_FUNCTION;
44         }
45         else
46             ret = SEC_E_INTERNAL_ERROR;
47         break;
48     case SECPKG_ATTR_CIPHER_STRENGTHS:
49         if (pBuffer)
50         {
51             /* FIXME: get from CryptoAPI */
52             FIXME("%d: stub\n", ulAttribute);
53             ret = SEC_E_UNSUPPORTED_FUNCTION;
54         }
55         else
56             ret = SEC_E_INTERNAL_ERROR;
57         break;
58     case SECPKG_ATTR_SUPPORTED_PROTOCOLS:
59         if (pBuffer)
60         {
61             /* FIXME: get from OpenSSL? */
62             FIXME("%d: stub\n", ulAttribute);
63             ret = SEC_E_UNSUPPORTED_FUNCTION;
64         }
65         else
66             ret = SEC_E_INTERNAL_ERROR;
67         break;
68     default:
69         ret = SEC_E_UNSUPPORTED_FUNCTION;
70     }
71     return ret;
72 }
73
74 static SECURITY_STATUS SEC_ENTRY schan_QueryCredentialsAttributesA(
75  PCredHandle phCredential, ULONG ulAttribute, PVOID pBuffer)
76 {
77     SECURITY_STATUS ret;
78
79     TRACE("(%p, %d, %p)\n", phCredential, ulAttribute, pBuffer);
80
81     switch (ulAttribute)
82     {
83     case SECPKG_CRED_ATTR_NAMES:
84         FIXME("SECPKG_CRED_ATTR_NAMES: stub\n");
85         ret = SEC_E_UNSUPPORTED_FUNCTION;
86         break;
87     default:
88         ret = schan_QueryCredentialsAttributes(phCredential, ulAttribute,
89          pBuffer);
90     }
91     return ret;
92 }
93
94 static SECURITY_STATUS SEC_ENTRY schan_QueryCredentialsAttributesW(
95  PCredHandle phCredential, ULONG ulAttribute, PVOID pBuffer)
96 {
97     SECURITY_STATUS ret;
98
99     TRACE("(%p, %d, %p)\n", phCredential, ulAttribute, pBuffer);
100
101     switch (ulAttribute)
102     {
103     case SECPKG_CRED_ATTR_NAMES:
104         FIXME("SECPKG_CRED_ATTR_NAMES: stub\n");
105         ret = SEC_E_UNSUPPORTED_FUNCTION;
106         break;
107     default:
108         ret = schan_QueryCredentialsAttributes(phCredential, ulAttribute,
109          pBuffer);
110     }
111     return ret;
112 }
113
114 static SECURITY_STATUS schan_CheckCreds(PSCHANNEL_CRED schanCred)
115 {
116     SECURITY_STATUS st;
117
118     switch (schanCred->dwVersion)
119     {
120     case SCH_CRED_V3:
121     case SCHANNEL_CRED_VERSION:
122         break;
123     default:
124         return SEC_E_INTERNAL_ERROR;
125     }
126
127     if (schanCred->cCreds == 0)
128         st = SEC_E_NO_CREDENTIALS;
129     else if (schanCred->cCreds > 1)
130         st = SEC_E_UNKNOWN_CREDENTIALS;
131     else
132     {
133         DWORD keySpec;
134         HCRYPTPROV csp;
135         BOOL ret, freeCSP;
136
137         ret = CryptAcquireCertificatePrivateKey(schanCred->paCred[0],
138          0, /* FIXME: what flags to use? */ NULL,
139          &csp, &keySpec, &freeCSP);
140         if (ret)
141         {
142             st = SEC_E_OK;
143             if (freeCSP)
144                 CryptReleaseContext(csp, 0);
145         }
146         else
147             st = SEC_E_UNKNOWN_CREDENTIALS;
148     }
149     return st;
150 }
151
152 static SECURITY_STATUS schan_AcquireClientCredentials(PSCHANNEL_CRED schanCred,
153  PCredHandle phCredential, PTimeStamp ptsExpiry)
154 {
155     SECURITY_STATUS st = SEC_E_OK;
156
157     if (schanCred)
158     {
159         st = schan_CheckCreds(schanCred);
160         if (st == SEC_E_NO_CREDENTIALS)
161             st = SEC_E_OK;
162     }
163
164     /* For now, the only thing I'm interested in is the direction of the
165      * connection, so just store it.
166      */
167     if (st == SEC_E_OK)
168     {
169         phCredential->dwUpper = SECPKG_CRED_OUTBOUND;
170         /* Outbound credentials have no expiry */
171         if (ptsExpiry)
172         {
173             ptsExpiry->LowPart = 0;
174             ptsExpiry->HighPart = 0;
175         }
176     }
177     return st;
178 }
179
180 static SECURITY_STATUS schan_AcquireServerCredentials(PSCHANNEL_CRED schanCred,
181  PCredHandle phCredential, PTimeStamp ptsExpiry)
182 {
183     SECURITY_STATUS st;
184
185     if (!schanCred) return SEC_E_NO_CREDENTIALS;
186
187     st = schan_CheckCreds(schanCred);
188     if (st == SEC_E_OK)
189     {
190         phCredential->dwUpper = SECPKG_CRED_INBOUND;
191         /* FIXME: get expiry from cert */
192     }
193     return st;
194 }
195
196 static SECURITY_STATUS schan_AcquireCredentialsHandle(ULONG fCredentialUse,
197  PSCHANNEL_CRED schanCred, PCredHandle phCredential, PTimeStamp ptsExpiry)
198 {
199     SECURITY_STATUS ret;
200
201     if (fCredentialUse == SECPKG_CRED_OUTBOUND)
202         ret = schan_AcquireClientCredentials(schanCred, phCredential,
203          ptsExpiry);
204     else
205         ret = schan_AcquireServerCredentials(schanCred, phCredential,
206          ptsExpiry);
207     return ret;
208 }
209
210 static SECURITY_STATUS SEC_ENTRY schan_AcquireCredentialsHandleA(
211  SEC_CHAR *pszPrincipal, SEC_CHAR *pszPackage, ULONG fCredentialUse,
212  PLUID pLogonID, PVOID pAuthData, SEC_GET_KEY_FN pGetKeyFn,
213  PVOID pGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
214 {
215     TRACE("(%s, %s, 0x%08x, %p, %p, %p, %p, %p, %p)\n",
216      debugstr_a(pszPrincipal), debugstr_a(pszPackage), fCredentialUse,
217      pLogonID, pAuthData, pGetKeyFn, pGetKeyArgument, phCredential, ptsExpiry);
218     return schan_AcquireCredentialsHandle(fCredentialUse,
219      (PSCHANNEL_CRED)pAuthData, phCredential, ptsExpiry);
220 }
221
222 static SECURITY_STATUS SEC_ENTRY schan_AcquireCredentialsHandleW(
223  SEC_WCHAR *pszPrincipal, SEC_WCHAR *pszPackage, ULONG fCredentialUse,
224  PLUID pLogonID, PVOID pAuthData, SEC_GET_KEY_FN pGetKeyFn,
225  PVOID pGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
226 {
227     TRACE("(%s, %s, 0x%08x, %p, %p, %p, %p, %p, %p)\n",
228      debugstr_w(pszPrincipal), debugstr_w(pszPackage), fCredentialUse,
229      pLogonID, pAuthData, pGetKeyFn, pGetKeyArgument, phCredential, ptsExpiry);
230     return schan_AcquireCredentialsHandle(fCredentialUse,
231      (PSCHANNEL_CRED)pAuthData, phCredential, ptsExpiry);
232 }
233
234 static SECURITY_STATUS SEC_ENTRY schan_FreeCredentialsHandle(
235  PCredHandle phCredential)
236 {
237     FIXME("(%p): stub\n", phCredential);
238     return SEC_E_OK;
239 }
240
241 /***********************************************************************
242  *              InitializeSecurityContextA
243  */
244 static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextA(
245  PCredHandle phCredential, PCtxtHandle phContext, SEC_CHAR *pszTargetName,
246  ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
247  PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext,
248  PSecBufferDesc pOutput, ULONG *pfContextAttr, PTimeStamp ptsExpiry)
249 {
250     SECURITY_STATUS ret;
251
252     TRACE("%p %p %s %d %d %d %p %d %p %p %p %p\n", phCredential, phContext,
253      debugstr_a(pszTargetName), fContextReq, Reserved1, TargetDataRep, pInput,
254      Reserved1, phNewContext, pOutput, pfContextAttr, ptsExpiry);
255     if(phCredential)
256     {
257         FIXME("stub\n");
258         ret = SEC_E_UNSUPPORTED_FUNCTION;
259     }
260     else
261     {
262         ret = SEC_E_INVALID_HANDLE;
263     }
264     return ret;
265 }
266
267 /***********************************************************************
268  *              InitializeSecurityContextW
269  */
270 static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW(
271  PCredHandle phCredential, PCtxtHandle phContext, SEC_WCHAR *pszTargetName,
272  ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
273  PSecBufferDesc pInput,ULONG Reserved2, PCtxtHandle phNewContext,
274  PSecBufferDesc pOutput, ULONG *pfContextAttr, PTimeStamp ptsExpiry)
275 {
276     SECURITY_STATUS ret;
277
278     TRACE("%p %p %s %d %d %d %p %d %p %p %p %p\n", phCredential, phContext,
279      debugstr_w(pszTargetName), fContextReq, Reserved1, TargetDataRep, pInput,
280      Reserved1, phNewContext, pOutput, pfContextAttr, ptsExpiry);
281     if (phCredential)
282     {
283         FIXME("stub\n");
284         ret = SEC_E_UNSUPPORTED_FUNCTION;
285     }
286     else
287     {
288         ret = SEC_E_INVALID_HANDLE;
289     }
290     return ret;
291 }
292
293 static SecurityFunctionTableA schanTableA = {
294     1,
295     NULL, /* EnumerateSecurityPackagesA */
296     schan_QueryCredentialsAttributesA,
297     schan_AcquireCredentialsHandleA,
298     schan_FreeCredentialsHandle,
299     NULL, /* Reserved2 */
300     schan_InitializeSecurityContextA, 
301     NULL, /* AcceptSecurityContext */
302     NULL, /* CompleteAuthToken */
303     NULL, /* DeleteSecurityContext */
304     NULL, /* ApplyControlToken */
305     NULL, /* QueryContextAttributesA */
306     NULL, /* ImpersonateSecurityContext */
307     NULL, /* RevertSecurityContext */
308     NULL, /* MakeSignature */
309     NULL, /* VerifySignature */
310     FreeContextBuffer,
311     NULL, /* QuerySecurityPackageInfoA */
312     NULL, /* Reserved3 */
313     NULL, /* Reserved4 */
314     NULL, /* ExportSecurityContext */
315     NULL, /* ImportSecurityContextA */
316     NULL, /* AddCredentialsA */
317     NULL, /* Reserved8 */
318     NULL, /* QuerySecurityContextToken */
319     NULL, /* EncryptMessage */
320     NULL, /* DecryptMessage */
321     NULL, /* SetContextAttributesA */
322 };
323
324 static SecurityFunctionTableW schanTableW = {
325     1,
326     NULL, /* EnumerateSecurityPackagesW */
327     schan_QueryCredentialsAttributesW,
328     schan_AcquireCredentialsHandleW,
329     schan_FreeCredentialsHandle,
330     NULL, /* Reserved2 */
331     schan_InitializeSecurityContextW, 
332     NULL, /* AcceptSecurityContext */
333     NULL, /* CompleteAuthToken */
334     NULL, /* DeleteSecurityContext */
335     NULL, /* ApplyControlToken */
336     NULL, /* QueryContextAttributesW */
337     NULL, /* ImpersonateSecurityContext */
338     NULL, /* RevertSecurityContext */
339     NULL, /* MakeSignature */
340     NULL, /* VerifySignature */
341     FreeContextBuffer,
342     NULL, /* QuerySecurityPackageInfoW */
343     NULL, /* Reserved3 */
344     NULL, /* Reserved4 */
345     NULL, /* ExportSecurityContext */
346     NULL, /* ImportSecurityContextW */
347     NULL, /* AddCredentialsW */
348     NULL, /* Reserved8 */
349     NULL, /* QuerySecurityContextToken */
350     NULL, /* EncryptMessage */
351     NULL, /* DecryptMessage */
352     NULL, /* SetContextAttributesW */
353 };
354
355 static const WCHAR schannelComment[] = { 'S','c','h','a','n','n','e','l',' ',
356  'S','e','c','u','r','i','t','y',' ','P','a','c','k','a','g','e',0 };
357
358 void SECUR32_initSchannelSP(void)
359 {
360     SecureProvider *provider = SECUR32_addProvider(&schanTableA, &schanTableW,
361      NULL);
362
363     if (provider)
364     {
365         /* This is what Windows reports.  This shouldn't break any applications
366          * even though the functions are missing, because the wrapper will
367          * return SEC_E_UNSUPPORTED_FUNCTION if our function is NULL.
368          */
369         static const long caps =
370          SECPKG_FLAG_INTEGRITY |
371          SECPKG_FLAG_PRIVACY |
372          SECPKG_FLAG_CONNECTION |
373          SECPKG_FLAG_MULTI_REQUIRED |
374          SECPKG_FLAG_EXTENDED_ERROR |
375          SECPKG_FLAG_IMPERSONATION |
376          SECPKG_FLAG_ACCEPT_WIN32_NAME |
377          SECPKG_FLAG_STREAM;
378         static const short version = 1;
379         static const long maxToken = 16384;
380         SEC_WCHAR *uniSPName = (SEC_WCHAR *)UNISP_NAME_W,
381          *schannel = (SEC_WCHAR *)SCHANNEL_NAME_W;
382
383         const SecPkgInfoW info[] = {
384          { caps, version, UNISP_RPC_ID, maxToken, uniSPName, uniSPName },
385          { caps, version, UNISP_RPC_ID, maxToken, schannel,
386           (SEC_WCHAR *)schannelComment },
387         };
388
389         SECUR32_addPackages(provider, sizeof(info) / sizeof(info[0]), NULL,
390          info);
391     }
392 }