secur32: Implement a Negotiate provider that forwards to NTLM.
[wine/multimedia.git] / dlls / secur32 / negotiate.c
blobac48a777e9af08c0771e73a4a8f2420de02d948a
1 /*
2 * Copyright 2005 Kai Blin
3 * Copyright 2012 Hans Leidekker for CodeWeavers
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 * This file implements a Negotiate provider that simply forwards to
20 * the NTLM provider.
23 #include <stdarg.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "sspi.h"
27 #include "rpc.h"
28 #include "wincred.h"
29 #include "secur32_priv.h"
31 #include "wine/debug.h"
32 #include "wine/unicode.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(secur32);
36 /***********************************************************************
37 * QueryCredentialsAttributesA
39 static SECURITY_STATUS SEC_ENTRY nego_QueryCredentialsAttributesA(
40 PCredHandle phCredential, ULONG ulAttribute, PVOID pBuffer)
42 FIXME("%p, %u, %p\n", phCredential, ulAttribute, pBuffer);
43 return SEC_E_UNSUPPORTED_FUNCTION;
46 /***********************************************************************
47 * QueryCredentialsAttributesW
49 static SECURITY_STATUS SEC_ENTRY nego_QueryCredentialsAttributesW(
50 PCredHandle phCredential, ULONG ulAttribute, PVOID pBuffer)
52 FIXME("%p, %u, %p\n", phCredential, ulAttribute, pBuffer);
53 return SEC_E_UNSUPPORTED_FUNCTION;
56 /***********************************************************************
57 * AcquireCredentialsHandleW
59 static SECURITY_STATUS SEC_ENTRY nego_AcquireCredentialsHandleW(
60 SEC_WCHAR *pszPrincipal, SEC_WCHAR *pszPackage, ULONG fCredentialUse,
61 PLUID pLogonID, PVOID pAuthData, SEC_GET_KEY_FN pGetKeyFn,
62 PVOID pGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry )
64 static SEC_WCHAR ntlmW[] = {'N','T','L','M',0};
65 SECURITY_STATUS ret;
67 TRACE("%s, %s, 0x%08x, %p, %p, %p, %p, %p, %p\n",
68 debugstr_w(pszPrincipal), debugstr_w(pszPackage), fCredentialUse,
69 pLogonID, pAuthData, pGetKeyFn, pGetKeyArgument, phCredential, ptsExpiry);
71 FIXME("forwarding to NTLM\n");
72 ret = ntlm_AcquireCredentialsHandleW( pszPrincipal, ntlmW, fCredentialUse,
73 pLogonID, pAuthData, pGetKeyFn, pGetKeyArgument,
74 phCredential, ptsExpiry );
75 if (ret == SEC_E_OK)
77 NtlmCredentials *cred = (NtlmCredentials *)phCredential->dwLower;
78 cred->no_cached_credentials = (pAuthData == NULL);
80 return ret;
83 /***********************************************************************
84 * AcquireCredentialsHandleA
86 static SECURITY_STATUS SEC_ENTRY nego_AcquireCredentialsHandleA(
87 SEC_CHAR *pszPrincipal, SEC_CHAR *pszPackage, ULONG fCredentialUse,
88 PLUID pLogonID, PVOID pAuthData, SEC_GET_KEY_FN pGetKeyFn,
89 PVOID pGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry )
91 SECURITY_STATUS ret = SEC_E_INSUFFICIENT_MEMORY;
92 SEC_WCHAR *user = NULL, *domain = NULL, *passwd = NULL, *package = NULL;
93 SEC_WINNT_AUTH_IDENTITY_W *identityW = NULL;
95 TRACE("%s, %s, 0x%08x, %p, %p, %p, %p, %p, %p\n",
96 debugstr_a(pszPrincipal), debugstr_a(pszPackage), fCredentialUse,
97 pLogonID, pAuthData, pGetKeyFn, pGetKeyArgument, phCredential, ptsExpiry);
99 if (pszPackage)
101 int package_len = MultiByteToWideChar( CP_ACP, 0, pszPackage, -1, NULL, 0 );
102 package = HeapAlloc( GetProcessHeap(), 0, package_len * sizeof(SEC_WCHAR) );
103 if (!package) return SEC_E_INSUFFICIENT_MEMORY;
104 MultiByteToWideChar( CP_ACP, 0, pszPackage, -1, package, package_len );
106 if (pAuthData)
108 SEC_WINNT_AUTH_IDENTITY_A *identity = pAuthData;
109 int user_len, domain_len, passwd_len;
111 if (identity->Flags == SEC_WINNT_AUTH_IDENTITY_ANSI)
113 identityW = HeapAlloc( GetProcessHeap(), 0, sizeof(*identityW) );
114 if (!identityW) goto done;
116 if (!identity->UserLength) user_len = 0;
117 else
119 user_len = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)identity->User,
120 identity->UserLength, NULL, 0 );
121 user = HeapAlloc( GetProcessHeap(), 0, user_len * sizeof(SEC_WCHAR) );
122 if (!user) goto done;
123 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)identity->User, identity->UserLength,
124 user, user_len );
126 if (!identity->DomainLength) domain_len = 0;
127 else
129 domain_len = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)identity->Domain,
130 identity->DomainLength, NULL, 0 );
131 domain = HeapAlloc( GetProcessHeap(), 0, domain_len * sizeof(SEC_WCHAR) );
132 if (!domain) goto done;
133 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)identity->Domain, identity->DomainLength,
134 domain, domain_len );
136 if (!identity->PasswordLength) passwd_len = 0;
137 else
139 passwd_len = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)identity->Password,
140 identity->PasswordLength, NULL, 0 );
141 passwd = HeapAlloc( GetProcessHeap(), 0, passwd_len * sizeof(SEC_WCHAR) );
142 if (!passwd) goto done;
143 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)identity->Password, identity->PasswordLength,
144 passwd, passwd_len );
146 identityW->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
147 identityW->User = user;
148 identityW->UserLength = user_len;
149 identityW->Domain = domain;
150 identityW->DomainLength = domain_len;
151 identityW->Password = passwd;
152 identityW->PasswordLength = passwd_len;
154 else identityW = (SEC_WINNT_AUTH_IDENTITY_W *)identity;
156 ret = nego_AcquireCredentialsHandleW( NULL, package, fCredentialUse, pLogonID, identityW,
157 pGetKeyFn, pGetKeyArgument, phCredential, ptsExpiry );
158 done:
159 HeapFree( GetProcessHeap(), 0, package );
160 HeapFree( GetProcessHeap(), 0, user );
161 HeapFree( GetProcessHeap(), 0, domain );
162 HeapFree( GetProcessHeap(), 0, passwd );
163 HeapFree( GetProcessHeap(), 0, identityW );
164 return ret;
167 /***********************************************************************
168 * InitializeSecurityContextW
170 static SECURITY_STATUS SEC_ENTRY nego_InitializeSecurityContextW(
171 PCredHandle phCredential, PCtxtHandle phContext, SEC_WCHAR *pszTargetName,
172 ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
173 PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext,
174 PSecBufferDesc pOutput, ULONG *pfContextAttr, PTimeStamp ptsExpiry )
176 TRACE("%p, %p, %s, 0x%08x, %u, %u, %p, %u, %p, %p, %p, %p\n",
177 phCredential, phContext, debugstr_w(pszTargetName), fContextReq,
178 Reserved1, TargetDataRep, pInput, Reserved1, phNewContext, pOutput,
179 pfContextAttr, ptsExpiry);
181 return ntlm_InitializeSecurityContextW( phCredential, phContext, pszTargetName,
182 fContextReq, Reserved1, TargetDataRep,
183 pInput, Reserved2, phNewContext,
184 pOutput, pfContextAttr, ptsExpiry );
187 /***********************************************************************
188 * InitializeSecurityContextA
190 static SECURITY_STATUS SEC_ENTRY nego_InitializeSecurityContextA(
191 PCredHandle phCredential, PCtxtHandle phContext, SEC_CHAR *pszTargetName,
192 ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
193 PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext,
194 PSecBufferDesc pOutput, ULONG *pfContextAttr, PTimeStamp ptsExpiry )
196 SECURITY_STATUS ret;
197 SEC_WCHAR *target = NULL;
199 TRACE("%p, %p, %s, 0x%08x, %u, %u, %p, %u, %p, %p, %p, %p\n",
200 phCredential, phContext, debugstr_a(pszTargetName), fContextReq,
201 Reserved1, TargetDataRep, pInput, Reserved1, phNewContext, pOutput,
202 pfContextAttr, ptsExpiry);
204 if (pszTargetName)
206 int target_len = MultiByteToWideChar( CP_ACP, 0, pszTargetName, -1, NULL, 0 );
207 target = HeapAlloc(GetProcessHeap(), 0, target_len * sizeof(SEC_WCHAR) );
208 if (!target) return SEC_E_INSUFFICIENT_MEMORY;
209 MultiByteToWideChar( CP_ACP, 0, pszTargetName, -1, target, target_len );
211 ret = nego_InitializeSecurityContextW( phCredential, phContext, target, fContextReq,
212 Reserved1, TargetDataRep, pInput, Reserved2,
213 phNewContext, pOutput, pfContextAttr, ptsExpiry );
214 HeapFree( GetProcessHeap(), 0, target );
215 return ret;
218 /***********************************************************************
219 * AcceptSecurityContext
221 static SECURITY_STATUS SEC_ENTRY nego_AcceptSecurityContext(
222 PCredHandle phCredential, PCtxtHandle phContext, PSecBufferDesc pInput,
223 ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext,
224 PSecBufferDesc pOutput, ULONG *pfContextAttr, PTimeStamp ptsExpiry)
226 TRACE("%p, %p, %p, 0x%08x, %u, %p, %p, %p, %p\n", phCredential, phContext,
227 pInput, fContextReq, TargetDataRep, phNewContext, pOutput, pfContextAttr,
228 ptsExpiry);
230 return ntlm_AcceptSecurityContext( phCredential, phContext, pInput,
231 fContextReq, TargetDataRep, phNewContext,
232 pOutput, pfContextAttr, ptsExpiry );
235 /***********************************************************************
236 * CompleteAuthToken
238 static SECURITY_STATUS SEC_ENTRY nego_CompleteAuthToken(PCtxtHandle phContext,
239 PSecBufferDesc pToken)
241 SECURITY_STATUS ret;
243 TRACE("%p %p\n", phContext, pToken);
244 if (phContext)
246 ret = SEC_E_UNSUPPORTED_FUNCTION;
248 else
250 ret = SEC_E_INVALID_HANDLE;
252 return ret;
255 /***********************************************************************
256 * DeleteSecurityContext
258 static SECURITY_STATUS SEC_ENTRY nego_DeleteSecurityContext(PCtxtHandle phContext)
260 TRACE("%p\n", phContext);
262 return ntlm_DeleteSecurityContext( phContext );
265 /***********************************************************************
266 * ApplyControlToken
268 static SECURITY_STATUS SEC_ENTRY nego_ApplyControlToken(PCtxtHandle phContext,
269 PSecBufferDesc pInput)
271 SECURITY_STATUS ret;
273 TRACE("%p %p\n", phContext, pInput);
274 if (phContext)
276 ret = SEC_E_UNSUPPORTED_FUNCTION;
278 else
280 ret = SEC_E_INVALID_HANDLE;
282 return ret;
285 /***********************************************************************
286 * QueryContextAttributesW
288 static SECURITY_STATUS SEC_ENTRY nego_QueryContextAttributesW(
289 PCtxtHandle phContext, ULONG ulAttribute, void *pBuffer)
291 TRACE("%p, %u, %p\n", phContext, ulAttribute, pBuffer);
293 switch (ulAttribute)
295 case SECPKG_ATTR_SIZES:
297 SecPkgContext_Sizes *sizes = (SecPkgContext_Sizes *)pBuffer;
298 sizes->cbMaxToken = 2888;
299 sizes->cbMaxSignature = 16;
300 sizes->cbSecurityTrailer = 16;
301 sizes->cbBlockSize = 0;
302 return SEC_E_OK;
304 case SECPKG_ATTR_NEGOTIATION_INFO:
306 SecPkgContext_NegotiationInfoW *info = (SecPkgContext_NegotiationInfoW *)pBuffer;
307 info->PackageInfo = ntlm_package_infoW;
308 info->NegotiationState = SECPKG_NEGOTIATION_COMPLETE;
309 return SEC_E_OK;
311 default:
312 return ntlm_QueryContextAttributesW( phContext, ulAttribute, pBuffer );
316 /***********************************************************************
317 * QueryContextAttributesA
319 static SECURITY_STATUS SEC_ENTRY nego_QueryContextAttributesA(PCtxtHandle phContext,
320 ULONG ulAttribute, void *pBuffer)
322 TRACE("%p, %u, %p\n", phContext, ulAttribute, pBuffer);
324 switch (ulAttribute)
326 case SECPKG_ATTR_SIZES:
328 SecPkgContext_Sizes *sizes = (SecPkgContext_Sizes *)pBuffer;
329 sizes->cbMaxToken = 2888;
330 sizes->cbMaxSignature = 16;
331 sizes->cbSecurityTrailer = 16;
332 sizes->cbBlockSize = 0;
333 return SEC_E_OK;
335 case SECPKG_ATTR_NEGOTIATION_INFO:
337 SecPkgContext_NegotiationInfoA *info = (SecPkgContext_NegotiationInfoA *)pBuffer;
338 info->PackageInfo = ntlm_package_infoA;
339 info->NegotiationState = SECPKG_NEGOTIATION_COMPLETE;
340 return SEC_E_OK;
342 default:
343 return ntlm_QueryContextAttributesA( phContext, ulAttribute, pBuffer );
347 /***********************************************************************
348 * ImpersonateSecurityContext
350 static SECURITY_STATUS SEC_ENTRY nego_ImpersonateSecurityContext(PCtxtHandle phContext)
352 SECURITY_STATUS ret;
354 TRACE("%p\n", phContext);
355 if (phContext)
357 ret = SEC_E_UNSUPPORTED_FUNCTION;
359 else
361 ret = SEC_E_INVALID_HANDLE;
363 return ret;
366 /***********************************************************************
367 * RevertSecurityContext
369 static SECURITY_STATUS SEC_ENTRY nego_RevertSecurityContext(PCtxtHandle phContext)
371 SECURITY_STATUS ret;
373 TRACE("%p\n", phContext);
374 if (phContext)
376 ret = SEC_E_UNSUPPORTED_FUNCTION;
378 else
380 ret = SEC_E_INVALID_HANDLE;
382 return ret;
385 /***********************************************************************
386 * MakeSignature
388 static SECURITY_STATUS SEC_ENTRY nego_MakeSignature(PCtxtHandle phContext,
389 ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo)
391 TRACE("%p, 0x%08x, %p, %u\n", phContext, fQOP, pMessage, MessageSeqNo);
393 return ntlm_MakeSignature( phContext, fQOP, pMessage, MessageSeqNo );
396 /***********************************************************************
397 * VerifySignature
399 static SECURITY_STATUS SEC_ENTRY nego_VerifySignature(PCtxtHandle phContext,
400 PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP)
402 TRACE("%p, %p, %u, %p\n", phContext, pMessage, MessageSeqNo, pfQOP);
404 return ntlm_VerifySignature( phContext, pMessage, MessageSeqNo, pfQOP );
407 /***********************************************************************
408 * FreeCredentialsHandle
410 SECURITY_STATUS SEC_ENTRY nego_FreeCredentialsHandle(PCredHandle phCredential)
412 TRACE("%p\n", phCredential);
414 return ntlm_FreeCredentialsHandle( phCredential );
417 /***********************************************************************
418 * EncryptMessage
420 SECURITY_STATUS SEC_ENTRY nego_EncryptMessage(PCtxtHandle phContext,
421 ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo)
423 TRACE("%p, 0x%08x, %p, %u\n", phContext, fQOP, pMessage, MessageSeqNo);
425 return ntlm_EncryptMessage( phContext, fQOP, pMessage, MessageSeqNo );
428 /***********************************************************************
429 * DecryptMessage
431 SECURITY_STATUS SEC_ENTRY nego_DecryptMessage(PCtxtHandle phContext,
432 PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP)
434 TRACE("%p, %p, %u, %p\n", phContext, pMessage, MessageSeqNo, pfQOP);
436 return ntlm_DecryptMessage( phContext, pMessage, MessageSeqNo, pfQOP );
439 static const SecurityFunctionTableA negoTableA = {
441 NULL, /* EnumerateSecurityPackagesA */
442 nego_QueryCredentialsAttributesA, /* QueryCredentialsAttributesA */
443 nego_AcquireCredentialsHandleA, /* AcquireCredentialsHandleA */
444 nego_FreeCredentialsHandle, /* FreeCredentialsHandle */
445 NULL, /* Reserved2 */
446 nego_InitializeSecurityContextA, /* InitializeSecurityContextA */
447 nego_AcceptSecurityContext, /* AcceptSecurityContext */
448 nego_CompleteAuthToken, /* CompleteAuthToken */
449 nego_DeleteSecurityContext, /* DeleteSecurityContext */
450 nego_ApplyControlToken, /* ApplyControlToken */
451 nego_QueryContextAttributesA, /* QueryContextAttributesA */
452 nego_ImpersonateSecurityContext, /* ImpersonateSecurityContext */
453 nego_RevertSecurityContext, /* RevertSecurityContext */
454 nego_MakeSignature, /* MakeSignature */
455 nego_VerifySignature, /* VerifySignature */
456 FreeContextBuffer, /* FreeContextBuffer */
457 NULL, /* QuerySecurityPackageInfoA */
458 NULL, /* Reserved3 */
459 NULL, /* Reserved4 */
460 NULL, /* ExportSecurityContext */
461 NULL, /* ImportSecurityContextA */
462 NULL, /* AddCredentialsA */
463 NULL, /* Reserved8 */
464 NULL, /* QuerySecurityContextToken */
465 nego_EncryptMessage, /* EncryptMessage */
466 nego_DecryptMessage, /* DecryptMessage */
467 NULL, /* SetContextAttributesA */
470 static const SecurityFunctionTableW negoTableW = {
472 NULL, /* EnumerateSecurityPackagesW */
473 nego_QueryCredentialsAttributesW, /* QueryCredentialsAttributesW */
474 nego_AcquireCredentialsHandleW, /* AcquireCredentialsHandleW */
475 nego_FreeCredentialsHandle, /* FreeCredentialsHandle */
476 NULL, /* Reserved2 */
477 nego_InitializeSecurityContextW, /* InitializeSecurityContextW */
478 nego_AcceptSecurityContext, /* AcceptSecurityContext */
479 nego_CompleteAuthToken, /* CompleteAuthToken */
480 nego_DeleteSecurityContext, /* DeleteSecurityContext */
481 nego_ApplyControlToken, /* ApplyControlToken */
482 nego_QueryContextAttributesW, /* QueryContextAttributesW */
483 nego_ImpersonateSecurityContext, /* ImpersonateSecurityContext */
484 nego_RevertSecurityContext, /* RevertSecurityContext */
485 nego_MakeSignature, /* MakeSignature */
486 nego_VerifySignature, /* VerifySignature */
487 FreeContextBuffer, /* FreeContextBuffer */
488 NULL, /* QuerySecurityPackageInfoW */
489 NULL, /* Reserved3 */
490 NULL, /* Reserved4 */
491 NULL, /* ExportSecurityContext */
492 NULL, /* ImportSecurityContextW */
493 NULL, /* AddCredentialsW */
494 NULL, /* Reserved8 */
495 NULL, /* QuerySecurityContextToken */
496 nego_EncryptMessage, /* EncryptMessage */
497 nego_DecryptMessage, /* DecryptMessage */
498 NULL, /* SetContextAttributesW */
501 #define NEGO_MAX_TOKEN 12000
503 static WCHAR nego_name_W[] = {'N','e','g','o','t','i','a','t','e',0};
504 static char nego_name_A[] = "Negotiate";
506 static WCHAR negotiate_comment_W[] =
507 {'M','i','c','r','o','s','o','f','t',' ','P','a','c','k','a','g','e',' ',
508 'N','e','g','o','t','i','a','t','o','r',0};
509 static CHAR negotiate_comment_A[] = "Microsoft Package Negotiator";
511 #define CAPS ( \
512 SECPKG_FLAG_INTEGRITY | \
513 SECPKG_FLAG_PRIVACY | \
514 SECPKG_FLAG_CONNECTION | \
515 SECPKG_FLAG_MULTI_REQUIRED | \
516 SECPKG_FLAG_EXTENDED_ERROR | \
517 SECPKG_FLAG_IMPERSONATION | \
518 SECPKG_FLAG_ACCEPT_WIN32_NAME | \
519 SECPKG_FLAG_NEGOTIABLE | \
520 SECPKG_FLAG_GSS_COMPATIBLE | \
521 SECPKG_FLAG_LOGON | \
522 SECPKG_FLAG_RESTRICTED_TOKENS )
524 void SECUR32_initNegotiateSP(void)
526 SecureProvider *provider = SECUR32_addProvider(&negoTableA, &negoTableW, NULL);
528 const SecPkgInfoW infoW = {CAPS, 1, RPC_C_AUTHN_GSS_NEGOTIATE, NEGO_MAX_TOKEN,
529 nego_name_W, negotiate_comment_W};
530 const SecPkgInfoA infoA = {CAPS, 1, RPC_C_AUTHN_GSS_NEGOTIATE, NEGO_MAX_TOKEN,
531 nego_name_A, negotiate_comment_A};
532 SECUR32_addPackages(provider, 1L, &infoA, &infoW);