[SECUR32_WINETEST]
authorAmine Khaldi <amine.khaldi@reactos.org>
Tue, 22 Apr 2014 11:12:43 +0000 (11:12 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Tue, 22 Apr 2014 11:12:43 +0000 (11:12 +0000)
* Sync with Wine 1.7.17.
CORE-8080

svn path=/trunk/; revision=62866

rostests/winetests/secur32/CMakeLists.txt
rostests/winetests/secur32/main.c
rostests/winetests/secur32/negotiate.c [new file with mode: 0644]
rostests/winetests/secur32/ntlm.c
rostests/winetests/secur32/schannel.c
rostests/winetests/secur32/secur32.c
rostests/winetests/secur32/testlist.c

index 7045667..9694d64 100644 (file)
@@ -1,17 +1,13 @@
 
-add_definitions(
-    -D__ROS_LONG64__
-    -D_DLL -D__USE_CRTIMP)
-
 list(APPEND SOURCE
     main.c
+    negotiate.c
     ntlm.c
     schannel.c
     secur32.c
     testlist.c)
 
 add_executable(secur32_winetest ${SOURCE})
-target_link_libraries(secur32_winetest wine)
 set_module_type(secur32_winetest win32cui)
-add_importlibs(secur32_winetest advapi32 msvcrt kernel32 ntdll)
+add_importlibs(secur32_winetest advapi32 ws2_32 msvcrt kernel32)
 add_cd_file(TARGET secur32_winetest DESTINATION reactos/bin FOR all)
index e652485..b5b21c3 100644 (file)
@@ -22,7 +22,7 @@
 
 #include <stdarg.h>
 #include <stdio.h>
-#include <assert.h>
+
 #include <windef.h>
 #include <winbase.h>
 #include <sspi.h>
@@ -108,7 +108,7 @@ static const char* getSecError(SECURITY_STATUS status)
 /* Helper for testQuerySecurityPagageInfo */
 
 static SECURITY_STATUS setupPackageA(SEC_CHAR *p_package_name, 
-        PSecPkgInfo *p_pkg_info)
+        PSecPkgInfoA *p_pkg_info)
 {
     SECURITY_STATUS ret;
     
@@ -121,7 +121,7 @@ static SECURITY_STATUS setupPackageA(SEC_CHAR *p_package_name,
 
 static void testInitSecurityInterface(void)
 {
-    PSecurityFunctionTable sec_fun_table = NULL;
+    PSecurityFunctionTableA sec_fun_table = NULL;
 
     sec_fun_table = pInitSecurityInterfaceA();
     ok(sec_fun_table != NULL, "InitSecurityInterface() returned NULL.\n");
@@ -133,7 +133,7 @@ static void testEnumerateSecurityPackages(void)
 
     SECURITY_STATUS sec_status;
     ULONG           num_packages, i;
-    PSecPkgInfo     pkg_info = NULL;
+    PSecPkgInfoA    pkg_info = NULL;
 
     trace("Running testEnumerateSecurityPackages\n");
     
@@ -197,7 +197,7 @@ static void testEnumerateSecurityPackages(void)
 static void testQuerySecurityPackageInfo(void)
 {
     SECURITY_STATUS     sec_status;
-    PSecPkgInfo         pkg_info;
+    PSecPkgInfoA        pkg_info;
     static SEC_CHAR     ntlm[]     = "NTLM",
                         winetest[] = "Winetest";
 
diff --git a/rostests/winetests/secur32/negotiate.c b/rostests/winetests/secur32/negotiate.c
new file mode 100644 (file)
index 0000000..91c3fa1
--- /dev/null
@@ -0,0 +1,387 @@
+/*
+ * Tests for the Negotiate security provider
+ *
+ * Copyright 2005, 2006 Kai Blin
+ * Copyright 2012 Hans Leidekker for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <windef.h>
+#include <winbase.h>
+#define SECURITY_WIN32
+#include <sspi.h>
+#include <rpc.h>
+#include <rpcdce.h>
+#include <secext.h>
+
+#include "wine/test.h"
+
+static HMODULE hsecur32;
+static SECURITY_STATUS (SEC_ENTRY * pAcceptSecurityContext)(PCredHandle, PCtxtHandle,
+    PSecBufferDesc, ULONG, ULONG, PCtxtHandle, PSecBufferDesc, PULONG, PTimeStamp);
+static SECURITY_STATUS (SEC_ENTRY * pAcquireCredentialsHandleA)(SEC_CHAR *, SEC_CHAR *,
+    ULONG, PLUID, PVOID, SEC_GET_KEY_FN, PVOID, PCredHandle, PTimeStamp);
+static SECURITY_STATUS (SEC_ENTRY * pCompleteAuthToken)(PCtxtHandle, PSecBufferDesc);
+static SECURITY_STATUS (SEC_ENTRY * pDecryptMessage)(PCtxtHandle, PSecBufferDesc, ULONG, PULONG);
+static SECURITY_STATUS (SEC_ENTRY * pDeleteSecurityContext)(PCtxtHandle);
+static SECURITY_STATUS (SEC_ENTRY * pEncryptMessage)(PCtxtHandle, ULONG, PSecBufferDesc, ULONG);
+static SECURITY_STATUS (SEC_ENTRY * pFreeContextBuffer)(PVOID);
+static SECURITY_STATUS (SEC_ENTRY * pFreeCredentialsHandle)(PCredHandle);
+static SECURITY_STATUS (SEC_ENTRY * pInitializeSecurityContextA)(PCredHandle, PCtxtHandle,
+    SEC_CHAR *, ULONG, ULONG, ULONG, PSecBufferDesc, ULONG, PCtxtHandle, PSecBufferDesc,
+    PULONG, PTimeStamp);
+static PSecurityFunctionTableA (SEC_ENTRY * pInitSecurityInterfaceA)(void);
+static SECURITY_STATUS (SEC_ENTRY * pMakeSignature)(PCtxtHandle, ULONG, PSecBufferDesc, ULONG);
+static SECURITY_STATUS (SEC_ENTRY * pQueryContextAttributesA)(PCtxtHandle, ULONG, PVOID);
+static SECURITY_STATUS (SEC_ENTRY * pQuerySecurityPackageInfoA)(SEC_CHAR *, PSecPkgInfoA *);
+static SECURITY_STATUS (SEC_ENTRY * pVerifySignature)(PCtxtHandle, PSecBufferDesc, ULONG, PULONG);
+
+static void init_function_ptrs(void)
+{
+    if (!(hsecur32 = LoadLibraryA("secur32.dll"))) return;
+    pAcceptSecurityContext      = (void *)GetProcAddress(hsecur32, "AcceptSecurityContext");
+    pAcquireCredentialsHandleA  = (void *)GetProcAddress(hsecur32, "AcquireCredentialsHandleA");
+    pCompleteAuthToken          = (void *)GetProcAddress(hsecur32, "CompleteAuthToken");
+    pDecryptMessage             = (void *)GetProcAddress(hsecur32, "DecryptMessage");
+    pDeleteSecurityContext      = (void *)GetProcAddress(hsecur32, "DeleteSecurityContext");
+    pEncryptMessage             = (void *)GetProcAddress(hsecur32, "EncryptMessage");
+    pFreeContextBuffer          = (void *)GetProcAddress(hsecur32, "FreeContextBuffer");
+    pFreeCredentialsHandle      = (void *)GetProcAddress(hsecur32, "FreeCredentialsHandle");
+    pInitializeSecurityContextA = (void *)GetProcAddress(hsecur32, "InitializeSecurityContextA");
+    pInitSecurityInterfaceA     = (void *)GetProcAddress(hsecur32, "InitSecurityInterfaceA");
+    pMakeSignature              = (void *)GetProcAddress(hsecur32, "MakeSignature");
+    pQueryContextAttributesA    = (void *)GetProcAddress(hsecur32, "QueryContextAttributesA");
+    pQuerySecurityPackageInfoA  = (void *)GetProcAddress(hsecur32, "QuerySecurityPackageInfoA");
+    pVerifySignature            = (void *)GetProcAddress(hsecur32, "VerifySignature");
+}
+
+#define NEGOTIATE_BASE_CAPS ( \
+    SECPKG_FLAG_INTEGRITY  | \
+    SECPKG_FLAG_PRIVACY    | \
+    SECPKG_FLAG_CONNECTION | \
+    SECPKG_FLAG_MULTI_REQUIRED | \
+    SECPKG_FLAG_EXTENDED_ERROR | \
+    SECPKG_FLAG_IMPERSONATION  | \
+    SECPKG_FLAG_ACCEPT_WIN32_NAME | \
+    SECPKG_FLAG_NEGOTIABLE        | \
+    SECPKG_FLAG_GSS_COMPATIBLE    | \
+    SECPKG_FLAG_LOGON )
+
+#define NTLM_BASE_CAPS ( \
+    SECPKG_FLAG_INTEGRITY  | \
+    SECPKG_FLAG_PRIVACY    | \
+    SECPKG_FLAG_TOKEN_ONLY | \
+    SECPKG_FLAG_CONNECTION | \
+    SECPKG_FLAG_MULTI_REQUIRED    | \
+    SECPKG_FLAG_IMPERSONATION     | \
+    SECPKG_FLAG_ACCEPT_WIN32_NAME | \
+    SECPKG_FLAG_NEGOTIABLE        | \
+    SECPKG_FLAG_LOGON )
+
+struct sspi_data
+{
+    CredHandle cred;
+    CtxtHandle ctxt;
+    PSecBufferDesc in_buf;
+    PSecBufferDesc out_buf;
+    PSEC_WINNT_AUTH_IDENTITY_A id;
+    ULONG max_token;
+};
+
+static void cleanup_buffers( struct sspi_data *data )
+{
+    unsigned int i;
+
+    if (data->in_buf)
+    {
+        for (i = 0; i < data->in_buf->cBuffers; ++i)
+            HeapFree( GetProcessHeap(), 0, data->in_buf->pBuffers[i].pvBuffer );
+        HeapFree( GetProcessHeap(), 0, data->in_buf->pBuffers );
+        HeapFree( GetProcessHeap(), 0, data->in_buf );
+    }
+    if (data->out_buf)
+    {
+        for (i = 0; i < data->out_buf->cBuffers; ++i)
+            HeapFree( GetProcessHeap(), 0, data->out_buf->pBuffers[i].pvBuffer );
+        HeapFree( GetProcessHeap(), 0, data->out_buf->pBuffers );
+        HeapFree( GetProcessHeap(), 0, data->out_buf );
+    }
+}
+
+static void setup_buffers( struct sspi_data *data, SecPkgInfoA *info )
+{
+    SecBuffer *buffer = HeapAlloc( GetProcessHeap(), 0, sizeof(SecBuffer) );
+
+    data->in_buf  = HeapAlloc( GetProcessHeap(), 0, sizeof(SecBufferDesc) );
+    data->out_buf = HeapAlloc( GetProcessHeap(), 0, sizeof(SecBufferDesc) );
+    data->max_token = info->cbMaxToken;
+
+    data->in_buf->ulVersion = SECBUFFER_VERSION;
+    data->in_buf->cBuffers  = 1;
+    data->in_buf->pBuffers  = buffer;
+
+    buffer->cbBuffer   = info->cbMaxToken;
+    buffer->BufferType = SECBUFFER_TOKEN;
+    buffer->pvBuffer   = HeapAlloc( GetProcessHeap(), 0, info->cbMaxToken );
+
+    buffer = HeapAlloc( GetProcessHeap(), 0, sizeof(SecBuffer) );
+
+    data->out_buf->ulVersion = SECBUFFER_VERSION;
+    data->out_buf->cBuffers  = 1;
+    data->out_buf->pBuffers  = buffer;
+
+    buffer->cbBuffer   = info->cbMaxToken;
+    buffer->BufferType = SECBUFFER_TOKEN;
+    buffer->pvBuffer   = HeapAlloc( GetProcessHeap(), 0, info->cbMaxToken );
+}
+
+static SECURITY_STATUS setup_client( struct sspi_data *data, SEC_CHAR *provider )
+{
+    SECURITY_STATUS ret;
+    SecPkgInfoA *info;
+    TimeStamp ttl;
+
+    trace( "setting up client\n" );
+
+    ret = pQuerySecurityPackageInfoA( provider, &info );
+    ok( ret == SEC_E_OK, "QuerySecurityPackageInfo returned %08x\n", ret );
+
+    setup_buffers( data, info );
+    pFreeContextBuffer( info );
+
+    ret = pAcquireCredentialsHandleA( NULL, provider, SECPKG_CRED_OUTBOUND, NULL,
+                                      data->id, NULL, NULL, &data->cred, &ttl );
+    ok( ret == SEC_E_OK, "AcquireCredentialsHandleA returned %08x\n", ret );
+    return ret;
+}
+
+static SECURITY_STATUS setup_server( struct sspi_data *data, SEC_CHAR *provider )
+{
+    SECURITY_STATUS ret;
+    SecPkgInfoA *info;
+    TimeStamp ttl;
+
+    trace( "setting up server\n" );
+
+    ret = pQuerySecurityPackageInfoA( provider, &info );
+    ok( ret == SEC_E_OK, "QuerySecurityPackageInfo returned %08x\n", ret );
+
+    setup_buffers( data, info );
+    pFreeContextBuffer( info );
+
+    ret = pAcquireCredentialsHandleA( NULL, provider, SECPKG_CRED_INBOUND, NULL,
+                                      NULL, NULL, NULL, &data->cred, &ttl );
+    ok( ret == SEC_E_OK, "AcquireCredentialsHandleA returned %08x\n", ret );
+    return ret;
+}
+
+static SECURITY_STATUS run_client( struct sspi_data *data, BOOL first )
+{
+    SECURITY_STATUS ret;
+    TimeStamp ttl;
+    ULONG attr;
+
+    trace( "running client for the %s time\n", first ? "first" : "second" );
+
+    data->out_buf->pBuffers[0].cbBuffer = data->max_token;
+    data->out_buf->pBuffers[0].BufferType = SECBUFFER_TOKEN;
+
+    ret = pInitializeSecurityContextA( first ? &data->cred : NULL, first ? NULL : &data->ctxt,
+                                       NULL, 0, 0, SECURITY_NETWORK_DREP, first ? NULL : data->in_buf,
+                                       0, &data->ctxt, data->out_buf, &attr, &ttl );
+    if (ret == SEC_I_COMPLETE_AND_CONTINUE || ret == SEC_I_COMPLETE_NEEDED)
+    {
+        pCompleteAuthToken( &data->ctxt, data->out_buf );
+        if (ret == SEC_I_COMPLETE_AND_CONTINUE)
+            ret = SEC_I_CONTINUE_NEEDED;
+        else if (ret == SEC_I_COMPLETE_NEEDED)
+            ret = SEC_E_OK;
+    }
+    ok( data->out_buf->pBuffers[0].BufferType == SECBUFFER_TOKEN,
+        "buffer type changed from SECBUFFER_TOKEN to %u\n", data->out_buf->pBuffers[0].BufferType );
+    ok( data->out_buf->pBuffers[0].cbBuffer < data->max_token,
+        "InitializeSecurityContext didn't change buffer size\n" );
+    return ret;
+}
+
+static SECURITY_STATUS run_server( struct sspi_data *data, BOOL first )
+{
+    SECURITY_STATUS ret;
+    TimeStamp ttl;
+    ULONG attr;
+
+    trace( "running server for the %s time\n", first ? "first" : "second" );
+
+    ret = pAcceptSecurityContext( &data->cred, first ? NULL : &data->ctxt,
+                                  data->in_buf, 0, SECURITY_NETWORK_DREP,
+                                  &data->ctxt, data->out_buf, &attr, &ttl );
+    if (ret == SEC_I_COMPLETE_AND_CONTINUE || ret == SEC_I_COMPLETE_NEEDED)
+    {
+        pCompleteAuthToken( &data->ctxt, data->out_buf );
+        if (ret == SEC_I_COMPLETE_AND_CONTINUE)
+            ret = SEC_I_CONTINUE_NEEDED;
+        else if (ret == SEC_I_COMPLETE_NEEDED)
+            ret = SEC_E_OK;
+    }
+    return ret;
+}
+
+static void communicate( struct sspi_data *from, struct sspi_data *to )
+{
+    trace( "running communicate\n" );
+    memset( to->in_buf->pBuffers[0].pvBuffer, 0, to->max_token );
+    memcpy( to->in_buf->pBuffers[0].pvBuffer, from->out_buf->pBuffers[0].pvBuffer,
+            from->out_buf->pBuffers[0].cbBuffer );
+    to->in_buf->pBuffers[0].cbBuffer = from->out_buf->pBuffers[0].cbBuffer;
+    memset( from->out_buf->pBuffers[0].pvBuffer, 0, from->max_token );
+}
+
+static void test_authentication(void)
+{
+    SECURITY_STATUS status_c = SEC_I_CONTINUE_NEEDED,
+                    status_s = SEC_I_CONTINUE_NEEDED, status;
+    struct sspi_data client, server;
+    SEC_WINNT_AUTH_IDENTITY_A id;
+    SecPkgContext_NegotiationInfoA info;
+    SecPkgContext_Sizes sizes;
+    SecPkgInfoA *pi;
+    BOOL first = TRUE;
+
+    id.User = (unsigned char *)"user";
+    id.UserLength = strlen( "user" );
+    id.Domain = (unsigned char *)"domain";
+    id.DomainLength = strlen( "domain" );
+    id.Password = (unsigned char *)"password";
+    id.PasswordLength = strlen( "password" );
+    id.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
+
+    client.id = &id;
+    if ((status = setup_client( &client, (SEC_CHAR *)"Negotiate" )))
+    {
+        skip( "setup_client returned %08x, skipping test\n", status );
+        return;
+    }
+    if ((status = setup_server( &server, (SEC_CHAR *)"Negotiate" )))
+    {
+        skip( "setup_server returned %08x, skipping test\n", status );
+        pFreeCredentialsHandle( &client.cred );
+        return;
+    }
+
+    while (status_c == SEC_I_CONTINUE_NEEDED && status_s == SEC_I_CONTINUE_NEEDED)
+    {
+        status_c = run_client( &client, first );
+        ok( status_c == SEC_E_OK || status_c == SEC_I_CONTINUE_NEEDED,
+            "client returned %08x, more tests will fail\n", status_c );
+
+        communicate( &client, &server );
+
+        status_s = run_server( &server, first );
+        ok( status_s == SEC_E_OK || status_s == SEC_I_CONTINUE_NEEDED ||
+            status_s == SEC_E_LOGON_DENIED,
+            "server returned %08x, more tests will fail\n", status_s );
+
+        communicate( &server, &client );
+        trace( "looping\n");
+        first = FALSE;
+    }
+    if (status_c != SEC_E_OK)
+    {
+        skip( "authentication failed, skipping remaining tests\n" );
+        goto done;
+    }
+
+    sizes.cbMaxToken        = 0xdeadbeef;
+    sizes.cbMaxSignature    = 0xdeadbeef;
+    sizes.cbSecurityTrailer = 0xdeadbeef;
+    sizes.cbBlockSize       = 0xdeadbeef;
+    status_c = pQueryContextAttributesA( &client.ctxt, SECPKG_ATTR_SIZES, &sizes );
+    ok( status_c == SEC_E_OK, "pQueryContextAttributesA returned %08x\n", status_c );
+    ok( sizes.cbMaxToken == 2888 || sizes.cbMaxToken == 1904,
+        "expected 2888 or 1904, got %u\n", sizes.cbMaxToken );
+    ok( sizes.cbMaxSignature == 16, "expected 16, got %u\n", sizes.cbMaxSignature );
+    ok( sizes.cbSecurityTrailer == 16, "expected 16, got %u\n", sizes.cbSecurityTrailer );
+    ok( !sizes.cbBlockSize, "expected 0, got %u\n", sizes.cbBlockSize );
+
+    memset( &info, 0, sizeof(info) );
+    status_c = pQueryContextAttributesA( &client.ctxt, SECPKG_ATTR_NEGOTIATION_INFO, &info );
+    ok( status_c == SEC_E_OK, "pQueryContextAttributesA returned %08x\n", status_c );
+
+    pi = info.PackageInfo;
+    ok( info.NegotiationState == SECPKG_NEGOTIATION_COMPLETE, "got %u\n", info.NegotiationState );
+    ok( pi != NULL, "expected non-NULL PackageInfo\n" );
+    if (pi)
+    {
+        ok( pi->fCapabilities == NTLM_BASE_CAPS ||
+            pi->fCapabilities == (NTLM_BASE_CAPS|SECPKG_FLAG_READONLY_WITH_CHECKSUM) ||
+            pi->fCapabilities == (NTLM_BASE_CAPS|SECPKG_FLAG_RESTRICTED_TOKENS) ||
+            pi->fCapabilities == (NTLM_BASE_CAPS|SECPKG_FLAG_RESTRICTED_TOKENS|
+                                  SECPKG_FLAG_APPCONTAINER_CHECKS),
+            "got %08x\n", pi->fCapabilities );
+        ok( pi->wVersion == 1, "got %u\n", pi->wVersion );
+        ok( pi->wRPCID == RPC_C_AUTHN_WINNT, "got %u\n", pi->wRPCID );
+        ok( !lstrcmpA( pi->Name, "NTLM" ), "got %s\n", pi->Name );
+    }
+
+done:
+    cleanup_buffers( &client );
+    cleanup_buffers( &server );
+
+    status_c = pDeleteSecurityContext( &client.ctxt );
+    ok( status_c == SEC_E_OK, "DeleteSecurityContext returned %08x\n", status_c );
+
+    status_s = pDeleteSecurityContext( &server.ctxt );
+    ok( status_s == SEC_E_OK, "DeleteSecurityContext returned %08x\n", status_s );
+
+    status_c = pFreeCredentialsHandle( &client.cred );
+    ok( status_c == SEC_E_OK, "FreeCredentialsHandle returned %08x\n", status_c );
+
+    status_s = pFreeCredentialsHandle(&server.cred);
+    ok( status_s == SEC_E_OK, "FreeCredentialsHandle returned %08x\n", status_s );
+}
+
+START_TEST(negotiate)
+{
+    SecPkgInfoA *info;
+
+    init_function_ptrs();
+
+    if (!pFreeCredentialsHandle || !pAcquireCredentialsHandleA || !pQuerySecurityPackageInfoA ||
+        !pFreeContextBuffer)
+    {
+        win_skip("functions are not available\n");
+        return;
+    }
+    if (pQuerySecurityPackageInfoA( (SEC_CHAR *)"Negotiate", &info ))
+    {
+        ok( 0, "Negotiate package not installed, skipping test\n" );
+        return;
+    }
+    ok( info->fCapabilities == NEGOTIATE_BASE_CAPS ||
+        info->fCapabilities == (NEGOTIATE_BASE_CAPS|SECPKG_FLAG_READONLY_WITH_CHECKSUM) ||
+        info->fCapabilities == (NEGOTIATE_BASE_CAPS|SECPKG_FLAG_RESTRICTED_TOKENS) ||
+        info->fCapabilities == (NEGOTIATE_BASE_CAPS|SECPKG_FLAG_RESTRICTED_TOKENS|
+                                SECPKG_FLAG_APPCONTAINER_CHECKS),
+        "got %08x\n", info->fCapabilities );
+    ok( info->wVersion == 1, "got %u\n", info->wVersion );
+    ok( info->wRPCID == RPC_C_AUTHN_GSS_NEGOTIATE, "got %u\n", info->wRPCID );
+    ok( !lstrcmpA( info->Name, "Negotiate" ), "got %s\n", info->Name );
+    pFreeContextBuffer( info );
+
+    test_authentication();
+}
index 027e094..1e865ad 100644 (file)
@@ -67,7 +67,7 @@ typedef struct _SspiData {
     CtxtHandle ctxt;
     PSecBufferDesc in_buf;
     PSecBufferDesc out_buf;
-    PSEC_WINNT_AUTH_IDENTITY id;
+    PSEC_WINNT_AUTH_IDENTITY_A id;
     ULONG max_token;
 } SspiData;
 
@@ -113,7 +113,7 @@ static BYTE message_binary[] =
    {0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x77, 0x6f, 0x72,
     0x6c, 0x64, 0x21};
 
-static char message[] = "Hello, world!";
+static const char message[] = "Hello, world!";
 
 static char message_header[] = "Header Test";
 
@@ -565,9 +565,9 @@ static void communicate(SspiData *from, SspiData *to)
 static void testInitializeSecurityContextFlags(void)
 {
     SECURITY_STATUS         sec_status;
-    PSecPkgInfo             pkg_info = NULL;
+    PSecPkgInfoA            pkg_info = NULL;
     SspiData                client;
-    SEC_WINNT_AUTH_IDENTITY id;
+    SEC_WINNT_AUTH_IDENTITY_A id;
     static char             sec_pkg_name[] = "NTLM",
                             test_user[]    = "testuser",
                             workgroup[]    = "WORKGROUP",
@@ -578,7 +578,7 @@ static void testInitializeSecurityContextFlags(void)
 
     if(pQuerySecurityPackageInfoA( sec_pkg_name, &pkg_info) != SEC_E_OK)
     {
-        skip("Package not installed, skipping test!\n");
+        ok(0, "NTLM package not installed, skipping test.\n");
         return;
     }
 
@@ -788,10 +788,10 @@ static void testAuth(ULONG data_rep, BOOL fake)
     SECURITY_STATUS         client_stat = SEC_I_CONTINUE_NEEDED;
     SECURITY_STATUS         server_stat = SEC_I_CONTINUE_NEEDED;
     SECURITY_STATUS         sec_status;
-    PSecPkgInfo             pkg_info = NULL;
+    PSecPkgInfoA            pkg_info = NULL;
     BOOL                    first = TRUE;
     SspiData                client, server;
-    SEC_WINNT_AUTH_IDENTITY id;
+    SEC_WINNT_AUTH_IDENTITY_A id;
     SecPkgContext_Sizes     ctxt_sizes;
     static char             sec_pkg_name[] = "NTLM",
                             test_user[] = "testuser",
@@ -800,7 +800,7 @@ static void testAuth(ULONG data_rep, BOOL fake)
 
     if(pQuerySecurityPackageInfoA( sec_pkg_name, &pkg_info)!= SEC_E_OK)
     {
-        skip("Package not installed, skipping test.\n");
+        ok(0, "NTLM package not installed, skipping test.\n");
         return;
     }
 
@@ -921,10 +921,10 @@ static void testSignSeal(void)
     SECURITY_STATUS         client_stat = SEC_I_CONTINUE_NEEDED;
     SECURITY_STATUS         server_stat = SEC_I_CONTINUE_NEEDED;
     SECURITY_STATUS         sec_status;
-    PSecPkgInfo             pkg_info = NULL;
+    PSecPkgInfoA            pkg_info = NULL;
     BOOL                    first = TRUE;
     SspiData                client, server;
-    SEC_WINNT_AUTH_IDENTITY id;
+    SEC_WINNT_AUTH_IDENTITY_A id;
     static char             sec_pkg_name[] = "NTLM";
     SecBufferDesc           crypt;
     SecBuffer               data[2], fake_data[2], complex_data[4];
@@ -942,7 +942,7 @@ static void testSignSeal(void)
      */
     if(pQuerySecurityPackageInfoA( sec_pkg_name, &pkg_info) != SEC_E_OK)
     {
-        skip("Package not installed, skipping test.\n");
+        ok(0, "NTLM package not installed, skipping test.\n");
         return;
     }
 
@@ -968,6 +968,7 @@ static void testSignSeal(void)
     }
 
     sec_status = setupFakeServer(&server, sec_pkg_name);
+    ok(sec_status == SEC_E_OK, "setupFakeServer returned %s\n", getSecError(sec_status));
 
     while(client_stat == SEC_I_CONTINUE_NEEDED && server_stat == SEC_I_CONTINUE_NEEDED)
     {
@@ -1003,7 +1004,7 @@ static void testSignSeal(void)
     fake_data[0].pvBuffer = HeapAlloc(GetProcessHeap(), 0, fake_data[0].cbBuffer);
 
     fake_data[1].BufferType = SECBUFFER_DATA;
-    fake_data[1].cbBuffer = lstrlen(message);
+    fake_data[1].cbBuffer = lstrlenA(message);
     fake_data[1].pvBuffer = HeapAlloc(GetProcessHeap(), 0, fake_data[1].cbBuffer);
 
     sec_status = pMakeSignature(&client.ctxt, 0, &crypt, 0);
@@ -1018,7 +1019,7 @@ static void testSignSeal(void)
     data[0].pvBuffer = HeapAlloc(GetProcessHeap(), 0, data[0].cbBuffer);
 
     data[1].BufferType = SECBUFFER_DATA;
-    data[1].cbBuffer = lstrlen(message);
+    data[1].cbBuffer = lstrlenA(message);
     data[1].pvBuffer = HeapAlloc(GetProcessHeap(), 0, data[1].cbBuffer);
     memcpy(data[1].pvBuffer, message, data[1].cbBuffer);
 
@@ -1057,47 +1058,43 @@ static void testSignSeal(void)
     ok(sec_status == SEC_E_OK, "EncryptMessage returned %s, not SEC_E_OK.\n",
             getSecError(sec_status));
 
-    ok(!memcmp(crypt.pBuffers[0].pvBuffer, crypt_trailer_client,
-               crypt.pBuffers[0].cbBuffer), "Crypt trailer not as expected.\n");
-    if (memcmp(crypt.pBuffers[0].pvBuffer, crypt_trailer_client,
-               crypt.pBuffers[0].cbBuffer))
-    {
-        int i;
-        for (i = 0; i < crypt.pBuffers[0].cbBuffer; i++)
-        {
-            if (i % 8 == 0) printf("     ");
-            printf("0x%02x,", ((unsigned char *)crypt.pBuffers[0].pvBuffer)[i]);
-            if (i % 8 == 7) printf("\n");
-        }
-        printf("\n");
-    }
-    ok(!memcmp(crypt.pBuffers[1].pvBuffer, crypt_message_client,
-               crypt.pBuffers[1].cbBuffer), "Crypt message not as expected.\n");
-    if (memcmp(crypt.pBuffers[1].pvBuffer, crypt_message_client,
-               crypt.pBuffers[1].cbBuffer))
+    /* first 8 bytes must always be the same */
+    ok(!memcmp(crypt.pBuffers[0].pvBuffer, crypt_trailer_client, 8), "Crypt trailer not as expected.\n");
+
+    /* the rest depends on the session key */
+    if (!memcmp(crypt.pBuffers[0].pvBuffer, crypt_trailer_client, crypt.pBuffers[0].cbBuffer))
     {
-        int i;
-        for (i = 0; i < crypt.pBuffers[1].cbBuffer; i++)
+        ok(!memcmp(crypt.pBuffers[0].pvBuffer, crypt_trailer_client,
+                   crypt.pBuffers[0].cbBuffer), "Crypt trailer not as expected.\n");
+        ok(!memcmp(crypt.pBuffers[1].pvBuffer, crypt_message_client,
+                   crypt.pBuffers[1].cbBuffer), "Crypt message not as expected.\n");
+        if (memcmp(crypt.pBuffers[1].pvBuffer, crypt_message_client,
+                   crypt.pBuffers[1].cbBuffer))
         {
-            if (i % 8 == 0) printf("     ");
-            printf("0x%02x,", ((unsigned char *)crypt.pBuffers[1].pvBuffer)[i]);
-            if (i % 8 == 7) printf("\n");
+            int i;
+            for (i = 0; i < crypt.pBuffers[1].cbBuffer; i++)
+            {
+                if (i % 8 == 0) printf("     ");
+                printf("0x%02x,", ((unsigned char *)crypt.pBuffers[1].pvBuffer)[i]);
+                if (i % 8 == 7) printf("\n");
+            }
+            printf("\n");
         }
-        printf("\n");
-    }
 
-    data[0].cbBuffer = sizeof(crypt_trailer_server);
-    data[1].cbBuffer = sizeof(crypt_message_server);
-    memcpy(data[0].pvBuffer, crypt_trailer_server, data[0].cbBuffer);
-    memcpy(data[1].pvBuffer, crypt_message_server, data[1].cbBuffer);
+        data[0].cbBuffer = sizeof(crypt_trailer_server);
+        data[1].cbBuffer = sizeof(crypt_message_server);
+        memcpy(data[0].pvBuffer, crypt_trailer_server, data[0].cbBuffer);
+        memcpy(data[1].pvBuffer, crypt_message_server, data[1].cbBuffer);
 
-    sec_status = pDecryptMessage(&client.ctxt, &crypt, 0, &qop);
+        sec_status = pDecryptMessage(&client.ctxt, &crypt, 0, &qop);
 
-    ok(sec_status == SEC_E_OK, "DecryptMessage returned %s, not SEC_E_OK.\n",
-            getSecError(sec_status));
-    ok(!memcmp(crypt.pBuffers[1].pvBuffer, message_binary,
-               crypt.pBuffers[1].cbBuffer),
-            "Failed to decrypt message correctly.\n");
+        ok(sec_status == SEC_E_OK, "DecryptMessage returned %s, not SEC_E_OK.\n",
+           getSecError(sec_status));
+        ok(!memcmp(crypt.pBuffers[1].pvBuffer, message_binary,
+                   crypt.pBuffers[1].cbBuffer),
+           "Failed to decrypt message correctly.\n");
+    }
+    else trace( "A different session key is being used\n" );
 
     trace("Testing with more than one buffer.\n");
 
@@ -1109,7 +1106,7 @@ static void testSignSeal(void)
     complex_data[0].pvBuffer = message_header;
 
     complex_data[1].BufferType = SECBUFFER_DATA;
-    complex_data[1].cbBuffer = lstrlen(message);
+    complex_data[1].cbBuffer = lstrlenA(message);
     complex_data[1].pvBuffer = HeapAlloc(GetProcessHeap(), 0, data[1].cbBuffer);
     memcpy(complex_data[1].pvBuffer, message, complex_data[1].cbBuffer);
 
@@ -1138,20 +1135,10 @@ static void testSignSeal(void)
     ok(sec_status == SEC_E_OK, "EncryptMessage returned %s, not SEC_E_OK.\n",
             getSecError(sec_status));
 
-    ok(!memcmp(crypt.pBuffers[3].pvBuffer, crypt_trailer_client2,
-               crypt.pBuffers[3].cbBuffer), "Crypt trailer not as expected.\n");
+    ok(!memcmp(crypt.pBuffers[3].pvBuffer, crypt_trailer_client2, 8), "Crypt trailer not as expected.\n");
+
     if (memcmp(crypt.pBuffers[3].pvBuffer, crypt_trailer_client2,
-               crypt.pBuffers[3].cbBuffer))
-    {
-        int i;
-        for (i = 0; i < crypt.pBuffers[3].cbBuffer; i++)
-        {
-            if (i % 8 == 0) printf("     ");
-            printf("0x%02x,", ((unsigned char *)crypt.pBuffers[3].pvBuffer)[i]);
-            if (i % 8 == 7) printf("\n");
-        }
-        printf("\n");
-    }
+               crypt.pBuffers[3].cbBuffer)) goto end;
 
     ok(!memcmp(crypt.pBuffers[1].pvBuffer, crypt_message_client2,
                crypt.pBuffers[1].cbBuffer), "Crypt message not as expected.\n");
@@ -1191,7 +1178,7 @@ end:
     HeapFree(GetProcessHeap(), 0, complex_data[3].pvBuffer);
 }
 
