4 * Copyright 2006 Juan Lang
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #define SECURITY_WIN32
30 #include "wine/test.h"
32 static HMODULE secdll
, crypt32dll
;
34 static ACQUIRE_CREDENTIALS_HANDLE_FN_A pAcquireCredentialsHandleA
;
35 static ENUMERATE_SECURITY_PACKAGES_FN_A pEnumerateSecurityPackagesA
;
36 static FREE_CONTEXT_BUFFER_FN pFreeContextBuffer
;
37 static FREE_CREDENTIALS_HANDLE_FN pFreeCredentialsHandle
;
38 static QUERY_CREDENTIALS_ATTRIBUTES_FN_A pQueryCredentialsAttributesA
;
39 static INITIALIZE_SECURITY_CONTEXT_FN_A pInitializeSecurityContextA
;
40 static QUERY_CONTEXT_ATTRIBUTES_FN_A pQueryContextAttributesA
;
41 static DELETE_SECURITY_CONTEXT_FN pDeleteSecurityContext
;
42 static DECRYPT_MESSAGE_FN pDecryptMessage
;
43 static ENCRYPT_MESSAGE_FN pEncryptMessage
;
45 static PCCERT_CONTEXT (WINAPI
*pCertCreateCertificateContext
)(DWORD
,const BYTE
*,DWORD
);
46 static BOOL (WINAPI
*pCertFreeCertificateContext
)(PCCERT_CONTEXT
);
47 static BOOL (WINAPI
*pCertSetCertificateContextProperty
)(PCCERT_CONTEXT
,DWORD
,DWORD
,const void*);
49 static BOOL (WINAPI
*pCryptAcquireContextW
)(HCRYPTPROV
*, LPCWSTR
, LPCWSTR
, DWORD
, DWORD
);
50 static BOOL (WINAPI
*pCryptDestroyKey
)(HCRYPTKEY
);
51 static BOOL (WINAPI
*pCryptImportKey
)(HCRYPTPROV
,CONST BYTE
*,DWORD
,HCRYPTKEY
,DWORD
,HCRYPTKEY
*);
52 static BOOL (WINAPI
*pCryptReleaseContext
)(HCRYPTPROV
,ULONG_PTR
);
54 static const BYTE bigCert
[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
55 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
56 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
57 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
58 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
59 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
60 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
61 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
62 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
63 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
64 static WCHAR cspNameW
[] = { 'W','i','n','e','C','r','y','p','t','T','e',
66 static BYTE privKey
[] = {
67 0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, 0x41, 0x32, 0x00,
68 0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x79, 0x10, 0x1c, 0xd0, 0x6b, 0x10,
69 0x18, 0x30, 0x94, 0x61, 0xdc, 0x0e, 0xcb, 0x96, 0x4e, 0x21, 0x3f, 0x79, 0xcd,
70 0xa9, 0x17, 0x62, 0xbc, 0xbb, 0x61, 0x4c, 0xe0, 0x75, 0x38, 0x6c, 0xf3, 0xde,
71 0x60, 0x86, 0x03, 0x97, 0x65, 0xeb, 0x1e, 0x6b, 0xdb, 0x53, 0x85, 0xad, 0x68,
72 0x21, 0xf1, 0x5d, 0xe7, 0x1f, 0xe6, 0x53, 0xb4, 0xbb, 0x59, 0x3e, 0x14, 0x27,
73 0xb1, 0x83, 0xa7, 0x3a, 0x54, 0xe2, 0x8f, 0x65, 0x8e, 0x6a, 0x4a, 0xcf, 0x3b,
74 0x1f, 0x65, 0xff, 0xfe, 0xf1, 0x31, 0x3a, 0x37, 0x7a, 0x8b, 0xcb, 0xc6, 0xd4,
75 0x98, 0x50, 0x36, 0x67, 0xe4, 0xa1, 0xe8, 0x7e, 0x8a, 0xc5, 0x23, 0xf2, 0x77,
76 0xf5, 0x37, 0x61, 0x49, 0x72, 0x59, 0xe8, 0x3d, 0xf7, 0x60, 0xb2, 0x77, 0xca,
77 0x78, 0x54, 0x6d, 0x65, 0x9e, 0x03, 0x97, 0x1b, 0x61, 0xbd, 0x0c, 0xd8, 0x06,
78 0x63, 0xe2, 0xc5, 0x48, 0xef, 0xb3, 0xe2, 0x6e, 0x98, 0x7d, 0xbd, 0x4e, 0x72,
79 0x91, 0xdb, 0x31, 0x57, 0xe3, 0x65, 0x3a, 0x49, 0xca, 0xec, 0xd2, 0x02, 0x4e,
80 0x22, 0x7e, 0x72, 0x8e, 0xf9, 0x79, 0x84, 0x82, 0xdf, 0x7b, 0x92, 0x2d, 0xaf,
81 0xc9, 0xe4, 0x33, 0xef, 0x89, 0x5c, 0x66, 0x99, 0xd8, 0x80, 0x81, 0x47, 0x2b,
82 0xb1, 0x66, 0x02, 0x84, 0x59, 0x7b, 0xc3, 0xbe, 0x98, 0x45, 0x4a, 0x3d, 0xdd,
83 0xea, 0x2b, 0xdf, 0x4e, 0xb4, 0x24, 0x6b, 0xec, 0xe7, 0xd9, 0x0c, 0x45, 0xb8,
84 0xbe, 0xca, 0x69, 0x37, 0x92, 0x4c, 0x38, 0x6b, 0x96, 0x6d, 0xcd, 0x86, 0x67,
85 0x5c, 0xea, 0x54, 0x94, 0xa4, 0xca, 0xa4, 0x02, 0xa5, 0x21, 0x4d, 0xae, 0x40,
86 0x8f, 0x9d, 0x51, 0x83, 0xf2, 0x3f, 0x33, 0xc1, 0x72, 0xb4, 0x1d, 0x94, 0x6e,
87 0x7d, 0xe4, 0x27, 0x3f, 0xea, 0xff, 0xe5, 0x9b, 0xa7, 0x5e, 0x55, 0x8e, 0x0d,
88 0x69, 0x1c, 0x7a, 0xff, 0x81, 0x9d, 0x53, 0x52, 0x97, 0x9a, 0x76, 0x79, 0xda,
89 0x93, 0x32, 0x16, 0xec, 0x69, 0x51, 0x1a, 0x4e, 0xc3, 0xf1, 0x72, 0x80, 0x78,
90 0x5e, 0x66, 0x4a, 0x8d, 0x85, 0x2f, 0x3f, 0xb2, 0xa7 };
92 static const BYTE selfSignedCert
[] = {
93 0x30, 0x82, 0x01, 0x1f, 0x30, 0x81, 0xce, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
94 0x10, 0xeb, 0x0d, 0x57, 0x2a, 0x9c, 0x09, 0xba, 0xa4, 0x4a, 0xb7, 0x25, 0x49,
95 0xd9, 0x3e, 0xb5, 0x73, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d,
96 0x05, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
97 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30,
98 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x36, 0x32, 0x39, 0x30, 0x35, 0x30, 0x30,
99 0x34, 0x36, 0x5a, 0x17, 0x0d, 0x30, 0x37, 0x30, 0x36, 0x32, 0x39, 0x31, 0x31,
100 0x30, 0x30, 0x34, 0x36, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
101 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e,
102 0x67, 0x00, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
103 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
104 0x00, 0xe2, 0x54, 0x3a, 0xa7, 0x83, 0xb1, 0x27, 0x14, 0x3e, 0x59, 0xbb, 0xb4,
105 0x53, 0xe6, 0x1f, 0xe7, 0x5d, 0xf1, 0x21, 0x68, 0xad, 0x85, 0x53, 0xdb, 0x6b,
106 0x1e, 0xeb, 0x65, 0x97, 0x03, 0x86, 0x60, 0xde, 0xf3, 0x6c, 0x38, 0x75, 0xe0,
107 0x4c, 0x61, 0xbb, 0xbc, 0x62, 0x17, 0xa9, 0xcd, 0x79, 0x3f, 0x21, 0x4e, 0x96,
108 0xcb, 0x0e, 0xdc, 0x61, 0x94, 0x30, 0x18, 0x10, 0x6b, 0xd0, 0x1c, 0x10, 0x79,
109 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
110 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x25, 0x90, 0x53, 0x34, 0xd9, 0x56, 0x41,
111 0x5e, 0xdb, 0x7e, 0x01, 0x36, 0xec, 0x27, 0x61, 0x5e, 0xb7, 0x4d, 0x90, 0x66,
112 0xa2, 0xe1, 0x9d, 0x58, 0x76, 0xd4, 0x9c, 0xba, 0x2c, 0x84, 0xc6, 0x83, 0x7a,
113 0x22, 0x0d, 0x03, 0x69, 0x32, 0x1a, 0x6d, 0xcb, 0x0c, 0x15, 0xb3, 0x6b, 0xc7,
114 0x0a, 0x8c, 0xb4, 0x5c, 0x34, 0x78, 0xe0, 0x3c, 0x9c, 0xe9, 0xf3, 0x30, 0x9f,
115 0xa8, 0x76, 0x57, 0x92, 0x36 };
117 static void InitFunctionPtrs(void)
121 crypt32dll
= LoadLibraryA("crypt32.dll");
122 secdll
= LoadLibraryA("secur32.dll");
124 secdll
= LoadLibraryA("security.dll");
125 advapi32dll
= GetModuleHandleA("advapi32.dll");
127 #define GET_PROC(h, func) p ## func = (void*)GetProcAddress(h, #func)
131 GET_PROC(secdll
, AcquireCredentialsHandleA
);
132 GET_PROC(secdll
, EnumerateSecurityPackagesA
);
133 GET_PROC(secdll
, FreeContextBuffer
);
134 GET_PROC(secdll
, FreeCredentialsHandle
);
135 GET_PROC(secdll
, QueryCredentialsAttributesA
);
136 GET_PROC(secdll
, InitializeSecurityContextA
);
137 GET_PROC(secdll
, QueryContextAttributesA
);
138 GET_PROC(secdll
, DeleteSecurityContext
);
139 GET_PROC(secdll
, DecryptMessage
);
140 GET_PROC(secdll
, EncryptMessage
);
143 GET_PROC(advapi32dll
, CryptAcquireContextW
);
144 GET_PROC(advapi32dll
, CryptDestroyKey
);
145 GET_PROC(advapi32dll
, CryptImportKey
);
146 GET_PROC(advapi32dll
, CryptReleaseContext
);
148 GET_PROC(crypt32dll
, CertFreeCertificateContext
);
149 GET_PROC(crypt32dll
, CertSetCertificateContextProperty
);
150 GET_PROC(crypt32dll
, CertCreateCertificateContext
);
155 static void test_strength(PCredHandle handle
)
157 SecPkgCred_CipherStrengths strength
= {-1,-1};
160 st
= pQueryCredentialsAttributesA(handle
, SECPKG_ATTR_CIPHER_STRENGTHS
, &strength
);
161 ok(st
== SEC_E_OK
, "QueryCredentialsAttributesA failed: %u\n", GetLastError());
162 ok(strength
.dwMinimumCipherStrength
, "dwMinimumCipherStrength not changed\n");
163 ok(strength
.dwMaximumCipherStrength
, "dwMaximumCipherStrength not changed\n");
164 trace("strength %d - %d\n", strength
.dwMinimumCipherStrength
, strength
.dwMaximumCipherStrength
);
167 static void testAcquireSecurityContext(void)
169 BOOL has_schannel
= FALSE
;
170 SecPkgInfoA
*package_info
;
175 SCHANNEL_CRED schanCred
;
176 PCCERT_CONTEXT certs
[2];
178 static CHAR unisp_name_a
[] = UNISP_NAME_A
;
179 WCHAR ms_def_prov_w
[MAX_PATH
];
182 CRYPT_KEY_PROV_INFO keyProvInfo
;
184 if (!pAcquireCredentialsHandleA
|| !pCertCreateCertificateContext
||
185 !pEnumerateSecurityPackagesA
|| !pFreeContextBuffer
||
186 !pFreeCredentialsHandle
|| !pCryptAcquireContextW
)
188 win_skip("Needed functions are not available\n");
192 if (SUCCEEDED(pEnumerateSecurityPackagesA(&i
, &package_info
)))
196 if (!strcmp(package_info
[i
].Name
, unisp_name_a
))
202 pFreeContextBuffer(package_info
);
206 skip("Schannel not available\n");
210 lstrcpyW(ms_def_prov_w
, MS_DEF_PROV_W
);
212 keyProvInfo
.pwszContainerName
= cspNameW
;
213 keyProvInfo
.pwszProvName
= ms_def_prov_w
;
214 keyProvInfo
.dwProvType
= PROV_RSA_FULL
;
215 keyProvInfo
.dwFlags
= 0;
216 keyProvInfo
.cProvParam
= 0;
217 keyProvInfo
.rgProvParam
= NULL
;
218 keyProvInfo
.dwKeySpec
= AT_SIGNATURE
;
220 certs
[0] = pCertCreateCertificateContext(X509_ASN_ENCODING
, bigCert
,
222 certs
[1] = pCertCreateCertificateContext(X509_ASN_ENCODING
, selfSignedCert
,
223 sizeof(selfSignedCert
));
225 SetLastError(0xdeadbeef);
226 ret
= pCryptAcquireContextW(&csp
, cspNameW
, MS_DEF_PROV_W
, PROV_RSA_FULL
,
228 if (!ret
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
230 /* WinMe would crash on some tests */
231 win_skip("CryptAcquireContextW is not implemented\n");
235 st
= pAcquireCredentialsHandleA(NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
, NULL
,
237 ok(st
== SEC_E_SECPKG_NOT_FOUND
,
238 "Expected SEC_E_SECPKG_NOT_FOUND, got %08x\n", st
);
241 /* Crashes on Win2K */
242 st
= pAcquireCredentialsHandleA(NULL
, unisp_name_a
, 0, NULL
, NULL
, NULL
,
244 ok(st
== SEC_E_NO_CREDENTIALS
, "Expected SEC_E_NO_CREDENTIALS, got %08x\n", st
);
246 /* Crashes on WinNT */
247 st
= pAcquireCredentialsHandleA(NULL
, unisp_name_a
, SECPKG_CRED_BOTH
, NULL
,
248 NULL
, NULL
, NULL
, NULL
, NULL
);
249 ok(st
== SEC_E_NO_CREDENTIALS
, "Expected SEC_E_NO_CREDENTIALS, got %08x\n", st
);
251 st
= pAcquireCredentialsHandleA(NULL
, unisp_name_a
, SECPKG_CRED_INBOUND
,
252 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
253 ok(st
== SEC_E_NO_CREDENTIALS
, "Expected SEC_E_NO_CREDENTIALS, got %08x\n", st
);
256 pAcquireCredentialsHandleA(NULL
, unisp_name_a
, SECPKG_CRED_OUTBOUND
,
257 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
259 st
= pAcquireCredentialsHandleA(NULL
, unisp_name_a
, SECPKG_CRED_OUTBOUND
,
260 NULL
, NULL
, NULL
, NULL
, &cred
, NULL
);
261 ok(st
== SEC_E_OK
, "AcquireCredentialsHandleA failed: %08x\n", st
);
263 pFreeCredentialsHandle(&cred
);
264 memset(&cred
, 0, sizeof(cred
));
265 st
= pAcquireCredentialsHandleA(NULL
, unisp_name_a
, SECPKG_CRED_OUTBOUND
,
266 NULL
, NULL
, NULL
, NULL
, &cred
, &exp
);
267 ok(st
== SEC_E_OK
, "AcquireCredentialsHandleA failed: %08x\n", st
);
268 /* expriy is indeterminate in win2k3 */
269 trace("expiry: %08x%08x\n", exp
.HighPart
, exp
.LowPart
);
270 pFreeCredentialsHandle(&cred
);
272 /* Bad version in SCHANNEL_CRED */
273 memset(&schanCred
, 0, sizeof(schanCred
));
274 st
= pAcquireCredentialsHandleA(NULL
, unisp_name_a
, SECPKG_CRED_OUTBOUND
,
275 NULL
, &schanCred
, NULL
, NULL
, NULL
, NULL
);
276 ok(st
== SEC_E_INTERNAL_ERROR
||
277 st
== SEC_E_UNKNOWN_CREDENTIALS
/* Vista/win2k8 */ ||
278 st
== SEC_E_INVALID_TOKEN
/* WinNT */, "st = %08x\n", st
);
279 st
= pAcquireCredentialsHandleA(NULL
, unisp_name_a
, SECPKG_CRED_INBOUND
,
280 NULL
, &schanCred
, NULL
, NULL
, NULL
, NULL
);
281 ok(st
== SEC_E_INTERNAL_ERROR
||
282 st
== SEC_E_UNKNOWN_CREDENTIALS
/* Vista/win2k8 */ ||
283 st
== SEC_E_INVALID_TOKEN
/* WinNT */, "st = %08x\n", st
);
285 /* No cert in SCHANNEL_CRED succeeds for outbound.. */
286 schanCred
.dwVersion
= SCHANNEL_CRED_VERSION
;
287 st
= pAcquireCredentialsHandleA(NULL
, unisp_name_a
, SECPKG_CRED_OUTBOUND
,
288 NULL
, &schanCred
, NULL
, NULL
, &cred
, NULL
);
289 ok(st
== SEC_E_OK
, "AcquireCredentialsHandleA failed: %08x\n", st
);
290 pFreeCredentialsHandle(&cred
);
291 /* but fails for inbound. */
292 st
= pAcquireCredentialsHandleA(NULL
, unisp_name_a
, SECPKG_CRED_INBOUND
,
293 NULL
, &schanCred
, NULL
, NULL
, &cred
, NULL
);
294 ok(st
== SEC_E_NO_CREDENTIALS
||
295 st
== SEC_E_OK
/* Vista/win2k8 */,
296 "Expected SEC_E_NO_CREDENTIALS or SEC_E_OK, got %08x\n", st
);
300 /* Crashes with bad paCred pointer */
301 schanCred
.cCreds
= 1;
302 pAcquireCredentialsHandleA(NULL
, unisp_name_a
, SECPKG_CRED_OUTBOUND
,
303 NULL
, &schanCred
, NULL
, NULL
, NULL
, NULL
);
306 /* Bogus cert in SCHANNEL_CRED. Windows fails with
307 * SEC_E_UNKNOWN_CREDENTIALS, but I'll accept SEC_E_NO_CREDENTIALS too.
309 schanCred
.cCreds
= 1;
310 schanCred
.paCred
= &certs
[0];
311 st
= pAcquireCredentialsHandleA(NULL
, unisp_name_a
, SECPKG_CRED_OUTBOUND
,
312 NULL
, &schanCred
, NULL
, NULL
, NULL
, NULL
);
313 ok(st
== SEC_E_UNKNOWN_CREDENTIALS
||
314 st
== SEC_E_NO_CREDENTIALS
||
315 st
== SEC_E_INVALID_TOKEN
/* WinNT */, "st = %08x\n", st
);
316 st
= pAcquireCredentialsHandleA(NULL
, unisp_name_a
, SECPKG_CRED_INBOUND
,
317 NULL
, &schanCred
, NULL
, NULL
, NULL
, NULL
);
318 ok(st
== SEC_E_UNKNOWN_CREDENTIALS
||
319 st
== SEC_E_NO_CREDENTIALS
||
320 st
== SEC_E_INVALID_TOKEN
/* WinNT */, "st = %08x\n", st
);
322 /* Good cert, but missing private key. Windows fails with
323 * SEC_E_NO_CREDENTIALS, but I'll accept SEC_E_UNKNOWN_CREDENTIALS too.
325 schanCred
.cCreds
= 1;
326 schanCred
.paCred
= &certs
[1];
327 st
= pAcquireCredentialsHandleA(NULL
, unisp_name_a
, SECPKG_CRED_OUTBOUND
,
328 NULL
, &schanCred
, NULL
, NULL
, &cred
, NULL
);
329 ok(st
== SEC_E_UNKNOWN_CREDENTIALS
|| st
== SEC_E_NO_CREDENTIALS
||
330 st
== SEC_E_INTERNAL_ERROR
, /* win2k */
331 "Expected SEC_E_UNKNOWN_CREDENTIALS, SEC_E_NO_CREDENTIALS "
332 "or SEC_E_INTERNAL_ERROR, got %08x\n", st
);
333 st
= pAcquireCredentialsHandleA(NULL
, unisp_name_a
, SECPKG_CRED_INBOUND
,
334 NULL
, &schanCred
, NULL
, NULL
, NULL
, NULL
);
335 ok(st
== SEC_E_UNKNOWN_CREDENTIALS
|| st
== SEC_E_NO_CREDENTIALS
||
336 st
== SEC_E_INTERNAL_ERROR
, /* win2k */
337 "Expected SEC_E_UNKNOWN_CREDENTIALS, SEC_E_NO_CREDENTIALS "
338 "or SEC_E_INTERNAL_ERROR, got %08x\n", st
);
340 /* Good cert, with CRYPT_KEY_PROV_INFO set before it's had a key loaded. */
341 if (pCertSetCertificateContextProperty
)
343 ret
= pCertSetCertificateContextProperty(certs
[1],
344 CERT_KEY_PROV_INFO_PROP_ID
, 0, &keyProvInfo
);
345 schanCred
.dwVersion
= SCH_CRED_V3
;
346 ok(ret
, "CertSetCertificateContextProperty failed: %08x\n", GetLastError());
347 st
= pAcquireCredentialsHandleA(NULL
, unisp_name_a
, SECPKG_CRED_OUTBOUND
,
348 NULL
, &schanCred
, NULL
, NULL
, &cred
, NULL
);
349 ok(st
== SEC_E_UNKNOWN_CREDENTIALS
|| st
== SEC_E_INTERNAL_ERROR
/* WinNT */,
350 "Expected SEC_E_UNKNOWN_CREDENTIALS or SEC_E_INTERNAL_ERROR, got %08x\n", st
);
351 st
= pAcquireCredentialsHandleA(NULL
, unisp_name_a
, SECPKG_CRED_INBOUND
,
352 NULL
, &schanCred
, NULL
, NULL
, &cred
, NULL
);
353 ok(st
== SEC_E_UNKNOWN_CREDENTIALS
|| st
== SEC_E_INTERNAL_ERROR
/* WinNT */,
354 "Expected SEC_E_UNKNOWN_CREDENTIALS or SEC_E_INTERNAL_ERROR, got %08x\n", st
);
357 ret
= pCryptAcquireContextW(&csp
, cspNameW
, MS_DEF_PROV_W
, PROV_RSA_FULL
,
359 ok(ret
, "CryptAcquireContextW failed: %08x\n", GetLastError());
363 ret
= pCryptImportKey(csp
, privKey
, sizeof(privKey
), 0, 0, &key
);
364 ok(ret
, "CryptImportKey failed: %08x\n", GetLastError());
373 pAcquireCredentialsHandleA(NULL
, unisp_name_a
, SECPKG_CRED_INBOUND
,
374 NULL
, &schanCred
, NULL
, NULL
, NULL
, NULL
);
376 /* Crashes on WinNT */
377 /* Good cert with private key, bogus version */
378 schanCred
.dwVersion
= SCH_CRED_V1
;
379 st
= pAcquireCredentialsHandleA(NULL
, unisp_name_a
, SECPKG_CRED_OUTBOUND
,
380 NULL
, &schanCred
, NULL
, NULL
, &cred
, NULL
);
381 ok(st
== SEC_E_INTERNAL_ERROR
||
382 st
== SEC_E_UNKNOWN_CREDENTIALS
/* Vista/win2k8 */,
383 "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st
);
384 st
= pAcquireCredentialsHandleA(NULL
, unisp_name_a
, SECPKG_CRED_INBOUND
,
385 NULL
, &schanCred
, NULL
, NULL
, &cred
, NULL
);
386 ok(st
== SEC_E_INTERNAL_ERROR
||
387 st
== SEC_E_UNKNOWN_CREDENTIALS
/* Vista/win2k8 */,
388 "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st
);
389 schanCred
.dwVersion
= SCH_CRED_V2
;
390 st
= pAcquireCredentialsHandleA(NULL
, unisp_name_a
, SECPKG_CRED_OUTBOUND
,
391 NULL
, &schanCred
, NULL
, NULL
, &cred
, NULL
);
392 ok(st
== SEC_E_INTERNAL_ERROR
||
393 st
== SEC_E_UNKNOWN_CREDENTIALS
/* Vista/win2k8 */,
394 "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st
);
395 st
= pAcquireCredentialsHandleA(NULL
, unisp_name_a
, SECPKG_CRED_INBOUND
,
396 NULL
, &schanCred
, NULL
, NULL
, &cred
, NULL
);
397 ok(st
== SEC_E_INTERNAL_ERROR
||
398 st
== SEC_E_UNKNOWN_CREDENTIALS
/* Vista/win2k8 */,
399 "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st
);
402 /* Succeeds on V3 or higher */
403 schanCred
.dwVersion
= SCH_CRED_V3
;
404 st
= pAcquireCredentialsHandleA(NULL
, unisp_name_a
, SECPKG_CRED_OUTBOUND
,
405 NULL
, &schanCred
, NULL
, NULL
, &cred
, NULL
);
406 ok(st
== SEC_E_OK
, "AcquireCredentialsHandleA failed: %08x\n", st
);
407 pFreeCredentialsHandle(&cred
);
408 st
= pAcquireCredentialsHandleA(NULL
, unisp_name_a
, SECPKG_CRED_INBOUND
,
409 NULL
, &schanCred
, NULL
, NULL
, &cred
, NULL
);
411 st
== SEC_E_UNKNOWN_CREDENTIALS
, /* win2k3 */
412 "AcquireCredentialsHandleA failed: %08x\n", st
);
413 pFreeCredentialsHandle(&cred
);
414 schanCred
.dwVersion
= SCHANNEL_CRED_VERSION
;
415 st
= pAcquireCredentialsHandleA(NULL
, unisp_name_a
, SECPKG_CRED_OUTBOUND
,
416 NULL
, &schanCred
, NULL
, NULL
, &cred
, NULL
);
417 ok(st
== SEC_E_OK
, "AcquireCredentialsHandleA failed: %08x\n", st
);
418 pFreeCredentialsHandle(&cred
);
419 st
= pAcquireCredentialsHandleA(NULL
, unisp_name_a
, SECPKG_CRED_INBOUND
,
420 NULL
, &schanCred
, NULL
, NULL
, &cred
, NULL
);
422 st
== SEC_E_UNKNOWN_CREDENTIALS
, /* win2k3 */
423 "AcquireCredentialsHandleA failed: %08x\n", st
);
424 if (st
== SEC_E_OK
) test_strength(&cred
);
425 pFreeCredentialsHandle(&cred
);
427 /* How about more than one cert? */
428 schanCred
.cCreds
= 2;
429 schanCred
.paCred
= certs
;
430 st
= pAcquireCredentialsHandleA(NULL
, unisp_name_a
, SECPKG_CRED_OUTBOUND
,
431 NULL
, &schanCred
, NULL
, NULL
, &cred
, NULL
);
432 ok(st
== SEC_E_UNKNOWN_CREDENTIALS
||
433 st
== SEC_E_NO_CREDENTIALS
/* Vista/win2k8 */ ||
434 st
== SEC_E_INVALID_TOKEN
/* WinNT */, "st = %08x\n", st
);
435 st
= pAcquireCredentialsHandleA(NULL
, unisp_name_a
, SECPKG_CRED_INBOUND
,
436 NULL
, &schanCred
, NULL
, NULL
, &cred
, NULL
);
437 ok(st
== SEC_E_UNKNOWN_CREDENTIALS
||
438 st
== SEC_E_NO_CREDENTIALS
||
439 st
== SEC_E_INVALID_TOKEN
/* WinNT */, "st = %08x\n", st
);
443 st
= pAcquireCredentialsHandleA(NULL
, unisp_name_a
, SECPKG_CRED_OUTBOUND
,
444 NULL
, &schanCred
, NULL
, NULL
, &cred
, NULL
);
445 ok(st
== SEC_E_UNKNOWN_CREDENTIALS
||
446 st
== SEC_E_NO_CREDENTIALS
||
447 st
== SEC_E_INVALID_TOKEN
/* WinNT */, "st = %08x\n", st
);
448 st
= pAcquireCredentialsHandleA(NULL
, unisp_name_a
, SECPKG_CRED_INBOUND
,
449 NULL
, &schanCred
, NULL
, NULL
, &cred
, NULL
);
450 ok(st
== SEC_E_UNKNOWN_CREDENTIALS
,
451 "Expected SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st
);
452 /* FIXME: what about two valid certs? */
454 if (pCryptDestroyKey
)
455 pCryptDestroyKey(key
);
458 if (pCryptReleaseContext
)
459 pCryptReleaseContext(csp
, 0);
460 pCryptAcquireContextW(&csp
, cspNameW
, MS_DEF_PROV_W
, PROV_RSA_FULL
,
463 if (pCertFreeCertificateContext
)
465 pCertFreeCertificateContext(certs
[0]);
466 pCertFreeCertificateContext(certs
[1]);
470 static const char http_request
[] = "HEAD /test.html HTTP/1.1\r\nHost: www.codeweavers.com\r\nConnection: close\r\n\r\n";
472 static void init_cred(SCHANNEL_CRED
*cred
)
474 cred
->dwVersion
= SCHANNEL_CRED_VERSION
;
477 cred
->hRootStore
= NULL
;
479 cred
->aphMappers
= NULL
;
480 cred
->cSupportedAlgs
= 0;
481 cred
->palgSupportedAlgs
= NULL
;
482 cred
->grbitEnabledProtocols
= SP_PROT_SSL3_CLIENT
;
483 cred
->dwMinimumCipherStrength
= 0;
484 cred
->dwMaximumCipherStrength
= 0;
485 cred
->dwSessionLifespan
= 0;
489 static void init_buffers(SecBufferDesc
*desc
, unsigned count
, unsigned size
)
491 desc
->ulVersion
= SECBUFFER_VERSION
;
492 desc
->cBuffers
= count
;
493 desc
->pBuffers
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, count
*sizeof(SecBuffer
));
495 desc
->pBuffers
[0].cbBuffer
= size
;
496 desc
->pBuffers
[0].pvBuffer
= HeapAlloc(GetProcessHeap(), 0, size
);
499 static void reset_buffers(SecBufferDesc
*desc
)
503 for (i
= 0; i
< desc
->cBuffers
; ++i
)
505 desc
->pBuffers
[i
].BufferType
= SECBUFFER_EMPTY
;
508 desc
->pBuffers
[i
].cbBuffer
= 0;
509 desc
->pBuffers
[i
].pvBuffer
= NULL
;
514 static void free_buffers(SecBufferDesc
*desc
)
516 HeapFree(GetProcessHeap(), 0, desc
->pBuffers
[0].pvBuffer
);
517 HeapFree(GetProcessHeap(), 0, desc
->pBuffers
);
520 static int receive_data(SOCKET sock
, SecBuffer
*buf
)
522 unsigned received
= 0;
526 unsigned char *data
= buf
->pvBuffer
;
527 unsigned expected
= 0;
530 ret
= recv(sock
, (char *)data
+received
, buf
->cbBuffer
-received
, 0);
533 skip("recv failed\n");
538 skip("connection closed\n");
543 while (expected
< received
)
545 unsigned frame_size
= 5 + ((data
[3]<<8) | data
[4]);
546 expected
+= frame_size
;
550 if (expected
== received
)
554 buf
->cbBuffer
= received
;
559 static void test_communication(void)
565 struct hostent
*host
;
566 struct sockaddr_in addr
;
568 SECURITY_STATUS status
;
572 CredHandle cred_handle
;
574 SecPkgContext_StreamSizes sizes
;
576 SecBufferDesc buffers
[2];
578 unsigned buf_size
= 4000;
582 if (!pAcquireCredentialsHandleA
|| !pFreeCredentialsHandle
||
583 !pInitializeSecurityContextA
|| !pDeleteSecurityContext
||
584 !pQueryContextAttributesA
|| !pDecryptMessage
|| !pEncryptMessage
)
586 skip("Required secur32 functions not available\n");
590 /* Create a socket and connect to www.codeweavers.com */
591 ret
= WSAStartup(0x0202, &wsa_data
);
594 skip("Can't init winsock 2.2\n");
598 host
= gethostbyname("www.codeweavers.com");
601 skip("Can't resolve www.codeweavers.com\n");
605 addr
.sin_family
= host
->h_addrtype
;
606 addr
.sin_addr
= *(struct in_addr
*)host
->h_addr_list
[0];
607 addr
.sin_port
= htons(443);
608 sock
= socket(host
->h_addrtype
, SOCK_STREAM
, 0);
609 if (sock
== SOCKET_ERROR
)
611 skip("Can't create socket\n");
615 ret
= connect(sock
, (struct sockaddr
*)&addr
, sizeof(addr
));
616 if (ret
== SOCKET_ERROR
)
618 skip("Can't connect to www.codeweavers.com\n");
622 /* Create client credentials */
624 cred
.dwFlags
= SCH_CRED_NO_DEFAULT_CREDS
|SCH_CRED_MANUAL_CRED_VALIDATION
;
626 status
= pAcquireCredentialsHandleA(NULL
, (SEC_CHAR
*)UNISP_NAME
, SECPKG_CRED_OUTBOUND
, NULL
,
627 &cred
, NULL
, NULL
, &cred_handle
, NULL
);
628 ok(status
== SEC_E_OK
, "AcquireCredentialsHandleA failed: %08x\n", status
);
629 if (status
!= SEC_E_OK
) return;
631 /* Initialize the connection */
632 init_buffers(&buffers
[0], 4, buf_size
);
633 init_buffers(&buffers
[1], 4, buf_size
);
635 buffers
[0].pBuffers
[0].BufferType
= SECBUFFER_TOKEN
;
636 status
= pInitializeSecurityContextA(&cred_handle
, NULL
, (SEC_CHAR
*)"localhost",
637 ISC_REQ_CONFIDENTIALITY
|ISC_REQ_STREAM
,
638 0, 0, NULL
, 0, &context
, &buffers
[0], &attrs
, NULL
);
639 ok(status
== SEC_I_CONTINUE_NEEDED
, "Expected SEC_I_CONTINUE_NEEDED, got %08x\n", status
);
641 buffers
[1].cBuffers
= 1;
642 buffers
[1].pBuffers
[0].BufferType
= SECBUFFER_TOKEN
;
643 data_size
= buffers
[0].pBuffers
[0].cbBuffer
;
644 status
= pInitializeSecurityContextA(&cred_handle
, &context
, (SEC_CHAR
*)"localhost",
645 ISC_REQ_CONFIDENTIALITY
|ISC_REQ_STREAM
,
646 0, 0, &buffers
[1], 0, NULL
, &buffers
[0], &attrs
, NULL
);
647 ok(status
== SEC_E_INVALID_TOKEN
, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status
);
649 buffers
[0].pBuffers
[0].cbBuffer
= buf_size
;
650 buffers
[1].cBuffers
= 4;
651 buffers
[1].pBuffers
[0].cbBuffer
= buf_size
;
653 status
= pInitializeSecurityContextA(&cred_handle
, NULL
, (SEC_CHAR
*)"localhost",
654 ISC_REQ_CONFIDENTIALITY
|ISC_REQ_STREAM
,
655 0, 0, NULL
, 0, &context
, &buffers
[0], &attrs
, NULL
);
656 ok(status
== SEC_I_CONTINUE_NEEDED
, "Expected SEC_I_CONTINUE_NEEDED, got %08x\n", status
);
658 while (status
== SEC_I_CONTINUE_NEEDED
)
660 buf
= &buffers
[0].pBuffers
[0];
661 send(sock
, buf
->pvBuffer
, buf
->cbBuffer
, 0);
662 buf
->cbBuffer
= buf_size
;
664 buf
= &buffers
[1].pBuffers
[0];
665 ret
= receive_data(sock
, buf
);
669 buf
->BufferType
= SECBUFFER_TOKEN
;
671 status
= pInitializeSecurityContextA(&cred_handle
, &context
, (SEC_CHAR
*)"localhost",
672 ISC_REQ_CONFIDENTIALITY
|ISC_REQ_STREAM
,
673 0, 0, &buffers
[1], 0, NULL
, &buffers
[0], &attrs
, NULL
);
674 buffers
[1].pBuffers
[0].cbBuffer
= buf_size
;
677 ok(status
== SEC_E_OK
|| broken(status
== SEC_E_INVALID_TOKEN
) /* WinNT */,
678 "InitializeSecurityContext failed: %08x\n", status
);
679 if(status
!= SEC_E_OK
) {
680 win_skip("Handshake failed\n");
684 pQueryContextAttributesA(&context
, SECPKG_ATTR_STREAM_SIZES
, &sizes
);
686 reset_buffers(&buffers
[0]);
688 /* Send a simple request so we get data for testing DecryptMessage */
689 buf
= &buffers
[0].pBuffers
[0];
690 data
= buf
->pvBuffer
;
691 buf
->BufferType
= SECBUFFER_STREAM_HEADER
;
692 buf
->cbBuffer
= sizes
.cbHeader
;
694 buf
->BufferType
= SECBUFFER_DATA
;
695 buf
->pvBuffer
= data
+ sizes
.cbHeader
;
696 buf
->cbBuffer
= sizeof(http_request
) - 1;
697 memcpy(buf
->pvBuffer
, http_request
, sizeof(http_request
) - 1);
699 buf
->BufferType
= SECBUFFER_STREAM_TRAILER
;
700 buf
->pvBuffer
= data
+ sizes
.cbHeader
+ sizeof(http_request
) -1;
701 buf
->cbBuffer
= sizes
.cbTrailer
;
703 status
= pEncryptMessage(&context
, 0, &buffers
[0], 0);
704 ok(status
== SEC_E_OK
, "EncryptMessage failed: %08x\n", status
);
705 if (status
!= SEC_E_OK
)
708 buf
= &buffers
[0].pBuffers
[0];
709 send(sock
, buf
->pvBuffer
, buffers
[0].pBuffers
[0].cbBuffer
+ buffers
[0].pBuffers
[1].cbBuffer
+ buffers
[0].pBuffers
[2].cbBuffer
, 0);
711 reset_buffers(&buffers
[0]);
712 buf
->cbBuffer
= buf_size
;
713 data_size
= receive_data(sock
, buf
);
715 /* Too few buffers */
716 --buffers
[0].cBuffers
;
717 status
= pDecryptMessage(&context
, &buffers
[0], 0, NULL
);
718 ok(status
== SEC_E_INVALID_TOKEN
, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status
);
721 ++buffers
[0].cBuffers
;
722 status
= pDecryptMessage(&context
, &buffers
[0], 0, NULL
);
723 ok(status
== SEC_E_INVALID_TOKEN
, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status
);
725 /* Two data buffers */
726 buffers
[0].pBuffers
[0].BufferType
= SECBUFFER_DATA
;
727 buffers
[0].pBuffers
[1].BufferType
= SECBUFFER_DATA
;
728 status
= pDecryptMessage(&context
, &buffers
[0], 0, NULL
);
729 ok(status
== SEC_E_INVALID_TOKEN
, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status
);
731 /* Too few empty buffers */
732 buffers
[0].pBuffers
[1].BufferType
= SECBUFFER_EXTRA
;
733 status
= pDecryptMessage(&context
, &buffers
[0], 0, NULL
);
734 ok(status
== SEC_E_INVALID_TOKEN
, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status
);
736 /* Incomplete data */
737 buffers
[0].pBuffers
[1].BufferType
= SECBUFFER_EMPTY
;
738 buffers
[0].pBuffers
[0].cbBuffer
= (data
[3]<<8) | data
[4];
739 status
= pDecryptMessage(&context
, &buffers
[0], 0, NULL
);
740 ok(status
== SEC_E_INCOMPLETE_MESSAGE
, "Expected SEC_E_INCOMPLETE_MESSAGE, got %08x\n", status
);
741 ok(buffers
[0].pBuffers
[0].BufferType
== SECBUFFER_MISSING
, "Expected first buffer to be SECBUFFER_MISSING\n");
742 ok(buffers
[0].pBuffers
[0].cbBuffer
== 5, "Expected first buffer to be a five bytes\n");
744 buffers
[0].pBuffers
[0].cbBuffer
= data_size
;
745 buffers
[0].pBuffers
[0].BufferType
= SECBUFFER_DATA
;
746 buffers
[0].pBuffers
[1].BufferType
= SECBUFFER_EMPTY
;
747 status
= pDecryptMessage(&context
, &buffers
[0], 0, NULL
);
748 ok(status
== SEC_E_OK
, "DecryptMessage failed: %08x\n", status
);
749 if (status
== SEC_E_OK
)
751 ok(buffers
[0].pBuffers
[0].BufferType
== SECBUFFER_STREAM_HEADER
, "Expected first buffer to be SECBUFFER_STREAM_HEADER\n");
752 ok(buffers
[0].pBuffers
[1].BufferType
== SECBUFFER_DATA
, "Expected second buffer to be SECBUFFER_DATA\n");
753 ok(buffers
[0].pBuffers
[2].BufferType
== SECBUFFER_STREAM_TRAILER
, "Expected third buffer to be SECBUFFER_STREAM_TRAILER\n");
755 data
= buffers
[0].pBuffers
[1].pvBuffer
;
756 data
[buffers
[0].pBuffers
[1].cbBuffer
] = 0;
759 pDeleteSecurityContext(&context
);
760 pFreeCredentialsHandle(&cred_handle
);
762 free_buffers(&buffers
[0]);
763 free_buffers(&buffers
[1]);
772 testAcquireSecurityContext();
773 test_communication();
778 FreeLibrary(crypt32dll
);