secur32: Implement AcquireCredentialsHandle in the SSP/AP wrapper.
[wine.git] / dlls / secur32 / lsa.c
blob2ec38184dab50c07505d35df374927146de4b2a5
1 /*
2 * Copyright (C) 2004 Juan Lang
3 * Copyright (C) 2007 Kai Blin
4 * Copyright (C) 2017, 2018 Dmitry Timoshkov
6 * Local Security Authority functions, as far as secur32 has them.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include <stdarg.h>
25 #include "ntstatus.h"
26 #define WIN32_NO_STATUS
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winreg.h"
30 #include "sspi.h"
31 #include "ntsecapi.h"
32 #include "ntsecpkg.h"
33 #include "winternl.h"
34 #include "rpc.h"
35 #include "secur32_priv.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(secur32);
41 #define LSA_MAGIC ('L' << 24 | 'S' << 16 | 'A' << 8 | ' ')
43 struct lsa_package
45 ULONG package_id;
46 HMODULE mod;
47 LSA_STRING *name;
48 ULONG lsa_api_version, lsa_table_count, user_api_version, user_table_count;
49 SECPKG_FUNCTION_TABLE *lsa_api;
50 SECPKG_USER_FUNCTION_TABLE *user_api;
53 static struct lsa_package *loaded_packages;
54 static ULONG loaded_packages_count;
56 struct lsa_connection
58 DWORD magic;
61 NTSTATUS WINAPI LsaCallAuthenticationPackage(HANDLE lsa_handle, ULONG package_id,
62 PVOID in_buffer, ULONG in_buffer_length,
63 PVOID *out_buffer, PULONG out_buffer_length, PNTSTATUS status)
65 ULONG i;
67 TRACE("%p,%u,%p,%u,%p,%p,%p\n", lsa_handle, package_id, in_buffer,
68 in_buffer_length, out_buffer, out_buffer_length, status);
70 for (i = 0; i < loaded_packages_count; i++)
72 if (loaded_packages[i].package_id == package_id)
74 if (loaded_packages[i].lsa_api->CallPackageUntrusted)
75 return loaded_packages[i].lsa_api->CallPackageUntrusted(NULL /* FIXME*/,
76 in_buffer, NULL, in_buffer_length, out_buffer, out_buffer_length, status);
78 return SEC_E_UNSUPPORTED_FUNCTION;
82 return STATUS_INVALID_PARAMETER;
85 NTSTATUS WINAPI LsaConnectUntrusted(PHANDLE LsaHandle)
87 struct lsa_connection *lsa_conn;
89 TRACE("%p\n", LsaHandle);
91 lsa_conn = HeapAlloc(GetProcessHeap(), 0, sizeof(*lsa_conn));
92 if (!lsa_conn) return STATUS_NO_MEMORY;
94 lsa_conn->magic = LSA_MAGIC;
95 *LsaHandle = lsa_conn;
97 return STATUS_SUCCESS;
100 NTSTATUS WINAPI LsaDeregisterLogonProcess(HANDLE LsaHandle)
102 FIXME("%p stub\n", LsaHandle);
103 return STATUS_SUCCESS;
106 NTSTATUS WINAPI LsaEnumerateLogonSessions(PULONG LogonSessionCount,
107 PLUID* LogonSessionList)
109 FIXME("%p %p stub\n", LogonSessionCount, LogonSessionList);
110 *LogonSessionCount = 0;
111 *LogonSessionList = NULL;
113 return STATUS_SUCCESS;
116 NTSTATUS WINAPI LsaFreeReturnBuffer(PVOID Buffer)
118 FIXME("%p stub\n", Buffer);
119 return STATUS_SUCCESS;
122 NTSTATUS WINAPI LsaGetLogonSessionData(PLUID LogonId,
123 PSECURITY_LOGON_SESSION_DATA* ppLogonSessionData)
125 FIXME("%p %p stub\n", LogonId, ppLogonSessionData);
126 *ppLogonSessionData = NULL;
127 return STATUS_NOT_IMPLEMENTED;
130 NTSTATUS WINAPI LsaLogonUser(HANDLE LsaHandle, PLSA_STRING OriginName,
131 SECURITY_LOGON_TYPE LogonType, ULONG AuthenticationPackage,
132 PVOID AuthenticationInformation, ULONG AuthenticationInformationLength,
133 PTOKEN_GROUPS LocalGroups, PTOKEN_SOURCE SourceContext,
134 PVOID* ProfileBuffer, PULONG ProfileBufferLength, PLUID LogonId,
135 PHANDLE Token, PQUOTA_LIMITS Quotas, PNTSTATUS SubStatus)
137 FIXME("%p %p %d %d %p %d %p %p %p %p %p %p %p %p stub\n", LsaHandle,
138 OriginName, LogonType, AuthenticationPackage,
139 AuthenticationInformation, AuthenticationInformationLength,
140 LocalGroups, SourceContext, ProfileBuffer, ProfileBufferLength,
141 LogonId, Token, Quotas, SubStatus);
142 return STATUS_SUCCESS;
145 static NTSTATUS NTAPI lsa_CreateLogonSession(LUID *logon_id)
147 FIXME("%p: stub\n", logon_id);
148 return STATUS_NOT_IMPLEMENTED;
151 static NTSTATUS NTAPI lsa_DeleteLogonSession(LUID *logon_id)
153 FIXME("%p: stub\n", logon_id);
154 return STATUS_NOT_IMPLEMENTED;
157 static NTSTATUS NTAPI lsa_AddCredential(LUID *logon_id, ULONG package_id,
158 LSA_STRING *primary_key, LSA_STRING *credentials)
160 FIXME("%p,%u,%p,%p: stub\n", logon_id, package_id, primary_key, credentials);
161 return STATUS_NOT_IMPLEMENTED;
164 static NTSTATUS NTAPI lsa_GetCredentials(LUID *logon_id, ULONG package_id, ULONG *context,
165 BOOLEAN retrieve_all, LSA_STRING *primary_key, ULONG *primary_key_len, LSA_STRING *credentials)
167 FIXME("%p,%#x,%p,%d,%p,%p,%p: stub\n", logon_id, package_id, context,
168 retrieve_all, primary_key, primary_key_len, credentials);
169 return STATUS_NOT_IMPLEMENTED;
172 static NTSTATUS NTAPI lsa_DeleteCredential(LUID *logon_id, ULONG package_id, LSA_STRING *primary_key)
174 FIXME("%p,%#x,%p: stub\n", logon_id, package_id, primary_key);
175 return STATUS_NOT_IMPLEMENTED;
178 static void * NTAPI lsa_AllocateLsaHeap(ULONG size)
180 TRACE("%u\n", size);
181 return HeapAlloc(GetProcessHeap(), 0, size);
184 static void NTAPI lsa_FreeLsaHeap(void *p)
186 TRACE("%p\n", p);
187 HeapFree(GetProcessHeap(), 0, p);
190 static NTSTATUS NTAPI lsa_AllocateClientBuffer(PLSA_CLIENT_REQUEST req, ULONG size, void **p)
192 TRACE("%p,%u,%p\n", req, size, p);
193 *p = HeapAlloc(GetProcessHeap(), 0, size);
194 return *p ? STATUS_SUCCESS : STATUS_NO_MEMORY;
197 static NTSTATUS NTAPI lsa_FreeClientBuffer(PLSA_CLIENT_REQUEST req, void *p)
199 TRACE("%p,%p\n", req, p);
200 HeapFree(GetProcessHeap(), 0, p);
201 return STATUS_SUCCESS;
204 static NTSTATUS NTAPI lsa_CopyToClientBuffer(PLSA_CLIENT_REQUEST req, ULONG size, void *client, void *buf)
206 TRACE("%p,%u,%p,%p\n", req, size, client, buf);
207 memcpy(client, buf, size);
208 return STATUS_SUCCESS;
211 static NTSTATUS NTAPI lsa_CopyFromClientBuffer(PLSA_CLIENT_REQUEST req, ULONG size, void *buf, void *client)
213 TRACE("%p,%u,%p,%p\n", req, size, buf, client);
214 memcpy(buf, client, size);
215 return STATUS_SUCCESS;
218 static LSA_DISPATCH_TABLE lsa_dispatch =
220 lsa_CreateLogonSession,
221 lsa_DeleteLogonSession,
222 lsa_AddCredential,
223 lsa_GetCredentials,
224 lsa_DeleteCredential,
225 lsa_AllocateLsaHeap,
226 lsa_FreeLsaHeap,
227 lsa_AllocateClientBuffer,
228 lsa_FreeClientBuffer,
229 lsa_CopyToClientBuffer,
230 lsa_CopyFromClientBuffer
233 static NTSTATUS NTAPI lsa_RegisterCallback(ULONG callback_id, PLSA_CALLBACK_FUNCTION callback)
235 FIXME("%u,%p: stub\n", callback_id, callback);
236 return STATUS_NOT_IMPLEMENTED;
239 static SECPKG_DLL_FUNCTIONS lsa_dll_dispatch =
241 lsa_AllocateLsaHeap,
242 lsa_FreeLsaHeap,
243 lsa_RegisterCallback
246 static SECURITY_STATUS lsa_lookup_package(SEC_WCHAR *nameW, struct lsa_package **lsa_package)
248 ULONG i;
249 UNICODE_STRING package_name, name;
251 for (i = 0; i < loaded_packages_count; i++)
253 if (RtlAnsiStringToUnicodeString(&package_name, loaded_packages[i].name, TRUE))
254 return SEC_E_INSUFFICIENT_MEMORY;
256 RtlInitUnicodeString(&name, nameW);
258 if (RtlEqualUnicodeString(&package_name, &name, TRUE))
260 RtlFreeUnicodeString(&package_name);
261 *lsa_package = &loaded_packages[i];
262 return SEC_E_OK;
265 RtlFreeUnicodeString(&package_name);
268 return SEC_E_SECPKG_NOT_FOUND;
271 static SECURITY_STATUS WINAPI lsa_AcquireCredentialsHandleW(
272 SEC_WCHAR *principal, SEC_WCHAR *package, ULONG credentials_use,
273 LUID *logon_id, void *auth_data, SEC_GET_KEY_FN get_key_fn,
274 void *get_key_arg, CredHandle *credential, TimeStamp *ts_expiry)
276 SECURITY_STATUS status;
277 struct lsa_package *lsa_package;
278 UNICODE_STRING principal_us;
279 LSA_SEC_HANDLE lsa_credential;
281 TRACE("%s %s %#x %p %p %p %p %p\n", debugstr_w(principal), debugstr_w(package),
282 credentials_use, auth_data, get_key_fn, get_key_arg, credential, ts_expiry);
284 if (!credential) return SEC_E_INVALID_HANDLE;
285 if (!package) return SEC_E_SECPKG_NOT_FOUND;
287 status = lsa_lookup_package(package, &lsa_package);
288 if (status != SEC_E_OK) return status;
290 if (!lsa_package->lsa_api || !lsa_package->lsa_api->SpAcquireCredentialsHandle)
291 return SEC_E_UNSUPPORTED_FUNCTION;
293 if (principal)
294 RtlInitUnicodeString(&principal_us, principal);
296 status = lsa_package->lsa_api->SpAcquireCredentialsHandle(principal ? &principal_us : NULL,
297 credentials_use, logon_id, auth_data, get_key_fn, get_key_arg, &lsa_credential, ts_expiry);
298 if (status == SEC_E_OK)
300 credential->dwLower = (ULONG_PTR)lsa_credential;
301 credential->dwUpper = (ULONG_PTR)lsa_package;
303 return status;
306 static SECURITY_STATUS WINAPI lsa_AcquireCredentialsHandleA(
307 SEC_CHAR *principal, SEC_CHAR *package, ULONG credentials_use,
308 LUID *logon_id, void *auth_data, SEC_GET_KEY_FN get_key_fn,
309 void *get_key_arg, CredHandle *credential, TimeStamp *ts_expiry)
311 SECURITY_STATUS status = SEC_E_INSUFFICIENT_MEMORY;
312 int len_user = 0, len_domain = 0, len_passwd = 0;
313 SEC_WCHAR *principalW = NULL, *packageW = NULL, *user = NULL, *domain = NULL, *passwd = NULL;
314 SEC_WINNT_AUTH_IDENTITY_W *auth_dataW = NULL;
315 SEC_WINNT_AUTH_IDENTITY_A *id = NULL;
317 TRACE("%s %s %#x %p %p %p %p %p\n", debugstr_a(principal), debugstr_a(package),
318 credentials_use, auth_data, get_key_fn, get_key_arg, credential, ts_expiry);
320 if (principal)
322 int len = MultiByteToWideChar( CP_ACP, 0, principal, -1, NULL, 0 );
323 if (!(principalW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(SEC_WCHAR) ))) goto done;
324 MultiByteToWideChar( CP_ACP, 0, principal, -1, principalW, len );
326 if (package)
328 int len = MultiByteToWideChar( CP_ACP, 0, package, -1, NULL, 0 );
329 if (!(packageW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(SEC_WCHAR) ))) goto done;
330 MultiByteToWideChar( CP_ACP, 0, package, -1, packageW, len );
332 if (auth_data)
334 id = (PSEC_WINNT_AUTH_IDENTITY_A)auth_data;
336 if (id->Flags == SEC_WINNT_AUTH_IDENTITY_ANSI)
338 if (!(auth_dataW = HeapAlloc( GetProcessHeap(), 0, sizeof(SEC_WINNT_AUTH_IDENTITY_W) ))) goto done;
339 if (id->UserLength)
341 len_user = MultiByteToWideChar( CP_ACP, 0, (char *)id->User, id->UserLength, NULL, 0 );
342 if (!(user = HeapAlloc( GetProcessHeap(), 0, len_user * sizeof(SEC_WCHAR) ))) goto done;
343 MultiByteToWideChar( CP_ACP, 0, (char *)id->User, id->UserLength, user, len_user );
345 if (id->DomainLength)
347 len_domain = MultiByteToWideChar( CP_ACP, 0, (char *)id->Domain, id->DomainLength, NULL, 0 );
348 if (!(domain = HeapAlloc( GetProcessHeap(), 0, len_domain * sizeof(SEC_WCHAR) ))) goto done;
349 MultiByteToWideChar( CP_ACP, 0, (char *)id->Domain, id->DomainLength, domain, len_domain );
351 if (id->PasswordLength)
353 len_passwd = MultiByteToWideChar( CP_ACP, 0, (char *)id->Password, id->PasswordLength, NULL, 0 );
354 if (!(passwd = HeapAlloc( GetProcessHeap(), 0, len_passwd * sizeof(SEC_WCHAR) ))) goto done;
355 MultiByteToWideChar( CP_ACP, 0, (char *)id->Password, id->PasswordLength, passwd, len_passwd );
357 auth_dataW->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
358 auth_dataW->User = user;
359 auth_dataW->UserLength = len_user;
360 auth_dataW->Domain = domain;
361 auth_dataW->DomainLength = len_domain;
362 auth_dataW->Password = passwd;
363 auth_dataW->PasswordLength = len_passwd;
365 else auth_dataW = (PSEC_WINNT_AUTH_IDENTITY_W)auth_data;
368 status = lsa_AcquireCredentialsHandleW( principalW, packageW, credentials_use, logon_id, auth_dataW, get_key_fn,
369 get_key_arg, credential, ts_expiry );
370 done:
371 if (auth_dataW != (SEC_WINNT_AUTH_IDENTITY_W *)id) HeapFree( GetProcessHeap(), 0, auth_dataW );
372 HeapFree( GetProcessHeap(), 0, packageW );
373 HeapFree( GetProcessHeap(), 0, principalW );
374 HeapFree( GetProcessHeap(), 0, user );
375 HeapFree( GetProcessHeap(), 0, domain );
376 HeapFree( GetProcessHeap(), 0, passwd );
377 return status;
380 static const SecurityFunctionTableW lsa_sspi_tableW =
383 NULL, /* EnumerateSecurityPackagesW */
384 NULL, /* QueryCredentialsAttributesW */
385 lsa_AcquireCredentialsHandleW,
386 NULL, /* FreeCredentialsHandle */
387 NULL, /* Reserved2 */
388 NULL, /* InitializeSecurityContextW */
389 NULL, /* AcceptSecurityContext */
390 NULL, /* CompleteAuthToken */
391 NULL, /* DeleteSecurityContext */
392 NULL, /* ApplyControlToken */
393 NULL, /* QueryContextAttributesW */
394 NULL, /* ImpersonateSecurityContext */
395 NULL, /* RevertSecurityContext */
396 NULL, /* MakeSignature */
397 NULL, /* VerifySignature */
398 NULL, /* FreeContextBuffer */
399 NULL, /* QuerySecurityPackageInfoW */
400 NULL, /* Reserved3 */
401 NULL, /* Reserved4 */
402 NULL, /* ExportSecurityContext */
403 NULL, /* ImportSecurityContextW */
404 NULL, /* AddCredentialsW */
405 NULL, /* Reserved8 */
406 NULL, /* QuerySecurityContextToken */
407 NULL, /* EncryptMessage */
408 NULL, /* DecryptMessage */
409 NULL, /* SetContextAttributesW */
412 static const SecurityFunctionTableA lsa_sspi_tableA =
415 NULL, /* EnumerateSecurityPackagesA */
416 NULL, /* QueryCredentialsAttributesA */
417 lsa_AcquireCredentialsHandleA,
418 NULL, /* FreeCredentialsHandle */
419 NULL, /* Reserved2 */
420 NULL, /* InitializeSecurityContextA */
421 NULL, /* AcceptSecurityContext */
422 NULL, /* CompleteAuthToken */
423 NULL, /* DeleteSecurityContext */
424 NULL, /* ApplyControlToken */
425 NULL, /* QueryContextAttributesA */
426 NULL, /* ImpersonateSecurityContext */
427 NULL, /* RevertSecurityContext */
428 NULL, /* MakeSignature */
429 NULL, /* VerifySignature */
430 NULL, /* FreeContextBuffer */
431 NULL, /* QuerySecurityPackageInfoA */
432 NULL, /* Reserved3 */
433 NULL, /* Reserved4 */
434 NULL, /* ExportSecurityContext */
435 NULL, /* ImportSecurityContextA */
436 NULL, /* AddCredentialsA */
437 NULL, /* Reserved8 */
438 NULL, /* QuerySecurityContextToken */
439 NULL, /* EncryptMessage */
440 NULL, /* DecryptMessage */
441 NULL, /* SetContextAttributesA */
444 static void add_package(struct lsa_package *package)
446 struct lsa_package *new_loaded_packages;
448 if (!loaded_packages)
449 new_loaded_packages = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_loaded_packages));
450 else
451 new_loaded_packages = HeapReAlloc(GetProcessHeap(), 0, loaded_packages, sizeof(*new_loaded_packages) * (loaded_packages_count + 1));
453 if (new_loaded_packages)
455 loaded_packages = new_loaded_packages;
456 loaded_packages[loaded_packages_count] = *package;
457 loaded_packages_count++;
461 static BOOL load_package(const WCHAR *name, struct lsa_package *package, ULONG package_id)
463 NTSTATUS (NTAPI *pSpLsaModeInitialize)(ULONG, PULONG, PSECPKG_FUNCTION_TABLE *, PULONG);
464 NTSTATUS (NTAPI *pSpUserModeInitialize)(ULONG, PULONG, PSECPKG_USER_FUNCTION_TABLE *, PULONG);
466 memset(package, 0, sizeof(*package));
468 package->mod = LoadLibraryW(name);
469 if (!package->mod) return FALSE;
471 pSpLsaModeInitialize = (void *)GetProcAddress(package->mod, "SpLsaModeInitialize");
472 if (pSpLsaModeInitialize)
474 NTSTATUS status;
476 status = pSpLsaModeInitialize(SECPKG_INTERFACE_VERSION, &package->lsa_api_version, &package->lsa_api, &package->lsa_table_count);
477 if (status == STATUS_SUCCESS)
479 status = package->lsa_api->InitializePackage(package_id, &lsa_dispatch, NULL, NULL, &package->name);
480 if (status == STATUS_SUCCESS)
482 TRACE("%s => %p, name %s, version %#x, api table %p, table count %u\n",
483 debugstr_w(name), package->mod, debugstr_an(package->name->Buffer, package->name->Length),
484 package->lsa_api_version, package->lsa_api, package->lsa_table_count);
485 package->package_id = package_id;
487 status = package->lsa_api->Initialize(package_id, NULL /* FIXME: params */, NULL);
488 if (status == STATUS_SUCCESS)
490 pSpUserModeInitialize = (void *)GetProcAddress(package->mod, "SpUserModeInitialize");
491 if (pSpUserModeInitialize)
493 status = pSpUserModeInitialize(SECPKG_INTERFACE_VERSION, &package->user_api_version, &package->user_api, &package->user_table_count);
494 if (status == STATUS_SUCCESS)
495 package->user_api->InstanceInit(SECPKG_INTERFACE_VERSION, &lsa_dll_dispatch, NULL);
498 return TRUE;
503 FreeLibrary(package->mod);
504 return FALSE;
507 #define MAX_SERVICE_NAME 260
509 void load_auth_packages(void)
511 static const WCHAR LSA_KEY[] = { 'S','y','s','t','e','m','\\',
512 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
513 'C','o','n','t','r','o','l','\\','L','s','a',0 };
514 DWORD err, i;
515 HKEY root;
516 SecureProvider *provider;
518 err = RegOpenKeyExW(HKEY_LOCAL_MACHINE, LSA_KEY, 0, KEY_READ, &root);
519 if (err != ERROR_SUCCESS) return;
521 i = 0;
522 for (;;)
524 WCHAR name[MAX_SERVICE_NAME];
525 struct lsa_package package;
527 err = RegEnumKeyW(root, i++, name, MAX_SERVICE_NAME);
528 if (err == ERROR_NO_MORE_ITEMS)
529 break;
531 if (err != ERROR_SUCCESS)
532 continue;
534 if (!load_package(name, &package, i))
535 continue;
537 add_package(&package);
540 RegCloseKey(root);
542 if (!loaded_packages_count) return;
544 provider = SECUR32_addProvider(&lsa_sspi_tableA, &lsa_sspi_tableW, NULL);
545 if (!provider)
547 ERR("Failed to add SSP/AP provider\n");
548 return;
551 for (i = 0; i < loaded_packages_count; i++)
553 SecPkgInfoW *info;
555 info = HeapAlloc(GetProcessHeap(), 0, loaded_packages[i].lsa_table_count * sizeof(*info));
556 if (info)
558 NTSTATUS status;
560 status = loaded_packages[i].lsa_api->GetInfo(info);
561 if (status == STATUS_SUCCESS)
562 SECUR32_addPackages(provider, loaded_packages[i].lsa_table_count, NULL, info);
564 HeapFree(GetProcessHeap(), 0, info);
569 NTSTATUS WINAPI LsaLookupAuthenticationPackage(HANDLE lsa_handle,
570 PLSA_STRING package_name, PULONG package_id)
572 ULONG i;
574 TRACE("%p %p %p\n", lsa_handle, package_name, package_id);
576 for (i = 0; i < loaded_packages_count; i++)
578 if (!RtlCompareString(loaded_packages[i].name, package_name, FALSE))
580 *package_id = loaded_packages[i].package_id;
581 return STATUS_SUCCESS;
585 return STATUS_UNSUCCESSFUL; /* FIXME */
588 NTSTATUS WINAPI LsaRegisterLogonProcess(PLSA_STRING LogonProcessName,
589 PHANDLE LsaHandle, PLSA_OPERATIONAL_MODE SecurityMode)
591 FIXME("%p %p %p stub\n", LogonProcessName, LsaHandle, SecurityMode);
592 return STATUS_SUCCESS;