secur32: Return a handle from LsaRegisterLogonProcess.
[wine.git] / dlls / secur32 / lsa.c
blob5fe6f3a8f21061ef8d519f43fb287a23ac46c56d
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 static const char *debugstr_as(const LSA_STRING *str)
63 if (!str) return "<null>";
64 return debugstr_an(str->Buffer, str->Length);
67 NTSTATUS WINAPI LsaCallAuthenticationPackage(HANDLE lsa_handle, ULONG package_id,
68 PVOID in_buffer, ULONG in_buffer_length,
69 PVOID *out_buffer, PULONG out_buffer_length, PNTSTATUS status)
71 ULONG i;
73 TRACE("%p,%u,%p,%u,%p,%p,%p\n", lsa_handle, package_id, in_buffer,
74 in_buffer_length, out_buffer, out_buffer_length, status);
76 for (i = 0; i < loaded_packages_count; i++)
78 if (loaded_packages[i].package_id == package_id)
80 if (loaded_packages[i].lsa_api->CallPackageUntrusted)
81 return loaded_packages[i].lsa_api->CallPackageUntrusted(NULL /* FIXME*/,
82 in_buffer, NULL, in_buffer_length, out_buffer, out_buffer_length, status);
84 return SEC_E_UNSUPPORTED_FUNCTION;
88 return STATUS_INVALID_PARAMETER;
91 struct lsa_connection *alloc_lsa_connection(void)
93 struct lsa_connection *ret;
94 if (!(ret = heap_alloc(sizeof(*ret)))) return NULL;
95 ret->magic = LSA_MAGIC;
96 return ret;
99 NTSTATUS WINAPI LsaConnectUntrusted(PHANDLE LsaHandle)
101 struct lsa_connection *lsa_conn;
103 TRACE("%p\n", LsaHandle);
105 if (!(lsa_conn = alloc_lsa_connection())) return STATUS_NO_MEMORY;
106 *LsaHandle = lsa_conn;
107 return STATUS_SUCCESS;
110 NTSTATUS WINAPI LsaRegisterLogonProcess(PLSA_STRING LogonProcessName,
111 PHANDLE LsaHandle, PLSA_OPERATIONAL_MODE SecurityMode)
113 struct lsa_connection *lsa_conn;
115 FIXME("%s %p %p stub\n", debugstr_as(LogonProcessName), LsaHandle, SecurityMode);
117 if (!(lsa_conn = alloc_lsa_connection())) return STATUS_NO_MEMORY;
118 *LsaHandle = lsa_conn;
119 return STATUS_SUCCESS;
122 NTSTATUS WINAPI LsaDeregisterLogonProcess(HANDLE LsaHandle)
124 struct lsa_connection *lsa_conn = (struct lsa_connection *)LsaHandle;
126 TRACE("%p\n", LsaHandle);
128 if (!lsa_conn || lsa_conn->magic != LSA_MAGIC) return STATUS_INVALID_HANDLE;
129 lsa_conn->magic = 0;
130 heap_free(lsa_conn);
132 return STATUS_SUCCESS;
135 NTSTATUS WINAPI LsaEnumerateLogonSessions(PULONG LogonSessionCount,
136 PLUID* LogonSessionList)
138 FIXME("%p %p stub\n", LogonSessionCount, LogonSessionList);
139 *LogonSessionCount = 0;
140 *LogonSessionList = NULL;
142 return STATUS_SUCCESS;
145 NTSTATUS WINAPI LsaFreeReturnBuffer(PVOID buffer)
147 TRACE("%p\n", buffer);
148 heap_free(buffer);
149 return STATUS_SUCCESS;
152 NTSTATUS WINAPI LsaGetLogonSessionData(PLUID LogonId,
153 PSECURITY_LOGON_SESSION_DATA* ppLogonSessionData)
155 FIXME("%p %p stub\n", LogonId, ppLogonSessionData);
156 *ppLogonSessionData = NULL;
157 return STATUS_NOT_IMPLEMENTED;
160 NTSTATUS WINAPI LsaLogonUser(HANDLE LsaHandle, PLSA_STRING OriginName,
161 SECURITY_LOGON_TYPE LogonType, ULONG AuthenticationPackage,
162 PVOID AuthenticationInformation, ULONG AuthenticationInformationLength,
163 PTOKEN_GROUPS LocalGroups, PTOKEN_SOURCE SourceContext,
164 PVOID* ProfileBuffer, PULONG ProfileBufferLength, PLUID LogonId,
165 PHANDLE Token, PQUOTA_LIMITS Quotas, PNTSTATUS SubStatus)
167 FIXME("%p %s %d %d %p %d %p %p %p %p %p %p %p %p stub\n", LsaHandle,
168 debugstr_as(OriginName), LogonType, AuthenticationPackage,
169 AuthenticationInformation, AuthenticationInformationLength,
170 LocalGroups, SourceContext, ProfileBuffer, ProfileBufferLength,
171 LogonId, Token, Quotas, SubStatus);
172 return STATUS_SUCCESS;
175 static NTSTATUS NTAPI lsa_CreateLogonSession(LUID *logon_id)
177 FIXME("%p: stub\n", logon_id);
178 return STATUS_NOT_IMPLEMENTED;
181 static NTSTATUS NTAPI lsa_DeleteLogonSession(LUID *logon_id)
183 FIXME("%p: stub\n", logon_id);
184 return STATUS_NOT_IMPLEMENTED;
187 static NTSTATUS NTAPI lsa_AddCredential(LUID *logon_id, ULONG package_id,
188 LSA_STRING *primary_key, LSA_STRING *credentials)
190 FIXME("%p,%u,%s,%s: stub\n", logon_id, package_id,
191 debugstr_as(primary_key), debugstr_as(credentials));
192 return STATUS_NOT_IMPLEMENTED;
195 static NTSTATUS NTAPI lsa_GetCredentials(LUID *logon_id, ULONG package_id, ULONG *context,
196 BOOLEAN retrieve_all, LSA_STRING *primary_key, ULONG *primary_key_len, LSA_STRING *credentials)
198 FIXME("%p,%#x,%p,%d,%p,%p,%p: stub\n", logon_id, package_id, context,
199 retrieve_all, primary_key, primary_key_len, credentials);
200 return STATUS_NOT_IMPLEMENTED;
203 static NTSTATUS NTAPI lsa_DeleteCredential(LUID *logon_id, ULONG package_id, LSA_STRING *primary_key)
205 FIXME("%p,%#x,%s: stub\n", logon_id, package_id, debugstr_as(primary_key));
206 return STATUS_NOT_IMPLEMENTED;
209 static void * NTAPI lsa_AllocateLsaHeap(ULONG size)
211 TRACE("%u\n", size);
212 return heap_alloc(size);
215 static void NTAPI lsa_FreeLsaHeap(void *p)
217 TRACE("%p\n", p);
218 heap_free(p);
221 static NTSTATUS NTAPI lsa_AllocateClientBuffer(PLSA_CLIENT_REQUEST req, ULONG size, void **p)
223 TRACE("%p,%u,%p\n", req, size, p);
224 *p = heap_alloc(size);
225 return *p ? STATUS_SUCCESS : STATUS_NO_MEMORY;
228 static NTSTATUS NTAPI lsa_FreeClientBuffer(PLSA_CLIENT_REQUEST req, void *p)
230 TRACE("%p,%p\n", req, p);
231 heap_free(p);
232 return STATUS_SUCCESS;
235 static NTSTATUS NTAPI lsa_CopyToClientBuffer(PLSA_CLIENT_REQUEST req, ULONG size, void *client, void *buf)
237 TRACE("%p,%u,%p,%p\n", req, size, client, buf);
238 memcpy(client, buf, size);
239 return STATUS_SUCCESS;
242 static NTSTATUS NTAPI lsa_CopyFromClientBuffer(PLSA_CLIENT_REQUEST req, ULONG size, void *buf, void *client)
244 TRACE("%p,%u,%p,%p\n", req, size, buf, client);
245 memcpy(buf, client, size);
246 return STATUS_SUCCESS;
249 static LSA_DISPATCH_TABLE lsa_dispatch =
251 lsa_CreateLogonSession,
252 lsa_DeleteLogonSession,
253 lsa_AddCredential,
254 lsa_GetCredentials,
255 lsa_DeleteCredential,
256 lsa_AllocateLsaHeap,
257 lsa_FreeLsaHeap,
258 lsa_AllocateClientBuffer,
259 lsa_FreeClientBuffer,
260 lsa_CopyToClientBuffer,
261 lsa_CopyFromClientBuffer
264 static NTSTATUS NTAPI lsa_RegisterCallback(ULONG callback_id, PLSA_CALLBACK_FUNCTION callback)
266 FIXME("%u,%p: stub\n", callback_id, callback);
267 return STATUS_NOT_IMPLEMENTED;
270 static SECPKG_DLL_FUNCTIONS lsa_dll_dispatch =
272 lsa_AllocateLsaHeap,
273 lsa_FreeLsaHeap,
274 lsa_RegisterCallback
277 static SECURITY_STATUS lsa_lookup_package(SEC_WCHAR *nameW, struct lsa_package **lsa_package)
279 ULONG i;
280 UNICODE_STRING package_name, name;
282 for (i = 0; i < loaded_packages_count; i++)
284 if (RtlAnsiStringToUnicodeString(&package_name, loaded_packages[i].name, TRUE))
285 return SEC_E_INSUFFICIENT_MEMORY;
287 RtlInitUnicodeString(&name, nameW);
289 if (RtlEqualUnicodeString(&package_name, &name, TRUE))
291 RtlFreeUnicodeString(&package_name);
292 *lsa_package = &loaded_packages[i];
293 return SEC_E_OK;
296 RtlFreeUnicodeString(&package_name);
299 return SEC_E_SECPKG_NOT_FOUND;
302 static SECURITY_STATUS WINAPI lsa_AcquireCredentialsHandleW(
303 SEC_WCHAR *principal, SEC_WCHAR *package, ULONG credentials_use,
304 LUID *logon_id, void *auth_data, SEC_GET_KEY_FN get_key_fn,
305 void *get_key_arg, CredHandle *credential, TimeStamp *ts_expiry)
307 SECURITY_STATUS status;
308 struct lsa_package *lsa_package;
309 UNICODE_STRING principal_us;
310 LSA_SEC_HANDLE lsa_credential;
312 TRACE("%s %s %#x %p %p %p %p %p\n", debugstr_w(principal), debugstr_w(package),
313 credentials_use, auth_data, get_key_fn, get_key_arg, credential, ts_expiry);
315 if (!credential) return SEC_E_INVALID_HANDLE;
316 if (!package) return SEC_E_SECPKG_NOT_FOUND;
318 status = lsa_lookup_package(package, &lsa_package);
319 if (status != SEC_E_OK) return status;
321 if (!lsa_package->lsa_api || !lsa_package->lsa_api->SpAcquireCredentialsHandle)
322 return SEC_E_UNSUPPORTED_FUNCTION;
324 if (principal)
325 RtlInitUnicodeString(&principal_us, principal);
327 status = lsa_package->lsa_api->SpAcquireCredentialsHandle(principal ? &principal_us : NULL,
328 credentials_use, logon_id, auth_data, get_key_fn, get_key_arg, &lsa_credential, ts_expiry);
329 if (status == SEC_E_OK)
331 credential->dwLower = (ULONG_PTR)lsa_credential;
332 credential->dwUpper = (ULONG_PTR)lsa_package;
334 return status;
337 static SECURITY_STATUS WINAPI lsa_AcquireCredentialsHandleA(
338 SEC_CHAR *principal, SEC_CHAR *package, ULONG credentials_use,
339 LUID *logon_id, void *auth_data, SEC_GET_KEY_FN get_key_fn,
340 void *get_key_arg, CredHandle *credential, TimeStamp *ts_expiry)
342 SECURITY_STATUS status = SEC_E_INSUFFICIENT_MEMORY;
343 int len_user = 0, len_domain = 0, len_passwd = 0;
344 SEC_WCHAR *principalW = NULL, *packageW = NULL, *user = NULL, *domain = NULL, *passwd = NULL;
345 SEC_WINNT_AUTH_IDENTITY_W *auth_dataW = NULL;
346 SEC_WINNT_AUTH_IDENTITY_A *id = NULL;
348 TRACE("%s %s %#x %p %p %p %p %p\n", debugstr_a(principal), debugstr_a(package),
349 credentials_use, auth_data, get_key_fn, get_key_arg, credential, ts_expiry);
351 if (principal)
353 int len = MultiByteToWideChar( CP_ACP, 0, principal, -1, NULL, 0 );
354 if (!(principalW = heap_alloc( len * sizeof(SEC_WCHAR) ))) goto done;
355 MultiByteToWideChar( CP_ACP, 0, principal, -1, principalW, len );
357 if (package)
359 int len = MultiByteToWideChar( CP_ACP, 0, package, -1, NULL, 0 );
360 if (!(packageW = heap_alloc( len * sizeof(SEC_WCHAR) ))) goto done;
361 MultiByteToWideChar( CP_ACP, 0, package, -1, packageW, len );
363 if (auth_data)
365 id = (PSEC_WINNT_AUTH_IDENTITY_A)auth_data;
367 if (id->Flags == SEC_WINNT_AUTH_IDENTITY_ANSI)
369 if (!(auth_dataW = heap_alloc( sizeof(SEC_WINNT_AUTH_IDENTITY_W) ))) goto done;
370 if (id->UserLength)
372 len_user = MultiByteToWideChar( CP_ACP, 0, (char *)id->User, id->UserLength, NULL, 0 );
373 if (!(user = heap_alloc( len_user * sizeof(SEC_WCHAR) ))) goto done;
374 MultiByteToWideChar( CP_ACP, 0, (char *)id->User, id->UserLength, user, len_user );
376 if (id->DomainLength)
378 len_domain = MultiByteToWideChar( CP_ACP, 0, (char *)id->Domain, id->DomainLength, NULL, 0 );
379 if (!(domain = heap_alloc( len_domain * sizeof(SEC_WCHAR) ))) goto done;
380 MultiByteToWideChar( CP_ACP, 0, (char *)id->Domain, id->DomainLength, domain, len_domain );
382 if (id->PasswordLength)
384 len_passwd = MultiByteToWideChar( CP_ACP, 0, (char *)id->Password, id->PasswordLength, NULL, 0 );
385 if (!(passwd = heap_alloc( len_passwd * sizeof(SEC_WCHAR) ))) goto done;
386 MultiByteToWideChar( CP_ACP, 0, (char *)id->Password, id->PasswordLength, passwd, len_passwd );
388 auth_dataW->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
389 auth_dataW->User = user;
390 auth_dataW->UserLength = len_user;
391 auth_dataW->Domain = domain;
392 auth_dataW->DomainLength = len_domain;
393 auth_dataW->Password = passwd;
394 auth_dataW->PasswordLength = len_passwd;
396 else auth_dataW = (PSEC_WINNT_AUTH_IDENTITY_W)auth_data;
399 status = lsa_AcquireCredentialsHandleW( principalW, packageW, credentials_use, logon_id, auth_dataW, get_key_fn,
400 get_key_arg, credential, ts_expiry );
401 done:
402 if (auth_dataW != (SEC_WINNT_AUTH_IDENTITY_W *)id) heap_free( auth_dataW );
403 heap_free( packageW );
404 heap_free( principalW );
405 heap_free( user );
406 heap_free( domain );
407 heap_free( passwd );
408 return status;
411 static SECURITY_STATUS WINAPI lsa_FreeCredentialsHandle(CredHandle *credential)
413 struct lsa_package *lsa_package;
414 LSA_SEC_HANDLE lsa_credential;
416 TRACE("%p\n", credential);
417 if (!credential) return SEC_E_INVALID_HANDLE;
419 lsa_package = (struct lsa_package *)credential->dwUpper;
420 lsa_credential = (LSA_SEC_HANDLE)credential->dwLower;
422 if (!lsa_package) return SEC_E_INVALID_HANDLE;
424 if (!lsa_package->lsa_api || !lsa_package->lsa_api->FreeCredentialsHandle)
425 return SEC_E_UNSUPPORTED_FUNCTION;
427 return lsa_package->lsa_api->FreeCredentialsHandle(lsa_credential);
430 static SECURITY_STATUS WINAPI lsa_InitializeSecurityContextW(
431 CredHandle *credential, CtxtHandle *context, SEC_WCHAR *target_name, ULONG context_req,
432 ULONG reserved1, ULONG target_data_rep, SecBufferDesc *input, ULONG reserved2,
433 CtxtHandle *new_context, SecBufferDesc *output, ULONG *context_attr, TimeStamp *ts_expiry)
435 SECURITY_STATUS status;
436 struct lsa_package *lsa_package = NULL;
437 LSA_SEC_HANDLE lsa_credential = 0, lsa_context = 0, new_lsa_context;
438 UNICODE_STRING target_name_us;
439 BOOLEAN mapped_context;
441 TRACE("%p %p %s %#x %d %d %p %d %p %p %p %p\n", credential, context,
442 debugstr_w(target_name), context_req, reserved1, target_data_rep, input,
443 reserved2, new_context, output, context_attr, ts_expiry);
445 if (context)
447 lsa_package = (struct lsa_package *)context->dwUpper;
448 lsa_context = (LSA_SEC_HANDLE)context->dwLower;
450 else if (credential)
452 lsa_package = (struct lsa_package *)credential->dwUpper;
453 lsa_credential = (LSA_SEC_HANDLE)credential->dwLower;
456 if (!lsa_package || !new_context) return SEC_E_INVALID_HANDLE;
458 if (!lsa_package->lsa_api || !lsa_package->lsa_api->InitLsaModeContext)
459 return SEC_E_UNSUPPORTED_FUNCTION;
461 if (target_name)
462 RtlInitUnicodeString(&target_name_us, target_name);
464 status = lsa_package->lsa_api->InitLsaModeContext(lsa_credential, lsa_context,
465 target_name ? &target_name_us : NULL, context_req, target_data_rep, input,
466 &new_lsa_context, output, context_attr, ts_expiry, &mapped_context, NULL /* FIXME */);
467 if (status == SEC_E_OK || status == SEC_I_CONTINUE_NEEDED)
469 new_context->dwLower = (ULONG_PTR)new_lsa_context;
470 new_context->dwUpper = (ULONG_PTR)lsa_package;
472 return status;
475 static SECURITY_STATUS WINAPI lsa_InitializeSecurityContextA(
476 CredHandle *credential, CtxtHandle *context, SEC_CHAR *target_name, ULONG context_req,
477 ULONG reserved1, ULONG target_data_rep, SecBufferDesc *input, ULONG reserved2,
478 CtxtHandle *new_context, SecBufferDesc *output, ULONG *context_attr, TimeStamp *ts_expiry)
480 SECURITY_STATUS status;
481 SEC_WCHAR *targetW = NULL;
483 TRACE("%p %p %s %#x %d %d %p %d %p %p %p %p\n", credential, context,
484 debugstr_a(target_name), context_req, reserved1, target_data_rep, input,
485 reserved2, new_context, output, context_attr, ts_expiry);
487 if (target_name)
489 int len = MultiByteToWideChar( CP_ACP, 0, target_name, -1, NULL, 0 );
490 if (!(targetW = heap_alloc( len * sizeof(SEC_WCHAR) ))) return SEC_E_INSUFFICIENT_MEMORY;
491 MultiByteToWideChar( CP_ACP, 0, target_name, -1, targetW, len );
494 status = lsa_InitializeSecurityContextW( credential, context, targetW, context_req, reserved1, target_data_rep,
495 input, reserved2, new_context, output, context_attr, ts_expiry );
496 heap_free( targetW );
497 return status;
500 static SECURITY_STATUS WINAPI lsa_AcceptSecurityContext(
501 CredHandle *credential, CtxtHandle *context, SecBufferDesc *input,
502 ULONG context_req, ULONG target_data_rep, CtxtHandle *new_context,
503 SecBufferDesc *output, ULONG *context_attr, TimeStamp *ts_expiry)
505 SECURITY_STATUS status;
506 struct lsa_package *lsa_package = NULL;
507 LSA_SEC_HANDLE lsa_credential = 0, lsa_context = 0, new_lsa_context;
508 BOOLEAN mapped_context;
510 TRACE("%p %p %p %#x %#x %p %p %p %p\n", credential, context, input,
511 context_req, target_data_rep, new_context, output, context_attr, ts_expiry);
513 if (context)
515 lsa_package = (struct lsa_package *)context->dwUpper;
516 lsa_context = (LSA_SEC_HANDLE)context->dwLower;
518 else if (credential)
520 lsa_package = (struct lsa_package *)credential->dwUpper;
521 lsa_credential = (LSA_SEC_HANDLE)credential->dwLower;
524 if (!lsa_package || !new_context) return SEC_E_INVALID_HANDLE;
526 if (!lsa_package->lsa_api || !lsa_package->lsa_api->AcceptLsaModeContext)
527 return SEC_E_UNSUPPORTED_FUNCTION;
529 status = lsa_package->lsa_api->AcceptLsaModeContext(lsa_credential, lsa_context,
530 input, context_req, target_data_rep, &new_lsa_context, output, context_attr,
531 ts_expiry, &mapped_context, NULL /* FIXME */);
532 if (status == SEC_E_OK || status == SEC_I_CONTINUE_NEEDED)
534 new_context->dwLower = (ULONG_PTR)new_lsa_context;
535 new_context->dwUpper = (ULONG_PTR)lsa_package;
537 return status;
540 static SECURITY_STATUS WINAPI lsa_DeleteSecurityContext(CtxtHandle *context)
542 struct lsa_package *lsa_package;
543 LSA_SEC_HANDLE lsa_context;
545 TRACE("%p\n", context);
547 if (!context) return SEC_E_INVALID_HANDLE;
549 lsa_package = (struct lsa_package *)context->dwUpper;
550 lsa_context = (LSA_SEC_HANDLE)context->dwLower;
552 if (!lsa_package) return SEC_E_INVALID_HANDLE;
554 if (!lsa_package->lsa_api || !lsa_package->lsa_api->DeleteContext)
555 return SEC_E_UNSUPPORTED_FUNCTION;
557 return lsa_package->lsa_api->DeleteContext(lsa_context);
560 static SECURITY_STATUS WINAPI lsa_QueryContextAttributesW(CtxtHandle *context, ULONG attribute, void *buffer)
562 struct lsa_package *lsa_package;
563 LSA_SEC_HANDLE lsa_context;
565 TRACE("%p %d %p\n", context, attribute, buffer);
567 if (!context) return SEC_E_INVALID_HANDLE;
569 lsa_package = (struct lsa_package *)context->dwUpper;
570 lsa_context = (LSA_SEC_HANDLE)context->dwLower;
572 if (!lsa_package) return SEC_E_INVALID_HANDLE;
574 if (!lsa_package->lsa_api || !lsa_package->lsa_api->SpQueryContextAttributes)
575 return SEC_E_UNSUPPORTED_FUNCTION;
577 return lsa_package->lsa_api->SpQueryContextAttributes(lsa_context, attribute, buffer);
580 static SecPkgInfoA *package_infoWtoA( const SecPkgInfoW *info )
582 SecPkgInfoA *ret;
583 int size_name = WideCharToMultiByte( CP_ACP, 0, info->Name, -1, NULL, 0, NULL, NULL );
584 int size_comment = WideCharToMultiByte( CP_ACP, 0, info->Comment, -1, NULL, 0, NULL, NULL );
586 if (!(ret = heap_alloc( sizeof(*ret) + size_name + size_comment ))) return NULL;
587 ret->fCapabilities = info->fCapabilities;
588 ret->wVersion = info->wVersion;
589 ret->wRPCID = info->wRPCID;
590 ret->cbMaxToken = info->cbMaxToken;
591 ret->Name = (SEC_CHAR *)(ret + 1);
592 WideCharToMultiByte( CP_ACP, 0, info->Name, -1, ret->Name, size_name, NULL, NULL );
593 ret->Comment = ret->Name + size_name;
594 WideCharToMultiByte( CP_ACP, 0, info->Comment, -1, ret->Comment, size_comment, NULL, NULL );
595 return ret;
598 static SECURITY_STATUS nego_info_WtoA( const SecPkgContext_NegotiationInfoW *infoW,
599 SecPkgContext_NegotiationInfoA *infoA )
601 infoA->NegotiationState = infoW->NegotiationState;
602 if (!(infoA->PackageInfo = package_infoWtoA( infoW->PackageInfo ))) return SEC_E_INSUFFICIENT_MEMORY;
603 return SEC_E_OK;
606 static SECURITY_STATUS WINAPI lsa_QueryContextAttributesA(CtxtHandle *context, ULONG attribute, void *buffer)
608 TRACE("%p %d %p\n", context, attribute, buffer);
610 if (!context) return SEC_E_INVALID_HANDLE;
612 switch (attribute)
614 case SECPKG_ATTR_SIZES:
615 return lsa_QueryContextAttributesW( context, attribute, buffer );
617 case SECPKG_ATTR_NEGOTIATION_INFO:
619 SecPkgContext_NegotiationInfoW infoW;
620 SecPkgContext_NegotiationInfoA *infoA = (SecPkgContext_NegotiationInfoA *)buffer;
621 SECURITY_STATUS status = lsa_QueryContextAttributesW( context, SECPKG_ATTR_NEGOTIATION_INFO, &infoW );
623 if (status != SEC_E_OK) return status;
624 status = nego_info_WtoA( &infoW, infoA );
625 FreeContextBuffer( infoW.PackageInfo );
626 return status;
629 #define X(x) case (x) : FIXME(#x" stub\n"); break
630 X(SECPKG_ATTR_ACCESS_TOKEN);
631 X(SECPKG_ATTR_AUTHORITY);
632 X(SECPKG_ATTR_DCE_INFO);
633 X(SECPKG_ATTR_KEY_INFO);
634 X(SECPKG_ATTR_LIFESPAN);
635 X(SECPKG_ATTR_NAMES);
636 X(SECPKG_ATTR_NATIVE_NAMES);
637 X(SECPKG_ATTR_PACKAGE_INFO);
638 X(SECPKG_ATTR_PASSWORD_EXPIRY);
639 X(SECPKG_ATTR_SESSION_KEY);
640 X(SECPKG_ATTR_STREAM_SIZES);
641 X(SECPKG_ATTR_TARGET_INFORMATION);
642 #undef X
643 default:
644 FIXME( "unknown attribute %u\n", attribute );
645 break;
648 return SEC_E_UNSUPPORTED_FUNCTION;
651 static SECURITY_STATUS WINAPI lsa_MakeSignature(CtxtHandle *context, ULONG quality_of_protection,
652 SecBufferDesc *message, ULONG message_seq_no)
654 struct lsa_package *lsa_package;
655 LSA_SEC_HANDLE lsa_context;
657 TRACE("%p %#x %p %u)\n", context, quality_of_protection, message, message_seq_no);
659 if (!context) return SEC_E_INVALID_HANDLE;
661 lsa_package = (struct lsa_package *)context->dwUpper;
662 lsa_context = (LSA_SEC_HANDLE)context->dwLower;
664 if (!lsa_package) return SEC_E_INVALID_HANDLE;
666 if (!lsa_package->user_api || !lsa_package->user_api->MakeSignature)
667 return SEC_E_UNSUPPORTED_FUNCTION;
669 return lsa_package->user_api->MakeSignature(lsa_context, quality_of_protection, message, message_seq_no);
672 static SECURITY_STATUS WINAPI lsa_VerifySignature(CtxtHandle *context, SecBufferDesc *message,
673 ULONG message_seq_no, ULONG *quality_of_protection)
675 struct lsa_package *lsa_package;
676 LSA_SEC_HANDLE lsa_context;
678 TRACE("%p %p %u %p)\n", context, message, message_seq_no, quality_of_protection);
680 if (!context) return SEC_E_INVALID_HANDLE;
682 lsa_package = (struct lsa_package *)context->dwUpper;
683 lsa_context = (LSA_SEC_HANDLE)context->dwLower;
685 if (!lsa_package) return SEC_E_INVALID_HANDLE;
687 if (!lsa_package->user_api || !lsa_package->user_api->VerifySignature)
688 return SEC_E_UNSUPPORTED_FUNCTION;
690 return lsa_package->user_api->VerifySignature(lsa_context, message, message_seq_no, quality_of_protection);
693 static SECURITY_STATUS WINAPI lsa_EncryptMessage(CtxtHandle *context, ULONG quality_of_protection,
694 SecBufferDesc *message, ULONG message_seq_no)
696 struct lsa_package *lsa_package;
697 LSA_SEC_HANDLE lsa_context;
699 TRACE("%p %#x %p %u)\n", context, quality_of_protection, message, message_seq_no);
701 if (!context) return SEC_E_INVALID_HANDLE;
703 lsa_package = (struct lsa_package *)context->dwUpper;
704 lsa_context = (LSA_SEC_HANDLE)context->dwLower;
706 if (!lsa_package) return SEC_E_INVALID_HANDLE;
708 if (!lsa_package->user_api || !lsa_package->user_api->SealMessage)
709 return SEC_E_UNSUPPORTED_FUNCTION;
711 return lsa_package->user_api->SealMessage(lsa_context, quality_of_protection, message, message_seq_no);
714 static SECURITY_STATUS WINAPI lsa_DecryptMessage(CtxtHandle *context, SecBufferDesc *message,
715 ULONG message_seq_no, ULONG *quality_of_protection)
717 struct lsa_package *lsa_package;
718 LSA_SEC_HANDLE lsa_context;
720 TRACE("%p %p %u %p)\n", context, message, message_seq_no, quality_of_protection);
722 if (!context) return SEC_E_INVALID_HANDLE;
724 lsa_package = (struct lsa_package *)context->dwUpper;
725 lsa_context = (LSA_SEC_HANDLE)context->dwLower;
727 if (!lsa_package) return SEC_E_INVALID_HANDLE;
729 if (!lsa_package->user_api || !lsa_package->user_api->UnsealMessage)
730 return SEC_E_UNSUPPORTED_FUNCTION;
732 return lsa_package->user_api->UnsealMessage(lsa_context, message, message_seq_no, quality_of_protection);
735 static const SecurityFunctionTableW lsa_sspi_tableW =
738 NULL, /* EnumerateSecurityPackagesW */
739 NULL, /* QueryCredentialsAttributesW */
740 lsa_AcquireCredentialsHandleW,
741 lsa_FreeCredentialsHandle,
742 NULL, /* Reserved2 */
743 lsa_InitializeSecurityContextW,
744 lsa_AcceptSecurityContext,
745 NULL, /* CompleteAuthToken */
746 lsa_DeleteSecurityContext,
747 NULL, /* ApplyControlToken */
748 lsa_QueryContextAttributesW,
749 NULL, /* ImpersonateSecurityContext */
750 NULL, /* RevertSecurityContext */
751 lsa_MakeSignature,
752 lsa_VerifySignature,
753 NULL, /* FreeContextBuffer */
754 NULL, /* QuerySecurityPackageInfoW */
755 NULL, /* Reserved3 */
756 NULL, /* Reserved4 */
757 NULL, /* ExportSecurityContext */
758 NULL, /* ImportSecurityContextW */
759 NULL, /* AddCredentialsW */
760 NULL, /* Reserved8 */
761 NULL, /* QuerySecurityContextToken */
762 lsa_EncryptMessage,
763 lsa_DecryptMessage,
764 NULL, /* SetContextAttributesW */
767 static const SecurityFunctionTableA lsa_sspi_tableA =
770 NULL, /* EnumerateSecurityPackagesA */
771 NULL, /* QueryCredentialsAttributesA */
772 lsa_AcquireCredentialsHandleA,
773 lsa_FreeCredentialsHandle,
774 NULL, /* Reserved2 */
775 lsa_InitializeSecurityContextA,
776 lsa_AcceptSecurityContext,
777 NULL, /* CompleteAuthToken */
778 lsa_DeleteSecurityContext,
779 NULL, /* ApplyControlToken */
780 lsa_QueryContextAttributesA,
781 NULL, /* ImpersonateSecurityContext */
782 NULL, /* RevertSecurityContext */
783 lsa_MakeSignature,
784 lsa_VerifySignature,
785 NULL, /* FreeContextBuffer */
786 NULL, /* QuerySecurityPackageInfoA */
787 NULL, /* Reserved3 */
788 NULL, /* Reserved4 */
789 NULL, /* ExportSecurityContext */
790 NULL, /* ImportSecurityContextA */
791 NULL, /* AddCredentialsA */
792 NULL, /* Reserved8 */
793 NULL, /* QuerySecurityContextToken */
794 lsa_EncryptMessage,
795 lsa_DecryptMessage,
796 NULL, /* SetContextAttributesA */
799 static void add_package(struct lsa_package *package)
801 struct lsa_package *new_loaded_packages;
803 if (!loaded_packages)
804 new_loaded_packages = heap_alloc(sizeof(*new_loaded_packages));
805 else
806 new_loaded_packages = heap_realloc(loaded_packages, sizeof(*new_loaded_packages) * (loaded_packages_count + 1));
808 if (new_loaded_packages)
810 loaded_packages = new_loaded_packages;
811 loaded_packages[loaded_packages_count] = *package;
812 loaded_packages_count++;
816 static BOOL load_package(const WCHAR *name, struct lsa_package *package, ULONG package_id)
818 NTSTATUS (NTAPI *pSpLsaModeInitialize)(ULONG, PULONG, PSECPKG_FUNCTION_TABLE *, PULONG);
819 NTSTATUS (NTAPI *pSpUserModeInitialize)(ULONG, PULONG, PSECPKG_USER_FUNCTION_TABLE *, PULONG);
821 memset(package, 0, sizeof(*package));
823 package->mod = LoadLibraryW(name);
824 if (!package->mod) return FALSE;
826 pSpLsaModeInitialize = (void *)GetProcAddress(package->mod, "SpLsaModeInitialize");
827 if (pSpLsaModeInitialize)
829 NTSTATUS status;
831 status = pSpLsaModeInitialize(SECPKG_INTERFACE_VERSION, &package->lsa_api_version, &package->lsa_api, &package->lsa_table_count);
832 if (status == STATUS_SUCCESS)
834 status = package->lsa_api->InitializePackage(package_id, &lsa_dispatch, NULL, NULL, &package->name);
835 if (status == STATUS_SUCCESS)
837 TRACE("%s => %p, name %s, version %#x, api table %p, table count %u\n",
838 debugstr_w(name), package->mod, debugstr_an(package->name->Buffer, package->name->Length),
839 package->lsa_api_version, package->lsa_api, package->lsa_table_count);
840 package->package_id = package_id;
842 status = package->lsa_api->Initialize(package_id, NULL /* FIXME: params */, NULL);
843 if (status == STATUS_SUCCESS)
845 pSpUserModeInitialize = (void *)GetProcAddress(package->mod, "SpUserModeInitialize");
846 if (pSpUserModeInitialize)
848 status = pSpUserModeInitialize(SECPKG_INTERFACE_VERSION, &package->user_api_version, &package->user_api, &package->user_table_count);
849 if (status == STATUS_SUCCESS)
850 package->user_api->InstanceInit(SECPKG_INTERFACE_VERSION, &lsa_dll_dispatch, NULL);
853 return TRUE;
858 FreeLibrary(package->mod);
859 return FALSE;
862 #define MAX_SERVICE_NAME 260
864 void load_auth_packages(void)
866 static const WCHAR LSA_KEY[] = { 'S','y','s','t','e','m','\\',
867 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
868 'C','o','n','t','r','o','l','\\','L','s','a',0 };
869 DWORD err, i;
870 HKEY root;
871 SecureProvider *provider;
873 err = RegOpenKeyExW(HKEY_LOCAL_MACHINE, LSA_KEY, 0, KEY_READ, &root);
874 if (err != ERROR_SUCCESS) return;
876 i = 0;
877 for (;;)
879 WCHAR name[MAX_SERVICE_NAME];
880 struct lsa_package package;
882 err = RegEnumKeyW(root, i++, name, MAX_SERVICE_NAME);
883 if (err == ERROR_NO_MORE_ITEMS)
884 break;
886 if (err != ERROR_SUCCESS)
887 continue;
889 if (!load_package(name, &package, i))
890 continue;
892 add_package(&package);
895 RegCloseKey(root);
897 if (!loaded_packages_count) return;
899 provider = SECUR32_addProvider(&lsa_sspi_tableA, &lsa_sspi_tableW, NULL);
900 if (!provider)
902 ERR("Failed to add SSP/AP provider\n");
903 return;
906 for (i = 0; i < loaded_packages_count; i++)
908 SecPkgInfoW *info;
910 info = heap_alloc(loaded_packages[i].lsa_table_count * sizeof(*info));
911 if (info)
913 NTSTATUS status;
915 status = loaded_packages[i].lsa_api->GetInfo(info);
916 if (status == STATUS_SUCCESS)
917 SECUR32_addPackages(provider, loaded_packages[i].lsa_table_count, NULL, info);
919 heap_free(info);
924 NTSTATUS WINAPI LsaLookupAuthenticationPackage(HANDLE lsa_handle,
925 PLSA_STRING package_name, PULONG package_id)
927 ULONG i;
929 TRACE("%p %s %p\n", lsa_handle, debugstr_as(package_name), package_id);
931 for (i = 0; i < loaded_packages_count; i++)
933 if (!RtlCompareString(loaded_packages[i].name, package_name, FALSE))
935 *package_id = loaded_packages[i].package_id;
936 return STATUS_SUCCESS;
940 return STATUS_UNSUCCESSFUL; /* FIXME */