main.c 8.94 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
/*
 * Schannel tests
 *
 * Copyright 2006 Yuval Fledel
 *
 * 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 <stdio.h>
#include <stdarg.h>
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include <windef.h>
#include <winbase.h>
#define SECURITY_WIN32
#include <security.h>
#include <schannel.h>
#include <ntsecapi.h>
#include <ntsecpkg.h>

#include "wine/test.h"

35
/* Helper macros to find the size of SECPKG_FUNCTION_TABLE */
36
#define SECPKG_FUNCTION_TABLE_SIZE_1 FIELD_OFFSET(SECPKG_FUNCTION_TABLE, \
37
    SetContextAttributes)
38
#define SECPKG_FUNCTION_TABLE_SIZE_2 FIELD_OFFSET(SECPKG_FUNCTION_TABLE, \
39
    SetCredentialsAttributes)
40 41 42 43 44 45 46
#define SECPKG_FUNCTION_TABLE_SIZE_3 FIELD_OFFSET(SECPKG_FUNCTION_TABLE, \
    ChangeAccountPassword)
#define SECPKG_FUNCTION_TABLE_SIZE_4 FIELD_OFFSET(SECPKG_FUNCTION_TABLE, \
    QueryMetaData)
#define SECPKG_FUNCTION_TABLE_SIZE_5 FIELD_OFFSET(SECPKG_FUNCTION_TABLE, \
    ValidateTargetInfo)
#define SECPKG_FUNCTION_TABLE_SIZE_6 sizeof(SECPKG_FUNCTION_TABLE)
47

48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
static NTSTATUS (NTAPI *pSpLsaModeInitialize)(ULONG, PULONG,
    PSECPKG_FUNCTION_TABLE*, PULONG);
static NTSTATUS (NTAPI *pSpUserModeInitialize)(ULONG, PULONG,
    PSECPKG_USER_FUNCTION_TABLE*, PULONG);

static void testInitialize(void)
{
    PSECPKG_USER_FUNCTION_TABLE pUserTables, pUserTables2;
    PSECPKG_FUNCTION_TABLE pTables, pTables2;
    ULONG cTables = 0, cUserTables = 0, Version = 0;
    NTSTATUS status;

    /* Passing NULL into one of the parameters of SpLsaModeInitialize or
       SpUserModeInitialize causes a crash. */

    /* SpLsaModeInitialize does not care about the LSA version. */
    status = pSpLsaModeInitialize(0, &Version, &pTables2, &cTables);
    ok(status == STATUS_SUCCESS, "status: 0x%x\n", status);
66 67 68
    ok(cTables == 2 ||
       broken(cTables == 1), /* Win2k */
       "cTables: %d\n", cTables);
69 70 71 72 73
    ok(pTables2 != NULL,"pTables: %p\n", pTables2);

    /* We can call it as many times we want. */
    status = pSpLsaModeInitialize(0x10000, &Version, &pTables, &cTables);
    ok(status == STATUS_SUCCESS, "status: 0x%x\n", status);
74 75 76
    ok(cTables == 2 ||
       broken(cTables == 1), /* Win2k */
       "cTables: %d\n", cTables);
77 78 79 80 81 82
    ok(pTables != NULL, "pTables: %p\n", pTables);
    /* It will always return the same pointer. */
    ok(pTables == pTables2, "pTables: %p, pTables2: %p\n", pTables, pTables2);

    status = pSpLsaModeInitialize(0x23456, &Version, &pTables, &cTables);
    ok(status == STATUS_SUCCESS, "status: 0x%x\n", status);
83 84 85
    ok(cTables == 2 ||
       broken(cTables == 1), /* Win2k */
       "cTables: %d\n", cTables);
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
    ok(pTables != NULL, "pTables: %p\n", pTables);
    ok(pTables == pTables2, "pTables: %p, pTables2: %p\n", pTables, pTables2);

    /* Bad versions to SpUserModeInitialize. Parameters unchanged */
    Version = 0xdead;
    cUserTables = 0xdead;
    pUserTables = NULL;
    status = pSpUserModeInitialize(0, &Version, &pUserTables, &cUserTables);
    ok(status == STATUS_INVALID_PARAMETER, "status: 0x%x\n", status);
    ok(Version == 0xdead, "Version: 0x%x\n", Version);
    ok(cUserTables == 0xdead, "cTables: %d\n", cUserTables);
    ok(pUserTables == NULL, "pUserTables: %p\n", pUserTables);

    status = pSpUserModeInitialize(0x20000, &Version, &pUserTables,
                                   &cUserTables);
    ok(status == STATUS_INVALID_PARAMETER, "status: 0x%x\n", status);
    ok(Version == 0xdead, "Version: 0x%x\n", Version);
    ok(cUserTables == 0xdead, "cTables: %d\n", cUserTables);
    ok(pUserTables == NULL, "pUserTables: %p\n", pUserTables);

    /* Good version to SpUserModeInitialize */
    status = pSpUserModeInitialize(SECPKG_INTERFACE_VERSION, &Version,
                                   &pUserTables, &cUserTables);
    ok(status == STATUS_SUCCESS, "status: 0x%x\n", status);
    ok(Version == SECPKG_INTERFACE_VERSION, "Version: 0x%x\n", Version);
111 112 113
    ok(cUserTables == 2 ||
       broken(cUserTables == 4), /* Win2k */
       "cUserTables: %d\n", cUserTables);
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
    ok(pUserTables != NULL, "pUserTables: %p\n", pUserTables);

    /* Initializing user again */
    status = pSpUserModeInitialize(SECPKG_INTERFACE_VERSION, &Version,
                                   &pUserTables2, &cTables);
    ok(status == STATUS_SUCCESS, "status: 0x%x\n", status);
    ok(pUserTables == pUserTables2, "pUserTables: %p, pUserTables2: %p\n",
       pUserTables, pUserTables2);
}

