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
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};
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
);
77 NtlmCredentials
*cred
= (NtlmCredentials
*)phCredential
->dwLower
;
78 cred
->no_cached_credentials
= (pAuthData
== NULL
);
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
);
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
);
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;
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
,
126 if (!identity
->DomainLength
) domain_len
= 0;
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;
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
);
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
);
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
)
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
);
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
);
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
,
230 return ntlm_AcceptSecurityContext( phCredential
, phContext
, pInput
,
231 fContextReq
, TargetDataRep
, phNewContext
,
232 pOutput
, pfContextAttr
, ptsExpiry
);
235 /***********************************************************************
238 static SECURITY_STATUS SEC_ENTRY
nego_CompleteAuthToken(PCtxtHandle phContext
,
239 PSecBufferDesc pToken
)
243 TRACE("%p %p\n", phContext
, pToken
);
246 ret
= SEC_E_UNSUPPORTED_FUNCTION
;
250 ret
= SEC_E_INVALID_HANDLE
;
255 /***********************************************************************
256 * DeleteSecurityContext
258 static SECURITY_STATUS SEC_ENTRY
nego_DeleteSecurityContext(PCtxtHandle phContext
)
260 TRACE("%p\n", phContext
);
262 return ntlm_DeleteSecurityContext( phContext
);
265 /***********************************************************************
268 static SECURITY_STATUS SEC_ENTRY
nego_ApplyControlToken(PCtxtHandle phContext
,
269 PSecBufferDesc pInput
)
273 TRACE("%p %p\n", phContext
, pInput
);
276 ret
= SEC_E_UNSUPPORTED_FUNCTION
;
280 ret
= SEC_E_INVALID_HANDLE
;
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
);
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;
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
;
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
);
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;
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
;
343 return ntlm_QueryContextAttributesA( phContext
, ulAttribute
, pBuffer
);
347 /***********************************************************************
348 * ImpersonateSecurityContext
350 static SECURITY_STATUS SEC_ENTRY
nego_ImpersonateSecurityContext(PCtxtHandle phContext
)
354 TRACE("%p\n", phContext
);
357 ret
= SEC_E_UNSUPPORTED_FUNCTION
;
361 ret
= SEC_E_INVALID_HANDLE
;
366 /***********************************************************************
367 * RevertSecurityContext
369 static SECURITY_STATUS SEC_ENTRY
nego_RevertSecurityContext(PCtxtHandle phContext
)
373 TRACE("%p\n", phContext
);
376 ret
= SEC_E_UNSUPPORTED_FUNCTION
;
380 ret
= SEC_E_INVALID_HANDLE
;
385 /***********************************************************************
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 /***********************************************************************
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 static SECURITY_STATUS SEC_ENTRY
nego_FreeCredentialsHandle(PCredHandle phCredential
)
412 TRACE("%p\n", phCredential
);
414 return ntlm_FreeCredentialsHandle( phCredential
);
417 /***********************************************************************
420 static 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 /***********************************************************************
431 static 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";
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
);