kerberos: Add support for SECPKG_CRED_BOTH.
[wine.git] / dlls / secur32 / lsa.c
blob3f119df04d05022fee742876f0c0b1fb0196be5a
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 "ddk/ntddk.h"
36 #include "rpc.h"
38 #include "wine/debug.h"
39 #include "secur32_priv.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(secur32);
43 #define LSA_MAGIC_CONNECTION ('L' << 24 | 'S' << 16 | 'A' << 8 | '0')
44 #define LSA_MAGIC_CREDENTIALS ('L' << 24 | 'S' << 16 | 'A' << 8 | '1')
45 #define LSA_MAGIC_CONTEXT ('L' << 24 | 'S' << 16 | 'A' << 8 | '2')
47 static const WCHAR *default_authentication_package = L"Negotiate";
49 struct lsa_package
51 ULONG package_id;
52 HMODULE mod;
53 LSA_STRING *name;
54 ULONG lsa_api_version, lsa_table_count, user_api_version, user_table_count;
55 SECPKG_FUNCTION_TABLE *lsa_api;
56 SECPKG_USER_FUNCTION_TABLE *user_api;
59 static struct lsa_package *loaded_packages;
60 static ULONG loaded_packages_count;
62 struct lsa_handle
64 DWORD magic;
65 struct lsa_package *package;
66 LSA_SEC_HANDLE handle;
69 static const char *debugstr_as(const LSA_STRING *str)
71 if (!str) return "<null>";
72 return debugstr_an(str->Buffer, str->Length);
75 SECPKG_FUNCTION_TABLE *lsa_find_package(const char *name, SECPKG_USER_FUNCTION_TABLE **user_api)
77 LSA_STRING package_name;
78 ULONG i;
80 RtlInitString(&package_name, name);
82 for (i = 0; i < loaded_packages_count; i++)
84 if (!RtlCompareString(loaded_packages[i].name, &package_name, FALSE))
86 *user_api = loaded_packages[i].user_api;
87 return loaded_packages[i].lsa_api;
90 return NULL;
93 NTSTATUS WINAPI LsaCallAuthenticationPackage(HANDLE lsa_handle, ULONG package_id,
94 PVOID in_buffer, ULONG in_buffer_length,
95 PVOID *out_buffer, PULONG out_buffer_length, PNTSTATUS status)
97 ULONG i;
99 TRACE("%p,%lu,%p,%lu,%p,%p,%p\n", lsa_handle, package_id, in_buffer,
100 in_buffer_length, out_buffer, out_buffer_length, status);
102 if (out_buffer) *out_buffer = NULL;
103 if (out_buffer_length) *out_buffer_length = 0;
104 if (status) *status = STATUS_SUCCESS;
106 for (i = 0; i < loaded_packages_count; i++)
108 if (loaded_packages[i].package_id == package_id)
110 if (loaded_packages[i].lsa_api->CallPackageUntrusted)
111 return loaded_packages[i].lsa_api->CallPackageUntrusted(NULL /* FIXME*/,
112 in_buffer, NULL, in_buffer_length, out_buffer, out_buffer_length, status);
114 return SEC_E_UNSUPPORTED_FUNCTION;
118 return STATUS_NO_SUCH_PACKAGE;
121 static struct lsa_handle *alloc_lsa_handle(ULONG magic)
123 struct lsa_handle *ret;
124 if (!(ret = calloc(1, sizeof(*ret)))) return NULL;
125 ret->magic = magic;
126 return ret;
129 NTSTATUS WINAPI LsaConnectUntrusted(PHANDLE LsaHandle)
131 struct lsa_handle *lsa_conn;
133 TRACE("%p\n", LsaHandle);
135 if (!(lsa_conn = alloc_lsa_handle(LSA_MAGIC_CONNECTION))) return STATUS_NO_MEMORY;
136 *LsaHandle = lsa_conn;
137 return STATUS_SUCCESS;
140 NTSTATUS WINAPI LsaRegisterLogonProcess(PLSA_STRING LogonProcessName,
141 PHANDLE LsaHandle, PLSA_OPERATIONAL_MODE SecurityMode)
143 struct lsa_handle *lsa_conn;
145 FIXME("%s %p %p stub\n", debugstr_as(LogonProcessName), LsaHandle, SecurityMode);
147 if (!(lsa_conn = alloc_lsa_handle(LSA_MAGIC_CONNECTION))) return STATUS_NO_MEMORY;
148 *LsaHandle = lsa_conn;
149 return STATUS_SUCCESS;
152 NTSTATUS WINAPI LsaDeregisterLogonProcess(HANDLE LsaHandle)
154 struct lsa_handle *lsa_conn = (struct lsa_handle *)LsaHandle;
156 TRACE("%p\n", LsaHandle);
158 if (!lsa_conn || lsa_conn->magic != LSA_MAGIC_CONNECTION) return STATUS_INVALID_HANDLE;
159 /* Ensure compiler doesn't optimize out the assignment with 0. */
160 SecureZeroMemory(&lsa_conn->magic, sizeof(lsa_conn->magic));
161 free(lsa_conn);
163 return STATUS_SUCCESS;
166 NTSTATUS WINAPI LsaEnumerateLogonSessions(PULONG LogonSessionCount,
167 PLUID* LogonSessionList)
169 FIXME("%p %p stub\n", LogonSessionCount, LogonSessionList);
170 *LogonSessionCount = 0;
171 *LogonSessionList = NULL;
173 return STATUS_SUCCESS;
176 NTSTATUS WINAPI LsaFreeReturnBuffer(PVOID buffer)
178 TRACE("%p\n", buffer);
179 free(buffer);
180 return STATUS_SUCCESS;
183 NTSTATUS WINAPI LsaGetLogonSessionData(PLUID LogonId,
184 PSECURITY_LOGON_SESSION_DATA* ppLogonSessionData)
186 SECURITY_LOGON_SESSION_DATA *data;
187 int authpkg_len;
188 WCHAR *end;
190 FIXME("%p %p semi-stub\n", LogonId, ppLogonSessionData);
192 authpkg_len = wcslen(default_authentication_package) * sizeof(WCHAR);
194 data = calloc(1, sizeof(*data) + authpkg_len + sizeof(WCHAR));
195 if (!data) return STATUS_NO_MEMORY;
197 data->Size = sizeof(*data);
198 data->LogonId = *LogonId;
200 end = (WCHAR *)(data + 1);
201 wcscpy(end, default_authentication_package);
203 data->AuthenticationPackage.Length = authpkg_len;
204 data->AuthenticationPackage.MaximumLength = authpkg_len + sizeof(WCHAR);
205 data->AuthenticationPackage.Buffer = end;
207 *ppLogonSessionData = data;
209 return STATUS_SUCCESS;
212 NTSTATUS WINAPI LsaLogonUser(HANDLE LsaHandle, PLSA_STRING OriginName,
213 SECURITY_LOGON_TYPE LogonType, ULONG AuthenticationPackage,
214 PVOID AuthenticationInformation, ULONG AuthenticationInformationLength,
215 PTOKEN_GROUPS LocalGroups, PTOKEN_SOURCE SourceContext,
216 PVOID* ProfileBuffer, PULONG ProfileBufferLength, PLUID LogonId,
217 PHANDLE Token, PQUOTA_LIMITS Quotas, PNTSTATUS SubStatus)
219 FIXME("%p %s %d %ld %p %ld %p %p %p %p %p %p %p %p stub\n", LsaHandle,
220 debugstr_as(OriginName), LogonType, AuthenticationPackage,
221 AuthenticationInformation, AuthenticationInformationLength,
222 LocalGroups, SourceContext, ProfileBuffer, ProfileBufferLength,
223 LogonId, Token, Quotas, SubStatus);
224 return STATUS_SUCCESS;
227 static NTSTATUS NTAPI lsa_CreateLogonSession(LUID *logon_id)
229 FIXME("%p: stub\n", logon_id);
230 return STATUS_NOT_IMPLEMENTED;
233 static NTSTATUS NTAPI lsa_DeleteLogonSession(LUID *logon_id)
235 FIXME("%p: stub\n", logon_id);
236 return STATUS_NOT_IMPLEMENTED;
239 static NTSTATUS NTAPI lsa_AddCredential(LUID *logon_id, ULONG package_id,
240 LSA_STRING *primary_key, LSA_STRING *credentials)
242 FIXME("%p,%lu,%s,%s: stub\n", logon_id, package_id,
243 debugstr_as(primary_key), debugstr_as(credentials));
244 return STATUS_NOT_IMPLEMENTED;
247 static NTSTATUS NTAPI lsa_GetCredentials(LUID *logon_id, ULONG package_id, ULONG *context,
248 BOOLEAN retrieve_all, LSA_STRING *primary_key, ULONG *primary_key_len, LSA_STRING *credentials)
250 FIXME("%p,%#lx,%p,%d,%p,%p,%p: stub\n", logon_id, package_id, context,
251 retrieve_all, primary_key, primary_key_len, credentials);
252 return STATUS_NOT_IMPLEMENTED;
255 static NTSTATUS NTAPI lsa_DeleteCredential(LUID *logon_id, ULONG package_id, LSA_STRING *primary_key)
257 FIXME("%p,%#lx,%s: stub\n", logon_id, package_id, debugstr_as(primary_key));
258 return STATUS_NOT_IMPLEMENTED;
261 static void * NTAPI lsa_AllocateLsaHeap(ULONG size)
263 TRACE("%lu\n", size);
264 return malloc(size);
267 static void NTAPI lsa_FreeLsaHeap(void *p)
269 TRACE("%p\n", p);
270 free(p);
273 static NTSTATUS NTAPI lsa_AllocateClientBuffer(PLSA_CLIENT_REQUEST req, ULONG size, void **p)
275 TRACE("%p,%lu,%p\n", req, size, p);
276 *p = malloc(size);
277 return *p ? STATUS_SUCCESS : STATUS_NO_MEMORY;
280 static NTSTATUS NTAPI lsa_FreeClientBuffer(PLSA_CLIENT_REQUEST req, void *p)
282 TRACE("%p,%p\n", req, p);
283 free(p);
284 return STATUS_SUCCESS;
287 static NTSTATUS NTAPI lsa_CopyToClientBuffer(PLSA_CLIENT_REQUEST req, ULONG size, void *client, void *buf)
289 TRACE("%p,%lu,%p,%p\n", req, size, client, buf);
290 memcpy(client, buf, size);
291 return STATUS_SUCCESS;
294 static NTSTATUS NTAPI lsa_CopyFromClientBuffer(PLSA_CLIENT_REQUEST req, ULONG size, void *buf, void *client)
296 TRACE("%p,%lu,%p,%p\n", req, size, buf, client);
297 memcpy(buf, client, size);
298 return STATUS_SUCCESS;
301 static LSA_DISPATCH_TABLE lsa_dispatch =
303 lsa_CreateLogonSession,
304 lsa_DeleteLogonSession,
305 lsa_AddCredential,
306 lsa_GetCredentials,
307 lsa_DeleteCredential,
308 lsa_AllocateLsaHeap,
309 lsa_FreeLsaHeap,
310 lsa_AllocateClientBuffer,
311 lsa_FreeClientBuffer,
312 lsa_CopyToClientBuffer,
313 lsa_CopyFromClientBuffer
316 static NTSTATUS NTAPI lsa_RegisterCallback(ULONG callback_id, PLSA_CALLBACK_FUNCTION callback)
318 FIXME("%lu,%p: stub\n", callback_id, callback);
319 return STATUS_NOT_IMPLEMENTED;
322 static SECPKG_DLL_FUNCTIONS lsa_dll_dispatch =
324 lsa_AllocateLsaHeap,
325 lsa_FreeLsaHeap,
326 lsa_RegisterCallback
329 static SECURITY_STATUS lsa_lookup_package(SEC_WCHAR *nameW, struct lsa_package **lsa_package)
331 ULONG i;
332 UNICODE_STRING package_name, name;
334 for (i = 0; i < loaded_packages_count; i++)
336 if (RtlAnsiStringToUnicodeString(&package_name, loaded_packages[i].name, TRUE))
337 return SEC_E_INSUFFICIENT_MEMORY;
339 RtlInitUnicodeString(&name, nameW);
341 if (RtlEqualUnicodeString(&package_name, &name, TRUE))
343 RtlFreeUnicodeString(&package_name);
344 *lsa_package = &loaded_packages[i];
345 return SEC_E_OK;
348 RtlFreeUnicodeString(&package_name);
351 return SEC_E_SECPKG_NOT_FOUND;
354 static SECURITY_STATUS WINAPI lsa_AcquireCredentialsHandleW(
355 SEC_WCHAR *principal, SEC_WCHAR *package, ULONG credentials_use,
356 LUID *logon_id, void *auth_data, SEC_GET_KEY_FN get_key_fn,
357 void *get_key_arg, CredHandle *credential, TimeStamp *ts_expiry)
359 SECURITY_STATUS status;
360 struct lsa_package *lsa_package;
361 struct lsa_handle *lsa_handle;
362 UNICODE_STRING principal_us;
363 LSA_SEC_HANDLE lsa_credential;
365 TRACE("%s %s %#lx %p %p %p %p %p\n", debugstr_w(principal), debugstr_w(package),
366 credentials_use, auth_data, get_key_fn, get_key_arg, credential, ts_expiry);
368 if (!credential) return SEC_E_INVALID_HANDLE;
369 if (!package) return SEC_E_SECPKG_NOT_FOUND;
371 status = lsa_lookup_package(package, &lsa_package);
372 if (status != SEC_E_OK) return status;
374 if (!lsa_package->lsa_api || !lsa_package->lsa_api->SpAcquireCredentialsHandle)
375 return SEC_E_UNSUPPORTED_FUNCTION;
377 if (principal)
378 RtlInitUnicodeString(&principal_us, principal);
380 status = lsa_package->lsa_api->SpAcquireCredentialsHandle(principal ? &principal_us : NULL,
381 credentials_use, logon_id, auth_data, get_key_fn, get_key_arg, &lsa_credential, ts_expiry);
382 if (status == SEC_E_OK)
384 if (!(lsa_handle = alloc_lsa_handle(LSA_MAGIC_CREDENTIALS))) return STATUS_NO_MEMORY;
385 lsa_handle->package = lsa_package;
386 lsa_handle->handle = lsa_credential;
387 credential->dwLower = (ULONG_PTR)lsa_handle;
388 credential->dwUpper = 0;
390 return status;
393 static SECURITY_STATUS WINAPI lsa_AcquireCredentialsHandleA(
394 SEC_CHAR *principal, SEC_CHAR *package, ULONG credentials_use,
395 LUID *logon_id, void *auth_data, SEC_GET_KEY_FN get_key_fn,
396 void *get_key_arg, CredHandle *credential, TimeStamp *ts_expiry)
398 SECURITY_STATUS status = SEC_E_INSUFFICIENT_MEMORY;
399 SEC_WCHAR *principalW = NULL, *packageW = NULL;
400 SEC_WINNT_AUTH_IDENTITY_A *id = auth_data;
401 SEC_WINNT_AUTH_IDENTITY_W idW = {};
403 TRACE("%s %s %#lx %p %p %p %p %p\n", debugstr_a(principal), debugstr_a(package),
404 credentials_use, auth_data, get_key_fn, get_key_arg, credential, ts_expiry);
406 if (principal)
408 int len = MultiByteToWideChar( CP_ACP, 0, principal, -1, NULL, 0 );
409 if (!(principalW = malloc( len * sizeof(SEC_WCHAR) ))) goto done;
410 MultiByteToWideChar( CP_ACP, 0, principal, -1, principalW, len );
412 if (package)
414 int len = MultiByteToWideChar( CP_ACP, 0, package, -1, NULL, 0 );
415 if (!(packageW = malloc( len * sizeof(SEC_WCHAR) ))) goto done;
416 MultiByteToWideChar( CP_ACP, 0, package, -1, packageW, len );
418 if (id && (id->Flags == SEC_WINNT_AUTH_IDENTITY_ANSI))
420 if (id->UserLength)
422 idW.UserLength = MultiByteToWideChar( CP_ACP, 0, (char *)id->User, id->UserLength, NULL, 0 );
423 if (!(idW.User = malloc( idW.UserLength * sizeof(SEC_WCHAR) ))) goto done;
424 MultiByteToWideChar( CP_ACP, 0, (char *)id->User, id->UserLength, idW.User, idW.UserLength );
426 if (id->DomainLength)
428 idW.DomainLength = MultiByteToWideChar( CP_ACP, 0, (char *)id->Domain, id->DomainLength, NULL, 0 );
429 if (!(idW.Domain = malloc( idW.DomainLength * sizeof(SEC_WCHAR) ))) goto done;
430 MultiByteToWideChar( CP_ACP, 0, (char *)id->Domain, id->DomainLength, idW.Domain, idW.DomainLength );
432 if (id->PasswordLength)
434 idW.PasswordLength = MultiByteToWideChar( CP_ACP, 0, (char *)id->Password, id->PasswordLength, NULL, 0 );
435 if (!(idW.Password = malloc( idW.PasswordLength * sizeof(SEC_WCHAR) ))) goto done;
436 MultiByteToWideChar( CP_ACP, 0, (char *)id->Password, id->PasswordLength, idW.Password, idW.PasswordLength );
438 idW.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
439 auth_data = &idW;
442 status = lsa_AcquireCredentialsHandleW( principalW, packageW, credentials_use, logon_id, auth_data, get_key_fn,
443 get_key_arg, credential, ts_expiry );
444 done:
445 free( packageW );
446 free( principalW );
447 free( idW.User );
448 free( idW.Domain );
449 free( idW.Password );
450 return status;
453 static SECURITY_STATUS WINAPI lsa_FreeCredentialsHandle(CredHandle *credential)
455 struct lsa_handle *lsa_cred;
456 SECURITY_STATUS status;
458 TRACE("%p\n", credential);
459 if (!credential) return SEC_E_INVALID_HANDLE;
461 lsa_cred = (struct lsa_handle *)credential->dwLower;
462 if (!lsa_cred || lsa_cred->magic != LSA_MAGIC_CREDENTIALS) return SEC_E_INVALID_HANDLE;
464 if (!lsa_cred->package->lsa_api || !lsa_cred->package->lsa_api->FreeCredentialsHandle)
465 return SEC_E_UNSUPPORTED_FUNCTION;
467 status = lsa_cred->package->lsa_api->FreeCredentialsHandle(lsa_cred->handle);
469 /* Ensure compiler doesn't optimize out the assignment with 0. */
470 SecureZeroMemory(&lsa_cred->magic, sizeof(lsa_cred->magic));
471 free(lsa_cred);
472 return status;
475 static SECURITY_STATUS WINAPI lsa_InitializeSecurityContextW(
476 CredHandle *credential, CtxtHandle *context, SEC_WCHAR *target_name, ULONG context_req,
477 ULONG reserved1, ULONG target_data_rep, SecBufferDesc *input, ULONG reserved2,
478 CtxtHandle *new_context, SecBufferDesc *output, ULONG *context_attr, TimeStamp *ts_expiry)
480 SECURITY_STATUS status;
481 struct lsa_handle *lsa_cred = NULL, *lsa_ctx = NULL, *new_lsa_ctx;
482 struct lsa_package *package = NULL;
483 UNICODE_STRING target_name_us;
484 BOOLEAN mapped_context;
485 LSA_SEC_HANDLE new_handle;
487 TRACE("%p %p %s %#lx %ld %ld %p %ld %p %p %p %p\n", credential, context,
488 debugstr_w(target_name), context_req, reserved1, target_data_rep, input,
489 reserved2, new_context, output, context_attr, ts_expiry);
491 if (context)
493 lsa_ctx = (struct lsa_handle *)context->dwLower;
494 if (lsa_ctx->magic != LSA_MAGIC_CONTEXT) return SEC_E_INVALID_HANDLE;
495 package = lsa_ctx->package;
497 else if (credential)
499 lsa_cred = (struct lsa_handle *)credential->dwLower;
500 if (lsa_cred->magic != LSA_MAGIC_CREDENTIALS) return SEC_E_INVALID_HANDLE;
501 package = lsa_cred->package;
503 if (!package || !new_context) return SEC_E_INVALID_HANDLE;
505 if (!package->lsa_api || !package->lsa_api->InitLsaModeContext)
506 return SEC_E_UNSUPPORTED_FUNCTION;
508 if (target_name)
509 RtlInitUnicodeString(&target_name_us, target_name);
511 status = package->lsa_api->InitLsaModeContext(lsa_cred ? lsa_cred->handle : 0,
512 lsa_ctx ? lsa_ctx->handle : 0, target_name ? &target_name_us : NULL, context_req, target_data_rep,
513 input, &new_handle, output, context_attr, ts_expiry, &mapped_context, NULL /* FIXME */);
514 if (status == SEC_E_OK || status == SEC_I_CONTINUE_NEEDED)
516 if (!(new_lsa_ctx = alloc_lsa_handle(LSA_MAGIC_CONTEXT))) return STATUS_NO_MEMORY;
517 new_lsa_ctx->package = package;
518 new_lsa_ctx->handle = new_handle;
519 new_context->dwLower = (ULONG_PTR)new_lsa_ctx;
520 new_context->dwUpper = 0;
522 return status;
525 static SECURITY_STATUS WINAPI lsa_InitializeSecurityContextA(
526 CredHandle *credential, CtxtHandle *context, SEC_CHAR *target_name, ULONG context_req,
527 ULONG reserved1, ULONG target_data_rep, SecBufferDesc *input, ULONG reserved2,
528 CtxtHandle *new_context, SecBufferDesc *output, ULONG *context_attr, TimeStamp *ts_expiry)
530 SECURITY_STATUS status;
531 SEC_WCHAR *targetW = NULL;
533 TRACE("%p %p %s %#lx %ld %ld %p %ld %p %p %p %p\n", credential, context,
534 debugstr_a(target_name), context_req, reserved1, target_data_rep, input,
535 reserved2, new_context, output, context_attr, ts_expiry);
537 if (target_name)
539 int len = MultiByteToWideChar( CP_ACP, 0, target_name, -1, NULL, 0 );
540 if (!(targetW = malloc( len * sizeof(SEC_WCHAR) ))) return SEC_E_INSUFFICIENT_MEMORY;
541 MultiByteToWideChar( CP_ACP, 0, target_name, -1, targetW, len );
544 status = lsa_InitializeSecurityContextW( credential, context, targetW, context_req, reserved1, target_data_rep,
545 input, reserved2, new_context, output, context_attr, ts_expiry );
546 free( targetW );
547 return status;
550 static SECURITY_STATUS WINAPI lsa_AcceptSecurityContext(
551 CredHandle *credential, CtxtHandle *context, SecBufferDesc *input,
552 ULONG context_req, ULONG target_data_rep, CtxtHandle *new_context,
553 SecBufferDesc *output, ULONG *context_attr, TimeStamp *ts_expiry)
555 SECURITY_STATUS status;
556 struct lsa_package *package = NULL;
557 struct lsa_handle *lsa_cred = NULL, *lsa_ctx = NULL, *new_lsa_ctx;
558 BOOLEAN mapped_context;
559 LSA_SEC_HANDLE new_handle;
561 TRACE("%p %p %p %#lx %#lx %p %p %p %p\n", credential, context, input,
562 context_req, target_data_rep, new_context, output, context_attr, ts_expiry);
564 if (context)
566 lsa_ctx = (struct lsa_handle *)context->dwLower;
567 if (lsa_ctx->magic != LSA_MAGIC_CONTEXT) return SEC_E_INVALID_HANDLE;
568 package = lsa_ctx->package;
570 else if (credential)
572 lsa_cred = (struct lsa_handle *)credential->dwLower;
573 if (lsa_cred->magic != LSA_MAGIC_CREDENTIALS) return SEC_E_INVALID_HANDLE;
574 package = lsa_cred->package;
576 if (!package || !new_context) return SEC_E_INVALID_HANDLE;
578 if (!package->lsa_api || !package->lsa_api->AcceptLsaModeContext)
579 return SEC_E_UNSUPPORTED_FUNCTION;
581 status = package->lsa_api->AcceptLsaModeContext(lsa_cred ? lsa_cred->handle : 0,
582 lsa_ctx ? lsa_ctx->handle : 0, input, context_req, target_data_rep, &new_handle, output,
583 context_attr, ts_expiry, &mapped_context, NULL /* FIXME */);
584 if (status == SEC_E_OK || status == SEC_I_CONTINUE_NEEDED)
586 if (!(new_lsa_ctx = alloc_lsa_handle(LSA_MAGIC_CONTEXT))) return STATUS_NO_MEMORY;
587 new_lsa_ctx->package = package;
588 new_lsa_ctx->handle = new_handle;
589 new_context->dwLower = (ULONG_PTR)new_lsa_ctx;
590 new_context->dwUpper = 0;
592 return status;
595 static SECURITY_STATUS WINAPI lsa_DeleteSecurityContext(CtxtHandle *context)
597 struct lsa_handle *lsa_ctx;
598 SECURITY_STATUS status;
600 TRACE("%p\n", context);
602 if (!context) return SEC_E_INVALID_HANDLE;
603 lsa_ctx = (struct lsa_handle *)context->dwLower;
604 if (!lsa_ctx || lsa_ctx->magic != LSA_MAGIC_CONTEXT) return SEC_E_INVALID_HANDLE;
606 if (!lsa_ctx->package->lsa_api || !lsa_ctx->package->lsa_api->DeleteContext)
607 return SEC_E_UNSUPPORTED_FUNCTION;
609 status = lsa_ctx->package->lsa_api->DeleteContext(lsa_ctx->handle);
610 free(lsa_ctx);
611 return status;
614 static SECURITY_STATUS WINAPI lsa_QueryContextAttributesW(CtxtHandle *context, ULONG attribute, void *buffer)
616 struct lsa_handle *lsa_ctx;
618 TRACE("%p %ld %p\n", context, attribute, buffer);
620 if (!context) return SEC_E_INVALID_HANDLE;
621 lsa_ctx = (struct lsa_handle *)context->dwLower;
622 if (!lsa_ctx || lsa_ctx->magic != LSA_MAGIC_CONTEXT) return SEC_E_INVALID_HANDLE;
624 if (!lsa_ctx->package->lsa_api || !lsa_ctx->package->lsa_api->SpQueryContextAttributes)
625 return SEC_E_UNSUPPORTED_FUNCTION;
627 return lsa_ctx->package->lsa_api->SpQueryContextAttributes(lsa_ctx->handle, attribute, buffer);
630 static SecPkgInfoA *package_infoWtoA( const SecPkgInfoW *info )
632 SecPkgInfoA *ret;
633 int size_name = WideCharToMultiByte( CP_ACP, 0, info->Name, -1, NULL, 0, NULL, NULL );
634 int size_comment = WideCharToMultiByte( CP_ACP, 0, info->Comment, -1, NULL, 0, NULL, NULL );
636 /* freed with FreeContextBuffer */
637 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*ret) + size_name + size_comment ))) return NULL;
638 ret->fCapabilities = info->fCapabilities;
639 ret->wVersion = info->wVersion;
640 ret->wRPCID = info->wRPCID;
641 ret->cbMaxToken = info->cbMaxToken;
642 ret->Name = (SEC_CHAR *)(ret + 1);
643 WideCharToMultiByte( CP_ACP, 0, info->Name, -1, ret->Name, size_name, NULL, NULL );
644 ret->Comment = ret->Name + size_name;
645 WideCharToMultiByte( CP_ACP, 0, info->Comment, -1, ret->Comment, size_comment, NULL, NULL );
646 return ret;
649 static SECURITY_STATUS nego_info_WtoA( const SecPkgContext_NegotiationInfoW *infoW,
650 SecPkgContext_NegotiationInfoA *infoA )
652 infoA->NegotiationState = infoW->NegotiationState;
653 if (!(infoA->PackageInfo = package_infoWtoA( infoW->PackageInfo ))) return SEC_E_INSUFFICIENT_MEMORY;
654 return SEC_E_OK;
657 static SECURITY_STATUS key_info_WtoA( const SecPkgContext_KeyInfoW *infoW, SecPkgContext_KeyInfoA *infoA )
659 int size;
661 size = WideCharToMultiByte( CP_ACP, 0, infoW->sSignatureAlgorithmName, -1, NULL, 0, NULL, NULL );
662 if (!(infoA->sSignatureAlgorithmName = RtlAllocateHeap( GetProcessHeap(), 0, size )))
663 return SEC_E_INSUFFICIENT_MEMORY;
664 WideCharToMultiByte( CP_ACP, 0, infoW->sSignatureAlgorithmName, -1, infoA->sSignatureAlgorithmName,
665 size, NULL, NULL );
667 size = WideCharToMultiByte( CP_ACP, 0, infoW->sEncryptAlgorithmName, -1, NULL, 0, NULL, NULL );
668 if (!(infoA->sEncryptAlgorithmName = RtlAllocateHeap( GetProcessHeap(), 0, size )))
670 RtlFreeHeap( GetProcessHeap(), 0, infoA->sSignatureAlgorithmName );
671 return SEC_E_INSUFFICIENT_MEMORY;
673 WideCharToMultiByte( CP_ACP, 0, infoW->sEncryptAlgorithmName, -1, infoA->sEncryptAlgorithmName,
674 size, NULL, NULL );
676 infoA->KeySize = infoW->KeySize;
677 infoA->SignatureAlgorithm = infoW->SignatureAlgorithm;
678 infoA->EncryptAlgorithm = infoW->EncryptAlgorithm;
679 return SEC_E_OK;
682 static SECURITY_STATUS WINAPI lsa_QueryContextAttributesA(CtxtHandle *context, ULONG attribute, void *buffer)
684 TRACE("%p %ld %p\n", context, attribute, buffer);
686 if (!context) return SEC_E_INVALID_HANDLE;
688 switch (attribute)
690 case SECPKG_ATTR_SIZES:
691 case SECPKG_ATTR_SESSION_KEY:
692 return lsa_QueryContextAttributesW( context, attribute, buffer );
694 case SECPKG_ATTR_NEGOTIATION_INFO:
696 SecPkgContext_NegotiationInfoW infoW;
697 SecPkgContext_NegotiationInfoA *infoA = (SecPkgContext_NegotiationInfoA *)buffer;
698 SECURITY_STATUS status = lsa_QueryContextAttributesW( context, SECPKG_ATTR_NEGOTIATION_INFO, &infoW );
700 if (status != SEC_E_OK) return status;
701 status = nego_info_WtoA( &infoW, infoA );
702 FreeContextBuffer( infoW.PackageInfo );
703 return status;
705 case SECPKG_ATTR_KEY_INFO:
707 SecPkgContext_KeyInfoW infoW;
708 SecPkgContext_KeyInfoA *infoA = (SecPkgContext_KeyInfoA *)buffer;
710 SECURITY_STATUS status = lsa_QueryContextAttributesW( context, SECPKG_ATTR_KEY_INFO, &infoW );
712 if (status != SEC_E_OK) return status;
713 status = key_info_WtoA( &infoW, infoA );
714 FreeContextBuffer( infoW.sSignatureAlgorithmName );
715 FreeContextBuffer( infoW.sEncryptAlgorithmName );
716 return status;
719 #define X(x) case (x) : FIXME(#x" stub\n"); break
720 X(SECPKG_ATTR_ACCESS_TOKEN);
721 X(SECPKG_ATTR_AUTHORITY);
722 X(SECPKG_ATTR_DCE_INFO);
723 X(SECPKG_ATTR_LIFESPAN);
724 X(SECPKG_ATTR_NAMES);
725 X(SECPKG_ATTR_NATIVE_NAMES);
726 X(SECPKG_ATTR_PACKAGE_INFO);
727 X(SECPKG_ATTR_PASSWORD_EXPIRY);
728 X(SECPKG_ATTR_STREAM_SIZES);
729 X(SECPKG_ATTR_TARGET_INFORMATION);
730 #undef X
731 default:
732 FIXME( "unknown attribute %lu\n", attribute );
733 break;
736 return SEC_E_UNSUPPORTED_FUNCTION;
739 static SECURITY_STATUS WINAPI lsa_MakeSignature(CtxtHandle *context, ULONG quality_of_protection,
740 SecBufferDesc *message, ULONG message_seq_no)
742 struct lsa_handle *lsa_ctx;
744 TRACE("%p %#lx %p %lu)\n", context, quality_of_protection, message, message_seq_no);
746 if (!context) return SEC_E_INVALID_HANDLE;
747 lsa_ctx = (struct lsa_handle *)context->dwLower;
748 if (!lsa_ctx || lsa_ctx->magic != LSA_MAGIC_CONTEXT) return SEC_E_INVALID_HANDLE;
750 if (!lsa_ctx->package->user_api || !lsa_ctx->package->user_api->MakeSignature)
751 return SEC_E_UNSUPPORTED_FUNCTION;
753 return lsa_ctx->package->user_api->MakeSignature(lsa_ctx->handle, quality_of_protection, message, message_seq_no);
756 static SECURITY_STATUS WINAPI lsa_VerifySignature(CtxtHandle *context, SecBufferDesc *message,
757 ULONG message_seq_no, ULONG *quality_of_protection)
759 struct lsa_handle *lsa_ctx;
761 TRACE("%p %p %lu %p)\n", context, message, message_seq_no, quality_of_protection);
763 if (!context) return SEC_E_INVALID_HANDLE;
764 lsa_ctx = (struct lsa_handle *)context->dwLower;
765 if (!lsa_ctx || lsa_ctx->magic != LSA_MAGIC_CONTEXT) return SEC_E_INVALID_HANDLE;
767 if (!lsa_ctx->package->user_api || !lsa_ctx->package->user_api->VerifySignature)
768 return SEC_E_UNSUPPORTED_FUNCTION;
770 return lsa_ctx->package->user_api->VerifySignature(lsa_ctx->handle, message, message_seq_no, quality_of_protection);
773 static SECURITY_STATUS WINAPI lsa_EncryptMessage(CtxtHandle *context, ULONG quality_of_protection,
774 SecBufferDesc *message, ULONG message_seq_no)
776 struct lsa_handle *lsa_ctx;
778 TRACE("%p %#lx %p %lu)\n", context, quality_of_protection, message, message_seq_no);
780 if (!context) return SEC_E_INVALID_HANDLE;
781 lsa_ctx = (struct lsa_handle *)context->dwLower;
782 if (!lsa_ctx || lsa_ctx->magic != LSA_MAGIC_CONTEXT) return SEC_E_INVALID_HANDLE;
784 if (!lsa_ctx->package->user_api || !lsa_ctx->package->user_api->SealMessage)
785 return SEC_E_UNSUPPORTED_FUNCTION;
787 return lsa_ctx->package->user_api->SealMessage(lsa_ctx->handle, quality_of_protection, message, message_seq_no);
790 static SECURITY_STATUS WINAPI lsa_DecryptMessage(CtxtHandle *context, SecBufferDesc *message,
791 ULONG message_seq_no, ULONG *quality_of_protection)
793 struct lsa_handle *lsa_ctx;
795 TRACE("%p %p %lu %p)\n", context, message, message_seq_no, quality_of_protection);
797 if (!context) return SEC_E_INVALID_HANDLE;
798 lsa_ctx = (struct lsa_handle *)context->dwLower;
799 if (!lsa_ctx || lsa_ctx->magic != LSA_MAGIC_CONTEXT) return SEC_E_INVALID_HANDLE;
801 if (!lsa_ctx->package->user_api || !lsa_ctx->package->user_api->UnsealMessage)
802 return SEC_E_UNSUPPORTED_FUNCTION;
804 return lsa_ctx->package->user_api->UnsealMessage(lsa_ctx->handle, message, message_seq_no, quality_of_protection);
807 static const SecurityFunctionTableW lsa_sspi_tableW =
810 NULL, /* EnumerateSecurityPackagesW */
811 NULL, /* QueryCredentialsAttributesW */
812 lsa_AcquireCredentialsHandleW,
813 lsa_FreeCredentialsHandle,
814 NULL, /* Reserved2 */
815 lsa_InitializeSecurityContextW,
816 lsa_AcceptSecurityContext,
817 NULL, /* CompleteAuthToken */
818 lsa_DeleteSecurityContext,
819 NULL, /* ApplyControlToken */
820 lsa_QueryContextAttributesW,
821 NULL, /* ImpersonateSecurityContext */
822 NULL, /* RevertSecurityContext */
823 lsa_MakeSignature,
824 lsa_VerifySignature,
825 NULL, /* FreeContextBuffer */
826 NULL, /* QuerySecurityPackageInfoW */
827 NULL, /* Reserved3 */
828 NULL, /* Reserved4 */
829 NULL, /* ExportSecurityContext */
830 NULL, /* ImportSecurityContextW */
831 NULL, /* AddCredentialsW */
832 NULL, /* Reserved8 */
833 NULL, /* QuerySecurityContextToken */
834 lsa_EncryptMessage,
835 lsa_DecryptMessage,
836 NULL, /* SetContextAttributesW */
839 static const SecurityFunctionTableA lsa_sspi_tableA =
842 NULL, /* EnumerateSecurityPackagesA */
843 NULL, /* QueryCredentialsAttributesA */
844 lsa_AcquireCredentialsHandleA,
845 lsa_FreeCredentialsHandle,
846 NULL, /* Reserved2 */
847 lsa_InitializeSecurityContextA,
848 lsa_AcceptSecurityContext,
849 NULL, /* CompleteAuthToken */
850 lsa_DeleteSecurityContext,
851 NULL, /* ApplyControlToken */
852 lsa_QueryContextAttributesA,
853 NULL, /* ImpersonateSecurityContext */
854 NULL, /* RevertSecurityContext */
855 lsa_MakeSignature,
856 lsa_VerifySignature,
857 NULL, /* FreeContextBuffer */
858 NULL, /* QuerySecurityPackageInfoA */
859 NULL, /* Reserved3 */
860 NULL, /* Reserved4 */
861 NULL, /* ExportSecurityContext */
862 NULL, /* ImportSecurityContextA */
863 NULL, /* AddCredentialsA */
864 NULL, /* Reserved8 */
865 NULL, /* QuerySecurityContextToken */
866 lsa_EncryptMessage,
867 lsa_DecryptMessage,
868 NULL, /* SetContextAttributesA */
871 static void add_package(struct lsa_package *package)
873 struct lsa_package *new_loaded_packages;
875 if (!loaded_packages)
876 new_loaded_packages = malloc(sizeof(*new_loaded_packages));
877 else
878 new_loaded_packages = realloc(loaded_packages, sizeof(*new_loaded_packages) * (loaded_packages_count + 1));
880 if (new_loaded_packages)
882 loaded_packages = new_loaded_packages;
883 loaded_packages[loaded_packages_count] = *package;
884 loaded_packages_count++;
888 static BOOL initialize_package(struct lsa_package *package,
889 NTSTATUS (NTAPI *pSpLsaModeInitialize)(ULONG, PULONG, PSECPKG_FUNCTION_TABLE *, PULONG),
890 NTSTATUS (NTAPI *pSpUserModeInitialize)(ULONG, PULONG, PSECPKG_USER_FUNCTION_TABLE *, PULONG))
892 NTSTATUS status;
894 if (!pSpLsaModeInitialize || !pSpUserModeInitialize)
895 return FALSE;
897 status = pSpLsaModeInitialize(SECPKG_INTERFACE_VERSION, &package->lsa_api_version, &package->lsa_api, &package->lsa_table_count);
898 if (status == STATUS_SUCCESS)
900 status = package->lsa_api->InitializePackage(package->package_id, &lsa_dispatch, NULL, NULL, &package->name);
901 if (status == STATUS_SUCCESS)
903 TRACE("name %s, version %#lx, api table %p, table count %lu\n",
904 debugstr_an(package->name->Buffer, package->name->Length),
905 package->lsa_api_version, package->lsa_api, package->lsa_table_count);
907 status = package->lsa_api->Initialize(package->package_id, NULL /* FIXME: params */, NULL);
908 if (status == STATUS_SUCCESS)
910 status = pSpUserModeInitialize(SECPKG_INTERFACE_VERSION, &package->user_api_version, &package->user_api, &package->user_table_count);
911 if (status == STATUS_SUCCESS)
913 package->user_api->InstanceInit(SECPKG_INTERFACE_VERSION, &lsa_dll_dispatch, NULL);
914 return TRUE;
920 return FALSE;
923 static BOOL load_package(const WCHAR *name, struct lsa_package *package, ULONG package_id)
925 NTSTATUS (NTAPI *pSpLsaModeInitialize)(ULONG, PULONG, PSECPKG_FUNCTION_TABLE *, PULONG);
926 NTSTATUS (NTAPI *pSpUserModeInitialize)(ULONG, PULONG, PSECPKG_USER_FUNCTION_TABLE *, PULONG);
928 memset(package, 0, sizeof(*package));
930 package->package_id = package_id;
931 package->mod = LoadLibraryW(name);
932 if (!package->mod) return FALSE;
934 pSpLsaModeInitialize = (void *)GetProcAddress(package->mod, "SpLsaModeInitialize");
935 pSpUserModeInitialize = (void *)GetProcAddress(package->mod, "SpUserModeInitialize");
937 if (initialize_package(package, pSpLsaModeInitialize, pSpUserModeInitialize))
938 return TRUE;
940 FreeLibrary(package->mod);
941 return FALSE;
944 #define MAX_SERVICE_NAME 260
946 void load_auth_packages(void)
948 DWORD err, i;
949 HKEY root;
950 SecureProvider *provider;
951 struct lsa_package package;
953 memset(&package, 0, sizeof(package));
955 /* "Negotiate" has package id 0, .Net depends on this. */
956 package.package_id = 0;
957 if (initialize_package(&package, nego_SpLsaModeInitialize, nego_SpUserModeInitialize))
958 add_package(&package);
960 err = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Control\\Lsa", 0, KEY_READ, &root);
961 if (err != ERROR_SUCCESS) return;
963 i = 0;
964 for (;;)
966 WCHAR name[MAX_SERVICE_NAME];
968 err = RegEnumKeyW(root, i, name, MAX_SERVICE_NAME);
969 if (err == ERROR_NO_MORE_ITEMS)
970 break;
972 if (err != ERROR_SUCCESS)
973 continue;
975 if (load_package(name, &package, i + 1))
976 add_package(&package);
978 i++;
981 RegCloseKey(root);
983 if (!loaded_packages_count) return;
985 provider = SECUR32_addProvider(&lsa_sspi_tableA, &lsa_sspi_tableW, NULL);
986 if (!provider)
988 ERR("Failed to add SSP/AP provider\n");
989 return;
992 for (i = 0; i < loaded_packages_count; i++)
994 SecPkgInfoW *info;
996 info = malloc(loaded_packages[i].lsa_table_count * sizeof(*info));
997 if (info)
999 NTSTATUS status;
1001 status = loaded_packages[i].lsa_api->GetInfo(info);
1002 if (status == STATUS_SUCCESS)
1003 SECUR32_addPackages(provider, loaded_packages[i].lsa_table_count, NULL, info);
1005 free(info);
1010 NTSTATUS WINAPI LsaLookupAuthenticationPackage(HANDLE lsa_handle,
1011 PLSA_STRING package_name, PULONG package_id)
1013 ULONG i;
1015 TRACE("%p %s %p\n", lsa_handle, debugstr_as(package_name), package_id);
1017 for (i = 0; i < loaded_packages_count; i++)
1019 if (!RtlCompareString(loaded_packages[i].name, package_name, FALSE))
1021 *package_id = loaded_packages[i].package_id;
1022 return STATUS_SUCCESS;
1026 return STATUS_UNSUCCESSFUL; /* FIXME */