-static void testAcquireCredentialsHandle(void)
+static BOOL testAcquireCredentialsHandle(void)
 {
     CredHandle cred;
     TimeStamp ttl;
@@ -1200,13 +1187,13 @@ static void testAcquireCredentialsHandle(void)
                 test_pass[] = "testpass",
                 sec_pkg_name[] = "NTLM";
     SECURITY_STATUS ret;
-    SEC_WINNT_AUTH_IDENTITY id;
-    PSecPkgInfo             pkg_info = NULL;
+    SEC_WINNT_AUTH_IDENTITY_A id;
+    PSecPkgInfoA pkg_info = NULL;
 
     if(pQuerySecurityPackageInfoA(sec_pkg_name, &pkg_info) != SEC_E_OK)
     {
-        skip("NTLM package not installed, skipping test\n");
-        return;
+        ok(0, "NTLM package not installed, skipping test\n");
+        return FALSE;
     }
     pFreeContextBuffer(pkg_info);
 
@@ -1257,6 +1244,7 @@ static void testAcquireCredentialsHandle(void)
     ok(ret == SEC_E_OK, "AcquireCredentialsHande() returned %s\n",
             getSecError(ret));
     pFreeCredentialsHandle(&cred);
+    return TRUE;
 }
 
 static void test_cred_multiple_use(void)
