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
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')
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
;
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
)
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
;
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
;
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
);
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
)
220 static void NTAPI
lsa_FreeLsaHeap(void *p
)
226 static NTSTATUS NTAPI
lsa_AllocateClientBuffer(PLSA_CLIENT_REQUEST req
, ULONG size
, void **p
)
228 TRACE("%p,%u,%p\n", req
, size
, p
);
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
);
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
,
260 lsa_DeleteCredential
,
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
=
282 static SECURITY_STATUS
lsa_lookup_package(SEC_WCHAR
*nameW
, struct lsa_package
**lsa_package
)
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
];
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
;
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;
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
);
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
);
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
);
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
;
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
);
411 if (auth_dataW
!= (SEC_WINNT_AUTH_IDENTITY_W
*)id
) free( auth_dataW
);
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
);
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
);
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
;
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
;
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;
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
);
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
);
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
);
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
;
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;
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
);
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
)
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
);
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
;
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
;
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
);
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
);
661 FIXME( "unknown attribute %u\n", attribute
);
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 */
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 */
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 */
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 */
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
));
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
)
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
);
859 FreeLibrary(package
->mod
);
863 #define MAX_SERVICE_NAME 260
865 void load_auth_packages(void)
869 SecureProvider
*provider
;
871 err
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, L
"System\\CurrentControlSet\\Control\\Lsa", 0, KEY_READ
, &root
);
872 if (err
!= ERROR_SUCCESS
) return;
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
)
884 if (err
!= ERROR_SUCCESS
)
887 if (!load_package(name
, &package
, i
))
890 add_package(&package
);
895 if (!loaded_packages_count
) return;
897 provider
= SECUR32_addProvider(&lsa_sspi_tableA
, &lsa_sspi_tableW
, NULL
);
900 ERR("Failed to add SSP/AP provider\n");
904 for (i
= 0; i
< loaded_packages_count
; i
++)
908 info
= malloc(loaded_packages
[i
].lsa_table_count
* sizeof(*info
));
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
);
922 NTSTATUS WINAPI
LsaLookupAuthenticationPackage(HANDLE lsa_handle
,
923 PLSA_STRING package_name
, PULONG package_id
)
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 */