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

Last change on this file since 21951 was 21916, checked in by dmik, 14 years ago

Merge branch gcc-kmk to trunk.

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 //cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": cs");
562 /* First load built-in providers */
563 SECUR32_initSchannelSP();
564 /* Do not load Negotiate yet. This breaks for some user on the wine-users
565 * mailing list as of 2006-09-12. Without Negotiate, applications should
566 * fall back to NTLM and that should work.*/
567#if 0
568 SECUR32_initNegotiateSP();
569#endif
570 SECUR32_initNTLMSP();
571 /* Now load providers from registry */
572 apiRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, securityProvidersKeyW, 0,
573 KEY_READ, &key);
574 if (apiRet == ERROR_SUCCESS)
575 {
576 WCHAR securityPkgNames[MAX_PATH]; /* arbitrary len */
577 DWORD size = sizeof(securityPkgNames) / sizeof(WCHAR), type;
578
579 apiRet = RegQueryValueExW(key, securityProvidersW, NULL, &type,
580 (PBYTE)securityPkgNames, &size);
581 if (apiRet == ERROR_SUCCESS && type == REG_SZ)
582 {
583 WCHAR *ptr;
584
585 size = size / sizeof(WCHAR);
586 for (ptr = securityPkgNames;
587 ptr < securityPkgNames + size; )
588 {
589 WCHAR *comma;
590
591 for (comma = ptr; *comma && *comma != ','; comma++)
592 ;
593 if (*comma == ',')
594 *comma = '\0';
595 for (; *ptr && isspace(*ptr) && ptr < securityPkgNames + size;
596 ptr++)
597 ;
598 if (*ptr)
599 _tryLoadProvider(ptr);
600 ptr += lstrlenW(ptr) + 1;
601 }
602 }
603 RegCloseKey(key);
604 }
605}
606
607SecurePackage *SECUR32_findPackageW(PCWSTR packageName)
608{
609 SecurePackage *ret = NULL;
610 BOOL matched = FALSE;
611
612 if (packageTable && packageName)
613 {
614 LIST_FOR_EACH_ENTRY(ret, &packageTable->table, SecurePackage, entry)
615 {
616 matched = !lstrcmpiW(ret->infoW.Name, packageName);
617 if (matched)
618 break;
619 }
620
621 if (!matched)
622 return NULL;
623
624 if (ret->provider && !ret->provider->loaded)
625 {
626 ret->provider->lib = LoadLibraryW(ret->provider->moduleName);
627 if (ret->provider->lib)
628 {
629 INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW =
630 (INIT_SECURITY_INTERFACE_W)GetProcAddress(ret->provider->lib,
631 SECURITY_ENTRYPOINT_ANSIW);
632 INIT_SECURITY_INTERFACE_A pInitSecurityInterfaceA =
633 (INIT_SECURITY_INTERFACE_A)GetProcAddress(ret->provider->lib,
634 SECURITY_ENTRYPOINT_ANSIA);
635 PSecurityFunctionTableA fnTableA = NULL;
636 PSecurityFunctionTableW fnTableW = NULL;
637
638 if (pInitSecurityInterfaceA)
639 fnTableA = pInitSecurityInterfaceA();
640 if (pInitSecurityInterfaceW)
641 fnTableW = pInitSecurityInterfaceW();
642 /* don't update built-in SecurityFunctionTable */
643 if (fnTableA != &securityFunctionTableA)
644 _makeFnTableA(&ret->provider->fnTableA, fnTableA, fnTableW);
645 if (fnTableW != &securityFunctionTableW)
646 _makeFnTableW(&ret->provider->fnTableW, fnTableA, fnTableW);
647 ret->provider->loaded = TRUE;
648 }
649 else
650 ret = NULL;
651 }
652 }
653 return ret;
654}
655
656SecurePackage *SECUR32_findPackageA(PCSTR packageName)
657{
658 SecurePackage *ret;
659
660 if (packageTable && packageName)
661 {
662 UNICODE_STRING package;
663
664 RtlCreateUnicodeStringFromAsciiz(&package, packageName);
665 ret = SECUR32_findPackageW(package.Buffer);
666 RtlFreeUnicodeString(&package);
667 }
668 else
669 ret = NULL;
670 return ret;
671}
672
673static void SECUR32_freeProviders(void)
674{
675 SecurePackage *package;
676 SecureProvider *provider;
677
678 TRACE("\n");
679 EnterCriticalSection(&cs);
680
681 SECUR32_deinitSchannelSP();
682
683 if (packageTable)
684 {
685 LIST_FOR_EACH_ENTRY(package, &packageTable->table, SecurePackage, entry)
686 {
687 HeapFree(GetProcessHeap(), 0, package->infoW.Name);
688 HeapFree(GetProcessHeap(), 0, package->infoW.Comment);
689 }
690
691 HeapFree(GetProcessHeap(), 0, packageTable);
692 packageTable = NULL;
693 }
694
695 if (providerTable)
696 {
697 LIST_FOR_EACH_ENTRY(provider, &providerTable->table, SecureProvider, entry)
698 {
699 HeapFree(GetProcessHeap(), 0, provider->moduleName);
700 if (provider->lib)
701 FreeLibrary(provider->lib);
702 }
703
704 HeapFree(GetProcessHeap(), 0, providerTable);
705 providerTable = NULL;
706 }
707
708 LeaveCriticalSection(&cs);
709 //cs.DebugInfo->Spare[0] = 0;
710 DeleteCriticalSection(&cs);
711}
712
713/***********************************************************************
714 * FreeContextBuffer (SECUR32.@)
715 *
716 * Doh--if pv was allocated by a crypto package, this may not be correct.
717 * The sample ssp seems to use LocalAlloc/LocalFee, but there doesn't seem to
718 * be any guarantee, nor is there an alloc function in secur32.
719 */
720SECURITY_STATUS WINAPI FreeContextBuffer(PVOID pv)
721{
722 HeapFree(GetProcessHeap(), 0, pv);
723
724 return SEC_E_OK;
725}
726
727/***********************************************************************
728 * EnumerateSecurityPackagesW (SECUR32.@)
729 */
730SECURITY_STATUS WINAPI EnumerateSecurityPackagesW(PULONG pcPackages,
731 PSecPkgInfoW *ppPackageInfo)
732{
733 SECURITY_STATUS ret = SEC_E_OK;
734
735 TRACE("(%p, %p)\n", pcPackages, ppPackageInfo);
736
737 /* windows just crashes if pcPackages or ppPackageInfo is NULL, so will I */
738 *pcPackages = 0;
739 EnterCriticalSection(&cs);
740 if (packageTable)
741 {
742 SecurePackage *package;
743 size_t bytesNeeded;
744
745 bytesNeeded = packageTable->numPackages * sizeof(SecPkgInfoW);
746 LIST_FOR_EACH_ENTRY(package, &packageTable->table, SecurePackage, entry)
747 {
748 if (package->infoW.Name)
749 bytesNeeded += (lstrlenW(package->infoW.Name) + 1) * sizeof(WCHAR);
750 if (package->infoW.Comment)
751 bytesNeeded += (lstrlenW(package->infoW.Comment) + 1) * sizeof(WCHAR);
752 }
753 if (bytesNeeded)
754 {
755 *ppPackageInfo = HeapAlloc(GetProcessHeap(), 0, bytesNeeded);
756 if (*ppPackageInfo)
757 {
758 ULONG i = 0;
759 PWSTR nextString;
760
761 *pcPackages = packageTable->numPackages;
762 nextString = (PWSTR)((PBYTE)*ppPackageInfo +
763 packageTable->numPackages * sizeof(SecPkgInfoW));
764 LIST_FOR_EACH_ENTRY(package, &packageTable->table, SecurePackage, entry)
765 {
766 PSecPkgInfoW pkgInfo = *ppPackageInfo + i++;
767
768 *pkgInfo = package->infoW;
769 if (package->infoW.Name)
770 {
771 TRACE("Name[%d] = %s\n", i - 1, debugstr_w(package->infoW.Name));
772 pkgInfo->Name = nextString;
773 lstrcpyW(nextString, package->infoW.Name);
774 nextString += lstrlenW(nextString) + 1;
775 }
776 else
777 pkgInfo->Name = NULL;
778 if (package->infoW.Comment)
779 {
780 TRACE("Comment[%d] = %s\n", i - 1, debugstr_w(package->infoW.Comment));
781 pkgInfo->Comment = nextString;
782 lstrcpyW(nextString, package->infoW.Comment);
783 nextString += lstrlenW(nextString) + 1;
784 }
785 else
786 pkgInfo->Comment = NULL;
787 }
788 }
789 else
790 ret = SEC_E_INSUFFICIENT_MEMORY;
791 }
792 }
793 LeaveCriticalSection(&cs);
794 TRACE("<-- 0x%08x\n", ret);
795 return ret;
796}
797
798/* Converts info (which is assumed to be an array of cPackages SecPkgInfoW
799 * structures) into an array of SecPkgInfoA structures, which it returns.
800 */
801static PSecPkgInfoA thunk_PSecPkgInfoWToA(ULONG cPackages,
802 const SecPkgInfoW *info)
803{
804 PSecPkgInfoA ret;
805
806 if (info)
807 {
808 size_t bytesNeeded = cPackages * sizeof(SecPkgInfoA);
809 ULONG i;
810
811 for (i = 0; i < cPackages; i++)
812 {
813 if (info[i].Name)
814 bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info[i].Name,
815 -1, NULL, 0, NULL, NULL);
816 if (info[i].Comment)
817 bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info[i].Comment,
818 -1, NULL, 0, NULL, NULL);
819 }
820 ret = HeapAlloc(GetProcessHeap(), 0, bytesNeeded);
821 if (ret)
822 {
823 PSTR nextString;
824
825 nextString = (PSTR)((PBYTE)ret + cPackages * sizeof(SecPkgInfoA));
826 for (i = 0; i < cPackages; i++)
827 {
828 PSecPkgInfoA pkgInfo = ret + i;
829 int bytes;
830
831 memcpy(pkgInfo, &info[i], sizeof(SecPkgInfoA));
832 if (info[i].Name)
833 {
834 pkgInfo->Name = nextString;
835 /* just repeat back to WideCharToMultiByte how many bytes
836 * it requires, since we asked it earlier
837 */
838 bytes = WideCharToMultiByte(CP_ACP, 0, info[i].Name, -1,
839 NULL, 0, NULL, NULL);
840 WideCharToMultiByte(CP_ACP, 0, info[i].Name, -1,
841 pkgInfo->Name, bytes, NULL, NULL);
842 nextString += lstrlenA(nextString) + 1;
843 }
844 else
845 pkgInfo->Name = NULL;
846 if (info[i].Comment)
847 {
848 pkgInfo->Comment = nextString;
849 /* just repeat back to WideCharToMultiByte how many bytes
850 * it requires, since we asked it earlier
851 */
852 bytes = WideCharToMultiByte(CP_ACP, 0, info[i].Comment, -1,
853 NULL, 0, NULL, NULL);
854 WideCharToMultiByte(CP_ACP, 0, info[i].Comment, -1,
855 pkgInfo->Comment, bytes, NULL, NULL);
856 nextString += lstrlenA(nextString) + 1;
857 }
858 else
859 pkgInfo->Comment = NULL;
860 }
861 }
862 }
863 else
864 ret = NULL;
865 return ret;
866}
867
868/***********************************************************************
869 * EnumerateSecurityPackagesA (SECUR32.@)
870 */
871SECURITY_STATUS WINAPI EnumerateSecurityPackagesA(PULONG pcPackages,
872 PSecPkgInfoA *ppPackageInfo)
873{
874 SECURITY_STATUS ret;
875 PSecPkgInfoW info;
876
877 ret = EnumerateSecurityPackagesW(pcPackages, &info);
878 if (ret == SEC_E_OK && *pcPackages && info)
879 {
880 *ppPackageInfo = thunk_PSecPkgInfoWToA(*pcPackages, info);
881 if (*pcPackages && !*ppPackageInfo)
882 {
883 *pcPackages = 0;
884 ret = SEC_E_INSUFFICIENT_MEMORY;
885 }
886 FreeContextBuffer(info);
887 }
888 return ret;
889}
890
891/***********************************************************************
892 * GetComputerObjectNameA (SECUR32.@)
893 *
894 * Get the local computer's name using the format specified.
895 *
896 * PARAMS
897 * NameFormat [I] The format for the name.
898 * lpNameBuffer [O] Pointer to buffer to receive the name.
899 * nSize [I/O] Size in characters of buffer.
900 *
901 * RETURNS
902 * TRUE If the name was written to lpNameBuffer.
903 * FALSE If the name couldn't be written.
904 *
905 * NOTES
906 * If lpNameBuffer is NULL, then the size of the buffer needed to hold the
907 * name will be returned in *nSize.
908 *
909 * nSize returns the number of characters written when lpNameBuffer is not
910 * NULL or the size of the buffer needed to hold the name when the buffer
911 * is too short or lpNameBuffer is NULL.
912 *
913 * It the buffer is too short, ERROR_INSUFFICIENT_BUFFER error will be set.
914 */
915BOOLEAN WINAPI GetComputerObjectNameA(
916 EXTENDED_NAME_FORMAT NameFormat, LPSTR lpNameBuffer, PULONG nSize)
917{
918 BOOLEAN rc;
919 LPWSTR bufferW = NULL;
920 ULONG sizeW = *nSize;
921 TRACE("(%d %p %p)\n", NameFormat, lpNameBuffer, nSize);
922 if (lpNameBuffer) {
923 bufferW = HeapAlloc(GetProcessHeap(), 0, sizeW * sizeof(WCHAR));
924 if (bufferW == NULL) {
925 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
926 return FALSE;
927 }
928 }
929 rc = GetComputerObjectNameW(NameFormat, bufferW, &sizeW);
930 if (rc && bufferW) {
931 ULONG len = WideCharToMultiByte(CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL);
932 WideCharToMultiByte(CP_ACP, 0, bufferW, -1, lpNameBuffer, *nSize, NULL, NULL);
933 *nSize = len;
934 }
935 else
936 *nSize = sizeW;
937 HeapFree(GetProcessHeap(), 0, bufferW);
938 return rc;
939}
940
941/***********************************************************************
942 * GetComputerObjectNameW (SECUR32.@)
943 */
944BOOLEAN WINAPI GetComputerObjectNameW(
945 EXTENDED_NAME_FORMAT NameFormat, LPWSTR lpNameBuffer, PULONG nSize)
946{
947 LSA_HANDLE policyHandle;
948 LSA_OBJECT_ATTRIBUTES objectAttributes;
949 PPOLICY_DNS_DOMAIN_INFO domainInfo;
950 NTSTATUS ntStatus;
951 BOOLEAN status;
952 TRACE("(%d %p %p)\n", NameFormat, lpNameBuffer, nSize);
953
954 if (NameFormat == NameUnknown)
955 {
956 SetLastError(ERROR_INVALID_PARAMETER);
957 return FALSE;
958 }
959
960 ZeroMemory(&objectAttributes, sizeof(objectAttributes));
961 objectAttributes.Length = sizeof(objectAttributes);
962
963 ntStatus = LsaOpenPolicy(NULL, &objectAttributes,
964 POLICY_VIEW_LOCAL_INFORMATION,
965 &policyHandle);
966 if (ntStatus != STATUS_SUCCESS)
967 {
968 SetLastError(LsaNtStatusToWinError(ntStatus));
969 WARN("LsaOpenPolicy failed with NT status %u\n", GetLastError());
970 return FALSE;
971 }
972
973 ntStatus = LsaQueryInformationPolicy(policyHandle,
974 PolicyDnsDomainInformation,
975 (PVOID *)&domainInfo);
976 if (ntStatus != STATUS_SUCCESS)
977 {
978 SetLastError(LsaNtStatusToWinError(ntStatus));
979 WARN("LsaQueryInformationPolicy failed with NT status %u\n",
980 GetLastError());
981 LsaClose(policyHandle);
982 return FALSE;
983 }
984
985 if (domainInfo->Sid)
986 {
987 switch (NameFormat)
988 {
989 case NameSamCompatible:
990 {
991 WCHAR name[MAX_COMPUTERNAME_LENGTH + 1];
992 DWORD size = sizeof(name)/sizeof(name[0]);
993 if (GetComputerNameW(name, &size))
994 {
995 DWORD len = domainInfo->Name.Length + size + 3;
996 if (lpNameBuffer)
997 {
998 if (*nSize < len)
999 {
1000 *nSize = len;
1001 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1002 status = FALSE;
1003 }
1004 else
1005 {
1006 WCHAR bs[] = { '\\', 0 };
1007 WCHAR ds[] = { '$', 0 };
1008 lstrcpyW(lpNameBuffer, domainInfo->Name.Buffer);
1009 lstrcatW(lpNameBuffer, bs);
1010 lstrcatW(lpNameBuffer, name);
1011 lstrcatW(lpNameBuffer, ds);
1012 status = TRUE;
1013 }
1014 }
1015 else /* just requesting length required */
1016 {
1017 *nSize = len;
1018 status = TRUE;
1019 }
1020 }
1021 else
1022 {
1023 SetLastError(ERROR_INTERNAL_ERROR);
1024 status = FALSE;
1025 }
1026 }
1027 break;
1028 case NameFullyQualifiedDN:
1029 case NameDisplay:
1030 case NameUniqueId:
1031 case NameCanonical:
1032 case NameUserPrincipal:
1033 case NameCanonicalEx:
1034 case NameServicePrincipal:
1035 case NameDnsDomain:
1036 FIXME("NameFormat %d not implemented\n", NameFormat);
1037 SetLastError(ERROR_CANT_ACCESS_DOMAIN_INFO);
1038 status = FALSE;
1039 break;
1040 default:
1041 SetLastError(ERROR_INVALID_PARAMETER);
1042 status = FALSE;
1043 }
1044 }
1045 else
1046 {
1047 SetLastError(ERROR_CANT_ACCESS_DOMAIN_INFO);
1048 status = FALSE;
1049 }
1050
1051 LsaFreeMemory(domainInfo);
1052 LsaClose(policyHandle);
1053
1054 return status;
1055}
1056
1057/***********************************************************************
1058 * GetUserNameExA (SECUR32.@)
1059 */
1060BOOLEAN WINAPI GetUserNameExA(
1061 EXTENDED_NAME_FORMAT NameFormat, LPSTR lpNameBuffer, PULONG nSize)
1062{
1063 FIXME("%d %p %p\n", NameFormat, lpNameBuffer, nSize);
1064 return FALSE;
1065}
1066
1067BOOLEAN WINAPI GetUserNameExW(
1068 EXTENDED_NAME_FORMAT NameFormat, LPWSTR lpNameBuffer, PULONG nSize)
1069{
1070 FIXME("%d %p %p\n", NameFormat, lpNameBuffer, nSize);
1071 return FALSE;
1072}
1073
1074BOOLEAN WINAPI TranslateNameA(
1075 LPCSTR lpAccountName, EXTENDED_NAME_FORMAT AccountNameFormat,
1076 EXTENDED_NAME_FORMAT DesiredNameFormat, LPSTR lpTranslatedName,
1077 PULONG nSize)
1078{
1079 FIXME("%p %d %d %p %p\n", lpAccountName, AccountNameFormat,
1080 DesiredNameFormat, lpTranslatedName, nSize);
1081 return FALSE;
1082}
1083
1084BOOLEAN WINAPI TranslateNameW(
1085 LPCWSTR lpAccountName, EXTENDED_NAME_FORMAT AccountNameFormat,
1086 EXTENDED_NAME_FORMAT DesiredNameFormat, LPWSTR lpTranslatedName,
1087 PULONG nSize)
1088{
1089 FIXME("%p %d %d %p %p\n", lpAccountName, AccountNameFormat,
1090 DesiredNameFormat, lpTranslatedName, nSize);
1091 return FALSE;
1092}
1093
1094/***********************************************************************
1095 * DllMain (SECUR32.0)
1096 */
1097BOOL WINAPI Secur32DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
1098{
1099 if (fdwReason == DLL_PROCESS_ATTACH)
1100 {
1101 DisableThreadLibraryCalls(hinstDLL);
1102 SECUR32_initializeProviders();
1103 }
1104 else if (fdwReason == DLL_PROCESS_DETACH)
1105 {
1106 SECUR32_freeProviders();
1107 }
1108
1109 return TRUE;
1110}
Note: See TracBrowser for help on using the repository browser.