@@ -1266,8 +1254,8 @@ static void test_cred_multiple_use(void)
                 test_pass[] = "testpass",
                 sec_pkg_name[] = "NTLM";
     SECURITY_STATUS ret;
-    SEC_WINNT_AUTH_IDENTITY id;
-    PSecPkgInfo             pkg_info = NULL;
+    SEC_WINNT_AUTH_IDENTITY_A id;
+    PSecPkgInfoA            pkg_info = NULL;
     CredHandle              cred;
     CtxtHandle              ctxt1;
     CtxtHandle              ctxt2;
@@ -1278,7 +1266,7 @@ static void test_cred_multiple_use(void)
 
     if(pQuerySecurityPackageInfoA(sec_pkg_name, &pkg_info) != SEC_E_OK)
     {
-        skip("NTLM package not installed, skipping test\n");
+        ok(0, "NTLM package not installed, skipping test\n");
         return;
     }
     buffers[0].cbBuffer = pkg_info->cbMaxToken;
@@ -1327,7 +1315,7 @@ static void test_cred_multiple_use(void)
 static void test_null_auth_data(void)
 {
     SECURITY_STATUS status;
-    PSecPkgInfo info;
+    PSecPkgInfoA info;
     CredHandle cred;
     CtxtHandle ctx;
     SecBufferDesc buffer_desc;
@@ -1339,7 +1327,7 @@ static void test_null_auth_data(void)
 
     if(pQuerySecurityPackageInfoA((SEC_CHAR *)"NTLM", &info) != SEC_E_OK)
     {
-        skip("NTLM package not installed, skipping test\n");
+        ok(0, "NTLM package not installed, skipping test\n");
         return;
     }
 
@@ -1382,7 +1370,8 @@ START_TEST(ntlm)
        pInitializeSecurityContextA && pCompleteAuthToken &&
        pQuerySecurityPackageInfoA)
     {
-        testAcquireCredentialsHandle();
+        if(!testAcquireCredentialsHandle())
+            goto cleanup;
         testInitializeSecurityContextFlags();
         if(pAcceptSecurityContext)
         {
@@ -1401,6 +1390,7 @@ START_TEST(ntlm)
     else
         win_skip("Needed functions are not available\n");
 
+cleanup:
     if(secdll)
         FreeLibrary(secdll);
 }
index 82e27db..078aec7 100644 (file)
@@ -24,6 +24,8 @@
 #define SECURITY_WIN32
 #include <security.h>
 #include <schannel.h>
+#include <winsock2.h>
+#include <ws2tcpip.h>
 
 #include "wine/test.h"
 
@@ -34,14 +36,20 @@ static ENUMERATE_SECURITY_PACKAGES_FN_A pEnumerateSecurityPackagesA;
 static FREE_CONTEXT_BUFFER_FN pFreeContextBuffer;
 static FREE_CREDENTIALS_HANDLE_FN pFreeCredentialsHandle;
 static QUERY_CREDENTIALS_ATTRIBUTES_FN_A pQueryCredentialsAttributesA;
+static INITIALIZE_SECURITY_CONTEXT_FN_A pInitializeSecurityContextA;
+static QUERY_CONTEXT_ATTRIBUTES_FN_A pQueryContextAttributesA;
+static DELETE_SECURITY_CONTEXT_FN pDeleteSecurityContext;
+static DECRYPT_MESSAGE_FN pDecryptMessage;
+static ENCRYPT_MESSAGE_FN pEncryptMessage;
 
 static PCCERT_CONTEXT (WINAPI *pCertCreateCertificateContext)(DWORD,const BYTE*,DWORD);
 static BOOL (WINAPI *pCertFreeCertificateContext)(PCCERT_CONTEXT);
 static BOOL (WINAPI *pCertSetCertificateContextProperty)(PCCERT_CONTEXT,DWORD,DWORD,const void*);
+static PCCERT_CONTEXT (WINAPI *pCertEnumCertificatesInStore)(HCERTSTORE,PCCERT_CONTEXT);
 
 static BOOL (WINAPI *pCryptAcquireContextW)(HCRYPTPROV*, LPCWSTR, LPCWSTR, DWORD, DWORD);
 static BOOL (WINAPI *pCryptDestroyKey)(HCRYPTKEY);
-static BOOL (WINAPI *pCryptImportKey)(HCRYPTPROV,CONST BYTE*,DWORD,HCRYPTKEY,DWORD,HCRYPTKEY*);
+static BOOL (WINAPI *pCryptImportKey)(HCRYPTPROV,const BYTE*,DWORD,HCRYPTKEY,DWORD,HCRYPTKEY*);
 static BOOL (WINAPI *pCryptReleaseContext)(HCRYPTPROV,ULONG_PTR);
 
 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
@@ -115,7 +123,7 @@ static void InitFunctionPtrs(void)
     secdll = LoadLibraryA("secur32.dll");
     if(!secdll)
         secdll = LoadLibraryA("security.dll");
-    advapi32dll = GetModuleHandleA("advapi32.dll");
+    advapi32dll = LoadLibraryA("advapi32.dll");
 
 #define GET_PROC(h, func)  p ## func = (void*)GetProcAddress(h, #func)
 
@@ -126,6 +134,11 @@ static void InitFunctionPtrs(void)
         GET_PROC(secdll, FreeContextBuffer);
         GET_PROC(secdll, FreeCredentialsHandle);
         GET_PROC(secdll, QueryCredentialsAttributesA);
+        GET_PROC(secdll, InitializeSecurityContextA);
+        GET_PROC(secdll, QueryContextAttributesA);
+        GET_PROC(secdll, DeleteSecurityContext);
+        GET_PROC(secdll, DecryptMessage);
+        GET_PROC(secdll, EncryptMessage);
     }
 
     GET_PROC(advapi32dll, CryptAcquireContextW);
