1 /* Copyright (C) 2004 Juan Lang 2 * 3 * This file implements loading of SSP DLLs. 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2.1 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this library; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 18 */ 19 20 #include "precomp.h" 21 22 #include <assert.h> 23 24 WINE_DEFAULT_DEBUG_CHANNEL(schannel); 25 26 typedef struct _SecurePackageTable 27 { 28 DWORD numPackages; 29 DWORD numAllocated; 30 struct list table; 31 } SecurePackageTable; 32 33 typedef struct _SecureProviderTable 34 { 35 DWORD numProviders; 36 DWORD numAllocated; 37 struct list table; 38 } SecureProviderTable; 39 40 /** 41 * Globals 42 */ 43 44 static CRITICAL_SECTION cs; 45 static CRITICAL_SECTION_DEBUG cs_debug = 46 { 47 0, 0, &cs, 48 { &cs_debug.ProcessLocksList, &cs_debug.ProcessLocksList }, 49 0, 0, { (DWORD_PTR)(__FILE__ ": cs") } 50 }; 51 static CRITICAL_SECTION cs = { &cs_debug, -1, 0, 0, 0, 0 }; 52 static SecurePackageTable *packageTable = NULL; 53 static SecureProviderTable *providerTable = NULL; 54 55 /*********************************************************************** 56 * EnumerateSecurityPackagesW (SECUR32.@) 57 */ 58 SECURITY_STATUS WINAPI schan_EnumerateSecurityPackagesW(PULONG pcPackages, 59 PSecPkgInfoW *ppPackageInfo) 60 { 61 SECURITY_STATUS ret = SEC_E_OK; 62 63 TRACE("(%p, %p)\n", pcPackages, ppPackageInfo); 64 65 /* windows just crashes if pcPackages or ppPackageInfo is NULL, so will I */ 66 *pcPackages = 0; 67 EnterCriticalSection(&cs); 68 if (packageTable) 69 { 70 SecurePackage *package; 71 size_t bytesNeeded; 72 73 bytesNeeded = packageTable->numPackages * sizeof(SecPkgInfoW); 74 LIST_FOR_EACH_ENTRY(package, &packageTable->table, SecurePackage, entry) 75 { 76 if (package->infoW.Name) 77 bytesNeeded += (lstrlenW(package->infoW.Name) + 1) * sizeof(WCHAR); 78 if (package->infoW.Comment) 79 bytesNeeded += (lstrlenW(package->infoW.Comment) + 1) * sizeof(WCHAR); 80 } 81 if (bytesNeeded) 82 { 83 *ppPackageInfo = HeapAlloc(GetProcessHeap(), 0, bytesNeeded); 84 if (*ppPackageInfo) 85 { 86 ULONG i = 0; 87 PWSTR nextString; 88 89 *pcPackages = packageTable->numPackages; 90 nextString = (PWSTR)((PBYTE)*ppPackageInfo + 91 packageTable->numPackages * sizeof(SecPkgInfoW)); 92 LIST_FOR_EACH_ENTRY(package, &packageTable->table, SecurePackage, entry) 93 { 94 PSecPkgInfoW pkgInfo = *ppPackageInfo + i++; 95 96 *pkgInfo = package->infoW; 97 if (package->infoW.Name) 98 { 99 TRACE("Name[%d] = %S\n", i - 1, package->infoW.Name); 100 pkgInfo->Name = nextString; 101 lstrcpyW(nextString, package->infoW.Name); 102 nextString += lstrlenW(nextString) + 1; 103 } 104 else 105 pkgInfo->Name = NULL; 106 if (package->infoW.Comment) 107 { 108 TRACE("Comment[%d] = %S\n", i - 1, package->infoW.Comment); 109 pkgInfo->Comment = nextString; 110 lstrcpyW(nextString, package->infoW.Comment); 111 nextString += lstrlenW(nextString) + 1; 112 } 113 else 114 pkgInfo->Comment = NULL; 115 } 116 } 117 else 118 ret = SEC_E_INSUFFICIENT_MEMORY; 119 } 120 } 121 LeaveCriticalSection(&cs); 122 TRACE("<-- 0x%08x\n", ret); 123 return ret; 124 } 125 126 /* Converts info (which is assumed to be an array of cPackages SecPkgInfoW 127 * structures) into an array of SecPkgInfoA structures, which it returns. 128 */ 129 static PSecPkgInfoA thunk_PSecPkgInfoWToA(ULONG cPackages, 130 const SecPkgInfoW *info) 131 { 132 PSecPkgInfoA ret; 133 134 if (info) 135 { 136 size_t bytesNeeded = cPackages * sizeof(SecPkgInfoA); 137 ULONG i; 138 139 for (i = 0; i < cPackages; i++) 140 { 141 if (info[i].Name) 142 bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info[i].Name, 143 -1, NULL, 0, NULL, NULL); 144 if (info[i].Comment) 145 bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info[i].Comment, 146 -1, NULL, 0, NULL, NULL); 147 } 148 ret = HeapAlloc(GetProcessHeap(), 0, bytesNeeded); 149 if (ret) 150 { 151 PSTR nextString; 152 153 nextString = (PSTR)((PBYTE)ret + cPackages * sizeof(SecPkgInfoA)); 154 for (i = 0; i < cPackages; i++) 155 { 156 PSecPkgInfoA pkgInfo = ret + i; 157 int bytes; 158 159 memcpy(pkgInfo, &info[i], sizeof(SecPkgInfoA)); 160 if (info[i].Name) 161 { 162 pkgInfo->Name = nextString; 163 /* just repeat back to WideCharToMultiByte how many bytes 164 * it requires, since we asked it earlier 165 */ 166 bytes = WideCharToMultiByte(CP_ACP, 0, info[i].Name, -1, 167 NULL, 0, NULL, NULL); 168 WideCharToMultiByte(CP_ACP, 0, info[i].Name, -1, 169 pkgInfo->Name, bytes, NULL, NULL); 170 nextString += lstrlenA(nextString) + 1; 171 } 172 else 173 pkgInfo->Name = NULL; 174 if (info[i].Comment) 175 { 176 pkgInfo->Comment = nextString; 177 /* just repeat back to WideCharToMultiByte how many bytes 178 * it requires, since we asked it earlier 179 */ 180 bytes = WideCharToMultiByte(CP_ACP, 0, info[i].Comment, -1, 181 NULL, 0, NULL, NULL); 182 WideCharToMultiByte(CP_ACP, 0, info[i].Comment, -1, 183 pkgInfo->Comment, bytes, NULL, NULL); 184 nextString += lstrlenA(nextString) + 1; 185 } 186 else 187 pkgInfo->Comment = NULL; 188 } 189 } 190 } 191 else 192 ret = NULL; 193 return ret; 194 } 195 196 /*********************************************************************** 197 * EnumerateSecurityPackagesA (SECUR32.@) 198 */ 199 SECURITY_STATUS WINAPI schan_EnumerateSecurityPackagesA(PULONG pcPackages, 200 PSecPkgInfoA *ppPackageInfo) 201 { 202 SECURITY_STATUS ret; 203 PSecPkgInfoW info; 204 205 ret = schan_EnumerateSecurityPackagesW(pcPackages, &info); 206 if (ret == SEC_E_OK && *pcPackages && info) 207 { 208 *ppPackageInfo = thunk_PSecPkgInfoWToA(*pcPackages, info); 209 if (*pcPackages && !*ppPackageInfo) 210 { 211 *pcPackages = 0; 212 ret = SEC_E_INSUFFICIENT_MEMORY; 213 } 214 schan_FreeContextBuffer(info); 215 } 216 return ret; 217 } 218 219 SECURITY_STATUS 220 WINAPI 221 schan_FreeContextBuffer ( 222 PVOID pvoid 223 ) 224 { 225 HeapFree(GetProcessHeap(), 0, pvoid); 226 return SEC_E_OK; 227 } 228 229 230 231 static PWSTR SECUR32_strdupW(PCWSTR str) 232 { 233 PWSTR ret; 234 235 if (str) 236 { 237 ret = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(str) + 1) * sizeof(WCHAR)); 238 if (ret) 239 lstrcpyW(ret, str); 240 } 241 else 242 ret = NULL; 243 return ret; 244 } 245 246 PWSTR SECUR32_AllocWideFromMultiByte(PCSTR str) 247 { 248 PWSTR ret; 249 250 if (str) 251 { 252 int charsNeeded = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); 253 254 if (charsNeeded) 255 { 256 ret = HeapAlloc(GetProcessHeap(), 0, charsNeeded * sizeof(WCHAR)); 257 if (ret) 258 MultiByteToWideChar(CP_ACP, 0, str, -1, ret, charsNeeded); 259 } 260 else 261 ret = NULL; 262 } 263 else 264 ret = NULL; 265 return ret; 266 } 267 268 PSTR SECUR32_AllocMultiByteFromWide(PCWSTR str) 269 { 270 PSTR ret; 271 272 if (str) 273 { 274 int charsNeeded = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0, 275 NULL, NULL); 276 277 if (charsNeeded) 278 { 279 ret = HeapAlloc(GetProcessHeap(), 0, charsNeeded); 280 if (ret) 281 WideCharToMultiByte(CP_ACP, 0, str, -1, ret, charsNeeded, 282 NULL, NULL); 283 } 284 else 285 ret = NULL; 286 } 287 else 288 ret = NULL; 289 return ret; 290 } 291 292 static void _copyPackageInfo(PSecPkgInfoW info, const SecPkgInfoA *inInfoA, 293 const SecPkgInfoW *inInfoW) 294 { 295 if (info && (inInfoA || inInfoW)) 296 { 297 /* odd, I know, but up until Name and Comment the structures are 298 * identical 299 */ 300 memcpy(info, inInfoW ? inInfoW : (const SecPkgInfoW *)inInfoA, sizeof(*info)); 301 if (inInfoW) 302 { 303 info->Name = SECUR32_strdupW(inInfoW->Name); 304 info->Comment = SECUR32_strdupW(inInfoW->Comment); 305 } 306 else 307 { 308 info->Name = SECUR32_AllocWideFromMultiByte(inInfoA->Name); 309 info->Comment = SECUR32_AllocWideFromMultiByte(inInfoA->Comment); 310 } 311 } 312 } 313 314 SecureProvider *SECUR32_addProvider(const SecurityFunctionTableA *fnTableA, 315 const SecurityFunctionTableW *fnTableW, PCWSTR moduleName) 316 { 317 SecureProvider *ret; 318 319 EnterCriticalSection(&cs); 320 321 if (!providerTable) 322 { 323 providerTable = HeapAlloc(GetProcessHeap(), 0, sizeof(SecureProviderTable)); 324 if (!providerTable) 325 { 326 LeaveCriticalSection(&cs); 327 return NULL; 328 } 329 330 list_init(&providerTable->table); 331 } 332 333 ret = HeapAlloc(GetProcessHeap(), 0, sizeof(SecureProvider)); 334 if (!ret) 335 { 336 LeaveCriticalSection(&cs); 337 return NULL; 338 } 339 340 list_add_tail(&providerTable->table, &ret->entry); 341 ret->lib = NULL; 342 343 #ifndef __REACTOS__ 344 if (fnTableA || fnTableW) 345 { 346 ret->moduleName = moduleName ? SECUR32_strdupW(moduleName) : NULL; 347 _makeFnTableA(&ret->fnTableA, fnTableA, fnTableW); 348 _makeFnTableW(&ret->fnTableW, fnTableA, fnTableW); 349 ret->loaded = !moduleName; 350 } 351 else 352 #endif 353 { 354 ret->moduleName = SECUR32_strdupW(moduleName); 355 ret->loaded = FALSE; 356 } 357 358 LeaveCriticalSection(&cs); 359 return ret; 360 } 361 362 void SECUR32_addPackages(SecureProvider *provider, ULONG toAdd, 363 const SecPkgInfoA *infoA, const SecPkgInfoW *infoW) 364 { 365 ULONG i; 366 367 assert(provider); 368 assert(infoA || infoW); 369 370 EnterCriticalSection(&cs); 371 372 if (!packageTable) 373 { 374 packageTable = HeapAlloc(GetProcessHeap(), 0, sizeof(SecurePackageTable)); 375 if (!packageTable) 376 { 377 LeaveCriticalSection(&cs); 378 return; 379 } 380 381 packageTable->numPackages = 0; 382 list_init(&packageTable->table); 383 } 384 385 for (i = 0; i < toAdd; i++) 386 { 387 SecurePackage *package = HeapAlloc(GetProcessHeap(), 0, sizeof(SecurePackage)); 388 if (!package) 389 continue; 390 391 list_add_tail(&packageTable->table, &package->entry); 392 393 package->provider = provider; 394 _copyPackageInfo(&package->infoW, 395 infoA ? &infoA[i] : NULL, 396 infoW ? &infoW[i] : NULL); 397 } 398 packageTable->numPackages += toAdd; 399 400 LeaveCriticalSection(&cs); 401 } 402