blob: 6ad2138db3f08e69a8fba3597cebb18f12a84d0c [file] [log] [blame]
Juan Lang3ed89c32004-03-02 04:57:35 +00001/* 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
Jonathan Ernst360a3f92006-05-18 14:49:52 +020017 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
Juan Lang3ed89c32004-03-02 04:57:35 +000018 */
Juan Langbc0f4482005-05-13 17:44:47 +000019#include <assert.h>
Juan Lang3ed89c32004-03-02 04:57:35 +000020#include <stdarg.h>
21#include "windef.h"
22#include "winbase.h"
23#include "winnls.h"
24#include "winreg.h"
25#include "winternl.h"
26#include "shlwapi.h"
27#include "sspi.h"
28#include "secur32_priv.h"
Mike McCormacke18965d2004-07-12 19:52:47 +000029#include "secext.h"
Hans Leidekker524251d2005-07-18 09:11:14 +000030#include "ntsecapi.h"
Juan Lang3ed89c32004-03-02 04:57:35 +000031#include "thunks.h"
32
Alexandre Julliard63a643e2005-08-30 08:55:20 +000033#include "wine/list.h"
Juan Lang3ed89c32004-03-02 04:57:35 +000034#include "wine/debug.h"
35
36WINE_DEFAULT_DEBUG_CHANNEL(secur32);
37
38/**
39 * Type definitions
40 */
41
42typedef struct _SecurePackageTable
43{
44 DWORD numPackages;
45 DWORD numAllocated;
Alexandre Julliard63a643e2005-08-30 08:55:20 +000046 struct list table;
Juan Lang3ed89c32004-03-02 04:57:35 +000047} SecurePackageTable;
48
49typedef struct _SecureProviderTable
50{
51 DWORD numProviders;
52 DWORD numAllocated;
Alexandre Julliard63a643e2005-08-30 08:55:20 +000053 struct list table;
Juan Lang3ed89c32004-03-02 04:57:35 +000054} SecureProviderTable;
55
56/**
57 * Prototypes
58 */
59
Juan Lang3ed89c32004-03-02 04:57:35 +000060/* Tries to load moduleName as a provider. If successful, enumerates what
61 * packages it can and adds them to the package and provider tables. Resizes
62 * tables as necessary.
63 */
64static void _tryLoadProvider(PWSTR moduleName);
65
66/* Initialization: read securityproviders value and attempt to open each dll
67 * there. For each DLL, call _tryLoadProvider to see if it's really an SSP.
68 * Two undocumented functions, AddSecurityPackage(A/W) and
69 * DeleteSecurityPackage(A/W), seem suspiciously like they'd register or
70 * unregister a dll, but I'm not sure.
71 */
72static void SECUR32_initializeProviders(void);
73
74/* Frees all loaded packages and providers */
75static void SECUR32_freeProviders(void);
76
77/**
78 * Globals
79 */
80
81static CRITICAL_SECTION cs;
82static SecurePackageTable *packageTable = NULL;
83static SecureProviderTable *providerTable = NULL;
84
85static SecurityFunctionTableA securityFunctionTableA = {
86 SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION_2,
87 EnumerateSecurityPackagesA,
88 QueryCredentialsAttributesA,
89 AcquireCredentialsHandleA,
90 FreeCredentialsHandle,
91 NULL, /* Reserved2 */
92 InitializeSecurityContextA,
93 AcceptSecurityContext,
94 CompleteAuthToken,
95 DeleteSecurityContext,
96 ApplyControlToken,
97 QueryContextAttributesA,
98 ImpersonateSecurityContext,
99 RevertSecurityContext,
100 MakeSignature,
101 VerifySignature,
102 FreeContextBuffer,
103 QuerySecurityPackageInfoA,
104 NULL, /* Reserved3 */
105 NULL, /* Reserved4 */
106 ExportSecurityContext,
107 ImportSecurityContextA,
108 AddCredentialsA,
109 NULL, /* Reserved8 */
110 QuerySecurityContextToken,
111 EncryptMessage,
112 DecryptMessage,
113 SetContextAttributesA
114};
115
116static SecurityFunctionTableW securityFunctionTableW = {
117 SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION_2,
118 EnumerateSecurityPackagesW,
119 QueryCredentialsAttributesW,
120 AcquireCredentialsHandleW,
121 FreeCredentialsHandle,
122 NULL, /* Reserved2 */
123 InitializeSecurityContextW,
124 AcceptSecurityContext,
125 CompleteAuthToken,
126 DeleteSecurityContext,
127 ApplyControlToken,
128 QueryContextAttributesW,
129 ImpersonateSecurityContext,
130 RevertSecurityContext,
131 MakeSignature,
132 VerifySignature,
133 FreeContextBuffer,
134 QuerySecurityPackageInfoW,
135 NULL, /* Reserved3 */
136 NULL, /* Reserved4 */
137 ExportSecurityContext,
138 ImportSecurityContextW,
139 AddCredentialsW,
140 NULL, /* Reserved8 */
141 QuerySecurityContextToken,
142 EncryptMessage,
143 DecryptMessage,
144 SetContextAttributesW
145};
146
Patrik Stridvall070db4e2004-05-17 21:08:31 +0000147/***********************************************************************
148 * InitSecurityInterfaceA (SECUR32.@)
149 */
150PSecurityFunctionTableA WINAPI InitSecurityInterfaceA(void)
Juan Lang3ed89c32004-03-02 04:57:35 +0000151{
152 return &securityFunctionTableA;
153}
154
Patrik Stridvall070db4e2004-05-17 21:08:31 +0000155/***********************************************************************
156 * InitSecurityInterfaceW (SECUR32.@)
157 */
158PSecurityFunctionTableW WINAPI InitSecurityInterfaceW(void)
Juan Lang3ed89c32004-03-02 04:57:35 +0000159{
160 return &securityFunctionTableW;
161}
162
Juan Lang3ed89c32004-03-02 04:57:35 +0000163PWSTR SECUR32_strdupW(PCWSTR str)
164{
165 PWSTR ret;
166
167 if (str)
168 {
169 ret = (PWSTR)SECUR32_ALLOC((lstrlenW(str) + 1) * sizeof(WCHAR));
170 if (ret)
171 lstrcpyW(ret, str);
172 }
173 else
174 ret = NULL;
175 return ret;
176}
177
178PWSTR SECUR32_AllocWideFromMultiByte(PCSTR str)
179{
180 PWSTR ret;
181
182 if (str)
183 {
184 int charsNeeded = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
185
186 if (charsNeeded)
187 {
188 ret = (PWSTR)SECUR32_ALLOC(charsNeeded * sizeof(WCHAR));
189 if (ret)
190 MultiByteToWideChar(CP_ACP, 0, str, -1, ret, charsNeeded);
191 }
192 else
193 ret = NULL;
194 }
195 else
196 ret = NULL;
197 return ret;
198}
199
200PSTR SECUR32_AllocMultiByteFromWide(PCWSTR str)
201{
202 PSTR ret;
203
204 if (str)
205 {
206 int charsNeeded = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0,
207 NULL, NULL);
208
209 if (charsNeeded)
210 {
211 ret = (PSTR)SECUR32_ALLOC(charsNeeded);
212 if (ret)
213 WideCharToMultiByte(CP_ACP, 0, str, -1, ret, charsNeeded,
214 NULL, NULL);
215 }
216 else
217 ret = NULL;
218 }
219 else
220 ret = NULL;
221 return ret;
222}
223
224static void _makeFnTableA(PSecurityFunctionTableA fnTableA,
Dmitry Timoshkov57a579f2006-01-24 14:00:32 +0100225 const SecurityFunctionTableA *inFnTableA,
226 const SecurityFunctionTableW *inFnTableW)
Juan Lang3ed89c32004-03-02 04:57:35 +0000227{
228 if (fnTableA)
229 {
230 if (inFnTableA)
231 {
232 /* The size of the version 1 table is based on platform sdk's
233 * sspi.h, though the sample ssp also provided with platform sdk
234 * implies only functions through QuerySecurityPackageInfoA are
235 * implemented (yikes)
236 */
237 size_t tableSize = inFnTableA->dwVersion == 1 ?
238 (LPBYTE)&inFnTableA->SetContextAttributesA -
239 (LPBYTE)inFnTableA : sizeof(SecurityFunctionTableA);
240
241 memcpy(fnTableA, inFnTableA, tableSize);
242 /* override this, since we can do it internally anyway */
243 fnTableA->QuerySecurityPackageInfoA =
244 QuerySecurityPackageInfoA;
245 }
246 else if (inFnTableW)
247 {
248 /* functions with thunks */
249 if (inFnTableW->AcquireCredentialsHandleW)
250 fnTableA->AcquireCredentialsHandleA =
251 thunk_AcquireCredentialsHandleA;
252 if (inFnTableW->InitializeSecurityContextW)
253 fnTableA->InitializeSecurityContextA =
254 thunk_InitializeSecurityContextA;
255 if (inFnTableW->ImportSecurityContextW)
256 fnTableA->ImportSecurityContextA =
257 thunk_ImportSecurityContextA;
258 if (inFnTableW->AddCredentialsW)
259 fnTableA->AddCredentialsA =
260 thunk_AddCredentialsA;
261 if (inFnTableW->QueryCredentialsAttributesW)
262 fnTableA->QueryCredentialsAttributesA =
263 thunk_QueryCredentialsAttributesA;
264 if (inFnTableW->QueryContextAttributesW)
265 fnTableA->QueryContextAttributesA =
266 thunk_QueryContextAttributesA;
267 if (inFnTableW->SetContextAttributesW)
268 fnTableA->SetContextAttributesA =
269 thunk_SetContextAttributesA;
270 /* this can't be thunked, there's no extra param to know which
271 * package to forward to */
272 fnTableA->EnumerateSecurityPackagesA = NULL;
273 /* functions with no thunks needed */
274 fnTableA->AcceptSecurityContext = inFnTableW->AcceptSecurityContext;
275 fnTableA->CompleteAuthToken = inFnTableW->CompleteAuthToken;
276 fnTableA->DeleteSecurityContext = inFnTableW->DeleteSecurityContext;
277 fnTableA->ImpersonateSecurityContext =
278 inFnTableW->ImpersonateSecurityContext;
279 fnTableA->RevertSecurityContext = inFnTableW->RevertSecurityContext;
280 fnTableA->MakeSignature = inFnTableW->MakeSignature;
281 fnTableA->VerifySignature = inFnTableW->VerifySignature;
282 fnTableA->FreeContextBuffer = inFnTableW->FreeContextBuffer;
283 fnTableA->QuerySecurityPackageInfoA =
284 QuerySecurityPackageInfoA;
285 fnTableA->ExportSecurityContext =
286 inFnTableW->ExportSecurityContext;
287 fnTableA->QuerySecurityContextToken =
288 inFnTableW->QuerySecurityContextToken;
289 fnTableA->EncryptMessage = inFnTableW->EncryptMessage;
290 fnTableA->DecryptMessage = inFnTableW->DecryptMessage;
291 }
292 }
293}
294
295static void _makeFnTableW(PSecurityFunctionTableW fnTableW,
Dmitry Timoshkov57a579f2006-01-24 14:00:32 +0100296 const SecurityFunctionTableA *inFnTableA,
297 const SecurityFunctionTableW *inFnTableW)
Juan Lang3ed89c32004-03-02 04:57:35 +0000298{
299 if (fnTableW)
300 {
301 if (inFnTableW)
302 {
303 /* The size of the version 1 table is based on platform sdk's
304 * sspi.h, though the sample ssp also provided with platform sdk
305 * implies only functions through QuerySecurityPackageInfoA are
306 * implemented (yikes)
307 */
308 size_t tableSize = inFnTableW->dwVersion == 1 ?
309 (LPBYTE)&inFnTableW->SetContextAttributesW -
310 (LPBYTE)inFnTableW : sizeof(SecurityFunctionTableW);
311
312 memcpy(fnTableW, inFnTableW, tableSize);
313 /* override this, since we can do it internally anyway */
314 fnTableW->QuerySecurityPackageInfoW =
315 QuerySecurityPackageInfoW;
316 }
317 else if (inFnTableA)
318 {
319 /* functions with thunks */
320 if (inFnTableA->AcquireCredentialsHandleA)
321 fnTableW->AcquireCredentialsHandleW =
322 thunk_AcquireCredentialsHandleW;
323 if (inFnTableA->InitializeSecurityContextA)
324 fnTableW->InitializeSecurityContextW =
325 thunk_InitializeSecurityContextW;
326 if (inFnTableA->ImportSecurityContextA)
327 fnTableW->ImportSecurityContextW =
328 thunk_ImportSecurityContextW;
329 if (inFnTableA->AddCredentialsA)
330 fnTableW->AddCredentialsW =
331 thunk_AddCredentialsW;
332 if (inFnTableA->QueryCredentialsAttributesA)
333 fnTableW->QueryCredentialsAttributesW =
334 thunk_QueryCredentialsAttributesW;
335 if (inFnTableA->QueryContextAttributesA)
336 fnTableW->QueryContextAttributesW =
337 thunk_QueryContextAttributesW;
338 if (inFnTableA->SetContextAttributesA)
339 fnTableW->SetContextAttributesW =
340 thunk_SetContextAttributesW;
341 /* this can't be thunked, there's no extra param to know which
342 * package to forward to */
343 fnTableW->EnumerateSecurityPackagesW = NULL;
344 /* functions with no thunks needed */
345 fnTableW->AcceptSecurityContext = inFnTableA->AcceptSecurityContext;
346 fnTableW->CompleteAuthToken = inFnTableA->CompleteAuthToken;
347 fnTableW->DeleteSecurityContext = inFnTableA->DeleteSecurityContext;
348 fnTableW->ImpersonateSecurityContext =
349 inFnTableA->ImpersonateSecurityContext;
350 fnTableW->RevertSecurityContext = inFnTableA->RevertSecurityContext;
351 fnTableW->MakeSignature = inFnTableA->MakeSignature;
352 fnTableW->VerifySignature = inFnTableA->VerifySignature;
353 fnTableW->FreeContextBuffer = inFnTableA->FreeContextBuffer;
354 fnTableW->QuerySecurityPackageInfoW =
355 QuerySecurityPackageInfoW;
356 fnTableW->ExportSecurityContext =
357 inFnTableA->ExportSecurityContext;
358 fnTableW->QuerySecurityContextToken =
359 inFnTableA->QuerySecurityContextToken;
360 fnTableW->EncryptMessage = inFnTableA->EncryptMessage;
361 fnTableW->DecryptMessage = inFnTableA->DecryptMessage;
362 }
363 }
364}
365
Juan Langbc0f4482005-05-13 17:44:47 +0000366static void _copyPackageInfo(PSecPkgInfoW info, const SecPkgInfoA *inInfoA,
367 const SecPkgInfoW *inInfoW)
Juan Lang3ed89c32004-03-02 04:57:35 +0000368{
369 if (info && (inInfoA || inInfoW))
370 {
371 /* odd, I know, but up until Name and Comment the structures are
372 * identical
373 */
374 memcpy(info, inInfoW ? inInfoW : (PSecPkgInfoW)inInfoA, sizeof(*info));
375 if (inInfoW)
376 {
377 info->Name = SECUR32_strdupW(inInfoW->Name);
378 info->Comment = SECUR32_strdupW(inInfoW->Comment);
379 }
380 else
381 {
382 info->Name = SECUR32_AllocWideFromMultiByte(inInfoA->Name);
383 info->Comment = SECUR32_AllocWideFromMultiByte(inInfoA->Comment);
384 }
385 }
386}
387
Dmitry Timoshkov57a579f2006-01-24 14:00:32 +0100388SecureProvider *SECUR32_addProvider(const SecurityFunctionTableA *fnTableA,
389 const SecurityFunctionTableW *fnTableW, const PWSTR moduleName)
Juan Langbc0f4482005-05-13 17:44:47 +0000390{
391 SecureProvider *ret;
392
393 EnterCriticalSection(&cs);
Alexandre Julliard63a643e2005-08-30 08:55:20 +0000394
395 if (!providerTable)
Juan Langbc0f4482005-05-13 17:44:47 +0000396 {
Alexandre Julliard63a643e2005-08-30 08:55:20 +0000397 providerTable = HeapAlloc(GetProcessHeap(), 0, sizeof(SecureProviderTable));
398 if (!providerTable)
Michael Stefaniuc968ad512006-05-01 15:56:53 +0200399 {
400 LeaveCriticalSection(&cs);
Alexandre Julliard63a643e2005-08-30 08:55:20 +0000401 return NULL;
Michael Stefaniuc968ad512006-05-01 15:56:53 +0200402 }
Alexandre Julliard63a643e2005-08-30 08:55:20 +0000403
404 list_init(&providerTable->table);
405 }
406
407 ret = HeapAlloc(GetProcessHeap(), 0, sizeof(SecureProvider));
408 if (!ret)
Michael Stefaniuc968ad512006-05-01 15:56:53 +0200409 {
410 LeaveCriticalSection(&cs);
Alexandre Julliard63a643e2005-08-30 08:55:20 +0000411 return NULL;
Michael Stefaniuc968ad512006-05-01 15:56:53 +0200412 }
Alexandre Julliard63a643e2005-08-30 08:55:20 +0000413
414 list_add_tail(&providerTable->table, &ret->entry);
415 ret->lib = NULL;
416
417 if (fnTableA || fnTableW)
418 {
419 ret->moduleName = NULL;
420 _makeFnTableA(&ret->fnTableA, fnTableA, fnTableW);
421 _makeFnTableW(&ret->fnTableW, fnTableA, fnTableW);
422 ret->loaded = TRUE;
Juan Langbc0f4482005-05-13 17:44:47 +0000423 }
424 else
Alexandre Julliard63a643e2005-08-30 08:55:20 +0000425 {
426 ret->moduleName = SECUR32_strdupW(moduleName);
427 ret->loaded = FALSE;
428 }
429
Juan Langbc0f4482005-05-13 17:44:47 +0000430 LeaveCriticalSection(&cs);
431 return ret;
432}
433
434void SECUR32_addPackages(SecureProvider *provider, ULONG toAdd,
435 const SecPkgInfoA *infoA, const SecPkgInfoW *infoW)
436{
Alexandre Julliard63a643e2005-08-30 08:55:20 +0000437 ULONG i;
438
Juan Langbc0f4482005-05-13 17:44:47 +0000439 assert(provider);
440 assert(infoA || infoW);
441
442 EnterCriticalSection(&cs);
Alexandre Julliard63a643e2005-08-30 08:55:20 +0000443
444 if (!packageTable)
Juan Langbc0f4482005-05-13 17:44:47 +0000445 {
Alexandre Julliard63a643e2005-08-30 08:55:20 +0000446 packageTable = HeapAlloc(GetProcessHeap(), 0, sizeof(SecurePackageTable));
447 if (!packageTable)
Michael Stefaniuc968ad512006-05-01 15:56:53 +0200448 {
449 LeaveCriticalSection(&cs);
Alexandre Julliard63a643e2005-08-30 08:55:20 +0000450 return;
Michael Stefaniuc968ad512006-05-01 15:56:53 +0200451 }
Juan Langbc0f4482005-05-13 17:44:47 +0000452
Alexandre Julliard63a643e2005-08-30 08:55:20 +0000453 packageTable->numPackages = 0;
454 list_init(&packageTable->table);
Juan Langbc0f4482005-05-13 17:44:47 +0000455 }
Alexandre Julliard63a643e2005-08-30 08:55:20 +0000456
457 for (i = 0; i < toAdd; i++)
458 {
459 SecurePackage *package = HeapAlloc(GetProcessHeap(), 0, sizeof(SecurePackage));
460 if (!package)
461 continue;
462
463 list_add_tail(&packageTable->table, &package->entry);
464
465 package->provider = provider;
466 _copyPackageInfo(&package->infoW,
467 infoA ? &infoA[i] : NULL,
468 infoW ? &infoW[i] : NULL);
469 }
470 packageTable->numPackages += toAdd;
471
Juan Langbc0f4482005-05-13 17:44:47 +0000472 LeaveCriticalSection(&cs);
473}
474
Juan Lang3ed89c32004-03-02 04:57:35 +0000475static void _tryLoadProvider(PWSTR moduleName)
476{
477 HMODULE lib = LoadLibraryW(moduleName);
478
479 if (lib)
480 {
481 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW =
482 (INIT_SECURITY_INTERFACE_W)GetProcAddress(lib,
483 SECURITY_ENTRYPOINT_ANSIW);
484 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA =
485 (INIT_SECURITY_INTERFACE_A)GetProcAddress(lib,
486 SECURITY_ENTRYPOINT_ANSIA);
487
488 TRACE("loaded %s, InitSecurityInterfaceA is %p, InitSecurityInterfaceW is %p\n",
489 debugstr_w(moduleName), pInitSecurityInterfaceA,
490 pInitSecurityInterfaceW);
491 if (pInitSecurityInterfaceW || pInitSecurityInterfaceA)
492 {
493 PSecurityFunctionTableA fnTableA = NULL;
494 PSecurityFunctionTableW fnTableW = NULL;
495 ULONG toAdd = 0;
496 PSecPkgInfoA infoA = NULL;
497 PSecPkgInfoW infoW = NULL;
498 SECURITY_STATUS ret = SEC_E_OK;
499
500 if (pInitSecurityInterfaceA)
501 fnTableA = pInitSecurityInterfaceA();
502 if (pInitSecurityInterfaceW)
503 fnTableW = pInitSecurityInterfaceW();
504 if (fnTableW && fnTableW->EnumerateSecurityPackagesW)
505 ret = fnTableW->EnumerateSecurityPackagesW(&toAdd, &infoW);
506 else if (fnTableA && fnTableA->EnumerateSecurityPackagesA)
507 ret = fnTableA->EnumerateSecurityPackagesA(&toAdd, &infoA);
508 if (ret == SEC_E_OK && toAdd > 0 && (infoW || infoA))
509 {
Juan Langbc0f4482005-05-13 17:44:47 +0000510 SecureProvider *provider = SECUR32_addProvider(NULL, NULL,
511 moduleName);
Juan Lang3ed89c32004-03-02 04:57:35 +0000512
Juan Langbc0f4482005-05-13 17:44:47 +0000513 if (provider)
514 SECUR32_addPackages(provider, toAdd, infoA, infoW);
Juan Lang3ed89c32004-03-02 04:57:35 +0000515 if (infoW)
516 fnTableW->FreeContextBuffer(infoW);
517 else
518 fnTableA->FreeContextBuffer(infoA);
519 }
520 }
521 FreeLibrary(lib);
522 }
523 else
524 WARN("failed to load %s\n", debugstr_w(moduleName));
525}
526
Francois Gougetebf0eb32004-04-20 00:34:52 +0000527static const WCHAR securityProvidersKeyW[] = {
Juan Lang3ed89c32004-03-02 04:57:35 +0000528 'S','Y','S','T','E','M','\\','C','u','r','r','e','n','t','C','o','n','t','r',
529 'o','l','S','e','t','\\','C','o','n','t','r','o','l','\\','S','e','c','u','r',
530 'i','t','y','P','r','o','v','i','d','e','r','s','\0'
531 };
532static const WCHAR securityProvidersW[] = {
533 'S','e','c','u','r','i','t','y','P','r','o','v','i','d','e','r','s',0
534 };
535
536static void SECUR32_initializeProviders(void)
537{
538 HKEY key;
539 long apiRet;
540
541 TRACE("\n");
542 InitializeCriticalSection(&cs);
Juan Langbc0f4482005-05-13 17:44:47 +0000543 /* First load built-in providers */
544 SECUR32_initSchannelSP();
Kai Blinece9de52005-08-15 20:52:18 +0000545 SECUR32_initNegotiateSP();
Kai Blin4fd3f402005-08-17 09:52:30 +0000546 SECUR32_initNTLMSP();
Juan Langbc0f4482005-05-13 17:44:47 +0000547 /* Now load providers from registry */
Juan Lang3ed89c32004-03-02 04:57:35 +0000548 apiRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, securityProvidersKeyW, 0,
549 KEY_READ, &key);
550 if (apiRet == ERROR_SUCCESS)
551 {
552 WCHAR securityPkgNames[MAX_PATH]; /* arbitrary len */
553 DWORD size = sizeof(securityPkgNames) / sizeof(WCHAR), type;
554
555 apiRet = RegQueryValueExW(key, securityProvidersW, NULL, &type,
556 (PBYTE)securityPkgNames, &size);
557 if (apiRet == ERROR_SUCCESS && type == REG_SZ)
558 {
559 WCHAR *ptr;
560
561 for (ptr = securityPkgNames;
562 ptr < (PWSTR)((PBYTE)securityPkgNames + size); )
563 {
564 WCHAR *comma;
565
566 for (comma = ptr; *comma && *comma != ','; comma++)
567 ;
568 if (*comma == ',')
569 *comma = '\0';
570 for (; *ptr && isspace(*ptr) && ptr < securityPkgNames + size;
571 ptr++)
572 ;
573 if (*ptr)
574 _tryLoadProvider(ptr);
575 ptr += lstrlenW(ptr) + 1;
576 }
577 }
578 RegCloseKey(key);
579 }
580}
581
582SecurePackage *SECUR32_findPackageW(PWSTR packageName)
583{
Juan Langbc0f4482005-05-13 17:44:47 +0000584 SecurePackage *ret = NULL;
Stefan Huehnere1364b02005-11-07 16:39:00 +0000585 BOOL matched = FALSE;
Juan Lang3ed89c32004-03-02 04:57:35 +0000586
587 if (packageTable && packageName)
588 {
Alexandre Julliard63a643e2005-08-30 08:55:20 +0000589 LIST_FOR_EACH_ENTRY(ret, &packageTable->table, SecurePackage, entry)
590 {
Stefan Huehnere1364b02005-11-07 16:39:00 +0000591 matched = !lstrcmpiW(ret->infoW.Name, packageName);
592 if (matched)
593 break;
Alexandre Julliard63a643e2005-08-30 08:55:20 +0000594 }
595
Stefan Huehnere1364b02005-11-07 16:39:00 +0000596 if (!matched)
597 return NULL;
598
599 if (ret->provider && !ret->provider->loaded)
Juan Lang3ed89c32004-03-02 04:57:35 +0000600 {
601 ret->provider->lib = LoadLibraryW(ret->provider->moduleName);
602 if (ret->provider->lib)
603 {
604 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW =
605 (INIT_SECURITY_INTERFACE_W)GetProcAddress(ret->provider->lib,
606 SECURITY_ENTRYPOINT_ANSIW);
607 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA =
608 (INIT_SECURITY_INTERFACE_A)GetProcAddress(ret->provider->lib,
609 SECURITY_ENTRYPOINT_ANSIA);
610 PSecurityFunctionTableA fnTableA = NULL;
611 PSecurityFunctionTableW fnTableW = NULL;
612
613 if (pInitSecurityInterfaceA)
614 fnTableA = pInitSecurityInterfaceA();
615 if (pInitSecurityInterfaceW)
616 fnTableW = pInitSecurityInterfaceW();
617 _makeFnTableA(&ret->provider->fnTableA, fnTableA, fnTableW);
618 _makeFnTableW(&ret->provider->fnTableW, fnTableA, fnTableW);
Juan Langbc0f4482005-05-13 17:44:47 +0000619 ret->provider->loaded = TRUE;
Juan Lang3ed89c32004-03-02 04:57:35 +0000620 }
621 else
622 ret = NULL;
623 }
624 }
Juan Lang3ed89c32004-03-02 04:57:35 +0000625 return ret;
626}
627
628SecurePackage *SECUR32_findPackageA(PSTR packageName)
629{
630 SecurePackage *ret;
631
632 if (packageTable && packageName)
633 {
634 UNICODE_STRING package;
635
636 RtlCreateUnicodeStringFromAsciiz(&package, packageName);
637 ret = SECUR32_findPackageW(package.Buffer);
638 RtlFreeUnicodeString(&package);
639 }
640 else
641 ret = NULL;
642 return ret;
643}
644
645static void SECUR32_freeProviders(void)
646{
Alexandre Julliard63a643e2005-08-30 08:55:20 +0000647 SecurePackage *package;
648 SecureProvider *provider;
Juan Lang3ed89c32004-03-02 04:57:35 +0000649
650 TRACE("\n");
651 EnterCriticalSection(&cs);
Alexandre Julliard63a643e2005-08-30 08:55:20 +0000652
Juan Lang3ed89c32004-03-02 04:57:35 +0000653 if (packageTable)
654 {
Alexandre Julliard63a643e2005-08-30 08:55:20 +0000655 LIST_FOR_EACH_ENTRY(package, &packageTable->table, SecurePackage, entry)
Juan Lang3ed89c32004-03-02 04:57:35 +0000656 {
Alexandre Julliard63a643e2005-08-30 08:55:20 +0000657 SECUR32_FREE(package->infoW.Name);
658 SECUR32_FREE(package->infoW.Comment);
Juan Lang3ed89c32004-03-02 04:57:35 +0000659 }
Alexandre Julliard63a643e2005-08-30 08:55:20 +0000660
Juan Lang3ed89c32004-03-02 04:57:35 +0000661 HeapFree(GetProcessHeap(), 0, packageTable);
662 packageTable = NULL;
663 }
Alexandre Julliard63a643e2005-08-30 08:55:20 +0000664
Juan Lang3ed89c32004-03-02 04:57:35 +0000665 if (providerTable)
666 {
Alexandre Julliard63a643e2005-08-30 08:55:20 +0000667 LIST_FOR_EACH_ENTRY(provider, &providerTable->table, SecureProvider, entry)
Juan Lang3ed89c32004-03-02 04:57:35 +0000668 {
Michael Stefaniuca8752002006-05-10 00:33:53 +0200669 SECUR32_FREE(provider->moduleName);
Alexandre Julliard63a643e2005-08-30 08:55:20 +0000670 if (provider->lib)
671 FreeLibrary(provider->lib);
Juan Lang3ed89c32004-03-02 04:57:35 +0000672 }
Alexandre Julliard63a643e2005-08-30 08:55:20 +0000673
Juan Lang3ed89c32004-03-02 04:57:35 +0000674 HeapFree(GetProcessHeap(), 0, providerTable);
675 providerTable = NULL;
676 }
Alexandre Julliard63a643e2005-08-30 08:55:20 +0000677
Juan Lang3ed89c32004-03-02 04:57:35 +0000678 LeaveCriticalSection(&cs);
679 DeleteCriticalSection(&cs);
680}
681
Patrik Stridvall070db4e2004-05-17 21:08:31 +0000682/***********************************************************************
683 * FreeContextBuffer (SECUR32.@)
684 *
685 * Doh--if pv was allocated by a crypto package, this may not be correct.
Juan Lang3ed89c32004-03-02 04:57:35 +0000686 * The sample ssp seems to use LocalAlloc/LocalFee, but there doesn't seem to
687 * be any guarantee, nor is there an alloc function in secur32.
688 */
Patrik Stridvall070db4e2004-05-17 21:08:31 +0000689SECURITY_STATUS WINAPI FreeContextBuffer(PVOID pv)
Juan Lang3ed89c32004-03-02 04:57:35 +0000690{
Michael Stefaniuca8752002006-05-10 00:33:53 +0200691 SECUR32_FREE(pv);
Juan Lang3ed89c32004-03-02 04:57:35 +0000692
Dmitry Timoshkovd89a0382006-04-27 20:52:58 +0900693 return SEC_E_OK;
Juan Lang3ed89c32004-03-02 04:57:35 +0000694}
695
Patrik Stridvall070db4e2004-05-17 21:08:31 +0000696/***********************************************************************
697 * EnumerateSecurityPackagesW (SECUR32.@)
698 */
699SECURITY_STATUS WINAPI EnumerateSecurityPackagesW(PULONG pcPackages,
Juan Lang3ed89c32004-03-02 04:57:35 +0000700 PSecPkgInfoW *ppPackageInfo)
701{
702 SECURITY_STATUS ret = SEC_E_OK;
703
Robert Shearman81d9e102006-02-10 14:51:59 +0100704 TRACE("(%p, %p)\n", pcPackages, ppPackageInfo);
705
Juan Lang3ed89c32004-03-02 04:57:35 +0000706 /* windows just crashes if pcPackages or ppPackageInfo is NULL, so will I */
707 *pcPackages = 0;
708 EnterCriticalSection(&cs);
709 if (packageTable)
710 {
Alexandre Julliard63a643e2005-08-30 08:55:20 +0000711 SecurePackage *package;
Juan Lang3ed89c32004-03-02 04:57:35 +0000712 size_t bytesNeeded;
713
714 bytesNeeded = packageTable->numPackages * sizeof(SecPkgInfoW);
Alexandre Julliard63a643e2005-08-30 08:55:20 +0000715 LIST_FOR_EACH_ENTRY(package, &packageTable->table, SecurePackage, entry)
Juan Lang3ed89c32004-03-02 04:57:35 +0000716 {
Alexandre Julliard63a643e2005-08-30 08:55:20 +0000717 if (package->infoW.Name)
718 bytesNeeded += (lstrlenW(package->infoW.Name) + 1) * sizeof(WCHAR);
719 if (package->infoW.Comment)
720 bytesNeeded += (lstrlenW(package->infoW.Comment) + 1) * sizeof(WCHAR);
Juan Lang3ed89c32004-03-02 04:57:35 +0000721 }
722 if (bytesNeeded)
723 {
724 *ppPackageInfo = (PSecPkgInfoW)SECUR32_ALLOC(bytesNeeded);
725 if (*ppPackageInfo)
726 {
Alexandre Julliard63a643e2005-08-30 08:55:20 +0000727 ULONG i = 0;
Juan Lang3ed89c32004-03-02 04:57:35 +0000728 PWSTR nextString;
729
730 *pcPackages = packageTable->numPackages;
731 nextString = (PWSTR)((PBYTE)*ppPackageInfo +
732 packageTable->numPackages * sizeof(SecPkgInfoW));
Alexandre Julliard63a643e2005-08-30 08:55:20 +0000733 LIST_FOR_EACH_ENTRY(package, &packageTable->table, SecurePackage, entry)
Juan Lang3ed89c32004-03-02 04:57:35 +0000734 {
Alexandre Julliard63a643e2005-08-30 08:55:20 +0000735 PSecPkgInfoW pkgInfo = *ppPackageInfo + i++;
Juan Lang3ed89c32004-03-02 04:57:35 +0000736
Alexandre Julliard63a643e2005-08-30 08:55:20 +0000737 memcpy(pkgInfo, &package->infoW, sizeof(SecPkgInfoW));
738 if (package->infoW.Name)
Juan Lang3ed89c32004-03-02 04:57:35 +0000739 {
Robert Shearman81d9e102006-02-10 14:51:59 +0100740 TRACE("Name[%ld] = %s\n", i - 1, debugstr_w(package->infoW.Name));
Juan Lang3ed89c32004-03-02 04:57:35 +0000741 pkgInfo->Name = nextString;
Alexandre Julliard63a643e2005-08-30 08:55:20 +0000742 lstrcpyW(nextString, package->infoW.Name);
Juan Lang3ed89c32004-03-02 04:57:35 +0000743 nextString += lstrlenW(nextString) + 1;
744 }
745 else
746 pkgInfo->Name = NULL;
Alexandre Julliard63a643e2005-08-30 08:55:20 +0000747 if (package->infoW.Comment)
Juan Lang3ed89c32004-03-02 04:57:35 +0000748 {
Robert Shearman81d9e102006-02-10 14:51:59 +0100749 TRACE("Comment[%ld] = %s\n", i - 1, debugstr_w(package->infoW.Comment));
Juan Lang3ed89c32004-03-02 04:57:35 +0000750 pkgInfo->Comment = nextString;
Alexandre Julliard63a643e2005-08-30 08:55:20 +0000751 lstrcpyW(nextString, package->infoW.Comment);
Juan Lang3ed89c32004-03-02 04:57:35 +0000752 nextString += lstrlenW(nextString) + 1;
753 }
754 else
755 pkgInfo->Comment = NULL;
756 }
757 }
758 else
759 ret = SEC_E_INSUFFICIENT_MEMORY;
760 }
761 }
762 LeaveCriticalSection(&cs);
Robert Shearman81d9e102006-02-10 14:51:59 +0100763 TRACE("<-- 0x%08lx\n", ret);
Juan Lang3ed89c32004-03-02 04:57:35 +0000764 return ret;
765}
766
767/* Converts info (which is assumed to be an array of cPackages SecPkgInfoW
768 * structures) into an array of SecPkgInfoA structures, which it returns.
769 */
770static PSecPkgInfoA thunk_PSecPkgInfoWToA(ULONG cPackages,
771 const PSecPkgInfoW info)
772{
773 PSecPkgInfoA ret;
774
775 if (info)
776 {
777 size_t bytesNeeded = cPackages * sizeof(SecPkgInfoA);
778 ULONG i;
779
780 for (i = 0; i < cPackages; i++)
781 {
782 if (info[i].Name)
783 bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info[i].Name,
784 -1, NULL, 0, NULL, NULL);
785 if (info[i].Comment)
786 bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info[i].Comment,
787 -1, NULL, 0, NULL, NULL);
788 }
789 ret = (PSecPkgInfoA)SECUR32_ALLOC(bytesNeeded);
790 if (ret)
791 {
792 PSTR nextString;
793
794 nextString = (PSTR)((PBYTE)ret + cPackages * sizeof(SecPkgInfoA));
795 for (i = 0; i < cPackages; i++)
796 {
797 PSecPkgInfoA pkgInfo = ret + i;
798 int bytes;
799
800 memcpy(pkgInfo, &info[i], sizeof(SecPkgInfoA));
801 if (info[i].Name)
802 {
803 pkgInfo->Name = nextString;
804 /* just repeat back to WideCharToMultiByte how many bytes
805 * it requires, since we asked it earlier
806 */
807 bytes = WideCharToMultiByte(CP_ACP, 0, info[i].Name, -1,
808 NULL, 0, NULL, NULL);
809 WideCharToMultiByte(CP_ACP, 0, info[i].Name, -1,
810 pkgInfo->Name, bytes, NULL, NULL);
811 nextString += lstrlenA(nextString) + 1;
812 }
813 else
814 pkgInfo->Name = NULL;
815 if (info[i].Comment)
816 {
817 pkgInfo->Comment = nextString;
818 /* just repeat back to WideCharToMultiByte how many bytes
819 * it requires, since we asked it earlier
820 */
821 bytes = WideCharToMultiByte(CP_ACP, 0, info[i].Comment, -1,
822 NULL, 0, NULL, NULL);
823 WideCharToMultiByte(CP_ACP, 0, info[i].Comment, -1,
824 pkgInfo->Comment, bytes, NULL, NULL);
825 nextString += lstrlenA(nextString) + 1;
826 }
827 else
828 pkgInfo->Comment = NULL;
829 }
830 }
831 }
832 else
833 ret = NULL;
834 return ret;
835}
836
Patrik Stridvall070db4e2004-05-17 21:08:31 +0000837/***********************************************************************
838 * EnumerateSecurityPackagesA (SECUR32.@)
839 */
840SECURITY_STATUS WINAPI EnumerateSecurityPackagesA(PULONG pcPackages,
Juan Lang3ed89c32004-03-02 04:57:35 +0000841 PSecPkgInfoA *ppPackageInfo)
842{
843 SECURITY_STATUS ret;
844 PSecPkgInfoW info;
845
846 ret = EnumerateSecurityPackagesW(pcPackages, &info);
847 if (ret == SEC_E_OK && *pcPackages && info)
848 {
849 *ppPackageInfo = thunk_PSecPkgInfoWToA(*pcPackages, info);
850 if (*pcPackages && !*ppPackageInfo)
851 {
852 *pcPackages = 0;
853 ret = SEC_E_INSUFFICIENT_MEMORY;
854 }
855 FreeContextBuffer(info);
856 }
857 return ret;
858}
859
Patrik Stridvall070db4e2004-05-17 21:08:31 +0000860/***********************************************************************
Mike McCormacke18965d2004-07-12 19:52:47 +0000861 * GetComputerObjectNameA (SECUR32.@)
862 */
863BOOLEAN WINAPI GetComputerObjectNameA(
864 EXTENDED_NAME_FORMAT NameFormat, LPSTR lpNameBuffer, PULONG nSize)
865{
866 FIXME("%d %p %p\n", NameFormat, lpNameBuffer, nSize);
867 return FALSE;
868}
869
870/***********************************************************************
871 * GetComputerObjectNameW (SECUR32.@)
872 */
873BOOLEAN WINAPI GetComputerObjectNameW(
874 EXTENDED_NAME_FORMAT NameFormat, LPWSTR lpNameBuffer, PULONG nSize)
875{
876 FIXME("%d %p %p\n", NameFormat, lpNameBuffer, nSize);
877 return FALSE;
878}
879
Hans Leidekker524251d2005-07-18 09:11:14 +0000880BOOLEAN WINAPI GetUserNameExA(
881 EXTENDED_NAME_FORMAT NameFormat, LPSTR lpNameBuffer, PULONG nSize)
882{
883 FIXME("%d %p %p\n", NameFormat, lpNameBuffer, nSize);
884 return FALSE;
885}
886
887BOOLEAN WINAPI GetUserNameExW(
888 EXTENDED_NAME_FORMAT NameFormat, LPWSTR lpNameBuffer, PULONG nSize)
889{
890 FIXME("%d %p %p\n", NameFormat, lpNameBuffer, nSize);
891 return FALSE;
892}
893
894NTSTATUS WINAPI LsaCallAuthenticationPackage(
895 HANDLE LsaHandle, ULONG AuthenticationPackage, PVOID ProtocolSubmitBuffer,
896 ULONG SubmitBufferLength, PVOID* ProtocolReturnBuffer, PULONG ReturnBufferLength,
Francois Gouget6fb12fc2005-08-16 16:01:49 +0000897 PNTSTATUS ProtocolStatus)
Hans Leidekker524251d2005-07-18 09:11:14 +0000898{
899 FIXME("%p %ld %p %ld %p %p %p\n", LsaHandle, AuthenticationPackage,
900 ProtocolSubmitBuffer, SubmitBufferLength, ProtocolReturnBuffer,
901 ReturnBufferLength, ProtocolStatus);
902 return 0;
903}
904
905NTSTATUS WINAPI LsaConnectUntrusted(PHANDLE LsaHandle)
906{
907 FIXME("%p\n", LsaHandle);
908 return 0;
909}
910
911NTSTATUS WINAPI LsaDeregisterLogonProcess(HANDLE LsaHandle)
912{
913 FIXME("%p\n", LsaHandle);
914 return 0;
915}
916
917BOOLEAN WINAPI TranslateNameA(
918 LPCSTR lpAccountName, EXTENDED_NAME_FORMAT AccountNameFormat,
919 EXTENDED_NAME_FORMAT DesiredNameFormat, LPSTR lpTranslatedName,
920 PULONG nSize)
921{
922 FIXME("%p %d %d %p %p\n", lpAccountName, AccountNameFormat,
923 DesiredNameFormat, lpTranslatedName, nSize);
924 return FALSE;
925}
926
927BOOLEAN WINAPI TranslateNameW(
928 LPCWSTR lpAccountName, EXTENDED_NAME_FORMAT AccountNameFormat,
929 EXTENDED_NAME_FORMAT DesiredNameFormat, LPWSTR lpTranslatedName,
930 PULONG nSize)
931{
932 FIXME("%p %d %d %p %p\n", lpAccountName, AccountNameFormat,
933 DesiredNameFormat, lpTranslatedName, nSize);
934 return FALSE;
935}
936
Mike McCormacke18965d2004-07-12 19:52:47 +0000937/***********************************************************************
Patrik Stridvall070db4e2004-05-17 21:08:31 +0000938 * DllMain (SECUR32.0)
939 */
Juan Lang3ed89c32004-03-02 04:57:35 +0000940BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
941{
942 if (fdwReason == DLL_PROCESS_ATTACH)
943 {
944 DisableThreadLibraryCalls(hinstDLL);
945 SECUR32_initializeProviders();
946 }
947 else if (fdwReason == DLL_PROCESS_DETACH)
948 {
949 SECUR32_freeProviders();
950 }
951
952 return TRUE;
953}