@@ -136,6 +149,7 @@ static void InitFunctionPtrs(void)
     GET_PROC(crypt32dll, CertFreeCertificateContext);
     GET_PROC(crypt32dll, CertSetCertificateContextProperty);
     GET_PROC(crypt32dll, CertCreateCertificateContext);
+    GET_PROC(crypt32dll, CertEnumCertificatesInStore);
 
 #undef GET_PROC
 }
@@ -152,6 +166,31 @@ static void test_strength(PCredHandle handle)
     trace("strength %d - %d\n", strength.dwMinimumCipherStrength, strength.dwMaximumCipherStrength);
 }
 
+static void test_supported_protocols(CredHandle *handle, unsigned exprots)
+{
+    SecPkgCred_SupportedProtocols protocols;
+    SECURITY_STATUS status;
+
+    status = pQueryCredentialsAttributesA(handle, SECPKG_ATTR_SUPPORTED_PROTOCOLS, &protocols);
+    ok(status == SEC_E_OK, "QueryCredentialsAttributes failed: %08x\n", status);
+
+    if(exprots)
+        ok(protocols.grbitProtocol == exprots, "protocols.grbitProtocol = %x, expected %x\n", protocols.grbitProtocol, exprots);
+
+    trace("Supported protocols:\n");
+
+#define X(flag, name) do { if(protocols.grbitProtocol & flag) { trace(name "\n"); protocols.grbitProtocol &= ~flag; } }while(0)
+    X(SP_PROT_SSL2_CLIENT, "SSL 2 client");
+    X(SP_PROT_SSL3_CLIENT, "SSL 3 client");
+    X(SP_PROT_TLS1_0_CLIENT, "TLS 1.0 client");
+    X(SP_PROT_TLS1_1_CLIENT, "TLS 1.1 client");
+    X(SP_PROT_TLS1_2_CLIENT, "TLS 1.2 client");
+#undef X
+
+    if(protocols.grbitProtocol)
+        trace("Unknown flags: %x\n", protocols.grbitProtocol);
+}
+
 static void testAcquireSecurityContext(void)
 {
     BOOL has_schannel = FALSE;
@@ -159,6 +198,7 @@ static void testAcquireSecurityContext(void)
     ULONG i;
     SECURITY_STATUS st;
     CredHandle cred;
+    SecPkgCredentials_NamesA names;
     TimeStamp exp;
     SCHANNEL_CRED schanCred;
     PCCERT_CONTEXT certs[2];
@@ -229,34 +269,41 @@ static void testAcquireSecurityContext(void)
         /* Crashes on Win2K */
         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, 0, NULL, NULL, NULL,
          NULL, NULL, NULL);