/* A helper function to find the dispatch table of the next package.
   Needed because SECPKG_FUNCTION_TABLE's size depend on the version */
static PSECPKG_FUNCTION_TABLE getNextSecPkgTable(PSECPKG_FUNCTION_TABLE pTable,
                                                 ULONG Version)
{
    size_t size;
130
    PSECPKG_FUNCTION_TABLE pNextTable;
131 132 133 134 135 136 137

    if (Version == SECPKG_INTERFACE_VERSION)
        size = SECPKG_FUNCTION_TABLE_SIZE_1;
    else if (Version == SECPKG_INTERFACE_VERSION_2)
        size = SECPKG_FUNCTION_TABLE_SIZE_2;
    else if (Version == SECPKG_INTERFACE_VERSION_3)
        size = SECPKG_FUNCTION_TABLE_SIZE_3;
138 139 140 141 142 143
    else if (Version == SECPKG_INTERFACE_VERSION_4)
        size = SECPKG_FUNCTION_TABLE_SIZE_4;
    else if (Version == SECPKG_INTERFACE_VERSION_5)
        size = SECPKG_FUNCTION_TABLE_SIZE_5;
    else if (Version == SECPKG_INTERFACE_VERSION_6)
        size = SECPKG_FUNCTION_TABLE_SIZE_6;
144 145 146 147 148
    else {
        ok(FALSE, "Unknown package version 0x%x\n", Version);
        return NULL;
    }

149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
    pNextTable = (PSECPKG_FUNCTION_TABLE)((PBYTE)pTable + size);
    /* Win7 function tables appear to be SECPKG_INTERFACE_VERSION_6 format,
       but unfortunately SpLsaModeInitialize returns SECPKG_INTERFACE_VERSION_3.
       We detect that by comparing the "Initialize" pointer from the old table
       to the "FreeCredentialsHandle" pointer of the new table. These functions
       have different numbers of arguments, so they can't possibly point to the
       same implementation */
    if (broken((void *) pTable->Initialize == (void *) pNextTable->FreeCredentialsHandle &&
               pNextTable->FreeCredentialsHandle != NULL))
    {
        win_skip("Invalid function pointers for next package\n");
        return NULL;
    }

    return pNextTable;
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
}

static void testGetInfo(void)
{
    PSECPKG_FUNCTION_TABLE pTables;
    SecPkgInfoW PackageInfo;
    ULONG cTables, Version;
    NTSTATUS status;

    /* Get the dispatch table */
    status = pSpLsaModeInitialize(0, &Version, &pTables, &cTables);
    ok(status == STATUS_SUCCESS, "status: 0x%x\n", status);

    /* Passing NULL into ->GetInfo causes a crash. */

    /* First package: Unified */
    status = pTables->GetInfo(&PackageInfo);
    ok(status == STATUS_SUCCESS, "status: 0x%x\n", status);
182
    ok(PackageInfo.fCapabilities == 0x107b3, "fCapabilities: 0x%x\n",
183 184 185
       PackageInfo.fCapabilities);
    ok(PackageInfo.wVersion == 1, "wVersion: %d\n", PackageInfo.wVersion);
    ok(PackageInfo.wRPCID == 14, "wRPCID: %d\n", PackageInfo.wRPCID);
186 187
    ok(PackageInfo.cbMaxToken == 0x4000 ||
       PackageInfo.cbMaxToken == 0x6000, /* Vista */
188
       "cbMaxToken: 0x%x\n",
189 190
       PackageInfo.cbMaxToken);

191 192 193 194 195 196
    /* Second package */
    if (cTables == 1)
    {
        win_skip("Second package missing\n");
        return;
    }
197 198 199 200
    pTables = getNextSecPkgTable(pTables, Version);
    if (!pTables)
        return;
    status = pTables->GetInfo(&PackageInfo);
201 202 203 204 205 206
    ok(status == STATUS_SUCCESS ||
       status == SEC_E_UNSUPPORTED_FUNCTION, /* win2k3 */
       "status: 0x%x\n", status);

    if (status == STATUS_SUCCESS)
    {
207
        ok(PackageInfo.fCapabilities == 0x107b3, "fCapabilities: 0x%x\n",
208 209 210
           PackageInfo.fCapabilities);
        ok(PackageInfo.wVersion == 1, "wVersion: %d\n", PackageInfo.wVersion);
        ok(PackageInfo.wRPCID == 14, "wRPCID: %d\n", PackageInfo.wRPCID);
211 212 213
        ok(PackageInfo.cbMaxToken == 0x4000 ||
           PackageInfo.cbMaxToken == 0x6000, /* Win7 */
           "cbMaxToken: 0x%x\n",
214 215
           PackageInfo.cbMaxToken);
    }
216 217 218 219 220 221
}

START_TEST(main)
{
    HMODULE hMod = LoadLibraryA("schannel.dll");
    if (!hMod) {
222
        win_skip("schannel.dll not available\n");
223 224 225
        return;
    }

226 227
    pSpLsaModeInitialize  = (void *)GetProcAddress(hMod, "SpLsaModeInitialize");
    pSpUserModeInitialize = (void *)GetProcAddress(hMod, "SpUserModeInitialize");
228 229 230 231 232 233

    if (pSpLsaModeInitialize && pSpUserModeInitialize)
    {
        testInitialize();
        testGetInfo();
    }
234
    else win_skip( "schannel functions not found\n" );
235 236 237

    FreeLibrary(hMod);
}