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
27 #define WIN32_NO_STATUS
35 #include "ddk/ntddk.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";
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
;
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
;
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
;
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
)
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
;
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
));
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
);
180 return STATUS_SUCCESS
;
183 NTSTATUS WINAPI
LsaGetLogonSessionData(PLUID LogonId
,
184 PSECURITY_LOGON_SESSION_DATA
* ppLogonSessionData
)
186 SECURITY_LOGON_SESSION_DATA
*data
;
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
);
267 static void NTAPI
lsa_FreeLsaHeap(void *p
)
273 static NTSTATUS NTAPI
lsa_AllocateClientBuffer(PLSA_CLIENT_REQUEST req
, ULONG size
, void **p
)
275 TRACE("%p,%lu,%p\n", req
, size
, p
);
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
);
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
,
307 lsa_DeleteCredential
,
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
=
329 static SECURITY_STATUS
lsa_lookup_package(SEC_WCHAR
*nameW
, struct lsa_package
**lsa_package
)
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
];
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
;
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;
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
);
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
);
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
))
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
;
442 status
= lsa_AcquireCredentialsHandleW( principalW
, packageW
, credentials_use
, logon_id
, auth_data
, get_key_fn
,
443 get_key_arg
, credential
, ts_expiry
);
449 free( idW
.Password
);
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
));
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
);
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
;
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
;
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;
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
);
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
);
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
);
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
;
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;
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
);
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
)
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
);
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
;
657 static SECURITY_STATUS
key_info_WtoA( const SecPkgContext_KeyInfoW
*infoW
, SecPkgContext_KeyInfoA
*infoA
)
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
,
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
,
676 infoA
->KeySize
= infoW
->KeySize
;
677 infoA
->SignatureAlgorithm
= infoW
->SignatureAlgorithm
;
678 infoA
->EncryptAlgorithm
= infoW
->EncryptAlgorithm
;
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
;
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
);
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
);
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
);
732 FIXME( "unknown attribute %lu\n", attribute
);
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 */
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 */
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 */
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 */
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
));
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
))
894 if (!pSpLsaModeInitialize
|| !pSpUserModeInitialize
)
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
);
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
))
940 FreeLibrary(package
->mod
);
944 #define MAX_SERVICE_NAME 260
946 void load_auth_packages(void)
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;
966 WCHAR name
[MAX_SERVICE_NAME
];
968 err
= RegEnumKeyW(root
, i
, name
, MAX_SERVICE_NAME
);
969 if (err
== ERROR_NO_MORE_ITEMS
)
972 if (err
!= ERROR_SUCCESS
)
975 if (load_package(name
, &package
, i
+ 1))
976 add_package(&package
);
983 if (!loaded_packages_count
) return;
985 provider
= SECUR32_addProvider(&lsa_sspi_tableA
, &lsa_sspi_tableW
, NULL
);
988 ERR("Failed to add SSP/AP provider\n");
992 for (i
= 0; i
< loaded_packages_count
; i
++)
996 info
= malloc(loaded_packages
[i
].lsa_table_count
* sizeof(*info
));
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
);
1010 NTSTATUS WINAPI
LsaLookupAuthenticationPackage(HANDLE lsa_handle
,
1011 PLSA_STRING package_name
, PULONG package_id
)
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 */