-        ok(st == SEC_E_NO_CREDENTIALS, "Expected SEC_E_NO_CREDENTIALS, got %08x\n",
-         st);
-    }
-    st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_BOTH, NULL,
-     NULL, NULL, NULL, NULL, NULL);
-    ok(st == SEC_E_NO_CREDENTIALS, "Expected SEC_E_NO_CREDENTIALS, got %08x\n",
-     st);
-    st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
-     NULL, NULL, NULL, NULL, NULL, NULL);
-    ok(st == SEC_E_NO_CREDENTIALS, "Expected SEC_E_NO_CREDENTIALS, got %08x\n",
-     st);
-    if (0)
-    {
+        ok(st == SEC_E_NO_CREDENTIALS, "Expected SEC_E_NO_CREDENTIALS, got %08x\n", st);
+
+        /* Crashes on WinNT */
+        st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_BOTH, NULL,
+         NULL, NULL, NULL, NULL, NULL);
+        ok(st == SEC_E_NO_CREDENTIALS, "Expected SEC_E_NO_CREDENTIALS, got %08x\n", st);
+
+        st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
+         NULL, NULL, NULL, NULL, NULL, NULL);
+        ok(st == SEC_E_NO_CREDENTIALS, "Expected SEC_E_NO_CREDENTIALS, got %08x\n", st);
+
         /* Crashes */
-        st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
+        pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
          NULL, NULL, NULL, NULL, NULL, NULL);
     }
     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
      NULL, NULL, NULL, NULL, &cred, NULL);
     ok(st == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", st);
-    if(st == SEC_E_OK)
+    if(st == SEC_E_OK) {
+        st = pQueryCredentialsAttributesA(&cred, SECPKG_ATTR_SUPPORTED_PROTOCOLS, NULL);
+        ok(st == SEC_E_INTERNAL_ERROR, "QueryCredentialsAttributes failed: %08x, expected SEC_E_INTERNAL_ERROR\n", st);
+
+        test_supported_protocols(&cred, 0);
         pFreeCredentialsHandle(&cred);
+    }
     memset(&cred, 0, sizeof(cred));
     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
      NULL, NULL, NULL, NULL, &cred, &exp);
     ok(st == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", st);
     /* expriy is indeterminate in win2k3 */
     trace("expiry: %08x%08x\n", exp.HighPart, exp.LowPart);
+
+    st = pQueryCredentialsAttributesA(&cred, SECPKG_CRED_ATTR_NAMES, &names);
+    ok(st == SEC_E_NO_CREDENTIALS || st == SEC_E_UNSUPPORTED_FUNCTION /* before Vista */, "expected SEC_E_NO_CREDENTIALS, got %08x\n", st);
+
     pFreeCredentialsHandle(&cred);
 
     /* Bad version in SCHANNEL_CRED */
@@ -264,13 +311,13 @@ static void testAcquireSecurityContext(void)
     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
      NULL, &schanCred, NULL, NULL, NULL, NULL);
     ok(st == SEC_E_INTERNAL_ERROR ||
-       st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */,
-       "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
+       st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */ ||
+       st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %08x\n", st);
     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
      NULL, &schanCred, NULL, NULL, NULL, NULL);
     ok(st == SEC_E_INTERNAL_ERROR ||
-       st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */,
-       "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
+       st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */ ||
+       st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %08x\n", st);
 
     /* No cert in SCHANNEL_CRED succeeds for outbound.. */
     schanCred.dwVersion = SCHANNEL_CRED_VERSION;
@@ -289,7 +336,7 @@ static void testAcquireSecurityContext(void)
     {
         /* Crashes with bad paCred pointer */
         schanCred.cCreds = 1;
-        st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
+        pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
          NULL, &schanCred, NULL, NULL, NULL, NULL);
     }
 
