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

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