mfmediaengine: Handle Play() when called before topology is set.
[wine.git] / dlls / secur32 / lsa.c
blob74eba65e10c0b30d678f046a1ef2669ff1f3a978
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>
24 #include <stdlib.h>
26 #include "ntstatus.h"
27 #define WIN32_NO_STATUS
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winreg.h"
31 #include "sspi.h"
32 #include "ntsecapi.h"
33 #include "ntsecpkg.h"
34 #include "winternl.h"
35 #include "rpc.h"
37 #include "wine/debug.h"
38 #include "secur32_priv.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(secur32);
42 #define LSA_MAGIC ('L' << 24 | 'S' << 16 | 'A' << 8 | ' ')
44 struct lsa_package
46 ULONG package_id;
47 HMODULE mod;
48 LSA_STRING *name;
49 ULONG lsa_api_version, lsa_table_count, user_api_version, user_table_count;
50 SECPKG_FUNCTION_TABLE *lsa_api;
51 SECPKG_USER_FUNCTION_TABLE *user_api;
54 static struct lsa_package *loaded_packages;
55 static ULONG loaded_packages_count;
57 struct lsa_connection
59 DWORD magic;
62 static const char *debugstr_as(const LSA_STRING *str)
64 if (!str) return "<null>";
65 return debugstr_an(str->Buffer, str->Length);
68 NTSTATUS WINAPI LsaCallAuthenticationPackage(HANDLE lsa_handle, ULONG package_id,
69 PVOID in_buffer, ULONG in_buffer_length,
70 PVOID *out_buffer, PULONG out_buffer_length, PNTSTATUS status)
72 ULONG i;
74 TRACE("%p,%u,%p,%u,%p,%p,%p\n", lsa_handle, package_id, in_buffer,
75 in_buffer_length, out_buffer, out_buffer_length, status);
77 for (i = 0; i < loaded_packages_count; i++)
79 if (loaded_packages[i].package_id == package_id)
81 if (loaded_packages[i].lsa_api->CallPackageUntrusted)
82 return loaded_packages[i].lsa_api->CallPackageUntrusted(NULL /* FIXME*/,
83 in_buffer, NULL, in_buffer_length, out_buffer, out_buffer_length, status);
85 return SEC_E_UNSUPPORTED_FUNCTION;
89 return STATUS_INVALID_PARAMETER;
92 static struct lsa_connection *alloc_lsa_connection(void)
94 struct lsa_connection *ret;
95 if (!(ret = malloc(sizeof(*ret)))) return NULL;
96 ret->magic = LSA_MAGIC;
97 return ret;
100 NTSTATUS WINAPI LsaConnectUntrusted(PHANDLE LsaHandle)
102 struct lsa_connection *lsa_conn;
104 TRACE("%p\n", LsaHandle);
106 if (!(lsa_conn = alloc_lsa_connection())) return STATUS_NO_MEMORY;
107 *LsaHandle = lsa_conn;
108 return STATUS_SUCCESS;
111 NTSTATUS WINAPI LsaRegisterLogonProcess(PLSA_STRING LogonProcessName,
112 PHANDLE LsaHandle, PLSA_OPERATIONAL_MODE SecurityMode)
114 struct lsa_connection *lsa_conn;
116 FIXME("%s %p %p stub\n", debugstr_as(LogonProcessName), LsaHandle, SecurityMode);
118 if (!(lsa_conn = alloc_lsa_connection())) return STATUS_NO_MEMORY;
119 *LsaHandle = lsa_conn;
120 return STATUS_SUCCESS;
123 NTSTATUS WINAPI LsaDeregisterLogonProcess(HANDLE LsaHandle)
125 struct lsa_connection *lsa_conn = (struct lsa_connection *)LsaHandle;
127 TRACE("%p\n", LsaHandle);
129 if (!lsa_conn || lsa_conn->magic != LSA_MAGIC) return STATUS_INVALID_HANDLE;
130 lsa_conn->magic = 0;
131 free(lsa_conn);
133 return STATUS_SUCCESS;
136 NTSTATUS WINAPI LsaEnumerateLogonSessions(PULONG LogonSessionCount,
137 PLUID* LogonSessionList)
139 FIXME("%p %p stub\n", LogonSessionCount, LogonSessionList);
140 *LogonSessionCount = 0;
141 *LogonSessionList = NULL;
143 return STATUS_SUCCESS;
146 NTSTATUS WINAPI LsaFreeReturnBuffer(PVOID buffer)
148 TRACE("%p\n", buffer);
149 free(buffer);
150 return STATUS_SUCCESS;
153 NTSTATUS WINAPI LsaGetLogonSessionData(PLUID LogonId,
154 PSECURITY_LOGON_SESSION_DATA* ppLogonSessionData)
156 FIXME("%p %p stub\n", LogonId, ppLogonSessionData);
157 *ppLogonSessionData = NULL;
158 return STATUS_NOT_IMPLEMENTED;
161 NTSTATUS WINAPI LsaLogonUser(HANDLE LsaHandle, PLSA_STRING OriginName,
162 SECURITY_LOGON_TYPE LogonType, ULONG AuthenticationPackage,
163 PVOID AuthenticationInformation, ULONG AuthenticationInformationLength,
164 PTOKEN_GROUPS LocalGroups, PTOKEN_SOURCE SourceContext,
165 PVOID* ProfileBuffer, PULONG ProfileBufferLength, PLUID LogonId,
166 PHANDLE Token, PQUOTA_LIMITS Quotas, PNTSTATUS SubStatus)
168 FIXME("%p %s %d %d %p %d %p %p %p %p %p %p %p %p stub\n", LsaHandle,
169 debugstr_as(OriginName), LogonType, AuthenticationPackage,
170 AuthenticationInformation, AuthenticationInformationLength,
171 LocalGroups, SourceContext, ProfileBuffer, ProfileBufferLength,
172 LogonId, Token, Quotas, SubStatus);
173 return STATUS_SUCCESS;
176 static NTSTATUS NTAPI lsa_CreateLogonSession(LUID *logon_id)
178 FIXME("%p: stub\n", logon_id);
179 return STATUS_NOT_IMPLEMENTED;
182 static NTSTATUS NTAPI lsa_DeleteLogonSession(LUID *logon_id)
184 FIXME("%p: stub\n", logon_id);
185 return STATUS_NOT_IMPLEMENTED;
188 static NTSTATUS NTAPI lsa_AddCredential(LUID *logon_id, ULONG package_id,
189 LSA_STRING *primary_key, LSA_STRING *credentials)
191 FIXME("%p,%u,%s,%s: stub\n", logon_id, package_id,
192 debugstr_as(primary_key), debugstr_as(credentials));
193 return STATUS_NOT_IMPLEMENTED;
196 static NTSTATUS NTAPI lsa_GetCredentials(LUID *logon_id, ULONG package_id, ULONG *context,
197 BOOLEAN retrieve_all, LSA_STRING *primary_key, ULONG *primary_key_len, LSA_STRING *credentials)
199 FIXME("%p,%#x,%p,%d,%p,%p,%p: stub\n", logon_id, package_id, context,
200 retrieve_all, primary_key, primary_key_len, credentials);
201 return STATUS_NOT_IMPLEMENTED;
204 static NTSTATUS NTAPI lsa_DeleteCredential(LUID *logon_id, ULONG package_id, LSA_STRING *primary_key)
206 FIXME("%p,%#x,%s: stub\n", logon_id, package_id, debugstr_as(primary_key));
207 return STATUS_NOT_IMPLEMENTED;
210 static void * NTAPI lsa_AllocateLsaHeap(ULONG size)
212 TRACE("%u\n", size);
213 return malloc(size);
216 static void NTAPI lsa_FreeLsaHeap(void *p)
218 TRACE("%p\n", p);
219 free(p);
222 static NTSTATUS NTAPI lsa_AllocateClientBuffer(PLSA_CLIENT_REQUEST req, ULONG size, void **p)
224 TRACE("%p,%u,%p\n", req, size, p);
225 *p = malloc(size);
226 return *p ? STATUS_SUCCESS : STATUS_NO_MEMORY;
229 static NTSTATUS NTAPI lsa_FreeClientBuffer(PLSA_CLIENT_REQUEST req, void *p)
231 TRACE("%p,%p\n", req, p);
232 free(p);
233 return STATUS_SUCCESS;
236 static NTSTATUS NTAPI lsa_CopyToClientBuffer(PLSA_CLIENT_REQUEST req, ULONG size, void *client, void *buf)
238 TRACE("%p,%u,%p,%p\n", req, size, client, buf);
239 memcpy(client, buf, size);
240 return STATUS_SUCCESS;
243 static NTSTATUS NTAPI lsa_CopyFromClientBuffer(PLSA_CLIENT_REQUEST req, ULONG size, void *buf, void *client)
245 TRACE("%p,%u,%p,%p\n", req, size, buf, client);
246 memcpy(buf, client, size);
247 return STATUS_SUCCESS;
250 static LSA_DISPATCH_TABLE lsa_dispatch =
252 lsa_CreateLogonSession,
253 lsa_DeleteLogonSession,
254 lsa_AddCredential,
255 lsa_GetCredentials,
256 lsa_DeleteCredential,
257 lsa_AllocateLsaHeap,
258 lsa_FreeLsaHeap,
259 lsa_AllocateClientBuffer,
260 lsa_FreeClientBuffer,
261 lsa_CopyToClientBuffer,
262 lsa_CopyFromClientBuffer
265 static NTSTATUS NTAPI lsa_RegisterCallback(ULONG callback_id, PLSA_CALLBACK_FUNCTION callback)
267 FIXME("%u,%p: stub\n", callback_id, callback);
268 return STATUS_NOT_IMPLEMENTED;
271 static SECPKG_DLL_FUNCTIONS lsa_dll_dispatch =
273 lsa_AllocateLsaHeap,
274 lsa_FreeLsaHeap,
275 lsa_RegisterCallback
278 static SECURITY_STATUS lsa_lookup_package(SEC_WCHAR *nameW, struct lsa_package **lsa_package)
280 ULONG i;
281 UNICODE_STRING package_name, name;
283 for (i = 0; i < loaded_packages_count; i++)
285 if (RtlAnsiStringToUnicodeString(&package_name, loaded_packages[i].name, TRUE))
286 return SEC_E_INSUFFICIENT_MEMORY;
288 RtlInitUnicodeString(&name, nameW);
290 if (RtlEqualUnicodeString(&package_name, &name, TRUE))
292 RtlFreeUnicodeString(&package_name);
293 *lsa_package = &loaded_packages[i];
294 return SEC_E_OK;
297 RtlFreeUnicodeString(&package_name);
300 return SEC_E_SECPKG_NOT_FOUND;
303 static SECURITY_STATUS WINAPI lsa_AcquireCredentialsHandleW(
304 SEC_WCHAR *principal, SEC_WCHAR *package, ULONG credentials_use,
305 LUID *logon_id, void *auth_data, SEC_GET_KEY_FN get_key_fn,
306 void *get_key_arg, CredHandle *credential, TimeStamp *ts_expiry)
308 SECURITY_STATUS status;
309 struct lsa_package *lsa_package;
310 UNICODE_STRING principal_us;
311 LSA_SEC_HANDLE lsa_credential;
313 TRACE("%s %s %#x %p %p %p %p %p\n", debugstr_w(principal), debugstr_w(package),
314 credentials_use, auth_data, get_key_fn, get_key_arg, credential, ts_expiry);
316 if (!credential) return SEC_E_INVALID_HANDLE;
317 if (!package) return SEC_E_SECPKG_NOT_FOUND;
319 status = lsa_lookup_package(package, &lsa_package);
320 if (status != SEC_E_OK) return status;
322 if (!lsa_package->lsa_api || !lsa_package->lsa_api->SpAcquireCredentialsHandle)
323 return SEC_E_UNSUPPORTED_FUNCTION;
325 if (principal)
326 RtlInitUnicodeString(&principal_us, principal);
328 status = lsa_package->lsa_api->SpAcquireCredentialsHandle(principal ? &principal_us : NULL,
329 credentials_use, logon_id, auth_data, get_key_fn, get_key_arg, &lsa_credential, ts_expiry);
330 if (status == SEC_E_OK)
332 credential->dwLower = (ULONG_PTR)lsa_credential;
333 credential->dwUpper = (ULONG_PTR)lsa_package;
335 return status;
338 static SECURITY_STATUS WINAPI lsa_AcquireCredentialsHandleA(
339 SEC_CHAR *principal, SEC_CHAR *package, ULONG credentials_use,
340 LUID *logon_id, void *auth_data, SEC_GET_KEY_FN get_key_fn,
341 void *get_key_arg, CredHandle *credential, TimeStamp *ts_expiry)
343 SECURITY_STATUS status = SEC_E_INSUFFICIENT_MEMORY;
344 int len_user = 0, len_domain = 0, len_passwd = 0;
345 SEC_WCHAR *principalW = NULL, *packageW = NULL, *user = NULL, *domain = NULL, *passwd = NULL;
346 SEC_WINNT_AUTH_IDENTITY_W *auth_dataW = NULL;
347 SEC_WINNT_AUTH_IDENTITY_A *id = NULL;
349 TRACE("%s %s %#x %p %p %p %p %p\n", debugstr_a(principal), debugstr_a(package),
350 credentials_use, auth_data, get_key_fn, get_key_arg, credential, ts_expiry);
352 if (principal)
354 int len = MultiByteToWideChar( CP_ACP, 0, principal, -1, NULL, 0 );
355 if (!(principalW = malloc( len * sizeof(SEC_WCHAR) ))) goto done;
356 MultiByteToWideChar( CP_ACP, 0, principal, -1, principalW, len );
358 if (package)
360 int len = MultiByteToWideChar( CP_ACP, 0, package, -1, NULL, 0 );
361 if (!(packageW = malloc( len * sizeof(SEC_WCHAR) ))) goto done;
362 MultiByteToWideChar( CP_ACP, 0, package, -1, packageW, len );
364 if (auth_data)
366 id = (PSEC_WINNT_AUTH_IDENTITY_A)auth_data;
368 if (id->Flags == SEC_WINNT_AUTH_IDENTITY_ANSI)
370 if (!(auth_dataW = malloc( sizeof(SEC_WINNT_AUTH_IDENTITY_W) ))) goto done;
371 if (id->UserLength)
373 len_user = MultiByteToWideChar( CP_ACP, 0, (char *)id->User, id->UserLength, NULL, 0 );
374 if (!(user = malloc( len_user * sizeof(SEC_WCHAR) ))) goto done;
375 MultiByteToWideChar( CP_ACP, 0, (char *)id->User, id->UserLength, user, len_user );
377 if (id->DomainLength)
379 len_domain = MultiByteToWideChar( CP_ACP, 0, (char *)id->Domain, id->DomainLength, NULL, 0 );
380 if (!(domain = malloc( len_domain * sizeof(SEC_WCHAR) ))) goto done;
381 MultiByteToWideChar( CP_ACP, 0, (char *)id->Domain, id->DomainLength, domain, len_domain );
383 if (id->PasswordLength)
385 len_passwd = MultiByteToWideChar( CP_ACP, 0, (char *)id->Password, id->PasswordLength, NULL, 0 );
386 if (!(passwd = malloc( len_passwd * sizeof(SEC_WCHAR) ))) goto done;
387 MultiByteToWideChar( CP_ACP, 0, (char *)id->Password, id->PasswordLength, passwd, len_passwd );
389 auth_dataW->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
390 auth_dataW->User = user;
391 auth_dataW->UserLength = len_user;
392 auth_dataW->Domain = domain;
393 auth_dataW->DomainLength = len_domain;
394 auth_dataW->Password = passwd;
395 auth_dataW->PasswordLength = len_passwd;
397 else auth_dataW = (PSEC_WINNT_AUTH_IDENTITY_W)auth_data;
400 status = lsa_AcquireCredentialsHandleW( principalW, packageW, credentials_use, logon_id, auth_dataW, get_key_fn,
401 get_key_arg, credential, ts_expiry );
402 done:
403 if (auth_dataW != (SEC_WINNT_AUTH_IDENTITY_W *)id) free( auth_dataW );
404 free( packageW );
405 free( principalW );
406 free( user );
407 free( domain );
408 free( passwd );
409 return status;
412 static SECURITY_STATUS WINAPI lsa_FreeCredentialsHandle(CredHandle *credential)
414 struct lsa_package *lsa_package;
415 LSA_SEC_HANDLE lsa_credential;
417 TRACE("%p\n", credential);
418 if (!credential) return SEC_E_INVALID_HANDLE;
420 lsa_package = (struct lsa_package *)credential->dwUpper;
421 lsa_credential = (LSA_SEC_HANDLE)credential->dwLower;
423 if (!lsa_package) return SEC_E_INVALID_HANDLE;
425 if (!lsa_package->lsa_api || !lsa_package->lsa_api->FreeCredentialsHandle)
426 return SEC_E_UNSUPPORTED_FUNCTION;
428 return lsa_package->lsa_api->FreeCredentialsHandle(lsa_credential);
431 static SECURITY_STATUS WINAPI lsa_InitializeSecurityContextW(
432 CredHandle *credential, CtxtHandle *context, SEC_WCHAR *target_name, ULONG context_req,
433 ULONG reserved1, ULONG target_data_rep, SecBufferDesc *input, ULONG reserved2,
434 CtxtHandle *new_context, SecBufferDesc *output, ULONG *context_attr, TimeStamp *ts_expiry)
436 SECURITY_STATUS status;
437 struct lsa_package *lsa_package = NULL;
438 LSA_SEC_HANDLE lsa_credential = 0, lsa_context = 0, new_lsa_context;
439 UNICODE_STRING target_name_us;
440 BOOLEAN mapped_context;
442 TRACE("%p %p %s %#x %d %d %p %d %p %p %p %p\n", credential, context,
443 debugstr_w(target_name), context_req, reserved1, target_data_rep, input,
444 reserved2, new_context, output, context_attr, ts_expiry);
446 if (context)
448 lsa_package = (struct lsa_package *)context->dwUpper;
449 lsa_context = (LSA_SEC_HANDLE)context->dwLower;
451 else if (credential)
453 lsa_package = (struct lsa_package *)credential->dwUpper;
454 lsa_credential = (LSA_SEC_HANDLE)credential->dwLower;
457 if (!lsa_package || !new_context) return SEC_E_INVALID_HANDLE;
459 if (!lsa_package->lsa_api || !lsa_package->lsa_api->InitLsaModeContext)
460 return SEC_E_UNSUPPORTED_FUNCTION;
462 if (target_name)
463 RtlInitUnicodeString(&target_name_us, target_name);
465 status = lsa_package->lsa_api->InitLsaModeContext(lsa_credential, lsa_context,
466 target_name ? &target_name_us : NULL, context_req, target_data_rep, input,
467 &new_lsa_context, output, context_attr, ts_expiry, &mapped_context, NULL /* FIXME */);
468 if (status == SEC_E_OK || status == SEC_I_CONTINUE_NEEDED)
470 new_context->dwLower = (ULONG_PTR)new_lsa_context;
471 new_context->dwUpper = (ULONG_PTR)lsa_package;
473 return status;
476 static SECURITY_STATUS WINAPI lsa_InitializeSecurityContextA(
477 CredHandle *credential, CtxtHandle *context, SEC_CHAR *target_name, ULONG context_req,
478 ULONG reserved1, ULONG target_data_rep, SecBufferDesc *input, ULONG reserved2,
479 CtxtHandle *new_context, SecBufferDesc *output, ULONG *context_attr, TimeStamp *ts_expiry)
481 SECURITY_STATUS status;
482 SEC_WCHAR *targetW = NULL;
484 TRACE("%p %p %s %#x %d %d %p %d %p %p %p %p\n", credential, context,
485 debugstr_a(target_name), context_req, reserved1, target_data_rep, input,
486 reserved2, new_context, output, context_attr, ts_expiry);
488 if (target_name)
490 int len = MultiByteToWideChar( CP_ACP, 0, target_name, -1, NULL, 0 );
491 if (!(targetW = malloc( len * sizeof(SEC_WCHAR) ))) return SEC_E_INSUFFICIENT_MEMORY;
492 MultiByteToWideChar( CP_ACP, 0, target_name, -1, targetW, len );
495 status = lsa_InitializeSecurityContextW( credential, context, targetW, context_req, reserved1, target_data_rep,
496 input, reserved2, new_context, output, context_attr, ts_expiry );
497 free( targetW );
498 return status;
501 static SECURITY_STATUS WINAPI lsa_AcceptSecurityContext(
502 CredHandle *credential, CtxtHandle *context, SecBufferDesc *input,
503 ULONG context_req, ULONG target_data_rep, CtxtHandle *new_context,
504 SecBufferDesc *output, ULONG *context_attr, TimeStamp *ts_expiry)
506 SECURITY_STATUS status;
507 struct lsa_package *lsa_package = NULL;
508 LSA_SEC_HANDLE lsa_credential = 0, lsa_context = 0, new_lsa_context;
509 BOOLEAN mapped_context;
511 TRACE("%p %p %p %#x %#x %p %p %p %p\n", credential, context, input,
512 context_req, target_data_rep, new_context, output, context_attr, ts_expiry);
514 if (context)
516 lsa_package = (struct lsa_package *)context->dwUpper;
517 lsa_context = (LSA_SEC_HANDLE)context->dwLower;
519 else if (credential)
521 lsa_package = (struct lsa_package *)credential->dwUpper;
522 lsa_credential = (LSA_SEC_HANDLE)credential->dwLower;
525 if (!lsa_package || !new_context) return SEC_E_INVALID_HANDLE;
527 if (!lsa_package->lsa_api || !lsa_package->lsa_api->AcceptLsaModeContext)
528 return SEC_E_UNSUPPORTED_FUNCTION;
530 status = lsa_package->lsa_api->AcceptLsaModeContext(lsa_credential, lsa_context,
531 input, context_req, target_data_rep, &new_lsa_context, output, context_attr,
532 ts_expiry, &mapped_context, NULL /* FIXME */);
533 if (status == SEC_E_OK || status == SEC_I_CONTINUE_NEEDED)
535 new_context->dwLower = (ULONG_PTR)new_lsa_context;
536 new_context->dwUpper = (ULONG_PTR)lsa_package;
538 return status;
541 static SECURITY_STATUS WINAPI lsa_DeleteSecurityContext(CtxtHandle *context)
543 struct lsa_package *lsa_package;
544 LSA_SEC_HANDLE lsa_context;
546 TRACE("%p\n", context);
548 if (!context) return SEC_E_INVALID_HANDLE;
550 lsa_package = (struct lsa_package *)context->dwUpper;
551 lsa_context = (LSA_SEC_HANDLE)context->dwLower;
553 if (!lsa_package) return SEC_E_INVALID_HANDLE;
555 if (!lsa_package->lsa_api || !lsa_package->lsa_api->DeleteContext)
556 return SEC_E_UNSUPPORTED_FUNCTION;
558 return lsa_package->lsa_api->DeleteContext(lsa_context);
561 static SECURITY_STATUS WINAPI lsa_QueryContextAttributesW(CtxtHandle *context, ULONG attribute, void *buffer)
563 struct lsa_package *lsa_package;
564 LSA_SEC_HANDLE lsa_context;
566 TRACE("%p %d %p\n", context, attribute, buffer);
568 if (!context) return SEC_E_INVALID_HANDLE;
570 lsa_package = (struct lsa_package *)context->dwUpper;
571 lsa_context = (LSA_SEC_HANDLE)context->dwLower;
573 if (!lsa_package) return SEC_E_INVALID_HANDLE;
575 if (!lsa_package->lsa_api || !lsa_package->lsa_api->SpQueryContextAttributes)
576 return SEC_E_UNSUPPORTED_FUNCTION;
578 return lsa_package->lsa_api->SpQueryContextAttributes(lsa_context, attribute, buffer);
581 static SecPkgInfoA *package_infoWtoA( const SecPkgInfoW *info )
583 SecPkgInfoA *ret;
584 int size_name = WideCharToMultiByte( CP_ACP, 0, info->Name, -1, NULL, 0, NULL, NULL );
585 int size_comment = WideCharToMultiByte( CP_ACP, 0, info->Comment, -1, NULL, 0, NULL, NULL );
587 /* freed with FreeContextBuffer */
588 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*ret) + size_name + size_comment ))) return NULL;
589 ret->fCapabilities = info->fCapabilities;
590 ret->wVersion = info->wVersion;
591 ret->wRPCID = info->wRPCID;
592 ret->cbMaxToken = info->cbMaxToken;
593 ret->Name = (SEC_CHAR *)(ret + 1);
594 WideCharToMultiByte( CP_ACP, 0, info->Name, -1, ret->Name, size_name, NULL, NULL );
595 ret->Comment = ret->Name + size_name;
596 WideCharToMultiByte( CP_ACP, 0, info->Comment, -1, ret->Comment, size_comment, NULL, NULL );
597 return ret;
600 static SECURITY_STATUS nego_info_WtoA( const SecPkgContext_NegotiationInfoW *infoW,
601 SecPkgContext_NegotiationInfoA *infoA )
603 infoA->NegotiationState = infoW->NegotiationState;
604 if (!(infoA->PackageInfo = package_infoWtoA( infoW->PackageInfo ))) return SEC_E_INSUFFICIENT_MEMORY;
605 return SEC_E_OK;
608 static SECURITY_STATUS WINAPI lsa_QueryContextAttributesA(CtxtHandle *context, ULONG attribute, void *buffer)
610 TRACE("%p %d %p\n", context, attribute, buffer);
612 if (!context) return SEC_E_INVALID_HANDLE;
614 switch (attribute)
616 case SECPKG_ATTR_SIZES:
617 return lsa_QueryContextAttributesW( context, attribute, buffer );
619 case SECPKG_ATTR_NEGOTIATION_INFO:
621 SecPkgContext_NegotiationInfoW infoW;
622 SecPkgContext_NegotiationInfoA *infoA = (SecPkgContext_NegotiationInfoA *)buffer;
623 SECURITY_STATUS status = lsa_QueryContextAttributesW( context, SECPKG_ATTR_NEGOTIATION_INFO, &infoW );
625 if (status != SEC_E_OK) return status;
626 status = nego_info_WtoA( &infoW, infoA );
627 FreeContextBuffer( infoW.PackageInfo );
628 return status;
631 #define X(x) case (x) : FIXME(#x" stub\n"); break
632 X(SECPKG_ATTR_ACCESS_TOKEN);
633 X(SECPKG_ATTR_AUTHORITY);
634 X(SECPKG_ATTR_DCE_INFO);
635 X(SECPKG_ATTR_KEY_INFO);
636 X(SECPKG_ATTR_LIFESPAN);
637 X(SECPKG_ATTR_NAMES);
638 X(SECPKG_ATTR_NATIVE_NAMES);
639 X(SECPKG_ATTR_PACKAGE_INFO);
640 X(SECPKG_ATTR_PASSWORD_EXPIRY);
641 X(SECPKG_ATTR_SESSION_KEY);
642 X(SECPKG_ATTR_STREAM_SIZES);
643 X(SECPKG_ATTR_TARGET_INFORMATION);
644 #undef X
645 default:
646 FIXME( "unknown attribute %u\n", attribute );
647 break;
650 return SEC_E_UNSUPPORTED_FUNCTION;
653 static SECURITY_STATUS WINAPI lsa_MakeSignature(CtxtHandle *context, ULONG quality_of_protection,
654 SecBufferDesc *message, ULONG message_seq_no)
656 struct lsa_package *lsa_package;
657 LSA_SEC_HANDLE lsa_context;
659 TRACE("%p %#x %p %u)\n", context, quality_of_protection, message, message_seq_no);
661 if (!context) return SEC_E_INVALID_HANDLE;
663 lsa_package = (struct lsa_package *)context->dwUpper;
664 lsa_context = (LSA_SEC_HANDLE)context->dwLower;
666 if (!lsa_package) return SEC_E_INVALID_HANDLE;
668 if (!lsa_package->user_api || !lsa_package->user_api->MakeSignature)
669 return SEC_E_UNSUPPORTED_FUNCTION;
671 return lsa_package->user_api->MakeSignature(lsa_context, quality_of_protection, message, message_seq_no);
674 static SECURITY_STATUS WINAPI lsa_VerifySignature(CtxtHandle *context, SecBufferDesc *message,
675 ULONG message_seq_no, ULONG *quality_of_protection)
677 struct lsa_package *lsa_package;
678 LSA_SEC_HANDLE lsa_context;
680 TRACE("%p %p %u %p)\n", context, message, message_seq_no, quality_of_protection);
682 if (!context) return SEC_E_INVALID_HANDLE;
684 lsa_package = (struct lsa_package *)context->dwUpper;
685 lsa_context = (LSA_SEC_HANDLE)context->dwLower;
687 if (!lsa_package) return SEC_E_INVALID_HANDLE;
689 if (!lsa_package->user_api || !lsa_package->user_api->VerifySignature)
690 return SEC_E_UNSUPPORTED_FUNCTION;
692 return lsa_package->user_api->VerifySignature(lsa_context, message, message_seq_no, quality_of_protection);
695 static SECURITY_STATUS WINAPI lsa_EncryptMessage(CtxtHandle *context, ULONG quality_of_protection,
696 SecBufferDesc *message, ULONG message_seq_no)
698 struct lsa_package *lsa_package;
699 LSA_SEC_HANDLE lsa_context;
701 TRACE("%p %#x %p %u)\n", context, quality_of_protection, message, message_seq_no);
703 if (!context) return SEC_E_INVALID_HANDLE;
705 lsa_package = (struct lsa_package *)context->dwUpper;
706 lsa_context = (LSA_SEC_HANDLE)context->dwLower;
708 if (!lsa_package) return SEC_E_INVALID_HANDLE;
710 if (!lsa_package->user_api || !lsa_package->user_api->SealMessage)
711 return SEC_E_UNSUPPORTED_FUNCTION;
713 return lsa_package->user_api->SealMessage(lsa_context, quality_of_protection, message, message_seq_no);
716 static SECURITY_STATUS WINAPI lsa_DecryptMessage(CtxtHandle *context, SecBufferDesc *message,
717 ULONG message_seq_no, ULONG *quality_of_protection)
719 struct lsa_package *lsa_package;
720 LSA_SEC_HANDLE lsa_context;
722 TRACE("%p %p %u %p)\n", context, message, message_seq_no, quality_of_protection);
724 if (!context) return SEC_E_INVALID_HANDLE;
726 lsa_package = (struct lsa_package *)context->dwUpper;
727 lsa_context = (LSA_SEC_HANDLE)context->dwLower;
729 if (!lsa_package) return SEC_E_INVALID_HANDLE;
731 if (!lsa_package->user_api || !lsa_package->user_api->UnsealMessage)
732 return SEC_E_UNSUPPORTED_FUNCTION;
734 return lsa_package->user_api->UnsealMessage(lsa_context, message, message_seq_no, quality_of_protection);
737 static const SecurityFunctionTableW lsa_sspi_tableW =
740 NULL, /* EnumerateSecurityPackagesW */
741 NULL, /* QueryCredentialsAttributesW */
742 lsa_AcquireCredentialsHandleW,
743 lsa_FreeCredentialsHandle,
744 NULL, /* Reserved2 */
745 lsa_InitializeSecurityContextW,
746 lsa_AcceptSecurityContext,
747 NULL, /* CompleteAuthToken */
748 lsa_DeleteSecurityContext,
749 NULL, /* ApplyControlToken */
750 lsa_QueryContextAttributesW,
751 NULL, /* ImpersonateSecurityContext */
752 NULL, /* RevertSecurityContext */
753 lsa_MakeSignature,
754 lsa_VerifySignature,
755 NULL, /* FreeContextBuffer */
756 NULL, /* QuerySecurityPackageInfoW */
757 NULL, /* Reserved3 */
758 NULL, /* Reserved4 */
759 NULL, /* ExportSecurityContext */
760 NULL, /* ImportSecurityContextW */
761 NULL, /* AddCredentialsW */
762 NULL, /* Reserved8 */
763 NULL, /* QuerySecurityContextToken */
764 lsa_EncryptMessage,
765 lsa_DecryptMessage,
766 NULL, /* SetContextAttributesW */
769 static const SecurityFunctionTableA lsa_sspi_tableA =
772 NULL, /* EnumerateSecurityPackagesA */
773 NULL, /* QueryCredentialsAttributesA */
774 lsa_AcquireCredentialsHandleA,
775 lsa_FreeCredentialsHandle,
776 NULL, /* Reserved2 */
777 lsa_InitializeSecurityContextA,
778 lsa_AcceptSecurityContext,
779 NULL, /* CompleteAuthToken */
780 lsa_DeleteSecurityContext,
781 NULL, /* ApplyControlToken */
782 lsa_QueryContextAttributesA,
783 NULL, /* ImpersonateSecurityContext */
784 NULL, /* RevertSecurityContext */
785 lsa_MakeSignature,
786 lsa_VerifySignature,
787 NULL, /* FreeContextBuffer */
788 NULL, /* QuerySecurityPackageInfoA */
789 NULL, /* Reserved3 */
790 NULL, /* Reserved4 */
791 NULL, /* ExportSecurityContext */
792 NULL, /* ImportSecurityContextA */
793 NULL, /* AddCredentialsA */
794 NULL, /* Reserved8 */
795 NULL, /* QuerySecurityContextToken */
796 lsa_EncryptMessage,
797 lsa_DecryptMessage,
798 NULL, /* SetContextAttributesA */
801 static void add_package(struct lsa_package *package)
803 struct lsa_package *new_loaded_packages;
805 if (!loaded_packages)
806 new_loaded_packages = malloc(sizeof(*new_loaded_packages));
807 else
808 new_loaded_packages = realloc(loaded_packages, sizeof(*new_loaded_packages) * (loaded_packages_count + 1));
810 if (new_loaded_packages)
812 loaded_packages = new_loaded_packages;
813 loaded_packages[loaded_packages_count] = *package;
814 loaded_packages_count++;
818 static BOOL load_package(const WCHAR *name, struct lsa_package *package, ULONG package_id)
820 NTSTATUS (NTAPI *pSpLsaModeInitialize)(ULONG, PULONG, PSECPKG_FUNCTION_TABLE *, PULONG);
821 NTSTATUS (NTAPI *pSpUserModeInitialize)(ULONG, PULONG, PSECPKG_USER_FUNCTION_TABLE *, PULONG);
823 memset(package, 0, sizeof(*package));
825 package->mod = LoadLibraryW(name);
826 if (!package->mod) return FALSE;
828 pSpLsaModeInitialize = (void *)GetProcAddress(package->mod, "SpLsaModeInitialize");
829 if (pSpLsaModeInitialize)
831 NTSTATUS status;
833 status = pSpLsaModeInitialize(SECPKG_INTERFACE_VERSION, &package->lsa_api_version, &package->lsa_api, &package->lsa_table_count);
834 if (status == STATUS_SUCCESS)
836 status = package->lsa_api->InitializePackage(package_id, &lsa_dispatch, NULL, NULL, &package->name);
837 if (status == STATUS_SUCCESS)
839 TRACE("%s => %p, name %s, version %#x, api table %p, table count %u\n",
840 debugstr_w(name), package->mod, debugstr_an(package->name->Buffer, package->name->Length),
841 package->lsa_api_version, package->lsa_api, package->lsa_table_count);
842 package->package_id = package_id;
844 status = package->lsa_api->Initialize(package_id, NULL /* FIXME: params */, NULL);
845 if (status == STATUS_SUCCESS)
847 pSpUserModeInitialize = (void *)GetProcAddress(package->mod, "SpUserModeInitialize");
848 if (pSpUserModeInitialize)
850 status = pSpUserModeInitialize(SECPKG_INTERFACE_VERSION, &package->user_api_version, &package->user_api, &package->user_table_count);
851 if (status == STATUS_SUCCESS)
852 package->user_api->InstanceInit(SECPKG_INTERFACE_VERSION, &lsa_dll_dispatch, NULL);
855 return TRUE;
860 FreeLibrary(package->mod);
861 return FALSE;
864 #define MAX_SERVICE_NAME 260
866 void load_auth_packages(void)
868 DWORD err, i;
869 HKEY root;
870 SecureProvider *provider;
872 err = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Control\\Lsa", 0, KEY_READ, &root);
873 if (err != ERROR_SUCCESS) return;
875 i = 0;
876 for (;;)
878 WCHAR name[MAX_SERVICE_NAME];
879 struct lsa_package package;
881 err = RegEnumKeyW(root, i++, name, MAX_SERVICE_NAME);
882 if (err == ERROR_NO_MORE_ITEMS)
883 break;
885 if (err != ERROR_SUCCESS)
886 continue;
888 if (!load_package(name, &package, i))
889 continue;
891 add_package(&package);
894 RegCloseKey(root);
896 if (!loaded_packages_count) return;
898 provider = SECUR32_addProvider(&lsa_sspi_tableA, &lsa_sspi_tableW, NULL);
899 if (!provider)
901 ERR("Failed to add SSP/AP provider\n");
902 return;
905 for (i = 0; i < loaded_packages_count; i++)
907 SecPkgInfoW *info;
909 info = malloc(loaded_packages[i].lsa_table_count * sizeof(*info));
910 if (info)
912 NTSTATUS status;
914 status = loaded_packages[i].lsa_api->GetInfo(info);
915 if (status == STATUS_SUCCESS)
916 SECUR32_addPackages(provider, loaded_packages[i].lsa_table_count, NULL, info);
918 free(info);
923 NTSTATUS WINAPI LsaLookupAuthenticationPackage(HANDLE lsa_handle,
924 PLSA_STRING package_name, PULONG package_id)
926 ULONG i;
928 TRACE("%p %s %p\n", lsa_handle, debugstr_as(package_name), package_id);
930 for (i = 0; i < loaded_packages_count; i++)
932 if (!RtlCompareString(loaded_packages[i].name, package_name, FALSE))
934 *package_id = loaded_packages[i].package_id;
935 return STATUS_SUCCESS;
939 return STATUS_UNSUCCESSFUL; /* FIXME */