source: trunk/src/secur32/secur32.c@ 22015

Last change on this file since 22015 was 21971, checked in by dmik, 14 years ago

Fix debug build break (r21967 regression).

Some code doesn't actually use RTL_CRITICAL_SECTION which
contains the needed debug fields.

File size: 35.4 KB
Line 
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 <assert.h>
21#include <stdarg.h>
22#include <memory.h>
23
24#include "ntstatus.h"
25#define WIN32_NO_STATUS
26#include "windef.h"
27#include "winbase.h"
28#include "winnls.h"
29#include "winreg.h"
30#include "winternl.h"
31#include "shlwapi.h"
32#include "sspi.h"
33#include "secur32_priv.h"
34#include "secext.h"
35#include "ntsecapi.h"
36#include "thunks.h"
37
38#include "wine/list.h"
39#include "wine/debug.h"
40#include "winerror.h"
41
42WINE_DEFAULT_DEBUG_CHANNEL(secur32);
43
44/**
45 * Type definitions
46 */
47
48typedef struct _SecurePackageTable
49{
50 DWORD numPackages;
51 DWORD numAllocated;
52 struct list table;
53} SecurePackageTable;
54
55typedef struct _SecureProviderTable
56{
57 DWORD numProviders;
58 DWORD numAllocated;
59 struct list table;
60} SecureProviderTable;
61
62/**
63 * Prototypes
64 */
65
66ULONG WIN32API LsaNtStatusToWinError(NTSTATUS Status);
67
68/* Tries to load moduleName as a provider. If successful, enumerates what
69 * packages it can and adds them to the package and provider tables. Resizes
70 * tables as necessary.
71 */
72static void _tryLoadProvider(PWSTR moduleName);
73
74/* Initialization: read securityproviders value and attempt to open each dll
75 * there. For each DLL, call _tryLoadProvider to see if it's really an SSP.
76 * Two undocumented functions, AddSecurityPackage(A/W) and
77 * DeleteSecurityPackage(A/W), seem suspiciously like they'd register or
78 * unregister a dll, but I'm not sure.
79 */
80static void SECUR32_initializeProviders(void);
81
82/* Frees all loaded packages and providers */
83static void SECUR32_freeProviders(void);
84
85/**
86 * Globals
87 */
88
89static CRITICAL_SECTION cs;
90static SecurePackageTable *packageTable = NULL;
91static SecureProviderTable *providerTable = NULL;
92
93static SecurityFunctionTableA securityFunctionTableA = {
94 SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION,
95 EnumerateSecurityPackagesA,
96 QueryCredentialsAttributesA,
97 AcquireCredentialsHandleA,
98 FreeCredentialsHandle,
99 NULL, /* Reserved2 */
100 InitializeSecurityContextA,
101 AcceptSecurityContext,
102 CompleteAuthToken,
103 DeleteSecurityContext,
104 ApplyControlToken,
105 QueryContextAttributesA,
106 ImpersonateSecurityContext,
107 RevertSecurityContext,
108 MakeSignature,
109 VerifySignature,
110 FreeContextBuffer,
111 QuerySecurityPackageInfoA,
112 EncryptMessage, /* Reserved3 */
113 DecryptMessage, /* Reserved4 */
114 ExportSecurityContext,
115 ImportSecurityContextA,
116 AddCredentialsA,
117 NULL, /* Reserved8 */
118 QuerySecurityContextToken,
119 EncryptMessage,
120 DecryptMessage,
121 SetContextAttributesA
122};
123
124static SecurityFunctionTableW securityFunctionTableW = {
125 SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION,
126 EnumerateSecurityPackagesW,
127 QueryCredentialsAttributesW,
128 AcquireCredentialsHandleW,
129 FreeCredentialsHandle,
130 NULL, /* Reserved2 */
131 InitializeSecurityContextW,
132 AcceptSecurityContext,
133 CompleteAuthToken,
134 DeleteSecurityContext,
135 ApplyControlToken,
136 QueryContextAttributesW,
137 ImpersonateSecurityContext,
138 RevertSecurityContext,
139 MakeSignature,
140 VerifySignature,
141 FreeContextBuffer,
142 QuerySecurityPackageInfoW,
143 EncryptMessage, /* Reserved3 */
144 DecryptMessage, /* Reserved4 */
145 ExportSecurityContext,
146 ImportSecurityContextW,
147 AddCredentialsW,
148 NULL, /* Reserved8 */
149 QuerySecurityContextToken,
150 EncryptMessage,
151 DecryptMessage,
152 SetContextAttributesW
153};
154
155/***********************************************************************
156 * InitSecurityInterfaceA (SECUR32.@)
157 */
158PSecurityFunctionTableA WINAPI InitSecurityInterfaceA(void)
159{
160 return &securityFunctionTableA;
161}
162
163/***********************************************************************
164 * InitSecurityInterfaceW (SECUR32.@)
165 */
166PSecurityFunctionTableW WINAPI InitSecurityInterfaceW(void)
167{
168 return &securityFunctionTableW;
169}
170
171PWSTR SECUR32_strdupW(PCWSTR str)
172{
173 PWSTR ret;
174
175 if (str)
176 {
177 ret = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(str) + 1) * sizeof(WCHAR));
178 if (ret)
179 lstrcpyW(ret, str);
180 }
181 else
182 ret = NULL;
183 return ret;
184}
185
186PWSTR SECUR32_AllocWideFromMultiByte(PCSTR str)
187{
188 PWSTR ret;
189
190 if (str)
191 {
192 int charsNeeded = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
193
194 if (charsNeeded)
195 {
196 ret = HeapAlloc(GetProcessHeap(), 0, charsNeeded * sizeof(WCHAR));
197 if (ret)
198 MultiByteToWideChar(CP_ACP, 0, str, -1, ret, charsNeeded);
199 }
200 else
201 ret = NULL;
202 }
203 else
204 ret = NULL;
205 return ret;
206}
207
208PSTR SECUR32_AllocMultiByteFromWide(PCWSTR str)
209{
210 PSTR ret;
211
212 if (str)
213 {
214 int charsNeeded = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0,
215 NULL, NULL);
216
217 if (charsNeeded)
218 {
219 ret = HeapAlloc(GetProcessHeap(), 0, charsNeeded);
220 if (ret)
221 WideCharToMultiByte(CP_ACP, 0, str, -1, ret, charsNeeded,
222 NULL, NULL);
223 }
224 else
225 ret = NULL;
226 }
227 else
228 ret = NULL;
229 return ret;
230}
231
232static void _makeFnTableA(PSecurityFunctionTableA fnTableA,
233 const SecurityFunctionTableA *inFnTableA,
234 const SecurityFunctionTableW *inFnTableW)
235{
236 if (fnTableA)
237 {
238 if (inFnTableA)
239 {
240 /* The size of the version 1 table is based on platform sdk's
241 * sspi.h, though the sample ssp also provided with platform sdk
242 * implies only functions through QuerySecurityPackageInfoA are
243 * implemented (yikes)
244 */
245 size_t tableSize = inFnTableA->dwVersion == 1 ?
246 (const BYTE *)&inFnTableA->SetContextAttributesA -
247 (const BYTE *)inFnTableA : sizeof(SecurityFunctionTableA);
248
249 memcpy(fnTableA, inFnTableA, tableSize);
250 /* override this, since we can do it internally anyway */
251 fnTableA->QuerySecurityPackageInfoA =
252 QuerySecurityPackageInfoA;
253 }
254 else if (inFnTableW)
255 {
256 /* functions with thunks */
257 if (inFnTableW->AcquireCredentialsHandleW)
258 fnTableA->AcquireCredentialsHandleA =
259 thunk_AcquireCredentialsHandleA;
260 if (inFnTableW->InitializeSecurityContextW)
261 fnTableA->InitializeSecurityContextA =
262 thunk_InitializeSecurityContextA;
263 if (inFnTableW->ImportSecurityContextW)
264 fnTableA->ImportSecurityContextA =
265 thunk_ImportSecurityContextA;
266 if (inFnTableW->AddCredentialsW)
267 fnTableA->AddCredentialsA =
268 thunk_AddCredentialsA;
269 if (inFnTableW->QueryCredentialsAttributesW)
270 fnTableA->QueryCredentialsAttributesA =
271 thunk_QueryCredentialsAttributesA;
272 if (inFnTableW->QueryContextAttributesW)
273 fnTableA->QueryContextAttributesA =
274 thunk_QueryContextAttributesA;
275 if (inFnTableW->SetContextAttributesW)
276 fnTableA->SetContextAttributesA =
277 thunk_SetContextAttributesA;
278 /* this can't be thunked, there's no extra param to know which
279 * package to forward to */
280 fnTableA->EnumerateSecurityPackagesA = NULL;
281 /* functions with no thunks needed */
282 fnTableA->AcceptSecurityContext = inFnTableW->AcceptSecurityContext;
283 fnTableA->CompleteAuthToken = inFnTableW->CompleteAuthToken;
284 fnTableA->DeleteSecurityContext = inFnTableW->DeleteSecurityContext;
285 fnTableA->ImpersonateSecurityContext =
286 inFnTableW->ImpersonateSecurityContext;
287 fnTableA->RevertSecurityContext = inFnTableW->RevertSecurityContext;
288 fnTableA->MakeSignature = inFnTableW->MakeSignature;
289 fnTableA->VerifySignature = inFnTableW->VerifySignature;
290 fnTableA->FreeContextBuffer = inFnTableW->FreeContextBuffer;
291 fnTableA->QuerySecurityPackageInfoA =
292 QuerySecurityPackageInfoA;
293 fnTableA->ExportSecurityContext =
294 inFnTableW->ExportSecurityContext;
295 fnTableA->QuerySecurityContextToken =
296 inFnTableW->QuerySecurityContextToken;
297 fnTableA->EncryptMessage = inFnTableW->EncryptMessage;
298 fnTableA->DecryptMessage = inFnTableW->DecryptMessage;
299 }
300 }
301}
302
303static void _makeFnTableW(PSecurityFunctionTableW fnTableW,
304 const SecurityFunctionTableA *inFnTableA,
305 const SecurityFunctionTableW *inFnTableW)
306{
307 if (fnTableW)
308 {
309 if (inFnTableW)
310 {
311 /* The size of the version 1 table is based on platform sdk's
312 * sspi.h, though the sample ssp also provided with platform sdk
313 * implies only functions through QuerySecurityPackageInfoA are
314 * implemented (yikes)
315 */
316 size_t tableSize = inFnTableW->dwVersion == 1 ?
317 (const BYTE *)&inFnTableW->SetContextAttributesW -
318 (const BYTE *)inFnTableW : sizeof(SecurityFunctionTableW);
319
320 memcpy(fnTableW, inFnTableW, tableSize);
321 /* override this, since we can do it internally anyway */
322 fnTableW->QuerySecurityPackageInfoW =
323 QuerySecurityPackageInfoW;
324 }
325 else if (inFnTableA)
326 {
327 /* functions with thunks */
328 if (inFnTableA->AcquireCredentialsHandleA)
329 fnTableW->AcquireCredentialsHandleW =
330 thunk_AcquireCredentialsHandleW;
331 if (inFnTableA->InitializeSecurityContextA)
332 fnTableW->InitializeSecurityContextW =
333 thunk_InitializeSecurityContextW;
334 if (inFnTableA->ImportSecurityContextA)
335 fnTableW->ImportSecurityContextW =
336 thunk_ImportSecurityContextW;
337 if (inFnTableA->AddCredentialsA)
338 fnTableW->AddCredentialsW =
339 thunk_AddCredentialsW;
340 if (inFnTableA->QueryCredentialsAttributesA)
341 fnTableW->QueryCredentialsAttributesW =
342 thunk_QueryCredentialsAttributesW;
343 if (inFnTableA->QueryContextAttributesA)
344 fnTableW->QueryContextAttributesW =
345 thunk_QueryContextAttributesW;
346 if (inFnTableA->SetContextAttributesA)
347 fnTableW->SetContextAttributesW =
348 thunk_SetContextAttributesW;
349 /* this can't be thunked, there's no extra param to know which
350 * package to forward to */
351 fnTableW->EnumerateSecurityPackagesW = NULL;
352 /* functions with no thunks needed */
353 fnTableW->AcceptSecurityContext = inFnTableA->AcceptSecurityContext;
354 fnTableW->CompleteAuthToken = inFnTableA->CompleteAuthToken;
355 fnTableW->DeleteSecurityContext = inFnTableA->DeleteSecurityContext;
356 fnTableW->ImpersonateSecurityContext =
357 inFnTableA->ImpersonateSecurityContext;
358 fnTableW->RevertSecurityContext = inFnTableA->RevertSecurityContext;
359 fnTableW->MakeSignature = inFnTableA->MakeSignature;
360 fnTableW->VerifySignature = inFnTableA->VerifySignature;
361 fnTableW->FreeContextBuffer = inFnTableA->FreeContextBuffer;
362 fnTableW->QuerySecurityPackageInfoW =
363 QuerySecurityPackageInfoW;
364 fnTableW->ExportSecurityContext =
365 inFnTableA->ExportSecurityContext;
366 fnTableW->QuerySecurityContextToken =
367 inFnTableA->QuerySecurityContextToken;
368 fnTableW->EncryptMessage = inFnTableA->EncryptMessage;
369 fnTableW->DecryptMessage = inFnTableA->DecryptMessage;
370 }
371 }
372}
373
374static void _copyPackageInfo(PSecPkgInfoW info, const SecPkgInfoA *inInfoA,
375 const SecPkgInfoW *inInfoW)
376{
377 if (info && (inInfoA || inInfoW))
378 {
379 /* odd, I know, but up until Name and Comment the structures are
380 * identical
381 */
382 memcpy(info, inInfoW ? inInfoW : (const SecPkgInfoW *)inInfoA, sizeof(*info));
383 if (inInfoW)
384 {
385 info->Name = SECUR32_strdupW(inInfoW->Name);
386 info->Comment = SECUR32_strdupW(inInfoW->Comment);
387 }
388 else
389 {
390 info->Name = SECUR32_AllocWideFromMultiByte(inInfoA->Name);
391 info->Comment = SECUR32_AllocWideFromMultiByte(inInfoA->Comment);
392 }
393 }
394}
395
396SecureProvider *SECUR32_addProvider(const SecurityFunctionTableA *fnTableA,
397 const SecurityFunctionTableW *fnTableW, PCWSTR moduleName)
398{
399 SecureProvider *ret;
400
401 EnterCriticalSection(&cs);
402
403 if (!providerTable)
404 {
405 providerTable = HeapAlloc(GetProcessHeap(), 0, sizeof(SecureProviderTable));
406 if (!providerTable)
407 {
408 LeaveCriticalSection(&cs);
409 return NULL;
410 }
411
412 list_init(&providerTable->table);
413 }
414
415 ret = HeapAlloc(GetProcessHeap(), 0, sizeof(SecureProvider));
416 if (!ret)
417 {
418 LeaveCriticalSection(&cs);
419 return NULL;
420 }
421
422 list_add_tail(&providerTable->table, &ret->entry);
423 ret->lib = NULL;
424
425 if (fnTableA || fnTableW)
426 {
427 ret->moduleName = moduleName ? SECUR32_strdupW(moduleName) : NULL;
428 _makeFnTableA(&ret->fnTableA, fnTableA, fnTableW);
429 _makeFnTableW(&ret->fnTableW, fnTableA, fnTableW);
430 ret->loaded = moduleName ? FALSE : TRUE;
431 }
432 else
433 {
434 ret->moduleName = SECUR32_strdupW(moduleName);
435 ret->loaded = FALSE;
436 }
437
438 LeaveCriticalSection(&cs);
439 return ret;
440}
441
442void SECUR32_addPackages(SecureProvider *provider, ULONG toAdd,
443 const SecPkgInfoA *infoA, const SecPkgInfoW *infoW)
444{
445 ULONG i;
446
447 assert(provider);
448 assert(infoA || infoW);
449
450 EnterCriticalSection(&cs);
451
452 if (!packageTable)
453 {
454 packageTable = HeapAlloc(GetProcessHeap(), 0, sizeof(SecurePackageTable));
455 if (!packageTable)
456 {
457 LeaveCriticalSection(&cs);
458 return;
459 }
460
461 packageTable->numPackages = 0;
462 list_init(&packageTable->table);
463 }
464
465 for (i = 0; i < toAdd; i++)
466 {
467 SecurePackage *package = HeapAlloc(GetProcessHeap(), 0, sizeof(SecurePackage));
468 if (!package)
469 continue;
470
471 list_add_tail(&packageTable->table, &package->entry);
472
473 package->provider = provider;
474 _copyPackageInfo(&package->infoW,
475 infoA ? &infoA[i] : NULL,
476 infoW ? &infoW[i] : NULL);
477 }
478 packageTable->numPackages += toAdd;
479
480 LeaveCriticalSection(&cs);
481}
482
483static void _tryLoadProvider(PWSTR moduleName)
484{
485 HMODULE lib = LoadLibraryW(moduleName);
486
487 if (lib)
488 {
489 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW =
490 (INIT_SECURITY_INTERFACE_W)GetProcAddress(lib,
491 SECURITY_ENTRYPOINT_ANSIW);
492 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA =
493 (INIT_SECURITY_INTERFACE_A)GetProcAddress(lib,
494 SECURITY_ENTRYPOINT_ANSIA);
495
496 TRACE("loaded %s, InitSecurityInterfaceA is %p, InitSecurityInterfaceW is %p\n",
497 debugstr_w(moduleName), pInitSecurityInterfaceA,
498 pInitSecurityInterfaceW);
499 if (pInitSecurityInterfaceW || pInitSecurityInterfaceA)
500 {
501 PSecurityFunctionTableA fnTableA = NULL;
502 PSecurityFunctionTableW fnTableW = NULL;
503 ULONG toAdd = 0;
504 PSecPkgInfoA infoA = NULL;
505 PSecPkgInfoW infoW = NULL;
506 SECURITY_STATUS ret = SEC_E_OK;
507
508 if (pInitSecurityInterfaceA)
509 fnTableA = pInitSecurityInterfaceA();
510 if (pInitSecurityInterfaceW)
511 fnTableW = pInitSecurityInterfaceW();
512 if (fnTableW && fnTableW->EnumerateSecurityPackagesW)
513 {
514 if (fnTableW != &securityFunctionTableW)
515 ret = fnTableW->EnumerateSecurityPackagesW(&toAdd, &infoW);
516 else
517 TRACE("%s has built-in providers, skip adding\n", debugstr_w(moduleName));
518 }
519 else if (fnTableA && fnTableA->EnumerateSecurityPackagesA)
520 {
521 if (fnTableA != &securityFunctionTableA)
522 ret = fnTableA->EnumerateSecurityPackagesA(&toAdd, &infoA);
523 else
524 TRACE("%s has built-in providers, skip adding\n", debugstr_w(moduleName));
525 }
526 if (ret == SEC_E_OK && toAdd > 0 && (infoW || infoA))
527 {
528 SecureProvider *provider = SECUR32_addProvider(NULL, NULL,
529 moduleName);
530
531 if (provider)
532 SECUR32_addPackages(provider, toAdd, infoA, infoW);
533 if (infoW)
534 fnTableW->FreeContextBuffer(infoW);
535 else
536 fnTableA->FreeContextBuffer(infoA);
537 }
538 }
539 FreeLibrary(lib);
540 }
541 else
542 WARN("failed to load %s\n", debugstr_w(moduleName));
543}
544
545static const WCHAR securityProvidersKeyW[] = {
546 'S','Y','S','T','E','M','\\','C','u','r','r','e','n','t','C','o','n','t','r',
547 'o','l','S','e','t','\\','C','o','n','t','r','o','l','\\','S','e','c','u','r',
548 'i','t','y','P','r','o','v','i','d','e','r','s','\0'
549 };
550static const WCHAR securityProvidersW[] = {
551 'S','e','c','u','r','i','t','y','P','r','o','v','i','d','e','r','s',0
552 };
553
554static void SECUR32_initializeProviders(void)
555{
556 HKEY key;
557 long apiRet;
558
559 TRACE("\n");
560 InitializeCriticalSection(&cs);
561#ifdef DEBUG
562 //cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": cs");
563#endif
564 /* First load built-in providers */
565 SECUR32_initSchannelSP();
566 /* Do not load Negotiate yet. This breaks for some user on the wine-users
567 * mailing list as of 2006-09-12. Without Negotiate, applications should
568 * fall back to NTLM and that should work.*/
569#if 0
570 SECUR32_initNegotiateSP();
571#endif
572 SECUR32_initNTLMSP();
573 /* Now load providers from registry */
574 apiRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, securityProvidersKeyW, 0,
575 KEY_READ, &key);
576 if (apiRet == ERROR_SUCCESS)
577 {
578 WCHAR securityPkgNames[MAX_PATH]; /* arbitrary len */
579 DWORD size = sizeof(securityPkgNames) / sizeof(WCHAR), type;
580
581 apiRet = RegQueryValueExW(key, securityProvidersW, NULL, &type,
582 (PBYTE)securityPkgNames, &size);
583 if (apiRet == ERROR_SUCCESS && type == REG_SZ)
584 {
585 WCHAR *ptr;
586
587 size = size / sizeof(WCHAR);
588 for (ptr = securityPkgNames;
589 ptr < securityPkgNames + size; )
590 {
591 WCHAR *comma;
592
593 for (comma = ptr; *comma && *comma != ','; comma++)
594 ;
595 if (*comma == ',')
596 *comma = '\0';
597 for (; *ptr && isspace(*ptr) && ptr < securityPkgNames + size;
598 ptr++)
599 ;
600 if (*ptr)
601 _tryLoadProvider(ptr);
602 ptr += lstrlenW(ptr) + 1;
603 }
604 }
605 RegCloseKey(key);
606 }
607}
608
609SecurePackage *SECUR32_findPackageW(PCWSTR packageName)
610{
611 SecurePackage *ret = NULL;
612 BOOL matched = FALSE;
613
614 if (packageTable && packageName)
615 {
616 LIST_FOR_EACH_ENTRY(ret, &packageTable->table, SecurePackage, entry)
617 {
618 matched = !lstrcmpiW(ret->infoW.Name, packageName);
619 if (matched)
620 break;
621 }
622
623 if (!matched)
624 return NULL;
625
626 if (ret->provider && !ret->provider->loaded)
627 {
628 ret->provider->lib = LoadLibraryW(ret->provider->moduleName);
629 if (ret->provider->lib)
630 {
631 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW =
632 (INIT_SECURITY_INTERFACE_W)GetProcAddress(ret->provider->lib,
633 SECURITY_ENTRYPOINT_ANSIW);
634 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA =
635 (INIT_SECURITY_INTERFACE_A)GetProcAddress(ret->provider->lib,
636 SECURITY_ENTRYPOINT_ANSIA);
637 PSecurityFunctionTableA fnTableA = NULL;
638 PSecurityFunctionTableW fnTableW = NULL;
639
640 if (pInitSecurityInterfaceA)
641 fnTableA = pInitSecurityInterfaceA();
642 if (pInitSecurityInterfaceW)
643 fnTableW = pInitSecurityInterfaceW();
644 /* don't update built-in SecurityFunctionTable */
645 if (fnTableA != &securityFunctionTableA)
646 _makeFnTableA(&ret->provider->fnTableA, fnTableA, fnTableW);
647 if (fnTableW != &securityFunctionTableW)
648 _makeFnTableW(&ret->provider->fnTableW, fnTableA, fnTableW);
649 ret->provider->loaded = TRUE;
650 }
651 else
652 ret = NULL;
653 }
654 }
655 return ret;
656}
657
658SecurePackage *SECUR32_findPackageA(PCSTR packageName)
659{
660 SecurePackage *ret;
661
662 if (packageTable && packageName)
663 {
664 UNICODE_STRING package;
665
666 RtlCreateUnicodeStringFromAsciiz(&package, packageName);
667 ret = SECUR32_findPackageW(package.Buffer);
668 RtlFreeUnicodeString(&package);
669 }
670 else
671 ret = NULL;
672 return ret;
673}
674
675static void SECUR32_freeProviders(void)
676{
677 SecurePackage *package;
678 SecureProvider *provider;
679
680 TRACE("\n");
681 EnterCriticalSection(&cs);
682
683 SECUR32_deinitSchannelSP();
684
685 if (packageTable)
686 {
687 LIST_FOR_EACH_ENTRY(package, &packageTable->table, SecurePackage, entry)
688 {
689 HeapFree(GetProcessHeap(), 0, package->infoW.Name);
690 HeapFree(GetProcessHeap(), 0, package->infoW.Comment);
691 }
692
693 HeapFree(GetProcessHeap(), 0, packageTable);
694 packageTable = NULL;
695 }
696
697 if (providerTable)
698 {
699 LIST_FOR_EACH_ENTRY(provider, &providerTable->table, SecureProvider, entry)
700 {
701 HeapFree(GetProcessHeap(), 0, provider->moduleName);
702 if (provider->lib)
703 FreeLibrary(provider->lib);
704 }
705
706 HeapFree(GetProcessHeap(), 0, providerTable);
707 providerTable = NULL;
708 }
709
710 LeaveCriticalSection(&cs);
711#ifdef DEBUG
712 //cs.DebugInfo->Spare[0] = 0;
713#endif
714 DeleteCriticalSection(&cs);
715}
716
717/***********************************************************************
718 * FreeContextBuffer (SECUR32.@)
719 *
720 * Doh--if pv was allocated by a crypto package, this may not be correct.
721 * The sample ssp seems to use LocalAlloc/LocalFee, but there doesn't seem to
722 * be any guarantee, nor is there an alloc function in secur32.
723 */
724SECURITY_STATUS WINAPI FreeContextBuffer(PVOID pv)
725{
726 HeapFree(GetProcessHeap(), 0, pv);
727
728 return SEC_E_OK;
729}
730
731/***********************************************************************
732 * EnumerateSecurityPackagesW (SECUR32.@)
733 */
734SECURITY_STATUS WINAPI EnumerateSecurityPackagesW(PULONG pcPackages,
735 PSecPkgInfoW *ppPackageInfo)
736{
737 SECURITY_STATUS ret = SEC_E_OK;
738
739 TRACE("(%p, %p)\n", pcPackages, ppPackageInfo);
740
741 /* windows just crashes if pcPackages or ppPackageInfo is NULL, so will I */
742 *pcPackages = 0;
743 EnterCriticalSection(&cs);
744 if (packageTable)
745 {
746 SecurePackage *package;
747 size_t bytesNeeded;
748
749 bytesNeeded = packageTable->numPackages * sizeof(SecPkgInfoW);
750 LIST_FOR_EACH_ENTRY(package, &packageTable->table, SecurePackage, entry)
751 {
752 if (package->infoW.Name)
753 bytesNeeded += (lstrlenW(package->infoW.Name) + 1) * sizeof(WCHAR);
754 if (package->infoW.Comment)
755 bytesNeeded += (lstrlenW(package->infoW.Comment) + 1) * sizeof(WCHAR);
756 }
757 if (bytesNeeded)
758 {
759 *ppPackageInfo = HeapAlloc(GetProcessHeap(), 0, bytesNeeded);
760 if (*ppPackageInfo)
761 {
762 ULONG i = 0;
763 PWSTR nextString;
764
765 *pcPackages = packageTable->numPackages;
766 nextString = (PWSTR)((PBYTE)*ppPackageInfo +
767 packageTable->numPackages * sizeof(SecPkgInfoW));
768 LIST_FOR_EACH_ENTRY(package, &packageTable->table, SecurePackage, entry)
769 {
770 PSecPkgInfoW pkgInfo = *ppPackageInfo + i++;
771
772 *pkgInfo = package->infoW;
773 if (package->infoW.Name)
774 {
775 TRACE("Name[%d] = %s\n", i - 1, debugstr_w(package->infoW.Name));
776 pkgInfo->Name = nextString;
777 lstrcpyW(nextString, package->infoW.Name);
778 nextString += lstrlenW(nextString) + 1;
779 }
780 else
781 pkgInfo->Name = NULL;
782 if (package->infoW.Comment)
783 {
784 TRACE("Comment[%d] = %s\n", i - 1, debugstr_w(package->infoW.Comment));
785 pkgInfo->Comment = nextString;
786 lstrcpyW(nextString, package->infoW.Comment);
787 nextString += lstrlenW(nextString) + 1;
788 }
789 else
790 pkgInfo->Comment = NULL;
791 }
792 }
793 else
794 ret = SEC_E_INSUFFICIENT_MEMORY;
795 }
796 }
797 LeaveCriticalSection(&cs);
798 TRACE("<-- 0x%08x\n", ret);
799 return ret;
800}
801
802/* Converts info (which is assumed to be an array of cPackages SecPkgInfoW
803 * structures) into an array of SecPkgInfoA structures, which it returns.
804 */
805static PSecPkgInfoA thunk_PSecPkgInfoWToA(ULONG cPackages,
806 const SecPkgInfoW *info)
807{
808 PSecPkgInfoA ret;
809
810 if (info)
811 {
812 size_t bytesNeeded = cPackages * sizeof(SecPkgInfoA);
813 ULONG i;
814
815 for (i = 0; i < cPackages; i++)
816 {
817 if (info[i].Name)
818 bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info[i].Name,
819 -1, NULL, 0, NULL, NULL);
820 if (info[i].Comment)
821 bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info[i].Comment,
822 -1, NULL, 0, NULL, NULL);
823 }
824 ret = HeapAlloc(GetProcessHeap(), 0, bytesNeeded);
825 if (ret)
826 {
827 PSTR nextString;
828
829 nextString = (PSTR)((PBYTE)ret + cPackages * sizeof(SecPkgInfoA));
830 for (i = 0; i < cPackages; i++)
831 {
832 PSecPkgInfoA pkgInfo = ret + i;
833 int bytes;
834
835 memcpy(pkgInfo, &info[i], sizeof(SecPkgInfoA));
836 if (info[i].Name)
837 {
838 pkgInfo->Name = nextString;
839 /* just repeat back to WideCharToMultiByte how many bytes
840 * it requires, since we asked it earlier
841 */
842 bytes = WideCharToMultiByte(CP_ACP, 0, info[i].Name, -1,
843 NULL, 0, NULL, NULL);
844 WideCharToMultiByte(CP_ACP, 0, info[i].Name, -1,
845 pkgInfo->Name, bytes, NULL, NULL);
846 nextString += lstrlenA(nextString) + 1;
847 }
848 else
849 pkgInfo->Name = NULL;
850 if (info[i].Comment)
851 {
852 pkgInfo->Comment = nextString;
853 /* just repeat back to WideCharToMultiByte how many bytes
854 * it requires, since we asked it earlier
855 */
856 bytes = WideCharToMultiByte(CP_ACP, 0, info[i].Comment, -1,
857 NULL, 0, NULL, NULL);
858 WideCharToMultiByte(CP_ACP, 0, info[i].Comment, -1,
859 pkgInfo->Comment, bytes, NULL, NULL);
860 nextString += lstrlenA(nextString) + 1;
861 }
862 else
863 pkgInfo->Comment = NULL;
864 }
865 }
866 }
867 else
868 ret = NULL;
869 return ret;
870}
871
872/***********************************************************************
873 * EnumerateSecurityPackagesA (SECUR32.@)
874 */
875SECURITY_STATUS WINAPI EnumerateSecurityPackagesA(PULONG pcPackages,
876 PSecPkgInfoA *ppPackageInfo)
877{
878 SECURITY_STATUS ret;
879 PSecPkgInfoW info;
880
881 ret = EnumerateSecurityPackagesW(pcPackages, &info);
882 if (ret == SEC_E_OK && *pcPackages && info)
883 {
884 *ppPackageInfo = thunk_PSecPkgInfoWToA(*pcPackages, info);
885 if (*pcPackages && !*ppPackageInfo)
886 {
887 *pcPackages = 0;
888 ret = SEC_E_INSUFFICIENT_MEMORY;
889 }
890 FreeContextBuffer(info);
891 }
892 return ret;
893}
894
895/***********************************************************************
896 * GetComputerObjectNameA (SECUR32.@)
897 *
898 * Get the local computer's name using the format specified.
899 *
900 * PARAMS
901 * NameFormat [I] The format for the name.
902 * lpNameBuffer [O] Pointer to buffer to receive the name.
903 * nSize [I/O] Size in characters of buffer.
904 *
905 * RETURNS
906 * TRUE If the name was written to lpNameBuffer.
907 * FALSE If the name couldn't be written.
908 *
909 * NOTES
910 * If lpNameBuffer is NULL, then the size of the buffer needed to hold the
911 * name will be returned in *nSize.
912 *
913 * nSize returns the number of characters written when lpNameBuffer is not
914 * NULL or the size of the buffer needed to hold the name when the buffer
915 * is too short or lpNameBuffer is NULL.
916 *
917 * It the buffer is too short, ERROR_INSUFFICIENT_BUFFER error will be set.
918 */
919BOOLEAN WINAPI GetComputerObjectNameA(
920 EXTENDED_NAME_FORMAT NameFormat, LPSTR lpNameBuffer, PULONG nSize)
921{
922 BOOLEAN rc;
923 LPWSTR bufferW = NULL;
924 ULONG sizeW = *nSize;
925 TRACE("(%d %p %p)\n", NameFormat, lpNameBuffer, nSize);
926 if (lpNameBuffer) {
927 bufferW = HeapAlloc(GetProcessHeap(), 0, sizeW * sizeof(WCHAR));
928 if (bufferW == NULL) {
929 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
930 return FALSE;
931 }
932 }
933 rc = GetComputerObjectNameW(NameFormat, bufferW, &sizeW);
934 if (rc && bufferW) {
935 ULONG len = WideCharToMultiByte(CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL);
936 WideCharToMultiByte(CP_ACP, 0, bufferW, -1, lpNameBuffer, *nSize, NULL, NULL);
937 *nSize = len;
938 }
939 else
940 *nSize = sizeW;
941 HeapFree(GetProcessHeap(), 0, bufferW);
942 return rc;
943}
944
945/***********************************************************************
946 * GetComputerObjectNameW (SECUR32.@)
947 */
948BOOLEAN WINAPI GetComputerObjectNameW(
949 EXTENDED_NAME_FORMAT NameFormat, LPWSTR lpNameBuffer, PULONG nSize)
950{
951 LSA_HANDLE policyHandle;
952 LSA_OBJECT_ATTRIBUTES objectAttributes;
953 PPOLICY_DNS_DOMAIN_INFO domainInfo;
954 NTSTATUS ntStatus;
955 BOOLEAN status;
956 TRACE("(%d %p %p)\n", NameFormat, lpNameBuffer, nSize);
957
958 if (NameFormat == NameUnknown)
959 {
960 SetLastError(ERROR_INVALID_PARAMETER);
961 return FALSE;
962 }
963
964 ZeroMemory(&objectAttributes, sizeof(objectAttributes));
965 objectAttributes.Length = sizeof(objectAttributes);
966
967 ntStatus = LsaOpenPolicy(NULL, &objectAttributes,
968 POLICY_VIEW_LOCAL_INFORMATION,
969 &policyHandle);
970 if (ntStatus != STATUS_SUCCESS)
971 {
972 SetLastError(LsaNtStatusToWinError(ntStatus));
973 WARN("LsaOpenPolicy failed with NT status %u\n", GetLastError());
974 return FALSE;
975 }
976
977 ntStatus = LsaQueryInformationPolicy(policyHandle,
978 PolicyDnsDomainInformation,
979 (PVOID *)&domainInfo);
980 if (ntStatus != STATUS_SUCCESS)
981 {
982 SetLastError(LsaNtStatusToWinError(ntStatus));
983 WARN("LsaQueryInformationPolicy failed with NT status %u\n",
984 GetLastError());
985 LsaClose(policyHandle);
986 return FALSE;
987 }
988
989 if (domainInfo->Sid)
990 {
991 switch (NameFormat)
992 {
993 case NameSamCompatible:
994 {
995 WCHAR name[MAX_COMPUTERNAME_LENGTH + 1];
996 DWORD size = sizeof(name)/sizeof(name[0]);
997 if (GetComputerNameW(name, &size))
998 {
999 DWORD len = domainInfo->Name.Length + size + 3;
1000 if (lpNameBuffer)
1001 {
1002 if (*nSize < len)
1003 {
1004 *nSize = len;
1005 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1006 status = FALSE;
1007 }
1008 else
1009 {
1010 WCHAR bs[] = { '\\', 0 };
1011 WCHAR ds[] = { '$', 0 };
1012 lstrcpyW(lpNameBuffer, domainInfo->Name.Buffer);
1013 lstrcatW(lpNameBuffer, bs);
1014 lstrcatW(lpNameBuffer, name);
1015 lstrcatW(lpNameBuffer, ds);
1016 status = TRUE;
1017 }
1018 }
1019 else /* just requesting length required */
1020 {
1021 *nSize = len;
1022 status = TRUE;
1023 }
1024 }
1025 else
1026 {
1027 SetLastError(ERROR_INTERNAL_ERROR);
1028 status = FALSE;
1029 }
1030 }
1031 break;
1032 case NameFullyQualifiedDN:
1033 case NameDisplay:
1034 case NameUniqueId:
1035 case NameCanonical:
1036 case NameUserPrincipal:
1037 case NameCanonicalEx:
1038 case NameServicePrincipal:
1039 case NameDnsDomain:
1040 FIXME("NameFormat %d not implemented\n", NameFormat);
1041 SetLastError(ERROR_CANT_ACCESS_DOMAIN_INFO);
1042 status = FALSE;
1043 break;
1044 default:
1045 SetLastError(ERROR_INVALID_PARAMETER);
1046 status = FALSE;
1047 }
1048 }
1049 else
1050 {
1051 SetLastError(ERROR_CANT_ACCESS_DOMAIN_INFO);
1052 status = FALSE;
1053 }
1054
1055 LsaFreeMemory(domainInfo);
1056 LsaClose(policyHandle);
1057
1058 return status;
1059}
1060
1061/***********************************************************************
1062 * GetUserNameExA (SECUR32.@)
1063 */
1064BOOLEAN WINAPI GetUserNameExA(
1065 EXTENDED_NAME_FORMAT NameFormat, LPSTR lpNameBuffer, PULONG nSize)
1066{
1067 FIXME("%d %p %p\n", NameFormat, lpNameBuffer, nSize);
1068 return FALSE;
1069}
1070
1071BOOLEAN WINAPI GetUserNameExW(
1072 EXTENDED_NAME_FORMAT NameFormat, LPWSTR lpNameBuffer, PULONG nSize)
1073{
1074 FIXME("%d %p %p\n", NameFormat, lpNameBuffer, nSize);
1075 return FALSE;
1076}
1077
1078BOOLEAN WINAPI TranslateNameA(
1079 LPCSTR lpAccountName, EXTENDED_NAME_FORMAT AccountNameFormat,
1080 EXTENDED_NAME_FORMAT DesiredNameFormat, LPSTR lpTranslatedName,
1081 PULONG nSize)
1082{
1083 FIXME("%p %d %d %p %p\n", lpAccountName, AccountNameFormat,
1084 DesiredNameFormat, lpTranslatedName, nSize);
1085 return FALSE;
1086}
1087
1088BOOLEAN WINAPI TranslateNameW(
1089 LPCWSTR lpAccountName, EXTENDED_NAME_FORMAT AccountNameFormat,
1090 EXTENDED_NAME_FORMAT DesiredNameFormat, LPWSTR lpTranslatedName,
1091 PULONG nSize)
1092{
1093 FIXME("%p %d %d %p %p\n", lpAccountName, AccountNameFormat,
1094 DesiredNameFormat, lpTranslatedName, nSize);
1095 return FALSE;
1096}
1097
1098/***********************************************************************
1099 * DllMain (SECUR32.0)
1100 */
1101BOOL WINAPI Secur32DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
1102{
1103 if (fdwReason == DLL_PROCESS_ATTACH)
1104 {
1105 DisableThreadLibraryCalls(hinstDLL);
1106 SECUR32_initializeProviders();
1107 }
1108 else if (fdwReason == DLL_PROCESS_DETACH)
1109 {
1110 SECUR32_freeProviders();
1111 }
1112
1113 return TRUE;
1114}
Note: See TracBrowser for help on using the repository browser.