@@ -300,14 +347,14 @@ static void testAcquireSecurityContext(void)
     schanCred.paCred = &certs[0];
     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
      NULL, &schanCred, NULL, NULL, NULL, NULL);
-    ok(st == SEC_E_UNKNOWN_CREDENTIALS || st == SEC_E_NO_CREDENTIALS,
-     "Expected SEC_E_UNKNOWN_CREDENTIALS or SEC_E_NO_CREDENTIALS, got %08x\n",
-     st);
+    ok(st == SEC_E_UNKNOWN_CREDENTIALS ||
+       st == SEC_E_NO_CREDENTIALS ||
+       st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %08x\n", st);
     st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
      NULL, &schanCred, NULL, NULL, NULL, NULL);
-    ok(st == SEC_E_UNKNOWN_CREDENTIALS || st == SEC_E_NO_CREDENTIALS,
-     "Expected SEC_E_UNKNOWN_CREDENTIALS or SEC_E_NO_CREDENTIALS, got %08x\n",
-     st);
+    ok(st == SEC_E_UNKNOWN_CREDENTIALS ||
+       st == SEC_E_NO_CREDENTIALS ||
+       st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %08x\n", st);
 
     /* Good cert, but missing private key. Windows fails with
      * SEC_E_NO_CREDENTIALS, but I'll accept SEC_E_UNKNOWN_CREDENTIALS too.
@@ -333,14 +380,15 @@ static void testAcquireSecurityContext(void)
         ret = pCertSetCertificateContextProperty(certs[1],
               CERT_KEY_PROV_INFO_PROP_ID, 0, &keyProvInfo);
         schanCred.dwVersion = SCH_CRED_V3;
+        ok(ret, "CertSetCertificateContextProperty failed: %08x\n", GetLastError());
         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
              NULL, &schanCred, NULL, NULL, &cred, NULL);
-        ok(st == SEC_E_UNKNOWN_CREDENTIALS,
-           "Expected SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
+        ok(st == SEC_E_UNKNOWN_CREDENTIALS || st == SEC_E_INTERNAL_ERROR /* WinNT */,
+           "Expected SEC_E_UNKNOWN_CREDENTIALS or SEC_E_INTERNAL_ERROR, got %08x\n", st);
         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
              NULL, &schanCred, NULL, NULL, &cred, NULL);
-        ok(st == SEC_E_UNKNOWN_CREDENTIALS,
-           "Expected SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
+        ok(st == SEC_E_UNKNOWN_CREDENTIALS || st == SEC_E_INTERNAL_ERROR /* WinNT */,
+           "Expected SEC_E_UNKNOWN_CREDENTIALS or SEC_E_INTERNAL_ERROR, got %08x\n", st);
     }
 
     ret = pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
@@ -359,32 +407,34 @@ static void testAcquireSecurityContext(void)
         if (0)
         {
             /* Crashes */
-            st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
+            pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
              NULL, &schanCred, NULL, NULL, NULL, NULL);
+
+            /* Crashes on WinNT */
+            /* Good cert with private key, bogus version */
+            schanCred.dwVersion = SCH_CRED_V1;
+            st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
+                NULL, &schanCred, NULL, NULL, &cred, NULL);
+            ok(st == SEC_E_INTERNAL_ERROR ||
+                st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */,
+                "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
+            st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
+                NULL, &schanCred, NULL, NULL, &cred, NULL);
+            ok(st == SEC_E_INTERNAL_ERROR ||
+                st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */,
+                "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
+            schanCred.dwVersion = SCH_CRED_V2;
+            st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
+                NULL, &schanCred, NULL, NULL, &cred, NULL);
+            ok(st == SEC_E_INTERNAL_ERROR ||
+                st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */,
+                "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
+            st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
+                NULL, &schanCred, NULL, NULL, &cred, NULL);
+            ok(st == SEC_E_INTERNAL_ERROR ||
+                st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */,
+                "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
         }
-        /* Good cert with private key, bogus version */
-        schanCred.dwVersion = SCH_CRED_V1;
-        st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
-         NULL, &schanCred, NULL, NULL, &cred, NULL);
-        ok(st == SEC_E_INTERNAL_ERROR ||
-           st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */,
-           "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
-        st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
-         NULL, &schanCred, NULL, NULL, &cred, NULL);
-        ok(st == SEC_E_INTERNAL_ERROR ||
-           st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */,
-           "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
-        schanCred.dwVersion = SCH_CRED_V2;
-        st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
-         NULL, &schanCred, NULL, NULL, &cred, NULL);
-        ok(st == SEC_E_INTERNAL_ERROR ||
-           st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */,
-           "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
-        st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
-         NULL, &schanCred, NULL, NULL, &cred, NULL);
-        ok(st == SEC_E_INTERNAL_ERROR ||
-           st == SEC_E_UNKNOWN_CREDENTIALS /* Vista/win2k8 */,
-           "Expected SEC_E_INTERNAL_ERROR or SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
 
         /* Succeeds on V3 or higher */
         schanCred.dwVersion = SCH_CRED_V3;
@@ -417,21 +467,21 @@ static void testAcquireSecurityContext(void)
         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
          NULL, &schanCred, NULL, NULL, &cred, NULL);
         ok(st == SEC_E_UNKNOWN_CREDENTIALS ||
-           st == SEC_E_NO_CREDENTIALS /* Vista/win2k8 */,
-           "Expected SEC_E_UNKNOWN_CREDENTIALS or SEC_E_NO_CREDENTIALS, got %08x\n", st);
+           st == SEC_E_NO_CREDENTIALS /* Vista/win2k8 */ ||
+           st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %08x\n", st);
         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
          NULL, &schanCred, NULL, NULL, &cred, NULL);
         ok(st == SEC_E_UNKNOWN_CREDENTIALS ||
-           st == SEC_E_NO_CREDENTIALS,
-           "Expected SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
+           st == SEC_E_NO_CREDENTIALS ||
+           st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %08x\n", st);
         tmp = certs[0];
         certs[0] = certs[1];
         certs[1] = tmp;
         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND,
          NULL, &schanCred, NULL, NULL, &cred, NULL);
         ok(st == SEC_E_UNKNOWN_CREDENTIALS ||
-           st == SEC_E_NO_CREDENTIALS,
-           "Expected SEC_E_UNKNOWN_CREDENTIALS, got %08x\n", st);
+           st == SEC_E_NO_CREDENTIALS ||
+           st == SEC_E_INVALID_TOKEN /* WinNT */, "st = %08x\n", st);
         st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND,
          NULL, &schanCred, NULL, NULL, &cred, NULL);
         ok(st == SEC_E_UNKNOWN_CREDENTIALS,
@@ -454,11 +504,407 @@ static void testAcquireSecurityContext(void)
     }
 }
 
