imm32/tests: Test ImmTranslateMessage / ImeToAsciiEx calls.
[wine.git] / dlls / secur32 / lsa.c
blob3cbd49e6b0edb108631a74cb14e94e8cc2559aca
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_CONNECTION ('L' << 24 | 'S' << 16 | 'A' << 8 | '0')
43 #define LSA_MAGIC_CREDENTIALS ('L' << 24 | 'S' << 16 | 'A' << 8 | '1')
44 #define LSA_MAGIC_CONTEXT ('L' << 24 | 'S' << 16 | 'A' << 8 | '2')
46 static const WCHAR *default_authentication_package = L"Negotiate";
48 struct lsa_package
50 ULONG package_id;
51 HMODULE mod;
52 LSA_STRING *name;
53 ULONG lsa_api_version, lsa_table_count, user_api_version, user_table_count;
54 SECPKG_FUNCTION_TABLE *lsa_api;
55 SECPKG_USER_FUNCTION_TABLE *user_api;
58 static struct lsa_package *loaded_packages;
59 static ULONG loaded_packages_count;
61 struct lsa_handle
63 DWORD magic;
64 struct lsa_package *package;
65 LSA_SEC_HANDLE handle;
68 static const char *debugstr_as(const LSA_STRING *str)
70 if (!str) return "<null>";
71 return debugstr_an(str->Buffer, str->Length);
74 NTSTATUS WINAPI LsaCallAuthenticationPackage(HANDLE lsa_handle, ULONG package_id,
75 PVOID in_buffer, ULONG in_buffer_length,
76 PVOID *out_buffer, PULONG out_buffer_length, PNTSTATUS status)
78 ULONG i;
80 TRACE("%p,%lu,%p,%lu,%p,%p,%p\n", lsa_handle, package_id, in_buffer,
81 in_buffer_length, out_buffer, out_buffer_length, status);
83 for (i = 0; i < loaded_packages_count; i++)
85 if (loaded_packages[i].package_id == package_id)
87 if (loaded_packages[i].lsa_api->CallPackageUntrusted)
88 return loaded_packages[i].lsa_api->CallPackageUntrusted(NULL /* FIXME*/,
89 in_buffer, NULL, in_buffer_length, out_buffer, out_buffer_length, status);
91 return SEC_E_UNSUPPORTED_FUNCTION;
95 return STATUS_INVALID_PARAMETER;
98 static struct lsa_handle *alloc_lsa_handle(ULONG magic)
100 struct lsa_handle *ret;
101 if (!(ret = calloc(1, sizeof(*ret)))) return NULL;
102 ret->magic = magic;
103 return ret;
106 NTSTATUS WINAPI LsaConnectUntrusted(PHANDLE LsaHandle)
108 struct lsa_handle *lsa_conn;
110 TRACE("%p\n", LsaHandle);
112 if (!(lsa_conn = alloc_lsa_handle(LSA_MAGIC_CONNECTION))) return STATUS_NO_MEMORY;
113 *LsaHandle = lsa_conn;
114 return STATUS_SUCCESS;
117 NTSTATUS WINAPI LsaRegisterLogonProcess(PLSA_STRING LogonProcessName,
118 PHANDLE LsaHandle, PLSA_OPERATIONAL_MODE SecurityMode)
120 struct lsa_handle *lsa_conn;
122 FIXME("%s %p %p stub\n", debugstr_as(LogonProcessName), LsaHandle, SecurityMode);
124 if (!(lsa_conn = alloc_lsa_handle(LSA_MAGIC_CONNECTION))) return STATUS_NO_MEMORY;
125 *LsaHandle = lsa_conn;
126 return STATUS_SUCCESS;
129 NTSTATUS WINAPI LsaDeregisterLogonProcess(HANDLE LsaHandle)
131 struct lsa_handle *lsa_conn = (struct lsa_handle *)LsaHandle;
133 TRACE("%p\n", LsaHandle);
135 if (!lsa_conn || lsa_conn->magic != LSA_MAGIC_CONNECTION) return STATUS_INVALID_HANDLE;
136 lsa_conn->magic = 0;
137 free(lsa_conn);
139 return STATUS_SUCCESS;
142 NTSTATUS WINAPI LsaEnumerateLogonSessions(PULONG LogonSessionCount,
143 PLUID* LogonSessionList)
145 FIXME("%p %p stub\n", LogonSessionCount, LogonSessionList);
146 *LogonSessionCount = 0;
147 *LogonSessionList = NULL;
149 return STATUS_SUCCESS;
152 NTSTATUS WINAPI LsaFreeReturnBuffer(PVOID buffer)
154 TRACE("%p\n", buffer);
155 free(buffer);
156 return STATUS_SUCCESS;
159 NTSTATUS WINAPI LsaGetLogonSessionData(PLUID LogonId,
160 PSECURITY_LOGON_SESSION_DATA* ppLogonSessionData)
162 SECURITY_LOGON_SESSION_DATA *data;
163 int authpkg_len;
164 WCHAR *end;
166 FIXME("%p %p semi-stub\n", LogonId, ppLogonSessionData);
168 authpkg_len = wcslen(default_authentication_package) * sizeof(WCHAR);
170 data = calloc(1, sizeof(*data) + authpkg_len + sizeof(WCHAR));
171 if (!data) return STATUS_NO_MEMORY;
173 data->Size = sizeof(*data);
174 data->LogonId = *LogonId;
176 end = (WCHAR *)(data + 1);
177 wcscpy(end, default_authentication_package);
179 data->AuthenticationPackage.Length = authpkg_len;
180 data->AuthenticationPackage.MaximumLength = authpkg_len + sizeof(WCHAR);
181 data->AuthenticationPackage.Buffer = end;
183 *ppLogonSessionData = data;
185 return STATUS_SUCCESS;
188 NTSTATUS WINAPI LsaLogonUser(HANDLE LsaHandle, PLSA_STRING OriginName,
189 SECURITY_LOGON_TYPE LogonType, ULONG AuthenticationPackage,
190 PVOID AuthenticationInformation, ULONG AuthenticationInformationLength,
191 PTOKEN_GROUPS LocalGroups, PTOKEN_SOURCE SourceContext,
192 PVOID* ProfileBuffer, PULONG ProfileBufferLength, PLUID LogonId,
193 PHANDLE Token, PQUOTA_LIMITS Quotas, PNTSTATUS SubStatus)
195 FIXME("%p %s %d %ld %p %ld %p %p %p %p %p %p %p %p stub\n", LsaHandle,
196 debugstr_as(OriginName), LogonType, AuthenticationPackage,
197 AuthenticationInformation, AuthenticationInformationLength,
198 LocalGroups, SourceContext, ProfileBuffer, ProfileBufferLength,
199 LogonId, Token, Quotas, SubStatus);
200 return STATUS_SUCCESS;
203 static NTSTATUS NTAPI lsa_CreateLogonSession(LUID *logon_id)
205 FIXME("%p: stub\n", logon_id);
206 return STATUS_NOT_IMPLEMENTED;
209 static NTSTATUS NTAPI lsa_DeleteLogonSession(LUID *logon_id)
211 FIXME("%p: stub\n", logon_id);
212 return STATUS_NOT_IMPLEMENTED;
215 static NTSTATUS NTAPI lsa_AddCredential(LUID *logon_id, ULONG package_id,
216 LSA_STRING *primary_key, LSA_STRING *credentials)
218 FIXME("%p,%lu,%s,%s: stub\n", logon_id, package_id,
219 debugstr_as(primary_key), debugstr_as(credentials));
220 return STATUS_NOT_IMPLEMENTED;
223 static NTSTATUS NTAPI lsa_GetCredentials(LUID *logon_id, ULONG package_id, ULONG *context,
224 BOOLEAN retrieve_all, LSA_STRING *primary_key, ULONG *primary_key_len, LSA_STRING *credentials)
226 FIXME("%p,%#lx,%p,%d,%p,%p,%p: stub\n", logon_id, package_id, context,
227 retrieve_all, primary_key, primary_key_len, credentials);
228 return STATUS_NOT_IMPLEMENTED;
231 static NTSTATUS NTAPI lsa_DeleteCredential(LUID *logon_id, ULONG package_id, LSA_STRING *primary_key)
233 FIXME("%p,%#lx,%s: stub\n", logon_id, package_id, debugstr_as(primary_key));
234 return STATUS_NOT_IMPLEMENTED;
237 static void * NTAPI lsa_AllocateLsaHeap(ULONG size)
239 TRACE("%lu\n", size);
240 return malloc(size);
243 static void NTAPI lsa_FreeLsaHeap(void *p)
245 TRACE("%p\n", p);
246 free(p);
249 static NTSTATUS NTAPI lsa_AllocateClientBuffer(PLSA_CLIENT_REQUEST req, ULONG size, void **p)
251 TRACE("%p,%lu,%p\n", req, size, p);
252 *p = malloc(size);
253 return *p ? STATUS_SUCCESS : STATUS_NO_MEMORY;
256 static NTSTATUS NTAPI lsa_FreeClientBuffer(PLSA_CLIENT_REQUEST req, void *p)
258 TRACE("%p,%p\n", req, p);
259 free(p);
260 return STATUS_SUCCESS;
263 static NTSTATUS NTAPI lsa_CopyToClientBuffer(PLSA_CLIENT_REQUEST req, ULONG size, void *client, void *buf)
265 TRACE("%p,%lu,%p,%p\n", req, size, client, buf);
266 memcpy(client, buf, size);
267 return STATUS_SUCCESS;
270 static NTSTATUS NTAPI lsa_CopyFromClientBuffer(PLSA_CLIENT_REQUEST req, ULONG size, void *buf, void *client)
272 TRACE("%p,%lu,%p,%p\n", req, size, buf, client);
273 memcpy(buf, client, size);
274 return STATUS_SUCCESS;
277 static LSA_DISPATCH_TABLE lsa_dispatch =
279 lsa_CreateLogonSession,
280 lsa_DeleteLogonSession,
281 lsa_AddCredential,
282 lsa_GetCredentials,
283 lsa_DeleteCredential,
284 lsa_AllocateLsaHeap,
285 lsa_FreeLsaHeap,
286 lsa_AllocateClientBuffer,
287 lsa_FreeClientBuffer,
288 lsa_CopyToClientBuffer,
289 lsa_CopyFromClientBuffer
292 static NTSTATUS NTAPI lsa_RegisterCallback(ULONG callback_id, PLSA_CALLBACK_FUNCTION callback)
294 FIXME("%lu,%p: stub\n", callback_id, callback);
295 return STATUS_NOT_IMPLEMENTED;
298 static SECPKG_DLL_FUNCTIONS lsa_dll_dispatch =
300 lsa_AllocateLsaHeap,
301 lsa_FreeLsaHeap,
302 lsa_RegisterCallback
305 static SECURITY_STATUS lsa_lookup_package(SEC_WCHAR *nameW, struct lsa_package **lsa_package)
307 ULONG i;
308 UNICODE_STRING package_name, name;
310 for (i = 0; i < loaded_packages_count; i++)
312 if (RtlAnsiStringToUnicodeString(&package_name, loaded_packages[i].name, TRUE))
313 return SEC_E_INSUFFICIENT_MEMORY;
315 RtlInitUnicodeString(&name, nameW);
317 if (RtlEqualUnicodeString(&package_name, &name, TRUE))
319 RtlFreeUnicodeString(&package_name);
320 *lsa_package = &loaded_packages[i];
321 return SEC_E_OK;
324 RtlFreeUnicodeString(&package_name);
327 return SEC_E_SECPKG_NOT_FOUND;
330 static SECURITY_STATUS WINAPI lsa_AcquireCredentialsHandleW(
331 SEC_WCHAR *principal, SEC_WCHAR *package, ULONG credentials_use,
332 LUID *logon_id, void *auth_data, SEC_GET_KEY_FN get_key_fn,
333 void *get_key_arg, CredHandle *credential, TimeStamp *ts_expiry)
335 SECURITY_STATUS status;
336 struct lsa_package *lsa_package;
337 struct lsa_handle *lsa_handle;
338 UNICODE_STRING principal_us;
339 LSA_SEC_HANDLE lsa_credential;
341 TRACE("%s %s %#lx %p %p %p %p %p\n", debugstr_w(principal), debugstr_w(package),
342 credentials_use, auth_data, get_key_fn, get_key_arg, credential, ts_expiry);
344 if (!credential) return SEC_E_INVALID_HANDLE;
345 if (!package) return SEC_E_SECPKG_NOT_FOUND;
347 status = lsa_lookup_package(package, &lsa_package);
348 if (status != SEC_E_OK) return status;
350 if (!lsa_package->lsa_api || !lsa_package->lsa_api->SpAcquireCredentialsHandle)
351 return SEC_E_UNSUPPORTED_FUNCTION;
353 if (principal)
354 RtlInitUnicodeString(&principal_us, principal);
356 status = lsa_package->lsa_api->SpAcquireCredentialsHandle(principal ? &principal_us : NULL,
357 credentials_use, logon_id, auth_data, get_key_fn, get_key_arg, &lsa_credential, ts_expiry);
358 if (status == SEC_E_OK)
360 if (!(lsa_handle = alloc_lsa_handle(LSA_MAGIC_CREDENTIALS))) return STATUS_NO_MEMORY;
361 lsa_handle->package = lsa_package;
362 lsa_handle->handle = lsa_credential;
363 credential->dwLower = (ULONG_PTR)lsa_handle;
364 credential->dwUpper = 0;
366 return status;
369 static SECURITY_STATUS WINAPI lsa_AcquireCredentialsHandleA(
370 SEC_CHAR *principal, SEC_CHAR *package, ULONG credentials_use,
371 LUID *logon_id, void *auth_data, SEC_GET_KEY_FN get_key_fn,
372 void *get_key_arg, CredHandle *credential, TimeStamp *ts_expiry)
374 SECURITY_STATUS status = SEC_E_INSUFFICIENT_MEMORY;
375 SEC_WCHAR *principalW = NULL, *packageW = NULL;
376 SEC_WINNT_AUTH_IDENTITY_A *id = auth_data;
377 SEC_WINNT_AUTH_IDENTITY_W idW = {};
379 TRACE("%s %s %#lx %p %p %p %p %p\n", debugstr_a(principal), debugstr_a(package),
380 credentials_use, auth_data, get_key_fn, get_key_arg, credential, ts_expiry);
382 if (principal)
384 int len = MultiByteToWideChar( CP_ACP, 0, principal, -1, NULL, 0 );
385 if (!(principalW = malloc( len * sizeof(SEC_WCHAR) ))) goto done;
386 MultiByteToWideChar( CP_ACP, 0, principal, -1, principalW, len );
388 if (package)
390 int len = MultiByteToWideChar( CP_ACP, 0, package, -1, NULL, 0 );
391 if (!(packageW = malloc( len * sizeof(SEC_WCHAR) ))) goto done;
392 MultiByteToWideChar( CP_ACP, 0, package, -1, packageW, len );
394 if (id && (id->Flags == SEC_WINNT_AUTH_IDENTITY_ANSI))
396 if (id->UserLength)
398 idW.UserLength = MultiByteToWideChar( CP_ACP, 0, (char *)id->User, id->UserLength, NULL, 0 );
399 if (!(idW.User = malloc( idW.UserLength * sizeof(SEC_WCHAR) ))) goto done;
400 MultiByteToWideChar( CP_ACP, 0, (char *)id->User, id->UserLength, idW.User, idW.UserLength );
402 if (id->DomainLength)
404 idW.DomainLength = MultiByteToWideChar( CP_ACP, 0, (char *)id->Domain, id->DomainLength, NULL, 0 );
405 if (!(idW.Domain = malloc( idW.DomainLength * sizeof(SEC_WCHAR) ))) goto done;
406 MultiByteToWideChar( CP_ACP, 0, (char *)id->Domain, id->DomainLength, idW.Domain, idW.DomainLength );
408 if (id->PasswordLength)
410 idW.PasswordLength = MultiByteToWideChar( CP_ACP, 0, (char *)id->Password, id->PasswordLength, NULL, 0 );
411 if (!(idW.Password = malloc( idW.PasswordLength * sizeof(SEC_WCHAR) ))) goto done;
412 MultiByteToWideChar( CP_ACP, 0, (char *)id->Password, id->PasswordLength, idW.Password, idW.PasswordLength );
414 idW.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
415 auth_data = &idW;
418 status = lsa_AcquireCredentialsHandleW( principalW, packageW, credentials_use, logon_id, auth_data, get_key_fn,
419 get_key_arg, credential, ts_expiry );
420 done:
421 free( packageW );
422 free( principalW );
423 free( idW.User );
424 free( idW.Domain );
425 free( idW.Password );
426 return status;
429 static SECURITY_STATUS WINAPI lsa_FreeCredentialsHandle(CredHandle *credential)
431 struct lsa_handle *lsa_cred;
432 SECURITY_STATUS status;
434 TRACE("%p\n", credential);
435 if (!credential) return SEC_E_INVALID_HANDLE;
437 lsa_cred = (struct lsa_handle *)credential->dwLower;
438 if (!lsa_cred || lsa_cred->magic != LSA_MAGIC_CREDENTIALS) return SEC_E_INVALID_HANDLE;
440 if (!lsa_cred->package->lsa_api || !lsa_cred->package->lsa_api->FreeCredentialsHandle)
441 return SEC_E_UNSUPPORTED_FUNCTION;
443 status = lsa_cred->package->lsa_api->FreeCredentialsHandle(lsa_cred->handle);
445 lsa_cred->magic = 0;
446 free(lsa_cred);
447 return status;
450 static SECURITY_STATUS WINAPI lsa_InitializeSecurityContextW(
451 CredHandle *credential, CtxtHandle *context, SEC_WCHAR *target_name, ULONG context_req,
452 ULONG reserved1, ULONG target_data_rep, SecBufferDesc *input, ULONG reserved2,
453 CtxtHandle *new_context, SecBufferDesc *output, ULONG *context_attr, TimeStamp *ts_expiry)
455 SECURITY_STATUS status;
456 struct lsa_handle *lsa_cred = NULL, *lsa_ctx = NULL, *new_lsa_ctx;
457 struct lsa_package *package = NULL;
458 UNICODE_STRING target_name_us;
459 BOOLEAN mapped_context;
460 LSA_SEC_HANDLE new_handle;
462 TRACE("%p %p %s %#lx %ld %ld %p %ld %p %p %p %p\n", credential, context,
463 debugstr_w(target_name), context_req, reserved1, target_data_rep, input,
464 reserved2, new_context, output, context_attr, ts_expiry);
466 if (context)
468 lsa_ctx = (struct lsa_handle *)context->dwLower;
469 if (lsa_ctx->magic != LSA_MAGIC_CONTEXT) return SEC_E_INVALID_HANDLE;
470 package = lsa_ctx->package;
472 else if (credential)
474 lsa_cred = (struct lsa_handle *)credential->dwLower;
475 if (lsa_cred->magic != LSA_MAGIC_CREDENTIALS) return SEC_E_INVALID_HANDLE;
476 package = lsa_cred->package;
478 if (!package || !new_context) return SEC_E_INVALID_HANDLE;
480 if (!package->lsa_api || !package->lsa_api->InitLsaModeContext)
481 return SEC_E_UNSUPPORTED_FUNCTION;
483 if (target_name)
484 RtlInitUnicodeString(&target_name_us, target_name);
486 status = package->lsa_api->InitLsaModeContext(lsa_cred ? lsa_cred->handle : 0,
487 lsa_ctx ? lsa_ctx->handle : 0, target_name ? &target_name_us : NULL, context_req, target_data_rep,
488 input, &new_handle, output, context_attr, ts_expiry, &mapped_context, NULL /* FIXME */);
489 if (status == SEC_E_OK || status == SEC_I_CONTINUE_NEEDED)
491 if (!(new_lsa_ctx = alloc_lsa_handle(LSA_MAGIC_CONTEXT))) return STATUS_NO_MEMORY;
492 new_lsa_ctx->package = package;
493 new_lsa_ctx->handle = new_handle;
494 new_context->dwLower = (ULONG_PTR)new_lsa_ctx;
495 new_context->dwUpper = 0;
497 return status;
500 static SECURITY_STATUS WINAPI lsa_InitializeSecurityContextA(
501 CredHandle *credential, CtxtHandle *context, SEC_CHAR *target_name, ULONG context_req,
502 ULONG reserved1, ULONG target_data_rep, SecBufferDesc *input, ULONG reserved2,
503 CtxtHandle *new_context, SecBufferDesc *output, ULONG *context_attr, TimeStamp *ts_expiry)
505 SECURITY_STATUS status;
506 SEC_WCHAR *targetW = NULL;
508 TRACE("%p %p %s %#lx %ld %ld %p %ld %p %p %p %p\n", credential, context,
509 debugstr_a(target_name), context_req, reserved1, target_data_rep, input,
510 reserved2, new_context, output, context_attr, ts_expiry);
512 if (target_name)
514 int len = MultiByteToWideChar( CP_ACP, 0, target_name, -1, NULL, 0 );
515 if (!(targetW = malloc( len * sizeof(SEC_WCHAR) ))) return SEC_E_INSUFFICIENT_MEMORY;
516 MultiByteToWideChar( CP_ACP, 0, target_name, -1, targetW, len );
519 status = lsa_InitializeSecurityContextW( credential, context, targetW, context_req, reserved1, target_data_rep,
520 input, reserved2, new_context, output, context_attr, ts_expiry );
521 free( targetW );
522 return status;
525 static SECURITY_STATUS WINAPI lsa_AcceptSecurityContext(
526 CredHandle *credential, CtxtHandle *context, SecBufferDesc *input,
527 ULONG context_req, ULONG target_data_rep, CtxtHandle *new_context,
528 SecBufferDesc *output, ULONG *context_attr, TimeStamp *ts_expiry)
530 SECURITY_STATUS status;
531 struct lsa_package *package = NULL;
532 struct lsa_handle *lsa_cred = NULL, *lsa_ctx = NULL, *new_lsa_ctx;
533 BOOLEAN mapped_context;
534 LSA_SEC_HANDLE new_handle;
536 TRACE("%p %p %p %#lx %#lx %p %p %p %p\n", credential, context, input,
537 context_req, target_data_rep, new_context, output, context_attr, ts_expiry);
539 if (context)
541 lsa_ctx = (struct lsa_handle *)context->dwLower;
542 if (lsa_ctx->magic != LSA_MAGIC_CONTEXT) return SEC_E_INVALID_HANDLE;
543 package = lsa_ctx->package;
545 else if (credential)
547 lsa_cred = (struct lsa_handle *)credential->dwLower;
548 if (lsa_cred->magic != LSA_MAGIC_CREDENTIALS) return SEC_E_INVALID_HANDLE;
549 package = lsa_cred->package;
551 if (!package || !new_context) return SEC_E_INVALID_HANDLE;
553 if (!package->lsa_api || !package->lsa_api->AcceptLsaModeContext)
554 return SEC_E_UNSUPPORTED_FUNCTION;
556 status = package->lsa_api->AcceptLsaModeContext(lsa_cred ? lsa_cred->handle : 0,
557 lsa_ctx ? lsa_ctx->handle : 0, input, context_req, target_data_rep, &new_handle, output,
558 context_attr, ts_expiry, &mapped_context, NULL /* FIXME */);
559 if (status == SEC_E_OK || status == SEC_I_CONTINUE_NEEDED)
561 if (!(new_lsa_ctx = alloc_lsa_handle(LSA_MAGIC_CONTEXT))) return STATUS_NO_MEMORY;
562 new_lsa_ctx->package = package;
563 new_lsa_ctx->handle = new_handle;
564 new_context->dwLower = (ULONG_PTR)new_lsa_ctx;
565 new_context->dwUpper = 0;
567 return status;
570 static SECURITY_STATUS WINAPI lsa_DeleteSecurityContext(CtxtHandle *context)
572 struct lsa_handle *lsa_ctx;
573 SECURITY_STATUS status;
575 TRACE("%p\n", context);
577 if (!context) return SEC_E_INVALID_HANDLE;
578 lsa_ctx = (struct lsa_handle *)context->dwLower;
579 if (!lsa_ctx || lsa_ctx->magic != LSA_MAGIC_CONTEXT) return SEC_E_INVALID_HANDLE;
581 if (!lsa_ctx->package->lsa_api || !lsa_ctx->package->lsa_api->DeleteContext)
582 return SEC_E_UNSUPPORTED_FUNCTION;
584 status = lsa_ctx->package->lsa_api->DeleteContext(lsa_ctx->handle);
585 free(lsa_ctx);
586 return status;
589 static SECURITY_STATUS WINAPI lsa_QueryContextAttributesW(CtxtHandle *context, ULONG attribute, void *buffer)
591 struct lsa_handle *lsa_ctx;
593 TRACE("%p %ld %p\n", context, attribute, buffer);
595 if (!context) return SEC_E_INVALID_HANDLE;
596 lsa_ctx = (struct lsa_handle *)context->dwLower;
597 if (!lsa_ctx || lsa_ctx->magic != LSA_MAGIC_CONTEXT) return SEC_E_INVALID_HANDLE;
599 if (!lsa_ctx->package->lsa_api || !lsa_ctx->package->lsa_api->SpQueryContextAttributes)
600 return SEC_E_UNSUPPORTED_FUNCTION;
602 return lsa_ctx->package->lsa_api->SpQueryContextAttributes(lsa_ctx->handle, attribute, buffer);
605 static SecPkgInfoA *package_infoWtoA( const SecPkgInfoW *info )
607 SecPkgInfoA *ret;
608 int size_name = WideCharToMultiByte( CP_ACP, 0, info->Name, -1, NULL, 0, NULL, NULL );
609 int size_comment = WideCharToMultiByte( CP_ACP, 0, info->Comment, -1, NULL, 0, NULL, NULL );
611 /* freed with FreeContextBuffer */
612 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*ret) + size_name + size_comment ))) return NULL;
613 ret->fCapabilities = info->fCapabilities;
614 ret->wVersion = info->wVersion;
615 ret->wRPCID = info->wRPCID;
616 ret->cbMaxToken = info->cbMaxToken;
617 ret->Name = (SEC_CHAR *)(ret + 1);
618 WideCharToMultiByte( CP_ACP, 0, info->Name, -1, ret->Name, size_name, NULL, NULL );
619 ret->Comment = ret->Name + size_name;
620 WideCharToMultiByte( CP_ACP, 0, info->Comment, -1, ret->Comment, size_comment, NULL, NULL );
621 return ret;
624 static SECURITY_STATUS nego_info_WtoA( const SecPkgContext_NegotiationInfoW *infoW,
625 SecPkgContext_NegotiationInfoA *infoA )
627 infoA->NegotiationState = infoW->NegotiationState;
628 if (!(infoA->PackageInfo = package_infoWtoA( infoW->PackageInfo ))) return SEC_E_INSUFFICIENT_MEMORY;
629 return SEC_E_OK;
632 static SECURITY_STATUS key_info_WtoA( const SecPkgContext_KeyInfoW *infoW, SecPkgContext_KeyInfoA *infoA )
634 int size;
636 size = WideCharToMultiByte( CP_ACP, 0, infoW->sSignatureAlgorithmName, -1, NULL, 0, NULL, NULL );
637 if (!(infoA->sSignatureAlgorithmName = RtlAllocateHeap( GetProcessHeap(), 0, size )))
638 return SEC_E_INSUFFICIENT_MEMORY;
639 WideCharToMultiByte( CP_ACP, 0, infoW->sSignatureAlgorithmName, -1, infoA->sSignatureAlgorithmName,
640 size, NULL, NULL );
642 size = WideCharToMultiByte( CP_ACP, 0, infoW->sEncryptAlgorithmName, -1, NULL, 0, NULL, NULL );
643 if (!(infoA->sEncryptAlgorithmName = RtlAllocateHeap( GetProcessHeap(), 0, size )))
645 RtlFreeHeap( GetProcessHeap(), 0, infoA->sSignatureAlgorithmName );
646 return SEC_E_INSUFFICIENT_MEMORY;
648 WideCharToMultiByte( CP_ACP, 0, infoW->sEncryptAlgorithmName, -1, infoA->sEncryptAlgorithmName,
649 size, NULL, NULL );
651 infoA->KeySize = infoW->KeySize;
652 infoA->SignatureAlgorithm = infoW->SignatureAlgorithm;
653 infoA->EncryptAlgorithm = infoW->EncryptAlgorithm;
654 return SEC_E_OK;
657 static SECURITY_STATUS WINAPI lsa_QueryContextAttributesA(CtxtHandle *context, ULONG attribute, void *buffer)
659 TRACE("%p %ld %p\n", context, attribute, buffer);
661 if (!context) return SEC_E_INVALID_HANDLE;
663 switch (attribute)
665 case SECPKG_ATTR_SIZES:
666 return lsa_QueryContextAttributesW( context, attribute, buffer );
668 case SECPKG_ATTR_NEGOTIATION_INFO:
670 SecPkgContext_NegotiationInfoW infoW;
671 SecPkgContext_NegotiationInfoA *infoA = (SecPkgContext_NegotiationInfoA *)buffer;
672 SECURITY_STATUS status = lsa_QueryContextAttributesW( context, SECPKG_ATTR_NEGOTIATION_INFO, &infoW );
674 if (status != SEC_E_OK) return status;
675 status = nego_info_WtoA( &infoW, infoA );
676 FreeContextBuffer( infoW.PackageInfo );
677 return status;
679 case SECPKG_ATTR_KEY_INFO:
681 SecPkgContext_KeyInfoW infoW;
682 SecPkgContext_KeyInfoA *infoA = (SecPkgContext_KeyInfoA *)buffer;
684 SECURITY_STATUS status = lsa_QueryContextAttributesW( context, SECPKG_ATTR_KEY_INFO, &infoW );
686 if (status != SEC_E_OK) return status;
687 status = key_info_WtoA( &infoW, infoA );
688 FreeContextBuffer( infoW.sSignatureAlgorithmName );
689 FreeContextBuffer( infoW.sEncryptAlgorithmName );
690 return status;
693 #define X(x) case (x) : FIXME(#x" stub\n"); break
694 X(SECPKG_ATTR_ACCESS_TOKEN);
695 X(SECPKG_ATTR_AUTHORITY);
696 X(SECPKG_ATTR_DCE_INFO);
697 X(SECPKG_ATTR_LIFESPAN);
698 X(SECPKG_ATTR_NAMES);
699 X(SECPKG_ATTR_NATIVE_NAMES);
700 X(SECPKG_ATTR_PACKAGE_INFO);
701 X(SECPKG_ATTR_PASSWORD_EXPIRY);
702 X(SECPKG_ATTR_SESSION_KEY);
703 X(SECPKG_ATTR_STREAM_SIZES);
704 X(SECPKG_ATTR_TARGET_INFORMATION);
705 #undef X
706 default:
707 FIXME( "unknown attribute %lu\n", attribute );
708 break;
711 return SEC_E_UNSUPPORTED_FUNCTION;
714 static SECURITY_STATUS WINAPI lsa_MakeSignature(CtxtHandle *context, ULONG quality_of_protection,
715 SecBufferDesc *message, ULONG message_seq_no)
717 struct lsa_handle *lsa_ctx;
719 TRACE("%p %#lx %p %lu)\n", context, quality_of_protection, message, message_seq_no);
721 if (!context) return SEC_E_INVALID_HANDLE;
722 lsa_ctx = (struct lsa_handle *)context->dwLower;
723 if (!lsa_ctx || lsa_ctx->magic != LSA_MAGIC_CONTEXT) return SEC_E_INVALID_HANDLE;
725 if (!lsa_ctx->package->user_api || !lsa_ctx->package->user_api->MakeSignature)
726 return SEC_E_UNSUPPORTED_FUNCTION;
728 return lsa_ctx->package->user_api->MakeSignature(lsa_ctx->handle, quality_of_protection, message, message_seq_no);
731 static SECURITY_STATUS WINAPI lsa_VerifySignature(CtxtHandle *context, SecBufferDesc *message,
732 ULONG message_seq_no, ULONG *quality_of_protection)
734 struct lsa_handle *lsa_ctx;
736 TRACE("%p %p %lu %p)\n", context, message, message_seq_no, quality_of_protection);
738 if (!context) return SEC_E_INVALID_HANDLE;
739 lsa_ctx = (struct lsa_handle *)context->dwLower;
740 if (!lsa_ctx || lsa_ctx->magic != LSA_MAGIC_CONTEXT) return SEC_E_INVALID_HANDLE;
742 if (!lsa_ctx->package->user_api || !lsa_ctx->package->user_api->VerifySignature)
743 return SEC_E_UNSUPPORTED_FUNCTION;
745 return lsa_ctx->package->user_api->VerifySignature(lsa_ctx->handle, message, message_seq_no, quality_of_protection);
748 static SECURITY_STATUS WINAPI lsa_EncryptMessage(CtxtHandle *context, ULONG quality_of_protection,
749 SecBufferDesc *message, ULONG message_seq_no)
751 struct lsa_handle *lsa_ctx;
753 TRACE("%p %#lx %p %lu)\n", context, quality_of_protection, message, message_seq_no);
755 if (!context) return SEC_E_INVALID_HANDLE;
756 lsa_ctx = (struct lsa_handle *)context->dwLower;
757 if (!lsa_ctx || lsa_ctx->magic != LSA_MAGIC_CONTEXT) return SEC_E_INVALID_HANDLE;
759 if (!lsa_ctx->package->user_api || !lsa_ctx->package->user_api->SealMessage)
760 return SEC_E_UNSUPPORTED_FUNCTION;
762 return lsa_ctx->package->user_api->SealMessage(lsa_ctx->handle, quality_of_protection, message, message_seq_no);
765 static SECURITY_STATUS WINAPI lsa_DecryptMessage(CtxtHandle *context, SecBufferDesc *message,
766 ULONG message_seq_no, ULONG *quality_of_protection)
768 struct lsa_handle *lsa_ctx;
770 TRACE("%p %p %lu %p)\n", context, message, message_seq_no, quality_of_protection);
772 if (!context) return SEC_E_INVALID_HANDLE;
773 lsa_ctx = (struct lsa_handle *)context->dwLower;
774 if (!lsa_ctx || lsa_ctx->magic != LSA_MAGIC_CONTEXT) return SEC_E_INVALID_HANDLE;
776 if (!lsa_ctx->package->user_api || !lsa_ctx->package->user_api->UnsealMessage)
777 return SEC_E_UNSUPPORTED_FUNCTION;
779 return lsa_ctx->package->user_api->UnsealMessage(lsa_ctx->handle, message, message_seq_no, quality_of_protection);
782 static const SecurityFunctionTableW lsa_sspi_tableW =
785 NULL, /* EnumerateSecurityPackagesW */
786 NULL, /* QueryCredentialsAttributesW */
787 lsa_AcquireCredentialsHandleW,
788 lsa_FreeCredentialsHandle,
789 NULL, /* Reserved2 */
790 lsa_InitializeSecurityContextW,
791 lsa_AcceptSecurityContext,
792 NULL, /* CompleteAuthToken */
793 lsa_DeleteSecurityContext,
794 NULL, /* ApplyControlToken */
795 lsa_QueryContextAttributesW,
796 NULL, /* ImpersonateSecurityContext */
797 NULL, /* RevertSecurityContext */
798 lsa_MakeSignature,
799 lsa_VerifySignature,
800 NULL, /* FreeContextBuffer */
801 NULL, /* QuerySecurityPackageInfoW */
802 NULL, /* Reserved3 */
803 NULL, /* Reserved4 */
804 NULL, /* ExportSecurityContext */
805 NULL, /* ImportSecurityContextW */
806 NULL, /* AddCredentialsW */
807 NULL, /* Reserved8 */
808 NULL, /* QuerySecurityContextToken */
809 lsa_EncryptMessage,
810 lsa_DecryptMessage,
811 NULL, /* SetContextAttributesW */
814 static const SecurityFunctionTableA lsa_sspi_tableA =
817 NULL, /* EnumerateSecurityPackagesA */
818 NULL, /* QueryCredentialsAttributesA */
819 lsa_AcquireCredentialsHandleA,
820 lsa_FreeCredentialsHandle,
821 NULL, /* Reserved2 */
822 lsa_InitializeSecurityContextA,
823 lsa_AcceptSecurityContext,
824 NULL, /* CompleteAuthToken */
825 lsa_DeleteSecurityContext,
826 NULL, /* ApplyControlToken */
827 lsa_QueryContextAttributesA,
828 NULL, /* ImpersonateSecurityContext */
829 NULL, /* RevertSecurityContext */
830 lsa_MakeSignature,
831 lsa_VerifySignature,
832 NULL, /* FreeContextBuffer */
833 NULL, /* QuerySecurityPackageInfoA */
834 NULL, /* Reserved3 */
835 NULL, /* Reserved4 */
836 NULL, /* ExportSecurityContext */
837 NULL, /* ImportSecurityContextA */
838 NULL, /* AddCredentialsA */
839 NULL, /* Reserved8 */
840 NULL, /* QuerySecurityContextToken */
841 lsa_EncryptMessage,
842 lsa_DecryptMessage,
843 NULL, /* SetContextAttributesA */
846 static void add_package(struct lsa_package *package)
848 struct lsa_package *new_loaded_packages;
850 if (!loaded_packages)
851 new_loaded_packages = malloc(sizeof(*new_loaded_packages));
852 else
853 new_loaded_packages = realloc(loaded_packages, sizeof(*new_loaded_packages) * (loaded_packages_count + 1));
855 if (new_loaded_packages)
857 loaded_packages = new_loaded_packages;
858 loaded_packages[loaded_packages_count] = *package;
859 loaded_packages_count++;
863 static BOOL load_package(const WCHAR *name, struct lsa_package *package, ULONG package_id)
865 NTSTATUS (NTAPI *pSpLsaModeInitialize)(ULONG, PULONG, PSECPKG_FUNCTION_TABLE *, PULONG);
866 NTSTATUS (NTAPI *pSpUserModeInitialize)(ULONG, PULONG, PSECPKG_USER_FUNCTION_TABLE *, PULONG);
868 memset(package, 0, sizeof(*package));
870 package->mod = LoadLibraryW(name);
871 if (!package->mod) return FALSE;
873 pSpLsaModeInitialize = (void *)GetProcAddress(package->mod, "SpLsaModeInitialize");
874 if (pSpLsaModeInitialize)
876 NTSTATUS status;
878 status = pSpLsaModeInitialize(SECPKG_INTERFACE_VERSION, &package->lsa_api_version, &package->lsa_api, &package->lsa_table_count);
879 if (status == STATUS_SUCCESS)
881 status = package->lsa_api->InitializePackage(package_id, &lsa_dispatch, NULL, NULL, &package->name);
882 if (status == STATUS_SUCCESS)
884 TRACE("%s => %p, name %s, version %#lx, api table %p, table count %lu\n",
885 debugstr_w(name), package->mod, debugstr_an(package->name->Buffer, package->name->Length),
886 package->lsa_api_version, package->lsa_api, package->lsa_table_count);
887 package->package_id = package_id;
889 status = package->lsa_api->Initialize(package_id, NULL /* FIXME: params */, NULL);
890 if (status == STATUS_SUCCESS)
892 pSpUserModeInitialize = (void *)GetProcAddress(package->mod, "SpUserModeInitialize");
893 if (pSpUserModeInitialize)
895 status = pSpUserModeInitialize(SECPKG_INTERFACE_VERSION, &package->user_api_version, &package->user_api, &package->user_table_count);
896 if (status == STATUS_SUCCESS)
897 package->user_api->InstanceInit(SECPKG_INTERFACE_VERSION, &lsa_dll_dispatch, NULL);
900 return TRUE;
905 FreeLibrary(package->mod);
906 return FALSE;
909 #define MAX_SERVICE_NAME 260
911 void load_auth_packages(void)
913 DWORD err, i;
914 HKEY root;
915 SecureProvider *provider;
917 err = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Control\\Lsa", 0, KEY_READ, &root);
918 if (err != ERROR_SUCCESS) return;
920 i = 0;
921 for (;;)
923 WCHAR name[MAX_SERVICE_NAME];
924 struct lsa_package package;
926 err = RegEnumKeyW(root, i++, name, MAX_SERVICE_NAME);
927 if (err == ERROR_NO_MORE_ITEMS)
928 break;
930 if (err != ERROR_SUCCESS)
931 continue;
933 if (!load_package(name, &package, i))
934 continue;
936 add_package(&package);
939 RegCloseKey(root);
941 if (!loaded_packages_count) return;
943 provider = SECUR32_addProvider(&lsa_sspi_tableA, &lsa_sspi_tableW, NULL);
944 if (!provider)
946 ERR("Failed to add SSP/AP provider\n");
947 return;
950 for (i = 0; i < loaded_packages_count; i++)
952 SecPkgInfoW *info;
954 info = malloc(loaded_packages[i].lsa_table_count * sizeof(*info));
955 if (info)
957 NTSTATUS status;
959 status = loaded_packages[i].lsa_api->GetInfo(info);
960 if (status == STATUS_SUCCESS)
961 SECUR32_addPackages(provider, loaded_packages[i].lsa_table_count, NULL, info);
963 free(info);
968 NTSTATUS WINAPI LsaLookupAuthenticationPackage(HANDLE lsa_handle,
969 PLSA_STRING package_name, PULONG package_id)
971 ULONG i;
973 TRACE("%p %s %p\n", lsa_handle, debugstr_as(package_name), package_id);
975 for (i = 0; i < loaded_packages_count; i++)
977 if (!RtlCompareString(loaded_packages[i].name, package_name, FALSE))
979 *package_id = loaded_packages[i].package_id;
980 return STATUS_SUCCESS;
984 return STATUS_UNSUCCESSFUL; /* FIXME */