user32: Uppercase the RawInput device names sans the GUID.
[wine.git] / dlls / secur32 / lsa.c
blobbd3cac4704f11e6225995a3089da2e362dcd33db
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 struct lsa_package
48 ULONG package_id;
49 HMODULE mod;
50 LSA_STRING *name;
51 ULONG lsa_api_version, lsa_table_count, user_api_version, user_table_count;
52 SECPKG_FUNCTION_TABLE *lsa_api;
53 SECPKG_USER_FUNCTION_TABLE *user_api;
56 static struct lsa_package *loaded_packages;
57 static ULONG loaded_packages_count;
59 struct lsa_handle
61 DWORD magic;
62 struct lsa_package *package;
63 LSA_SEC_HANDLE handle;
66 static const char *debugstr_as(const LSA_STRING *str)
68 if (!str) return "<null>";
69 return debugstr_an(str->Buffer, str->Length);
72 NTSTATUS WINAPI LsaCallAuthenticationPackage(HANDLE lsa_handle, ULONG package_id,
73 PVOID in_buffer, ULONG in_buffer_length,
74 PVOID *out_buffer, PULONG out_buffer_length, PNTSTATUS status)
76 ULONG i;
78 TRACE("%p,%u,%p,%u,%p,%p,%p\n", lsa_handle, package_id, in_buffer,
79 in_buffer_length, out_buffer, out_buffer_length, status);
81 for (i = 0; i < loaded_packages_count; i++)
83 if (loaded_packages[i].package_id == package_id)
85 if (loaded_packages[i].lsa_api->CallPackageUntrusted)
86 return loaded_packages[i].lsa_api->CallPackageUntrusted(NULL /* FIXME*/,
87 in_buffer, NULL, in_buffer_length, out_buffer, out_buffer_length, status);
89 return SEC_E_UNSUPPORTED_FUNCTION;
93 return STATUS_INVALID_PARAMETER;
96 static struct lsa_handle *alloc_lsa_handle(ULONG magic)
98 struct lsa_handle *ret;
99 if (!(ret = calloc(1, sizeof(*ret)))) return NULL;
100 ret->magic = magic;
101 return ret;
104 NTSTATUS WINAPI LsaConnectUntrusted(PHANDLE LsaHandle)
106 struct lsa_handle *lsa_conn;
108 TRACE("%p\n", LsaHandle);
110 if (!(lsa_conn = alloc_lsa_handle(LSA_MAGIC_CONNECTION))) return STATUS_NO_MEMORY;
111 *LsaHandle = lsa_conn;
112 return STATUS_SUCCESS;
115 NTSTATUS WINAPI LsaRegisterLogonProcess(PLSA_STRING LogonProcessName,
116 PHANDLE LsaHandle, PLSA_OPERATIONAL_MODE SecurityMode)
118 struct lsa_handle *lsa_conn;
120 FIXME("%s %p %p stub\n", debugstr_as(LogonProcessName), LsaHandle, SecurityMode);
122 if (!(lsa_conn = alloc_lsa_handle(LSA_MAGIC_CONNECTION))) return STATUS_NO_MEMORY;
123 *LsaHandle = lsa_conn;
124 return STATUS_SUCCESS;
127 NTSTATUS WINAPI LsaDeregisterLogonProcess(HANDLE LsaHandle)
129 struct lsa_handle *lsa_conn = (struct lsa_handle *)LsaHandle;
131 TRACE("%p\n", LsaHandle);
133 if (!lsa_conn || lsa_conn->magic != LSA_MAGIC_CONNECTION) return STATUS_INVALID_HANDLE;
134 lsa_conn->magic = 0;
135 free(lsa_conn);
137 return STATUS_SUCCESS;
140 NTSTATUS WINAPI LsaEnumerateLogonSessions(PULONG LogonSessionCount,
141 PLUID* LogonSessionList)
143 FIXME("%p %p stub\n", LogonSessionCount, LogonSessionList);
144 *LogonSessionCount = 0;
145 *LogonSessionList = NULL;
147 return STATUS_SUCCESS;
150 NTSTATUS WINAPI LsaFreeReturnBuffer(PVOID buffer)
152 TRACE("%p\n", buffer);
153 free(buffer);
154 return STATUS_SUCCESS;
157 NTSTATUS WINAPI LsaGetLogonSessionData(PLUID LogonId,
158 PSECURITY_LOGON_SESSION_DATA* ppLogonSessionData)
160 FIXME("%p %p stub\n", LogonId, ppLogonSessionData);
161 *ppLogonSessionData = NULL;
162 return STATUS_NOT_IMPLEMENTED;
165 NTSTATUS WINAPI LsaLogonUser(HANDLE LsaHandle, PLSA_STRING OriginName,
166 SECURITY_LOGON_TYPE LogonType, ULONG AuthenticationPackage,
167 PVOID AuthenticationInformation, ULONG AuthenticationInformationLength,
168 PTOKEN_GROUPS LocalGroups, PTOKEN_SOURCE SourceContext,
169 PVOID* ProfileBuffer, PULONG ProfileBufferLength, PLUID LogonId,
170 PHANDLE Token, PQUOTA_LIMITS Quotas, PNTSTATUS SubStatus)
172 FIXME("%p %s %d %d %p %d %p %p %p %p %p %p %p %p stub\n", LsaHandle,
173 debugstr_as(OriginName), LogonType, AuthenticationPackage,
174 AuthenticationInformation, AuthenticationInformationLength,
175 LocalGroups, SourceContext, ProfileBuffer, ProfileBufferLength,
176 LogonId, Token, Quotas, SubStatus);
177 return STATUS_SUCCESS;
180 static NTSTATUS NTAPI lsa_CreateLogonSession(LUID *logon_id)
182 FIXME("%p: stub\n", logon_id);
183 return STATUS_NOT_IMPLEMENTED;
186 static NTSTATUS NTAPI lsa_DeleteLogonSession(LUID *logon_id)
188 FIXME("%p: stub\n", logon_id);
189 return STATUS_NOT_IMPLEMENTED;
192 static NTSTATUS NTAPI lsa_AddCredential(LUID *logon_id, ULONG package_id,
193 LSA_STRING *primary_key, LSA_STRING *credentials)
195 FIXME("%p,%u,%s,%s: stub\n", logon_id, package_id,
196 debugstr_as(primary_key), debugstr_as(credentials));
197 return STATUS_NOT_IMPLEMENTED;
200 static NTSTATUS NTAPI lsa_GetCredentials(LUID *logon_id, ULONG package_id, ULONG *context,
201 BOOLEAN retrieve_all, LSA_STRING *primary_key, ULONG *primary_key_len, LSA_STRING *credentials)
203 FIXME("%p,%#x,%p,%d,%p,%p,%p: stub\n", logon_id, package_id, context,
204 retrieve_all, primary_key, primary_key_len, credentials);
205 return STATUS_NOT_IMPLEMENTED;
208 static NTSTATUS NTAPI lsa_DeleteCredential(LUID *logon_id, ULONG package_id, LSA_STRING *primary_key)
210 FIXME("%p,%#x,%s: stub\n", logon_id, package_id, debugstr_as(primary_key));
211 return STATUS_NOT_IMPLEMENTED;
214 static void * NTAPI lsa_AllocateLsaHeap(ULONG size)
216 TRACE("%u\n", size);
217 return malloc(size);
220 static void NTAPI lsa_FreeLsaHeap(void *p)
222 TRACE("%p\n", p);
223 free(p);
226 static NTSTATUS NTAPI lsa_AllocateClientBuffer(PLSA_CLIENT_REQUEST req, ULONG size, void **p)
228 TRACE("%p,%u,%p\n", req, size, p);
229 *p = malloc(size);
230 return *p ? STATUS_SUCCESS : STATUS_NO_MEMORY;
233 static NTSTATUS NTAPI lsa_FreeClientBuffer(PLSA_CLIENT_REQUEST req, void *p)
235 TRACE("%p,%p\n", req, p);
236 free(p);
237 return STATUS_SUCCESS;
240 static NTSTATUS NTAPI lsa_CopyToClientBuffer(PLSA_CLIENT_REQUEST req, ULONG size, void *client, void *buf)
242 TRACE("%p,%u,%p,%p\n", req, size, client, buf);
243 memcpy(client, buf, size);
244 return STATUS_SUCCESS;
247 static NTSTATUS NTAPI lsa_CopyFromClientBuffer(PLSA_CLIENT_REQUEST req, ULONG size, void *buf, void *client)
249 TRACE("%p,%u,%p,%p\n", req, size, buf, client);
250 memcpy(buf, client, size);
251 return STATUS_SUCCESS;
254 static LSA_DISPATCH_TABLE lsa_dispatch =
256 lsa_CreateLogonSession,
257 lsa_DeleteLogonSession,
258 lsa_AddCredential,
259 lsa_GetCredentials,
260 lsa_DeleteCredential,
261 lsa_AllocateLsaHeap,
262 lsa_FreeLsaHeap,
263 lsa_AllocateClientBuffer,
264 lsa_FreeClientBuffer,
265 lsa_CopyToClientBuffer,
266 lsa_CopyFromClientBuffer
269 static NTSTATUS NTAPI lsa_RegisterCallback(ULONG callback_id, PLSA_CALLBACK_FUNCTION callback)
271 FIXME("%u,%p: stub\n", callback_id, callback);
272 return STATUS_NOT_IMPLEMENTED;
275 static SECPKG_DLL_FUNCTIONS lsa_dll_dispatch =
277 lsa_AllocateLsaHeap,
278 lsa_FreeLsaHeap,
279 lsa_RegisterCallback
282 static SECURITY_STATUS lsa_lookup_package(SEC_WCHAR *nameW, struct lsa_package **lsa_package)
284 ULONG i;
285 UNICODE_STRING package_name, name;
287 for (i = 0; i < loaded_packages_count; i++)
289 if (RtlAnsiStringToUnicodeString(&package_name, loaded_packages[i].name, TRUE))
290 return SEC_E_INSUFFICIENT_MEMORY;
292 RtlInitUnicodeString(&name, nameW);
294 if (RtlEqualUnicodeString(&package_name, &name, TRUE))
296 RtlFreeUnicodeString(&package_name);
297 *lsa_package = &loaded_packages[i];
298 return SEC_E_OK;
301 RtlFreeUnicodeString(&package_name);
304 return SEC_E_SECPKG_NOT_FOUND;
307 static SECURITY_STATUS WINAPI lsa_AcquireCredentialsHandleW(
308 SEC_WCHAR *principal, SEC_WCHAR *package, ULONG credentials_use,
309 LUID *logon_id, void *auth_data, SEC_GET_KEY_FN get_key_fn,
310 void *get_key_arg, CredHandle *credential, TimeStamp *ts_expiry)
312 SECURITY_STATUS status;
313 struct lsa_package *lsa_package;
314 struct lsa_handle *lsa_handle;
315 UNICODE_STRING principal_us;
316 LSA_SEC_HANDLE lsa_credential;
318 TRACE("%s %s %#x %p %p %p %p %p\n", debugstr_w(principal), debugstr_w(package),
319 credentials_use, auth_data, get_key_fn, get_key_arg, credential, ts_expiry);
321 if (!credential) return SEC_E_INVALID_HANDLE;
322 if (!package) return SEC_E_SECPKG_NOT_FOUND;
324 status = lsa_lookup_package(package, &lsa_package);
325 if (status != SEC_E_OK) return status;
327 if (!lsa_package->lsa_api || !lsa_package->lsa_api->SpAcquireCredentialsHandle)
328 return SEC_E_UNSUPPORTED_FUNCTION;
330 if (principal)
331 RtlInitUnicodeString(&principal_us, principal);
333 status = lsa_package->lsa_api->SpAcquireCredentialsHandle(principal ? &principal_us : NULL,
334 credentials_use, logon_id, auth_data, get_key_fn, get_key_arg, &lsa_credential, ts_expiry);
335 if (status == SEC_E_OK)
337 if (!(lsa_handle = alloc_lsa_handle(LSA_MAGIC_CREDENTIALS))) return STATUS_NO_MEMORY;
338 lsa_handle->package = lsa_package;
339 lsa_handle->handle = lsa_credential;
340 credential->dwLower = (ULONG_PTR)lsa_handle;
341 credential->dwUpper = 0;
343 return status;
346 static SECURITY_STATUS WINAPI lsa_AcquireCredentialsHandleA(
347 SEC_CHAR *principal, SEC_CHAR *package, ULONG credentials_use,
348 LUID *logon_id, void *auth_data, SEC_GET_KEY_FN get_key_fn,
349 void *get_key_arg, CredHandle *credential, TimeStamp *ts_expiry)
351 SECURITY_STATUS status = SEC_E_INSUFFICIENT_MEMORY;
352 int len_user = 0, len_domain = 0, len_passwd = 0;
353 SEC_WCHAR *principalW = NULL, *packageW = NULL, *user = NULL, *domain = NULL, *passwd = NULL;
354 SEC_WINNT_AUTH_IDENTITY_W *auth_dataW = NULL;
355 SEC_WINNT_AUTH_IDENTITY_A *id = NULL;
357 TRACE("%s %s %#x %p %p %p %p %p\n", debugstr_a(principal), debugstr_a(package),
358 credentials_use, auth_data, get_key_fn, get_key_arg, credential, ts_expiry);
360 if (principal)
362 int len = MultiByteToWideChar( CP_ACP, 0, principal, -1, NULL, 0 );
363 if (!(principalW = malloc( len * sizeof(SEC_WCHAR) ))) goto done;
364 MultiByteToWideChar( CP_ACP, 0, principal, -1, principalW, len );
366 if (package)
368 int len = MultiByteToWideChar( CP_ACP, 0, package, -1, NULL, 0 );
369 if (!(packageW = malloc( len * sizeof(SEC_WCHAR) ))) goto done;
370 MultiByteToWideChar( CP_ACP, 0, package, -1, packageW, len );
372 if (auth_data)
374 id = (PSEC_WINNT_AUTH_IDENTITY_A)auth_data;
376 if (id->Flags == SEC_WINNT_AUTH_IDENTITY_ANSI)
378 if (!(auth_dataW = malloc( sizeof(SEC_WINNT_AUTH_IDENTITY_W) ))) goto done;
379 if (id->UserLength)
381 len_user = MultiByteToWideChar( CP_ACP, 0, (char *)id->User, id->UserLength, NULL, 0 );
382 if (!(user = malloc( len_user * sizeof(SEC_WCHAR) ))) goto done;
383 MultiByteToWideChar( CP_ACP, 0, (char *)id->User, id->UserLength, user, len_user );
385 if (id->DomainLength)
387 len_domain = MultiByteToWideChar( CP_ACP, 0, (char *)id->Domain, id->DomainLength, NULL, 0 );
388 if (!(domain = malloc( len_domain * sizeof(SEC_WCHAR) ))) goto done;
389 MultiByteToWideChar( CP_ACP, 0, (char *)id->Domain, id->DomainLength, domain, len_domain );
391 if (id->PasswordLength)
393 len_passwd = MultiByteToWideChar( CP_ACP, 0, (char *)id->Password, id->PasswordLength, NULL, 0 );
394 if (!(passwd = malloc( len_passwd * sizeof(SEC_WCHAR) ))) goto done;
395 MultiByteToWideChar( CP_ACP, 0, (char *)id->Password, id->PasswordLength, passwd, len_passwd );
397 auth_dataW->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
398 auth_dataW->User = user;
399 auth_dataW->UserLength = len_user;
400 auth_dataW->Domain = domain;
401 auth_dataW->DomainLength = len_domain;
402 auth_dataW->Password = passwd;
403 auth_dataW->PasswordLength = len_passwd;
405 else auth_dataW = (PSEC_WINNT_AUTH_IDENTITY_W)auth_data;
408 status = lsa_AcquireCredentialsHandleW( principalW, packageW, credentials_use, logon_id, auth_dataW, get_key_fn,
409 get_key_arg, credential, ts_expiry );
410 done:
411 if (auth_dataW != (SEC_WINNT_AUTH_IDENTITY_W *)id) free( auth_dataW );
412 free( packageW );
413 free( principalW );
414 free( user );
415 free( domain );
416 free( passwd );
417 return status;
420 static SECURITY_STATUS WINAPI lsa_FreeCredentialsHandle(CredHandle *credential)
422 struct lsa_handle *lsa_cred;
423 SECURITY_STATUS status;
425 TRACE("%p\n", credential);
426 if (!credential) return SEC_E_INVALID_HANDLE;
428 lsa_cred = (struct lsa_handle *)credential->dwLower;
429 if (!lsa_cred || lsa_cred->magic != LSA_MAGIC_CREDENTIALS) return SEC_E_INVALID_HANDLE;
431 if (!lsa_cred->package->lsa_api || !lsa_cred->package->lsa_api->FreeCredentialsHandle)
432 return SEC_E_UNSUPPORTED_FUNCTION;
434 status = lsa_cred->package->lsa_api->FreeCredentialsHandle(lsa_cred->handle);
436 lsa_cred->magic = 0;
437 free(lsa_cred);
438 return status;
441 static SECURITY_STATUS WINAPI lsa_InitializeSecurityContextW(
442 CredHandle *credential, CtxtHandle *context, SEC_WCHAR *target_name, ULONG context_req,
443 ULONG reserved1, ULONG target_data_rep, SecBufferDesc *input, ULONG reserved2,
444 CtxtHandle *new_context, SecBufferDesc *output, ULONG *context_attr, TimeStamp *ts_expiry)
446 SECURITY_STATUS status;
447 struct lsa_handle *lsa_cred = NULL, *lsa_ctx = NULL, *new_lsa_ctx;
448 struct lsa_package *package = NULL;
449 UNICODE_STRING target_name_us;
450 BOOLEAN mapped_context;
451 LSA_SEC_HANDLE new_handle;
453 TRACE("%p %p %s %#x %d %d %p %d %p %p %p %p\n", credential, context,
454 debugstr_w(target_name), context_req, reserved1, target_data_rep, input,
455 reserved2, new_context, output, context_attr, ts_expiry);
457 if (context)
459 lsa_ctx = (struct lsa_handle *)context->dwLower;
460 if (lsa_ctx->magic != LSA_MAGIC_CONTEXT) return SEC_E_INVALID_HANDLE;
461 package = lsa_ctx->package;
463 else if (credential)
465 lsa_cred = (struct lsa_handle *)credential->dwLower;
466 if (lsa_cred->magic != LSA_MAGIC_CREDENTIALS) return SEC_E_INVALID_HANDLE;
467 package = lsa_cred->package;
469 if (!package || !new_context) return SEC_E_INVALID_HANDLE;
471 if (!package->lsa_api || !package->lsa_api->InitLsaModeContext)
472 return SEC_E_UNSUPPORTED_FUNCTION;
474 if (target_name)
475 RtlInitUnicodeString(&target_name_us, target_name);
477 status = package->lsa_api->InitLsaModeContext(lsa_cred ? lsa_cred->handle : 0,
478 lsa_ctx ? lsa_ctx->handle : 0, target_name ? &target_name_us : NULL, context_req, target_data_rep,
479 input, &new_handle, output, context_attr, ts_expiry, &mapped_context, NULL /* FIXME */);
480 if (status == SEC_E_OK || status == SEC_I_CONTINUE_NEEDED)
482 if (!(new_lsa_ctx = alloc_lsa_handle(LSA_MAGIC_CONTEXT))) return STATUS_NO_MEMORY;
483 new_lsa_ctx->package = package;
484 new_lsa_ctx->handle = new_handle;
485 new_context->dwLower = (ULONG_PTR)new_lsa_ctx;
486 new_context->dwUpper = 0;
488 return status;
491 static SECURITY_STATUS WINAPI lsa_InitializeSecurityContextA(
492 CredHandle *credential, CtxtHandle *context, SEC_CHAR *target_name, ULONG context_req,
493 ULONG reserved1, ULONG target_data_rep, SecBufferDesc *input, ULONG reserved2,
494 CtxtHandle *new_context, SecBufferDesc *output, ULONG *context_attr, TimeStamp *ts_expiry)
496 SECURITY_STATUS status;
497 SEC_WCHAR *targetW = NULL;
499 TRACE("%p %p %s %#x %d %d %p %d %p %p %p %p\n", credential, context,
500 debugstr_a(target_name), context_req, reserved1, target_data_rep, input,
501 reserved2, new_context, output, context_attr, ts_expiry);
503 if (target_name)
505 int len = MultiByteToWideChar( CP_ACP, 0, target_name, -1, NULL, 0 );
506 if (!(targetW = malloc( len * sizeof(SEC_WCHAR) ))) return SEC_E_INSUFFICIENT_MEMORY;
507 MultiByteToWideChar( CP_ACP, 0, target_name, -1, targetW, len );
510 status = lsa_InitializeSecurityContextW( credential, context, targetW, context_req, reserved1, target_data_rep,
511 input, reserved2, new_context, output, context_attr, ts_expiry );
512 free( targetW );
513 return status;
516 static SECURITY_STATUS WINAPI lsa_AcceptSecurityContext(
517 CredHandle *credential, CtxtHandle *context, SecBufferDesc *input,
518 ULONG context_req, ULONG target_data_rep, CtxtHandle *new_context,
519 SecBufferDesc *output, ULONG *context_attr, TimeStamp *ts_expiry)
521 SECURITY_STATUS status;
522 struct lsa_package *package = NULL;
523 struct lsa_handle *lsa_cred = NULL, *lsa_ctx = NULL, *new_lsa_ctx;
524 BOOLEAN mapped_context;
525 LSA_SEC_HANDLE new_handle;
527 TRACE("%p %p %p %#x %#x %p %p %p %p\n", credential, context, input,
528 context_req, target_data_rep, new_context, output, context_attr, ts_expiry);
530 if (context)
532 lsa_ctx = (struct lsa_handle *)context->dwLower;
533 if (lsa_ctx->magic != LSA_MAGIC_CONTEXT) return SEC_E_INVALID_HANDLE;
534 package = lsa_ctx->package;
536 else if (credential)
538 lsa_cred = (struct lsa_handle *)credential->dwLower;
539 if (lsa_cred->magic != LSA_MAGIC_CREDENTIALS) return SEC_E_INVALID_HANDLE;
540 package = lsa_cred->package;
542 if (!package || !new_context) return SEC_E_INVALID_HANDLE;
544 if (!package->lsa_api || !package->lsa_api->AcceptLsaModeContext)
545 return SEC_E_UNSUPPORTED_FUNCTION;
547 status = package->lsa_api->AcceptLsaModeContext(lsa_cred ? lsa_cred->handle : 0,
548 lsa_ctx ? lsa_ctx->handle : 0, input, context_req, target_data_rep, &new_handle, output,
549 context_attr, ts_expiry, &mapped_context, NULL /* FIXME */);
550 if (status == SEC_E_OK || status == SEC_I_CONTINUE_NEEDED)
552 if (!(new_lsa_ctx = alloc_lsa_handle(LSA_MAGIC_CONTEXT))) return STATUS_NO_MEMORY;
553 new_lsa_ctx->package = package;
554 new_lsa_ctx->handle = new_handle;
555 new_context->dwLower = (ULONG_PTR)new_lsa_ctx;
556 new_context->dwUpper = 0;
558 return status;
561 static SECURITY_STATUS WINAPI lsa_DeleteSecurityContext(CtxtHandle *context)
563 struct lsa_handle *lsa_ctx;
564 SECURITY_STATUS status;
566 TRACE("%p\n", context);
568 if (!context) return SEC_E_INVALID_HANDLE;
569 lsa_ctx = (struct lsa_handle *)context->dwLower;
570 if (!lsa_ctx || lsa_ctx->magic != LSA_MAGIC_CONTEXT) return SEC_E_INVALID_HANDLE;
572 if (!lsa_ctx->package->lsa_api || !lsa_ctx->package->lsa_api->DeleteContext)
573 return SEC_E_UNSUPPORTED_FUNCTION;
575 status = lsa_ctx->package->lsa_api->DeleteContext(lsa_ctx->handle);
576 free(lsa_ctx);
577 return status;
580 static SECURITY_STATUS WINAPI lsa_QueryContextAttributesW(CtxtHandle *context, ULONG attribute, void *buffer)
582 struct lsa_handle *lsa_ctx;
584 TRACE("%p %d %p\n", context, attribute, buffer);
586 if (!context) return SEC_E_INVALID_HANDLE;
587 lsa_ctx = (struct lsa_handle *)context->dwLower;
588 if (!lsa_ctx || lsa_ctx->magic != LSA_MAGIC_CONTEXT) return SEC_E_INVALID_HANDLE;
590 if (!lsa_ctx->package->lsa_api || !lsa_ctx->package->lsa_api->SpQueryContextAttributes)
591 return SEC_E_UNSUPPORTED_FUNCTION;
593 return lsa_ctx->package->lsa_api->SpQueryContextAttributes(lsa_ctx->handle, attribute, buffer);
596 static SecPkgInfoA *package_infoWtoA( const SecPkgInfoW *info )
598 SecPkgInfoA *ret;
599 int size_name = WideCharToMultiByte( CP_ACP, 0, info->Name, -1, NULL, 0, NULL, NULL );
600 int size_comment = WideCharToMultiByte( CP_ACP, 0, info->Comment, -1, NULL, 0, NULL, NULL );
602 /* freed with FreeContextBuffer */
603 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*ret) + size_name + size_comment ))) return NULL;
604 ret->fCapabilities = info->fCapabilities;
605 ret->wVersion = info->wVersion;
606 ret->wRPCID = info->wRPCID;
607 ret->cbMaxToken = info->cbMaxToken;
608 ret->Name = (SEC_CHAR *)(ret + 1);
609 WideCharToMultiByte( CP_ACP, 0, info->Name, -1, ret->Name, size_name, NULL, NULL );
610 ret->Comment = ret->Name + size_name;
611 WideCharToMultiByte( CP_ACP, 0, info->Comment, -1, ret->Comment, size_comment, NULL, NULL );
612 return ret;
615 static SECURITY_STATUS nego_info_WtoA( const SecPkgContext_NegotiationInfoW *infoW,
616 SecPkgContext_NegotiationInfoA *infoA )
618 infoA->NegotiationState = infoW->NegotiationState;
619 if (!(infoA->PackageInfo = package_infoWtoA( infoW->PackageInfo ))) return SEC_E_INSUFFICIENT_MEMORY;
620 return SEC_E_OK;
623 static SECURITY_STATUS WINAPI lsa_QueryContextAttributesA(CtxtHandle *context, ULONG attribute, void *buffer)
625 TRACE("%p %d %p\n", context, attribute, buffer);
627 if (!context) return SEC_E_INVALID_HANDLE;
629 switch (attribute)
631 case SECPKG_ATTR_SIZES:
632 return lsa_QueryContextAttributesW( context, attribute, buffer );
634 case SECPKG_ATTR_NEGOTIATION_INFO:
636 SecPkgContext_NegotiationInfoW infoW;
637 SecPkgContext_NegotiationInfoA *infoA = (SecPkgContext_NegotiationInfoA *)buffer;
638 SECURITY_STATUS status = lsa_QueryContextAttributesW( context, SECPKG_ATTR_NEGOTIATION_INFO, &infoW );
640 if (status != SEC_E_OK) return status;
641 status = nego_info_WtoA( &infoW, infoA );
642 FreeContextBuffer( infoW.PackageInfo );
643 return status;
646 #define X(x) case (x) : FIXME(#x" stub\n"); break
647 X(SECPKG_ATTR_ACCESS_TOKEN);
648 X(SECPKG_ATTR_AUTHORITY);
649 X(SECPKG_ATTR_DCE_INFO);
650 X(SECPKG_ATTR_KEY_INFO);
651 X(SECPKG_ATTR_LIFESPAN);
652 X(SECPKG_ATTR_NAMES);
653 X(SECPKG_ATTR_NATIVE_NAMES);
654 X(SECPKG_ATTR_PACKAGE_INFO);
655 X(SECPKG_ATTR_PASSWORD_EXPIRY);
656 X(SECPKG_ATTR_SESSION_KEY);
657 X(SECPKG_ATTR_STREAM_SIZES);
658 X(SECPKG_ATTR_TARGET_INFORMATION);
659 #undef X
660 default:
661 FIXME( "unknown attribute %u\n", attribute );
662 break;
665 return SEC_E_UNSUPPORTED_FUNCTION;
668 static SECURITY_STATUS WINAPI lsa_MakeSignature(CtxtHandle *context, ULONG quality_of_protection,
669 SecBufferDesc *message, ULONG message_seq_no)
671 struct lsa_handle *lsa_ctx;
673 TRACE("%p %#x %p %u)\n", context, quality_of_protection, message, message_seq_no);
675 if (!context) return SEC_E_INVALID_HANDLE;
676 lsa_ctx = (struct lsa_handle *)context->dwLower;
677 if (!lsa_ctx || lsa_ctx->magic != LSA_MAGIC_CONTEXT) return SEC_E_INVALID_HANDLE;
679 if (!lsa_ctx->package->user_api || !lsa_ctx->package->user_api->MakeSignature)
680 return SEC_E_UNSUPPORTED_FUNCTION;
682 return lsa_ctx->package->user_api->MakeSignature(lsa_ctx->handle, quality_of_protection, message, message_seq_no);
685 static SECURITY_STATUS WINAPI lsa_VerifySignature(CtxtHandle *context, SecBufferDesc *message,
686 ULONG message_seq_no, ULONG *quality_of_protection)
688 struct lsa_handle *lsa_ctx;
690 TRACE("%p %p %u %p)\n", context, message, message_seq_no, quality_of_protection);
692 if (!context) return SEC_E_INVALID_HANDLE;
693 lsa_ctx = (struct lsa_handle *)context->dwLower;
694 if (!lsa_ctx || lsa_ctx->magic != LSA_MAGIC_CONTEXT) return SEC_E_INVALID_HANDLE;
696 if (!lsa_ctx->package->user_api || !lsa_ctx->package->user_api->VerifySignature)
697 return SEC_E_UNSUPPORTED_FUNCTION;
699 return lsa_ctx->package->user_api->VerifySignature(lsa_ctx->handle, message, message_seq_no, quality_of_protection);
702 static SECURITY_STATUS WINAPI lsa_EncryptMessage(CtxtHandle *context, ULONG quality_of_protection,
703 SecBufferDesc *message, ULONG message_seq_no)
705 struct lsa_handle *lsa_ctx;
707 TRACE("%p %#x %p %u)\n", context, quality_of_protection, message, message_seq_no);
709 if (!context) return SEC_E_INVALID_HANDLE;
710 lsa_ctx = (struct lsa_handle *)context->dwLower;
711 if (!lsa_ctx || lsa_ctx->magic != LSA_MAGIC_CONTEXT) return SEC_E_INVALID_HANDLE;
713 if (!lsa_ctx->package->user_api || !lsa_ctx->package->user_api->SealMessage)
714 return SEC_E_UNSUPPORTED_FUNCTION;
716 return lsa_ctx->package->user_api->SealMessage(lsa_ctx->handle, quality_of_protection, message, message_seq_no);
719 static SECURITY_STATUS WINAPI lsa_DecryptMessage(CtxtHandle *context, SecBufferDesc *message,
720 ULONG message_seq_no, ULONG *quality_of_protection)
722 struct lsa_handle *lsa_ctx;
724 TRACE("%p %p %u %p)\n", context, message, message_seq_no, quality_of_protection);
726 if (!context) return SEC_E_INVALID_HANDLE;
727 lsa_ctx = (struct lsa_handle *)context->dwLower;
728 if (!lsa_ctx || lsa_ctx->magic != LSA_MAGIC_CONTEXT) return SEC_E_INVALID_HANDLE;
730 if (!lsa_ctx->package->user_api || !lsa_ctx->package->user_api->UnsealMessage)
731 return SEC_E_UNSUPPORTED_FUNCTION;
733 return lsa_ctx->package->user_api->UnsealMessage(lsa_ctx->handle, message, message_seq_no, quality_of_protection);
736 static const SecurityFunctionTableW lsa_sspi_tableW =
739 NULL, /* EnumerateSecurityPackagesW */
740 NULL, /* QueryCredentialsAttributesW */
741 lsa_AcquireCredentialsHandleW,
742 lsa_FreeCredentialsHandle,
743 NULL, /* Reserved2 */
744 lsa_InitializeSecurityContextW,
745 lsa_AcceptSecurityContext,
746 NULL, /* CompleteAuthToken */
747 lsa_DeleteSecurityContext,
748 NULL, /* ApplyControlToken */
749 lsa_QueryContextAttributesW,
750 NULL, /* ImpersonateSecurityContext */
751 NULL, /* RevertSecurityContext */
752 lsa_MakeSignature,
753 lsa_VerifySignature,
754 NULL, /* FreeContextBuffer */
755 NULL, /* QuerySecurityPackageInfoW */
756 NULL, /* Reserved3 */
757 NULL, /* Reserved4 */
758 NULL, /* ExportSecurityContext */
759 NULL, /* ImportSecurityContextW */
760 NULL, /* AddCredentialsW */
761 NULL, /* Reserved8 */
762 NULL, /* QuerySecurityContextToken */
763 lsa_EncryptMessage,
764 lsa_DecryptMessage,
765 NULL, /* SetContextAttributesW */
768 static const SecurityFunctionTableA lsa_sspi_tableA =
771 NULL, /* EnumerateSecurityPackagesA */
772 NULL, /* QueryCredentialsAttributesA */
773 lsa_AcquireCredentialsHandleA,
774 lsa_FreeCredentialsHandle,
775 NULL, /* Reserved2 */
776 lsa_InitializeSecurityContextA,
777 lsa_AcceptSecurityContext,
778 NULL, /* CompleteAuthToken */
779 lsa_DeleteSecurityContext,
780 NULL, /* ApplyControlToken */
781 lsa_QueryContextAttributesA,
782 NULL, /* ImpersonateSecurityContext */
783 NULL, /* RevertSecurityContext */
784 lsa_MakeSignature,
785 lsa_VerifySignature,
786 NULL, /* FreeContextBuffer */
787 NULL, /* QuerySecurityPackageInfoA */
788 NULL, /* Reserved3 */
789 NULL, /* Reserved4 */
790 NULL, /* ExportSecurityContext */
791 NULL, /* ImportSecurityContextA */
792 NULL, /* AddCredentialsA */
793 NULL, /* Reserved8 */
794 NULL, /* QuerySecurityContextToken */
795 lsa_EncryptMessage,
796 lsa_DecryptMessage,
797 NULL, /* SetContextAttributesA */
800 static void add_package(struct lsa_package *package)
802 struct lsa_package *new_loaded_packages;
804 if (!loaded_packages)
805 new_loaded_packages = malloc(sizeof(*new_loaded_packages));
806 else
807 new_loaded_packages = realloc(loaded_packages, sizeof(*new_loaded_packages) * (loaded_packages_count + 1));
809 if (new_loaded_packages)
811 loaded_packages = new_loaded_packages;
812 loaded_packages[loaded_packages_count] = *package;
813 loaded_packages_count++;
817 static BOOL load_package(const WCHAR *name, struct lsa_package *package, ULONG package_id)
819 NTSTATUS (NTAPI *pSpLsaModeInitialize)(ULONG, PULONG, PSECPKG_FUNCTION_TABLE *, PULONG);
820 NTSTATUS (NTAPI *pSpUserModeInitialize)(ULONG, PULONG, PSECPKG_USER_FUNCTION_TABLE *, PULONG);
822 memset(package, 0, sizeof(*package));
824 package->mod = LoadLibraryW(name);
825 if (!package->mod) return FALSE;
827 pSpLsaModeInitialize = (void *)GetProcAddress(package->mod, "SpLsaModeInitialize");
828 if (pSpLsaModeInitialize)
830 NTSTATUS status;
832 status = pSpLsaModeInitialize(SECPKG_INTERFACE_VERSION, &package->lsa_api_version, &package->lsa_api, &package->lsa_table_count);
833 if (status == STATUS_SUCCESS)
835 status = package->lsa_api->InitializePackage(package_id, &lsa_dispatch, NULL, NULL, &package->name);
836 if (status == STATUS_SUCCESS)
838 TRACE("%s => %p, name %s, version %#x, api table %p, table count %u\n",
839 debugstr_w(name), package->mod, debugstr_an(package->name->Buffer, package->name->Length),
840 package->lsa_api_version, package->lsa_api, package->lsa_table_count);
841 package->package_id = package_id;
843 status = package->lsa_api->Initialize(package_id, NULL /* FIXME: params */, NULL);
844 if (status == STATUS_SUCCESS)
846 pSpUserModeInitialize = (void *)GetProcAddress(package->mod, "SpUserModeInitialize");
847 if (pSpUserModeInitialize)
849 status = pSpUserModeInitialize(SECPKG_INTERFACE_VERSION, &package->user_api_version, &package->user_api, &package->user_table_count);
850 if (status == STATUS_SUCCESS)
851 package->user_api->InstanceInit(SECPKG_INTERFACE_VERSION, &lsa_dll_dispatch, NULL);
854 return TRUE;
859 FreeLibrary(package->mod);
860 return FALSE;
863 #define MAX_SERVICE_NAME 260
865 void load_auth_packages(void)
867 DWORD err, i;
868 HKEY root;
869 SecureProvider *provider;
871 err = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Control\\Lsa", 0, KEY_READ, &root);
872 if (err != ERROR_SUCCESS) return;
874 i = 0;
875 for (;;)
877 WCHAR name[MAX_SERVICE_NAME];
878 struct lsa_package package;
880 err = RegEnumKeyW(root, i++, name, MAX_SERVICE_NAME);
881 if (err == ERROR_NO_MORE_ITEMS)
882 break;
884 if (err != ERROR_SUCCESS)
885 continue;
887 if (!load_package(name, &package, i))
888 continue;
890 add_package(&package);
893 RegCloseKey(root);
895 if (!loaded_packages_count) return;
897 provider = SECUR32_addProvider(&lsa_sspi_tableA, &lsa_sspi_tableW, NULL);
898 if (!provider)
900 ERR("Failed to add SSP/AP provider\n");
901 return;
904 for (i = 0; i < loaded_packages_count; i++)
906 SecPkgInfoW *info;
908 info = malloc(loaded_packages[i].lsa_table_count * sizeof(*info));
909 if (info)
911 NTSTATUS status;
913 status = loaded_packages[i].lsa_api->GetInfo(info);
914 if (status == STATUS_SUCCESS)
915 SECUR32_addPackages(provider, loaded_packages[i].lsa_table_count, NULL, info);
917 free(info);
922 NTSTATUS WINAPI LsaLookupAuthenticationPackage(HANDLE lsa_handle,
923 PLSA_STRING package_name, PULONG package_id)
925 ULONG i;
927 TRACE("%p %s %p\n", lsa_handle, debugstr_as(package_name), package_id);
929 for (i = 0; i < loaded_packages_count; i++)
931 if (!RtlCompareString(loaded_packages[i].name, package_name, FALSE))
933 *package_id = loaded_packages[i].package_id;
934 return STATUS_SUCCESS;
938 return STATUS_UNSUCCESSFUL; /* FIXME */