+static void test_remote_cert(PCCERT_CONTEXT remote_cert)
+{
+    PCCERT_CONTEXT iter = NULL;
+    BOOL incl_remote = FALSE;
+    unsigned cert_cnt = 0;
+
+    ok(remote_cert->hCertStore != NULL, "hCertStore == NULL\n");
+
+    while((iter = pCertEnumCertificatesInStore(remote_cert->hCertStore, iter))) {
+        if(iter == remote_cert)
+            incl_remote = TRUE;
+        cert_cnt++;
+    }
+
+    ok(cert_cnt == 2, "cert_cnt = %u\n", cert_cnt);
+    ok(incl_remote, "context does not contain cert itself\n");
+}
+
+static const char http_request[] = "HEAD /test.html HTTP/1.1\r\nHost: www.winehq.org\r\nConnection: close\r\n\r\n";
+
+static void init_cred(SCHANNEL_CRED *cred)
+{
+    cred->dwVersion = SCHANNEL_CRED_VERSION;
+    cred->cCreds = 0;
+    cred->paCred = 0;
+    cred->hRootStore = NULL;
+    cred->cMappers = 0;
+    cred->aphMappers = NULL;
+    cred->cSupportedAlgs = 0;
+    cred->palgSupportedAlgs = NULL;
+    cred->grbitEnabledProtocols = SP_PROT_SSL3_CLIENT;
+    cred->dwMinimumCipherStrength = 0;
+    cred->dwMaximumCipherStrength = 0;
+    cred->dwSessionLifespan = 0;
+    cred->dwFlags = 0;
+}
+
+static void init_buffers(SecBufferDesc *desc, unsigned count, unsigned size)
+{
+    desc->ulVersion = SECBUFFER_VERSION;
+    desc->cBuffers = count;
+    desc->pBuffers = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, count*sizeof(SecBuffer));
+
+    desc->pBuffers[0].cbBuffer = size;
+    desc->pBuffers[0].pvBuffer = HeapAlloc(GetProcessHeap(), 0, size);
+}
+
+static void reset_buffers(SecBufferDesc *desc)
+{
+    unsigned i;
+
+    for (i = 0; i < desc->cBuffers; ++i)
+    {
+        desc->pBuffers[i].BufferType = SECBUFFER_EMPTY;
+        if (i > 0)
+        {
+            desc->pBuffers[i].cbBuffer = 0;
+            desc->pBuffers[i].pvBuffer = NULL;
+        }
+    }
+}
+
+static void free_buffers(SecBufferDesc *desc)
+{
+    HeapFree(GetProcessHeap(), 0, desc->pBuffers[0].pvBuffer);
+    HeapFree(GetProcessHeap(), 0, desc->pBuffers);
+}
+
+static int receive_data(SOCKET sock, SecBuffer *buf)
+{
+    unsigned received = 0;
+
+    while (1)
+    {
+        unsigned char *data = buf->pvBuffer;
+        unsigned expected = 0;
+        int ret;
+
+        ret = recv(sock, (char *)data+received, buf->cbBuffer-received, 0);
+        if (ret == -1)
+        {
+            skip("recv failed\n");
+            return -1;
+        }
+        else if(ret == 0)
+        {
+            skip("connection closed\n");
+            return -1;
+        }
+        received += ret;
+
+        while (expected < received)
+        {
+            unsigned frame_size = 5 + ((data[3]<<8) | data[4]);
+            expected += frame_size;
+            data += frame_size;
+        }
+
+        if (expected == received)
+            break;
+    }
+
+    buf->cbBuffer = received;
+
+    return received;
+}
+
+static void test_communication(void)
+{
+    int ret;
+
+    WSADATA wsa_data;
+    SOCKET sock;
+    struct hostent *host;
+    struct sockaddr_in addr;
+
+    SECURITY_STATUS status;
+    ULONG attrs;
+
+    SCHANNEL_CRED cred;
+    CredHandle cred_handle;
+    CtxtHandle context;
+    SecPkgCredentials_NamesA names;
+    SecPkgContext_StreamSizes sizes;
+    SecPkgContext_ConnectionInfo conn_info;
+    CERT_CONTEXT *cert;
+
+    SecBufferDesc buffers[2];
+    SecBuffer *buf;
+    unsigned buf_size = 4000;
+    unsigned char *data;
+    unsigned data_size;
+
+    if (!pAcquireCredentialsHandleA || !pFreeCredentialsHandle ||
+        !pInitializeSecurityContextA || !pDeleteSecurityContext ||
+        !pQueryContextAttributesA || !pDecryptMessage || !pEncryptMessage)
+    {
+        skip("Required secur32 functions not available\n");
+        return;
+    }
+
+    /* Create a socket and connect to www.winehq.org */
+    ret = WSAStartup(0x0202, &wsa_data);
+    if (ret)
+    {
+        skip("Can't init winsock 2.2\n");
+        return;
+    }
+
+    host = gethostbyname("www.winehq.org");
+    if (!host)
+    {
+        skip("Can't resolve www.winehq.org\n");
+        return;
+    }
+
+    addr.sin_family = host->h_addrtype;
+    addr.sin_addr = *(struct in_addr *)host->h_addr_list[0];
+    addr.sin_port = htons(443);
+    sock = socket(host->h_addrtype, SOCK_STREAM, 0);
+    if (sock == SOCKET_ERROR)
+    {
+        skip("Can't create socket\n");
+        return;
+    }
+
+    ret = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
+    if (ret == SOCKET_ERROR)
+    {
+        skip("Can't connect to www.winehq.org\n");
+        return;
+    }
+
+    /* Create client credentials */
+    init_cred(&cred);
+    cred.dwFlags = SCH_CRED_NO_DEFAULT_CREDS|SCH_CRED_MANUAL_CRED_VALIDATION;
+
+    status = pAcquireCredentialsHandleA(NULL, (SEC_CHAR *)UNISP_NAME_A, SECPKG_CRED_OUTBOUND, NULL,
+        &cred, NULL, NULL, &cred_handle, NULL);
+    ok(status == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", status);
+    if (status != SEC_E_OK) return;
+
+    test_supported_protocols(&cred_handle, SP_PROT_SSL3_CLIENT);
+
+    /* Initialize the connection */
+    init_buffers(&buffers[0], 4, buf_size);
+    init_buffers(&buffers[1], 4, buf_size);
+
+    buffers[0].pBuffers[0].BufferType = SECBUFFER_TOKEN;
+    status = pInitializeSecurityContextA(&cred_handle, NULL, (SEC_CHAR *)"localhost",
+        ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
+        0, 0, NULL, 0, &context, &buffers[0], &attrs, NULL);
+    ok(status == SEC_I_CONTINUE_NEEDED, "Expected SEC_I_CONTINUE_NEEDED, got %08x\n", status);
+
+    buffers[1].cBuffers = 1;
+    buffers[1].pBuffers[0].BufferType = SECBUFFER_TOKEN;
+    buffers[0].pBuffers[0].cbBuffer = 1;
+    status = pInitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
+            ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
+            0, 0, &buffers[1], 0, NULL, &buffers[0], &attrs, NULL);
+    ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
+todo_wine
+    ok(buffers[0].pBuffers[0].cbBuffer == 0, "Output buffer size was not set to 0.\n");
+
+    status = pInitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
+            ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
+            0, 0, &buffers[1], 0, NULL, &buffers[0], &attrs, NULL);
+todo_wine
+    ok(status == SEC_E_INSUFFICIENT_MEMORY || status == SEC_E_INVALID_TOKEN,
+       "Expected SEC_E_INSUFFICIENT_MEMORY or SEC_E_INVALID_TOKEN, got %08x\n", status);
+
+    buffers[0].pBuffers[0].cbBuffer = buf_size;
+
+    status = pInitializeSecurityContextA(&cred_handle, NULL, (SEC_CHAR *)"localhost",
+            ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
+            0, 0, NULL, 0, &context, &buffers[0], &attrs, NULL);
+    ok(status == SEC_I_CONTINUE_NEEDED, "Expected SEC_I_CONTINUE_NEEDED, got %08x\n", status);
+
+    buf = &buffers[0].pBuffers[0];
+    send(sock, buf->pvBuffer, buf->cbBuffer, 0);
+    buf->cbBuffer = buf_size;
+
+    status = pInitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
+            ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
+            0, 0, NULL, 0, NULL, &buffers[0], &attrs, NULL);
+    ok(status == SEC_E_INCOMPLETE_MESSAGE, "Got unexpected status %#x.\n", status);
+    ok(buffers[0].pBuffers[0].cbBuffer == buf_size, "Output buffer size changed.\n");
+    ok(buffers[0].pBuffers[0].BufferType == SECBUFFER_TOKEN, "Output buffer type changed.\n");
+
+    buffers[1].cBuffers = 4;
+    buffers[1].pBuffers[0].cbBuffer = 0;
+
+    status = pInitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
+            ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
+            0, 0, &buffers[1], 0, NULL, &buffers[0], &attrs, NULL);
+    ok(status == SEC_E_INCOMPLETE_MESSAGE, "Got unexpected status %#x.\n", status);
+    ok(buffers[0].pBuffers[0].cbBuffer == buf_size, "Output buffer size changed.\n");
+    ok(buffers[0].pBuffers[0].BufferType == SECBUFFER_TOKEN, "Output buffer type changed.\n");
+
+    buf = &buffers[1].pBuffers[0];
+    buf->cbBuffer = buf_size;
+    ret = receive_data(sock, buf);
+    if (ret == -1)
+        return;
+
+    buffers[1].pBuffers[0].cbBuffer = 4;
+    status = pInitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
+            ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
+            0, 0, &buffers[1], 0, NULL, &buffers[0], &attrs, NULL);
+    ok(status == SEC_E_INCOMPLETE_MESSAGE, "Got unexpected status %#x.\n", status);
+    ok(buffers[0].pBuffers[0].cbBuffer == buf_size, "Output buffer size changed.\n");
+    ok(buffers[0].pBuffers[0].BufferType == SECBUFFER_TOKEN, "Output buffer type changed.\n");
+
+    buffers[1].pBuffers[0].cbBuffer = 5;
+    status = pInitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
+            ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
+            0, 0, &buffers[1], 0, NULL, &buffers[0], &attrs, NULL);
+    ok(status == SEC_E_INCOMPLETE_MESSAGE, "Got unexpected status %#x.\n", status);
+    ok(buffers[0].pBuffers[0].cbBuffer == buf_size, "Output buffer size changed.\n");
+    ok(buffers[0].pBuffers[0].BufferType == SECBUFFER_TOKEN, "Output buffer type changed.\n");
+
+    buffers[1].pBuffers[0].cbBuffer = ret;
+    status = pInitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
+            ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
+            0, 0, &buffers[1], 0, NULL, &buffers[0], &attrs, NULL);
+    buffers[1].pBuffers[0].cbBuffer = buf_size;
+    while (status == SEC_I_CONTINUE_NEEDED)
+    {
+        buf = &buffers[0].pBuffers[0];
+        send(sock, buf->pvBuffer, buf->cbBuffer, 0);
+        buf->cbBuffer = buf_size;
+
+        buf = &buffers[1].pBuffers[0];
+        ret = receive_data(sock, buf);
+        if (ret == -1)
+            return;
+
+        buf->BufferType = SECBUFFER_TOKEN;
+
+        status = pInitializeSecurityContextA(&cred_handle, &context, (SEC_CHAR *)"localhost",
+            ISC_REQ_CONFIDENTIALITY|ISC_REQ_STREAM,
+            0, 0, &buffers[1], 0, NULL, &buffers[0], &attrs, NULL);
+        buffers[1].pBuffers[0].cbBuffer = buf_size;
+    }
+
+    ok(status == SEC_E_OK || broken(status == SEC_E_INVALID_TOKEN) /* WinNT */,
+        "InitializeSecurityContext failed: %08x\n", status);
+    if(status != SEC_E_OK) {
+        win_skip("Handshake failed\n");
+        return;
+    }
+
+    status = pQueryCredentialsAttributesA(&cred_handle, SECPKG_CRED_ATTR_NAMES, &names);
+    ok(status == SEC_E_NO_CREDENTIALS || status == SEC_E_UNSUPPORTED_FUNCTION /* before Vista */, "expected SEC_E_NO_CREDENTIALS, got %08x\n", status);
+
+    status = pQueryContextAttributesA(&context, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (void*)&cert);
+    ok(status == SEC_E_OK, "QueryContextAttributesW(SECPKG_ATTR_REMOTE_CERT_CONTEXT) failed: %08x\n", status);
+    if(status == SEC_E_OK) {
+        test_remote_cert(cert);
+        pCertFreeCertificateContext(cert);
+    }
+
+    status = pQueryContextAttributesA(&context, SECPKG_ATTR_CONNECTION_INFO, (void*)&conn_info);
+    ok(status == SEC_E_OK, "QueryContextAttributesW(SECPKG_ATTR_CONNECTION_INFO) failed: %08x\n", status);
+    if(status == SEC_E_OK) {
+        ok(conn_info.dwCipherStrength == 128 || conn_info.dwCipherStrength == 168,
+           "conn_info.dwCipherStrength = %d\n", conn_info.dwCipherStrength);
+        ok(conn_info.dwHashStrength >= 128, "conn_info.dwHashStrength = %d\n", conn_info.dwHashStrength);
+    }
+
+    status = pQueryContextAttributesA(&context, SECPKG_ATTR_STREAM_SIZES, &sizes);
+    ok(status == SEC_E_OK, "QueryContextAttributesW(SECPKG_ATTR_STREAM_SIZES) failed: %08x\n", status);
+
+    reset_buffers(&buffers[0]);
+
+    /* Send a simple request so we get data for testing DecryptMessage */
+    buf = &buffers[0].pBuffers[0];
+    data = buf->pvBuffer;
+    buf->BufferType = SECBUFFER_STREAM_HEADER;
+    buf->cbBuffer = sizes.cbHeader;
+    ++buf;
+    buf->BufferType = SECBUFFER_DATA;
+    buf->pvBuffer = data + sizes.cbHeader;
+    buf->cbBuffer = sizeof(http_request) - 1;
+    memcpy(buf->pvBuffer, http_request, sizeof(http_request) - 1);
+    ++buf;
+    buf->BufferType = SECBUFFER_STREAM_TRAILER;
+    buf->pvBuffer = data + sizes.cbHeader + sizeof(http_request) -1;
+    buf->cbBuffer = sizes.cbTrailer;
+
+    status = pEncryptMessage(&context, 0, &buffers[0], 0);
+    ok(status == SEC_E_OK, "EncryptMessage failed: %08x\n", status);
+    if (status != SEC_E_OK)
+        return;
+
+    buf = &buffers[0].pBuffers[0];
+    send(sock, buf->pvBuffer, buffers[0].pBuffers[0].cbBuffer + buffers[0].pBuffers[1].cbBuffer + buffers[0].pBuffers[2].cbBuffer, 0);
+
+    reset_buffers(&buffers[0]);
+    buf->cbBuffer = buf_size;
+    data_size = receive_data(sock, buf);
+
+    /* Too few buffers */
+    --buffers[0].cBuffers;
+    status = pDecryptMessage(&context, &buffers[0], 0, NULL);
+    ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
+
+    /* No data buffer */
+    ++buffers[0].cBuffers;
+    status = pDecryptMessage(&context, &buffers[0], 0, NULL);
+    ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
+
+    /* Two data buffers */
+    buffers[0].pBuffers[0].BufferType = SECBUFFER_DATA;
+    buffers[0].pBuffers[1].BufferType = SECBUFFER_DATA;
+    status = pDecryptMessage(&context, &buffers[0], 0, NULL);
+    ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
+
+    /* Too few empty buffers */
+    buffers[0].pBuffers[1].BufferType = SECBUFFER_EXTRA;
+    status = pDecryptMessage(&context, &buffers[0], 0, NULL);
+    ok(status == SEC_E_INVALID_TOKEN, "Expected SEC_E_INVALID_TOKEN, got %08x\n", status);
+
+    /* Incomplete data */
+    buffers[0].pBuffers[1].BufferType = SECBUFFER_EMPTY;
+    buffers[0].pBuffers[0].cbBuffer = (data[3]<<8) | data[4];
+    status = pDecryptMessage(&context, &buffers[0], 0, NULL);
+    ok(status == SEC_E_INCOMPLETE_MESSAGE, "Expected SEC_E_INCOMPLETE_MESSAGE, got %08x\n", status);
+    ok(buffers[0].pBuffers[0].BufferType == SECBUFFER_MISSING, "Expected first buffer to be SECBUFFER_MISSING\n");
+    ok(buffers[0].pBuffers[0].cbBuffer == 5, "Expected first buffer to be a five bytes\n");
+
+    buffers[0].pBuffers[0].cbBuffer = data_size;
+    buffers[0].pBuffers[0].BufferType = SECBUFFER_DATA;
+    buffers[0].pBuffers[1].BufferType = SECBUFFER_EMPTY;
+    status = pDecryptMessage(&context, &buffers[0], 0, NULL);
+    ok(status == SEC_E_OK, "DecryptMessage failed: %08x\n", status);
+    if (status == SEC_E_OK)
+    {
+        ok(buffers[0].pBuffers[0].BufferType == SECBUFFER_STREAM_HEADER, "Expected first buffer to be SECBUFFER_STREAM_HEADER\n");
+        ok(buffers[0].pBuffers[1].BufferType == SECBUFFER_DATA, "Expected second buffer to be SECBUFFER_DATA\n");
+        ok(buffers[0].pBuffers[2].BufferType == SECBUFFER_STREAM_TRAILER, "Expected third buffer to be SECBUFFER_STREAM_TRAILER\n");
+
+        data = buffers[0].pBuffers[1].pvBuffer;
+        data[buffers[0].pBuffers[1].cbBuffer] = 0;
+    }
+
+    pDeleteSecurityContext(&context);
+    pFreeCredentialsHandle(&cred_handle);
+
+    free_buffers(&buffers[0]);
+    free_buffers(&buffers[1]);
+
+    closesocket(sock);
+}
+
 START_TEST(schannel)
 {
     InitFunctionPtrs();
 
     testAcquireSecurityContext();
+    test_communication();
 
     if(secdll)
         FreeLibrary(secdll);
index 0ad6f0f..6e67784 100644 (file)
@@ -118,7 +118,7 @@ static void testGetUserNameExA(void)
     }
 
     if (0) /* Crashes on Windows */
-        rc = pGetUserNameExA(NameSamCompatible, NULL, NULL);
+        pGetUserNameExA(NameSamCompatible, NULL, NULL);
 
     size = 0;
     rc = pGetUserNameExA(NameSamCompatible, NULL, &size);
@@ -128,7 +128,7 @@ static void testGetUserNameExA(void)
     if (0) /* Crashes on Windows with big enough size */
     {
         /* Returned size is already big enough */
-        rc = pGetUserNameExA(NameSamCompatible, NULL, &size);
+        pGetUserNameExA(NameSamCompatible, NULL, &size);
     }
 
     size = 0;
@@ -165,7 +165,7 @@ static void testGetUserNameExW(void)
     }
 
     if (0) /* Crashes on Windows */
-        rc = pGetUserNameExW(NameSamCompatible, NULL, NULL);
+        pGetUserNameExW(NameSamCompatible, NULL, NULL);
 
     size = 0;
     rc = pGetUserNameExW(NameSamCompatible, NULL, &size);
@@ -175,7 +175,7 @@ static void testGetUserNameExW(void)
     if (0) /* Crashes on Windows with big enough size */
     {
         /* Returned size is already big enough */
-        rc = pGetUserNameExW(NameSamCompatible, NULL, &size);
+        pGetUserNameExW(NameSamCompatible, NULL, &size);
     }
 
     size = 0;
@@ -198,14 +198,12 @@ static void test_InitSecurityInterface(void)
     sftA = pInitSecurityInterfaceA();
     ok(sftA != NULL, "pInitSecurityInterfaceA failed\n");
     ok(sftA->dwVersion == SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION, "wrong dwVersion %d in security function table\n", sftA->dwVersion);
-    ok(!sftA->Reserved2 || broken(sftA->Reserved2 != NULL) /* WinME */,
+    ok(!sftA->Reserved2,
        "Reserved2 should be NULL instead of %p in security function table\n",
        sftA->Reserved2);
-    ok(sftA->Reserved3 == sftA->EncryptMessage ||
-       broken(sftA->Reserved3 != sftA->EncryptMessage) /* Win9x */,
+    ok(sftA->Reserved3 == sftA->EncryptMessage,
        "Reserved3 should be equal to EncryptMessage in the security function table\n");
-    ok(sftA->Reserved4 == sftA->DecryptMessage ||
-       broken(sftA->Reserved4 != sftA->DecryptMessage) /* Win9x */,
+    ok(sftA->Reserved4 == sftA->DecryptMessage,
        "Reserved4 should be equal to DecryptMessage in the security function table\n");
 
     if (!pInitSecurityInterfaceW)
index cc04b84..b6df7d2 100644 (file)
@@ -1,21 +1,20 @@
 /* Automatically generated file; DO NOT EDIT!! */
 
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-
 #define STANDALONE
-#include "wine/test.h"
+#include <wine/test.h>
 
-extern void func_secur32(void);
-extern void func_schannel(void);
-extern void func_ntlm(void);
 extern void func_main(void);
+extern void func_negotiate(void);
+extern void func_ntlm(void);
+extern void func_schannel(void);
+extern void func_secur32(void);
 
 const struct test winetest_testlist[] =
 {
+    { "main", func_main },
+    { "negotiate", func_negotiate },
+    { "ntlm", func_ntlm },
+    { "schannel", func_schannel },
     { "secur32", func_secur32 },
-       { "schannel", func_schannel },
-       { "ntlm", func_ntlm },
-       { "main", func_main },
     { 0, 0 }
 };