ntdll: Validate blocks in the heap pending free request list.
[wine.git] / dlls / kerberos / krb5_ap.c
blob42d3358a20d2f4740fbe546b43ae725a65af56d5
1 /*
2 * Copyright 2017 Dmitry Timoshkov
3 * Copyright 2017 George Popoff
4 * Copyright 2008 Robert Shearman for CodeWeavers
5 * Copyright 2017 Hans Leidekker for CodeWeavers
7 * Kerberos5 Authentication Package
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include <stdarg.h>
25 #include <stdlib.h>
26 #include "ntstatus.h"
27 #define WIN32_NO_STATUS
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winnls.h"
31 #include "rpc.h"
32 #include "sspi.h"
33 #include "ntsecapi.h"
34 #include "ntsecpkg.h"
35 #include "winternl.h"
37 #include "wine/debug.h"
38 #include "unixlib.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(kerberos);
42 #define KERBEROS_CAPS \
43 ( SECPKG_FLAG_INTEGRITY \
44 | SECPKG_FLAG_PRIVACY \
45 | SECPKG_FLAG_TOKEN_ONLY \
46 | SECPKG_FLAG_DATAGRAM \
47 | SECPKG_FLAG_CONNECTION \
48 | SECPKG_FLAG_MULTI_REQUIRED \
49 | SECPKG_FLAG_EXTENDED_ERROR \
50 | SECPKG_FLAG_IMPERSONATION \
51 | SECPKG_FLAG_ACCEPT_WIN32_NAME \
52 | SECPKG_FLAG_NEGOTIABLE \
53 | SECPKG_FLAG_GSS_COMPATIBLE \
54 | SECPKG_FLAG_LOGON \
55 | SECPKG_FLAG_MUTUAL_AUTH \
56 | SECPKG_FLAG_DELEGATION \
57 | SECPKG_FLAG_READONLY_WITH_CHECKSUM \
58 | SECPKG_FLAG_RESTRICTED_TOKENS \
59 | SECPKG_FLAG_APPCONTAINER_CHECKS)
61 static WCHAR kerberos_name_W[] = L"Kerberos";
62 static WCHAR kerberos_comment_W[] = L"Microsoft Kerberos V1.0";
63 static const SecPkgInfoW infoW =
65 KERBEROS_CAPS,
67 RPC_C_AUTHN_GSS_KERBEROS,
68 KERBEROS_MAX_BUF,
69 kerberos_name_W,
70 kerberos_comment_W
73 static ULONG kerberos_package_id;
74 static LSA_DISPATCH_TABLE lsa_dispatch;
76 struct cred_handle
78 UINT64 handle;
81 struct context_handle
83 UINT64 handle;
86 static LSA_SEC_HANDLE create_context_handle( struct context_handle *ctx, UINT64 new_context )
88 UINT64 context = ctx ? ctx->handle : 0;
89 if (new_context && new_context != context)
91 struct context_handle *new_ctx = malloc(sizeof(*new_ctx));
92 new_ctx->handle = new_context;
93 return (LSA_SEC_HANDLE)new_ctx;
95 else
96 return (LSA_SEC_HANDLE)ctx;
99 static int get_buffer_index( const SecBufferDesc *desc, DWORD type )
101 UINT i;
102 if (!desc) return -1;
103 for (i = 0; i < desc->cBuffers; i++)
105 if (desc->pBuffers[i].BufferType == type) return i;
107 return -1;
110 static const char *debugstr_us( const UNICODE_STRING *us )
112 if (!us) return "<null>";
113 return debugstr_wn( us->Buffer, us->Length / sizeof(WCHAR) );
116 static void expiry_to_timestamp( ULONG expiry, TimeStamp *timestamp )
118 LARGE_INTEGER time;
120 if (!timestamp) return;
121 NtQuerySystemTime( &time );
122 RtlSystemTimeToLocalTime( &time, &time );
123 time.QuadPart += expiry * (ULONGLONG)10000000;
124 timestamp->LowPart = time.QuadPart;
125 timestamp->HighPart = time.QuadPart >> 32;
128 static NTSTATUS NTAPI kerberos_LsaApInitializePackage(ULONG package_id, PLSA_DISPATCH_TABLE dispatch,
129 PLSA_STRING database, PLSA_STRING confidentiality, PLSA_STRING *package_name)
131 char *kerberos_name;
133 if (!__wine_unixlib_handle)
135 if (__wine_init_unix_call() || KRB5_CALL( process_attach, NULL ))
136 ERR( "no Kerberos support, expect problems\n" );
139 kerberos_package_id = package_id;
140 lsa_dispatch = *dispatch;
142 kerberos_name = lsa_dispatch.AllocateLsaHeap(sizeof(MICROSOFT_KERBEROS_NAME_A));
143 if (!kerberos_name) return STATUS_NO_MEMORY;
145 memcpy(kerberos_name, MICROSOFT_KERBEROS_NAME_A, sizeof(MICROSOFT_KERBEROS_NAME_A));
147 *package_name = lsa_dispatch.AllocateLsaHeap(sizeof(**package_name));
148 if (!*package_name)
150 lsa_dispatch.FreeLsaHeap(kerberos_name);
151 return STATUS_NO_MEMORY;
154 RtlInitString(*package_name, kerberos_name);
156 return STATUS_SUCCESS;
159 static NTSTATUS copy_to_client( PLSA_CLIENT_REQUEST lsa_req, KERB_QUERY_TKT_CACHE_RESPONSE *resp,
160 void **out, ULONG size )
162 NTSTATUS status;
163 ULONG i;
164 char *client_str;
165 KERB_QUERY_TKT_CACHE_RESPONSE *client_resp;
167 status = lsa_dispatch.AllocateClientBuffer(lsa_req, size, out );
168 if (status != STATUS_SUCCESS) return status;
170 client_resp = *out;
171 status = lsa_dispatch.CopyToClientBuffer(lsa_req, offsetof(KERB_QUERY_TKT_CACHE_RESPONSE, Tickets),
172 client_resp, resp);
173 if (status != STATUS_SUCCESS) goto fail;
175 client_str = (char *)&client_resp->Tickets[resp->CountOfTickets];
177 for (i = 0; i < resp->CountOfTickets; i++)
179 KERB_TICKET_CACHE_INFO ticket = resp->Tickets[i];
181 RtlSecondsSince1970ToTime( resp->Tickets[i].StartTime.QuadPart, &ticket.StartTime );
182 RtlSecondsSince1970ToTime( resp->Tickets[i].EndTime.QuadPart, &ticket.EndTime );
183 RtlSecondsSince1970ToTime( resp->Tickets[i].RenewTime.QuadPart, &ticket.RenewTime );
185 status = lsa_dispatch.CopyToClientBuffer(lsa_req, ticket.RealmName.MaximumLength,
186 client_str, ticket.RealmName.Buffer);
187 if (status != STATUS_SUCCESS) goto fail;
188 ticket.RealmName.Buffer = (WCHAR *)client_str;
189 client_str += ticket.RealmName.MaximumLength;
191 status = lsa_dispatch.CopyToClientBuffer(lsa_req, ticket.ServerName.MaximumLength,
192 client_str, ticket.ServerName.Buffer);
193 if (status != STATUS_SUCCESS) goto fail;
194 ticket.ServerName.Buffer = (WCHAR *)client_str;
195 client_str += ticket.ServerName.MaximumLength;
197 status = lsa_dispatch.CopyToClientBuffer(lsa_req, sizeof(ticket), &client_resp->Tickets[i], &ticket);
198 if (status != STATUS_SUCCESS) goto fail;
200 return STATUS_SUCCESS;
202 fail:
203 lsa_dispatch.FreeClientBuffer(lsa_req, client_resp);
204 return status;
207 static NTSTATUS NTAPI kerberos_LsaApCallPackageUntrusted(PLSA_CLIENT_REQUEST req, void *in_buf,
208 void *client_buf_base, ULONG in_buf_len, void **out_buf, ULONG *out_buf_len, NTSTATUS *ret_status)
210 KERB_PROTOCOL_MESSAGE_TYPE msg;
212 TRACE("%p, %p, %p, %lu, %p, %p, %p\n", req, in_buf, client_buf_base, in_buf_len, out_buf, out_buf_len, ret_status);
214 if (!in_buf || in_buf_len < sizeof(msg)) return STATUS_INVALID_PARAMETER;
216 msg = *(KERB_PROTOCOL_MESSAGE_TYPE *)in_buf;
217 switch (msg)
219 case KerbQueryTicketCacheMessage:
221 KERB_QUERY_TKT_CACHE_REQUEST *query = (KERB_QUERY_TKT_CACHE_REQUEST *)in_buf;
222 NTSTATUS status;
224 if (!in_buf || in_buf_len != sizeof(*query) || !out_buf || !out_buf_len) return STATUS_INVALID_PARAMETER;
225 if (query->LogonId.HighPart || query->LogonId.LowPart) return STATUS_ACCESS_DENIED;
227 *out_buf_len = 1024;
228 for (;;)
230 KERB_QUERY_TKT_CACHE_RESPONSE *resp = malloc( *out_buf_len );
231 struct query_ticket_cache_params params = { resp, out_buf_len };
232 status = KRB5_CALL( query_ticket_cache, &params );
233 if (status == STATUS_SUCCESS) status = copy_to_client( req, resp, out_buf, *out_buf_len );
234 free( resp );
235 if (status != STATUS_BUFFER_TOO_SMALL) break;
237 *ret_status = status;
238 break;
240 case KerbRetrieveTicketMessage:
241 FIXME("KerbRetrieveTicketMessage stub\n");
242 *ret_status = STATUS_NOT_IMPLEMENTED;
243 break;
245 case KerbPurgeTicketCacheMessage:
246 FIXME("KerbPurgeTicketCacheMessage stub\n");
247 *ret_status = STATUS_NOT_IMPLEMENTED;
248 break;
250 default: /* All other requests should call LsaApCallPackage */
251 WARN("%u => access denied\n", msg);
252 *ret_status = STATUS_ACCESS_DENIED;
253 break;
256 return *ret_status;
259 static NTSTATUS NTAPI kerberos_SpGetInfo(SecPkgInfoW *info)
261 TRACE("%p\n", info);
263 /* LSA will make a copy before forwarding the structure, so
264 * it's safe to put pointers to dynamic or constant data there.
266 *info = infoW;
268 return STATUS_SUCCESS;
271 static char *get_str_unixcp( const UNICODE_STRING *str )
273 char *ret;
274 int len = WideCharToMultiByte( CP_UNIXCP, 0, str->Buffer, str->Length / sizeof(WCHAR), NULL, 0, NULL, NULL );
275 if (!(ret = malloc( len + 1 ))) return NULL;
276 WideCharToMultiByte( CP_UNIXCP, 0, str->Buffer, str->Length / sizeof(WCHAR), ret, len, NULL, NULL );
277 ret[len] = 0;
278 return ret;
281 static char *get_username_unixcp( const WCHAR *user, ULONG user_len, const WCHAR *domain, ULONG domain_len )
283 int len_user, len_domain;
284 char *ret;
286 len_user = WideCharToMultiByte( CP_UNIXCP, 0, user, user_len, NULL, 0, NULL, NULL );
287 len_domain = WideCharToMultiByte( CP_UNIXCP, 0, domain, domain_len, NULL, 0, NULL, NULL );
288 if (!(ret = malloc( len_user + len_domain + 2 ))) return NULL;
290 WideCharToMultiByte( CP_UNIXCP, 0, user, user_len, ret, len_user, NULL, NULL );
291 ret[len_user] = '@';
292 WideCharToMultiByte( CP_UNIXCP, 0, domain, domain_len, ret + len_user + 1, len_domain, NULL, NULL );
293 ret[len_user + len_domain + 1] = 0;
294 return ret;
297 static char *get_password_unixcp( const WCHAR *passwd, ULONG passwd_len )
299 int len;
300 char *ret;
302 len = WideCharToMultiByte( CP_UNIXCP, WC_NO_BEST_FIT_CHARS, passwd, passwd_len, NULL, 0, NULL, NULL );
303 if (!(ret = malloc( len + 1 ))) return NULL;
304 WideCharToMultiByte( CP_UNIXCP, 0, passwd, passwd_len, ret, len, NULL, NULL );
305 ret[len] = 0;
306 return ret;
309 static NTSTATUS NTAPI kerberos_SpAcquireCredentialsHandle(
310 UNICODE_STRING *principal_us, ULONG credential_use, LUID *logon_id, void *auth_data,
311 void *get_key_fn, void *get_key_arg, LSA_SEC_HANDLE *credential, TimeStamp *expiry )
313 char *principal = NULL, *username = NULL, *password = NULL;
314 SEC_WINNT_AUTH_IDENTITY_W *id = auth_data;
315 NTSTATUS status = SEC_E_INSUFFICIENT_MEMORY;
316 struct cred_handle *cred_handle;
317 ULONG exptime;
319 TRACE( "%s, %#lx, %p, %p, %p, %p, %p, %p\n", debugstr_us(principal_us), credential_use,
320 logon_id, auth_data, get_key_fn, get_key_arg, credential, expiry );
322 if (principal_us && !(principal = get_str_unixcp( principal_us ))) return SEC_E_INSUFFICIENT_MEMORY;
323 if (id)
325 if (id->Flags & SEC_WINNT_AUTH_IDENTITY_ANSI)
327 FIXME( "ANSI identity not supported\n" );
328 status = SEC_E_UNSUPPORTED_FUNCTION;
329 goto done;
331 if (!(username = get_username_unixcp( id->User, id->UserLength, id->Domain, id->DomainLength ))) goto done;
332 if (!(password = get_password_unixcp( id->Password, id->PasswordLength ))) goto done;
335 if (!(cred_handle = calloc( 1, sizeof(*cred_handle) )))
337 status = SEC_E_INSUFFICIENT_MEMORY;
338 goto done;
342 struct acquire_credentials_handle_params params = { principal, credential_use, username, password,
343 &cred_handle->handle, &exptime };
344 if (!(status = KRB5_CALL( acquire_credentials_handle, &params )))
345 *credential = (LSA_SEC_HANDLE)cred_handle;
346 else
347 free( cred_handle );
348 expiry_to_timestamp( exptime, expiry );
351 done:
352 free( principal );
353 free( username );
354 free( password );
355 return status;
358 static NTSTATUS NTAPI kerberos_SpFreeCredentialsHandle( LSA_SEC_HANDLE credential )
360 struct cred_handle *cred_handle = (void *)credential;
361 struct free_credentials_handle_params params;
362 NTSTATUS status;
364 TRACE( "%Ix\n", credential );
366 if (!cred_handle) return SEC_E_INVALID_HANDLE;
368 params.credential = cred_handle->handle;
369 status = KRB5_CALL( free_credentials_handle, &params );
370 free(cred_handle);
371 return status;
374 static NTSTATUS NTAPI kerberos_SpInitLsaModeContext( LSA_SEC_HANDLE credential, LSA_SEC_HANDLE context,
375 UNICODE_STRING *target_name, ULONG context_req, ULONG target_data_rep, SecBufferDesc *input,
376 LSA_SEC_HANDLE *new_context, SecBufferDesc *output, ULONG *context_attr, TimeStamp *expiry,
377 BOOLEAN *mapped_context, SecBuffer *context_data )
379 static const ULONG supported = ISC_REQ_CONFIDENTIALITY | ISC_REQ_INTEGRITY | ISC_REQ_SEQUENCE_DETECT |
380 ISC_REQ_REPLAY_DETECT | ISC_REQ_MUTUAL_AUTH | ISC_REQ_USE_DCE_STYLE |
381 ISC_REQ_IDENTIFY | ISC_REQ_CONNECTION;
382 char *target = NULL;
383 NTSTATUS status;
384 ULONG exptime;
386 TRACE( "%Ix, %Ix, %s, %#lx, %lu, %p, %p, %p, %p, %p, %p, %p\n", credential, context, debugstr_us(target_name),
387 context_req, target_data_rep, input, new_context, output, context_attr, expiry,
388 mapped_context, context_data );
389 if (context_req & ~supported) FIXME( "flags %#lx not supported\n", context_req & ~supported );
391 if (!context && !input && !credential) return SEC_E_INVALID_HANDLE;
392 if (target_name && !(target = get_str_unixcp( target_name ))) return SEC_E_INSUFFICIENT_MEMORY;
393 else
395 struct cred_handle *cred_handle = (struct cred_handle *)credential;
396 struct context_handle *context_handle = (struct context_handle *)context;
397 struct initialize_context_params params = { 0 };
398 UINT64 new_context_handle = 0;
399 int idx;
401 params.credential = cred_handle ? cred_handle->handle : 0;
402 params.context = context_handle ? context_handle->handle : 0;
403 params.target_name = target;
404 params.context_req = context_req;
405 params.new_context = &new_context_handle;
406 params.context_attr = context_attr;
407 params.expiry = &exptime;
409 idx = get_buffer_index( input, SECBUFFER_TOKEN );
410 if (idx != -1)
412 params.input_token = input->pBuffers[idx].pvBuffer;
413 params.input_token_length = input->pBuffers[idx].cbBuffer;
416 if ((idx = get_buffer_index( output, SECBUFFER_TOKEN )) == -1) return SEC_E_INVALID_TOKEN;
417 params.output_token = output->pBuffers[idx].pvBuffer;
418 params.output_token_length = &output->pBuffers[idx].cbBuffer;
420 status = KRB5_CALL( initialize_context, &params );
421 if (status == SEC_E_OK || status == SEC_I_CONTINUE_NEEDED)
422 *new_context = create_context_handle( context_handle, new_context_handle );
423 if (!status)
425 *mapped_context = TRUE;
426 expiry_to_timestamp( exptime, expiry );
429 /* FIXME: initialize context_data */
430 free( target );
431 return status;
434 static NTSTATUS NTAPI kerberos_SpAcceptLsaModeContext( LSA_SEC_HANDLE credential, LSA_SEC_HANDLE context,
435 SecBufferDesc *input, ULONG context_req, ULONG target_data_rep, LSA_SEC_HANDLE *new_context,
436 SecBufferDesc *output, ULONG *context_attr, TimeStamp *expiry, BOOLEAN *mapped_context, SecBuffer *context_data )
438 NTSTATUS status = SEC_E_INVALID_HANDLE;
439 ULONG exptime;
440 int idx;
442 TRACE( "%Ix, %Ix, %#lx, %lu, %p, %p, %p, %p, %p, %p, %p\n", credential, context, context_req, target_data_rep,
443 input, new_context, output, context_attr, expiry, mapped_context, context_data );
444 if (context_req) FIXME( "ignoring flags %#lx\n", context_req );
446 if (context || input || credential)
448 struct cred_handle *cred_handle = (struct cred_handle *)credential;
449 struct context_handle *context_handle = (struct context_handle *)context;
450 struct accept_context_params params = { 0 };
451 UINT64 new_context_handle = 0;
453 params.credential = cred_handle ? cred_handle->handle : 0;
454 params.context = context_handle ? context_handle->handle : 0;
455 params.new_context = &new_context_handle;
456 params.context_attr = context_attr;
457 params.expiry = &exptime;
459 if (input)
461 if ((idx = get_buffer_index( input, SECBUFFER_TOKEN )) == -1) return SEC_E_INVALID_TOKEN;
462 params.input_token = input->pBuffers[idx].pvBuffer;
463 params.input_token_length = input->pBuffers[idx].cbBuffer;
465 if ((idx = get_buffer_index( output, SECBUFFER_TOKEN )) == -1) return SEC_E_INVALID_TOKEN;
466 params.output_token = output->pBuffers[idx].pvBuffer;
467 params.output_token_length = &output->pBuffers[idx].cbBuffer;
469 /* FIXME: check if larger output buffer exists */
470 status = KRB5_CALL( accept_context, &params );
471 if (status == SEC_E_OK || status == SEC_I_CONTINUE_NEEDED)
472 *new_context = create_context_handle( context_handle, new_context_handle );
473 if (!status)
475 *mapped_context = TRUE;
476 expiry_to_timestamp( exptime, expiry );
478 /* FIXME: initialize context_data */
480 return status;
483 static NTSTATUS NTAPI kerberos_SpDeleteContext( LSA_SEC_HANDLE context )
485 struct context_handle *context_handle = (void *)context;
486 struct delete_context_params params;
487 NTSTATUS status;
489 TRACE( "%Ix\n", context );
491 if (!context) return SEC_E_INVALID_HANDLE;
493 params.context = context_handle->handle;
494 status = KRB5_CALL( delete_context, &params );
495 free( context_handle );
496 return status;
499 static SecPkgInfoW *build_package_info( const SecPkgInfoW *info )
501 SecPkgInfoW *ret;
502 DWORD size_name = (wcslen(info->Name) + 1) * sizeof(WCHAR);
503 DWORD size_comment = (wcslen(info->Comment) + 1) * sizeof(WCHAR);
505 if (!(ret = malloc( sizeof(*ret) + size_name + size_comment ))) return NULL;
506 ret->fCapabilities = info->fCapabilities;
507 ret->wVersion = info->wVersion;
508 ret->wRPCID = info->wRPCID;
509 ret->cbMaxToken = info->cbMaxToken;
510 ret->Name = (SEC_WCHAR *)(ret + 1);
511 memcpy( ret->Name, info->Name, size_name );
512 ret->Comment = (SEC_WCHAR *)((char *)ret->Name + size_name);
513 memcpy( ret->Comment, info->Comment, size_comment );
514 return ret;
517 static NTSTATUS NTAPI kerberos_SpQueryContextAttributes( LSA_SEC_HANDLE context, ULONG attribute, void *buffer )
519 struct context_handle *context_handle = (void *)context;
521 TRACE( "%Ix, %lu, %p\n", context, attribute, buffer );
523 if (!context) return SEC_E_INVALID_HANDLE;
525 switch (attribute)
527 #define X(x) case (x) : FIXME(#x" stub\n"); break
528 X(SECPKG_ATTR_ACCESS_TOKEN);
529 X(SECPKG_ATTR_AUTHORITY);
530 X(SECPKG_ATTR_DCE_INFO);
531 X(SECPKG_ATTR_KEY_INFO);
532 X(SECPKG_ATTR_LIFESPAN);
533 X(SECPKG_ATTR_NAMES);
534 X(SECPKG_ATTR_NATIVE_NAMES);
535 X(SECPKG_ATTR_PACKAGE_INFO);
536 X(SECPKG_ATTR_PASSWORD_EXPIRY);
537 X(SECPKG_ATTR_SESSION_KEY);
538 X(SECPKG_ATTR_STREAM_SIZES);
539 X(SECPKG_ATTR_TARGET_INFORMATION);
540 case SECPKG_ATTR_SIZES:
542 struct query_context_attributes_params params = { context_handle->handle, attribute, buffer };
543 return KRB5_CALL( query_context_attributes, &params );
545 case SECPKG_ATTR_NEGOTIATION_INFO:
547 SecPkgContext_NegotiationInfoW *info = (SecPkgContext_NegotiationInfoW *)buffer;
548 if (!(info->PackageInfo = build_package_info( &infoW ))) return SEC_E_INSUFFICIENT_MEMORY;
549 info->NegotiationState = SECPKG_NEGOTIATION_COMPLETE;
550 return SEC_E_OK;
552 #undef X
553 default:
554 FIXME( "unknown attribute %lu\n", attribute );
555 break;
558 return SEC_E_UNSUPPORTED_FUNCTION;
561 static NTSTATUS NTAPI kerberos_SpInitialize(ULONG_PTR package_id, SECPKG_PARAMETERS *params,
562 LSA_SECPKG_FUNCTION_TABLE *lsa_function_table)
564 TRACE("%Iu, %p, %p\n", package_id, params, lsa_function_table);
566 if (!__wine_unixlib_handle)
568 if (__wine_init_unix_call() || KRB5_CALL( process_attach, NULL ))
569 WARN( "no Kerberos support\n" );
570 return STATUS_UNSUCCESSFUL;
572 return STATUS_SUCCESS;
575 static NTSTATUS NTAPI kerberos_SpShutdown(void)
577 TRACE("\n");
578 return STATUS_SUCCESS;
581 static SECPKG_FUNCTION_TABLE kerberos_table =
583 kerberos_LsaApInitializePackage, /* InitializePackage */
584 NULL, /* LsaLogonUser */
585 NULL, /* CallPackage */
586 NULL, /* LogonTerminated */
587 kerberos_LsaApCallPackageUntrusted, /* CallPackageUntrusted */
588 NULL, /* CallPackagePassthrough */
589 NULL, /* LogonUserEx */
590 NULL, /* LogonUserEx2 */
591 kerberos_SpInitialize,
592 kerberos_SpShutdown,
593 kerberos_SpGetInfo,
594 NULL, /* AcceptCredentials */
595 kerberos_SpAcquireCredentialsHandle,
596 NULL, /* SpQueryCredentialsAttributes */
597 kerberos_SpFreeCredentialsHandle,
598 NULL, /* SaveCredentials */
599 NULL, /* GetCredentials */
600 NULL, /* DeleteCredentials */
601 kerberos_SpInitLsaModeContext,
602 kerberos_SpAcceptLsaModeContext,
603 kerberos_SpDeleteContext,
604 NULL, /* ApplyControlToken */
605 NULL, /* GetUserInfo */
606 NULL, /* GetExtendedInformation */
607 kerberos_SpQueryContextAttributes,
608 NULL, /* SpAddCredentials */
609 NULL, /* SetExtendedInformation */
610 NULL, /* SetContextAttributes */
611 NULL, /* SetCredentialsAttributes */
612 NULL, /* ChangeAccountPassword */
613 NULL, /* QueryMetaData */
614 NULL, /* ExchangeMetaData */
615 NULL, /* GetCredUIContext */
616 NULL, /* UpdateCredentials */
617 NULL, /* ValidateTargetInfo */
618 NULL, /* PostLogonUser */
621 NTSTATUS NTAPI SpLsaModeInitialize(ULONG lsa_version, PULONG package_version,
622 PSECPKG_FUNCTION_TABLE *table, PULONG table_count)
624 TRACE("%#lx, %p, %p, %p\n", lsa_version, package_version, table, table_count);
626 *package_version = SECPKG_INTERFACE_VERSION;
627 *table = &kerberos_table;
628 *table_count = 1;
629 return STATUS_SUCCESS;
632 static NTSTATUS NTAPI kerberos_SpInstanceInit(ULONG version, SECPKG_DLL_FUNCTIONS *dll_function_table, void **user_functions)
634 TRACE("%#lx, %p, %p\n", version, dll_function_table, user_functions);
635 return STATUS_SUCCESS;
638 static NTSTATUS SEC_ENTRY kerberos_SpMakeSignature( LSA_SEC_HANDLE context, ULONG quality_of_protection,
639 SecBufferDesc *message, ULONG message_seq_no )
641 TRACE( "%Ix, %#lx, %p, %lu\n", context, quality_of_protection, message, message_seq_no );
642 if (quality_of_protection) FIXME( "ignoring quality_of_protection %#lx\n", quality_of_protection );
643 if (message_seq_no) FIXME( "ignoring message_seq_no %lu\n", message_seq_no );
645 if (context)
647 struct context_handle *context_handle = (void *)context;
648 struct make_signature_params params;
649 int data_idx, token_idx;
651 /* FIXME: multiple data buffers, read-only buffers */
652 if ((data_idx = get_buffer_index( message, SECBUFFER_DATA )) == -1) return SEC_E_INVALID_TOKEN;
653 if ((token_idx = get_buffer_index( message, SECBUFFER_TOKEN )) == -1) return SEC_E_INVALID_TOKEN;
655 params.context = context_handle->handle;
656 params.data_length = message->pBuffers[data_idx].cbBuffer;
657 params.data = message->pBuffers[data_idx].pvBuffer;
658 params.token_length = &message->pBuffers[token_idx].cbBuffer;
659 params.token = message->pBuffers[token_idx].pvBuffer;
661 return KRB5_CALL( make_signature, &params );
663 else return SEC_E_INVALID_HANDLE;
666 static NTSTATUS NTAPI kerberos_SpVerifySignature( LSA_SEC_HANDLE context, SecBufferDesc *message,
667 ULONG message_seq_no, ULONG *quality_of_protection )
669 TRACE( "%Ix, %p, %lu, %p\n", context, message, message_seq_no, quality_of_protection );
670 if (message_seq_no) FIXME( "ignoring message_seq_no %lu\n", message_seq_no );
672 if (context)
674 struct context_handle *context_handle = (void *)context;
675 struct verify_signature_params params;
676 int data_idx, token_idx;
678 if ((data_idx = get_buffer_index( message, SECBUFFER_DATA )) == -1) return SEC_E_INVALID_TOKEN;
679 if ((token_idx = get_buffer_index( message, SECBUFFER_TOKEN )) == -1) return SEC_E_INVALID_TOKEN;
681 params.context = context_handle->handle;
682 params.data_length = message->pBuffers[data_idx].cbBuffer;
683 params.data = message->pBuffers[data_idx].pvBuffer;
684 params.token_length = message->pBuffers[token_idx].cbBuffer;
685 params.token = message->pBuffers[token_idx].pvBuffer;
686 params.qop = quality_of_protection;
688 return KRB5_CALL( verify_signature, &params );
690 else return SEC_E_INVALID_HANDLE;
693 static NTSTATUS NTAPI kerberos_SpSealMessage( LSA_SEC_HANDLE context, ULONG quality_of_protection,
694 SecBufferDesc *message, ULONG message_seq_no )
696 TRACE( "%Ix, %#lx, %p, %lu\n", context, quality_of_protection, message, message_seq_no );
697 if (message_seq_no) FIXME( "ignoring message_seq_no %lu\n", message_seq_no );
699 if (context)
701 struct context_handle *context_handle = (void *)context;
702 struct seal_message_params params;
703 int data_idx, token_idx;
705 /* FIXME: multiple data buffers, read-only buffers */
706 if ((data_idx = get_buffer_index( message, SECBUFFER_DATA )) == -1) return SEC_E_INVALID_TOKEN;
707 if ((token_idx = get_buffer_index( message, SECBUFFER_TOKEN )) == -1) return SEC_E_INVALID_TOKEN;
709 params.context = context_handle->handle;
710 params.data_length = message->pBuffers[data_idx].cbBuffer;
711 params.data = message->pBuffers[data_idx].pvBuffer;
712 params.token_length = &message->pBuffers[token_idx].cbBuffer;
713 params.token = message->pBuffers[token_idx].pvBuffer;
714 params.qop = quality_of_protection;
716 return KRB5_CALL( seal_message, &params );
718 else return SEC_E_INVALID_HANDLE;
721 static NTSTATUS NTAPI kerberos_SpUnsealMessage( LSA_SEC_HANDLE context, SecBufferDesc *message,
722 ULONG message_seq_no, ULONG *quality_of_protection )
724 TRACE( "%Ix, %p, %lu, %p\n", context, message, message_seq_no, quality_of_protection );
725 if (message_seq_no) FIXME( "ignoring message_seq_no %lu\n", message_seq_no );
727 if (context)
729 struct context_handle *context_handle = (void *)context;
730 struct unseal_message_params params;
731 int data_idx, token_idx;
733 if ((data_idx = get_buffer_index( message, SECBUFFER_DATA )) == -1) return SEC_E_INVALID_TOKEN;
734 if ((token_idx = get_buffer_index( message, SECBUFFER_TOKEN )) == -1) return SEC_E_INVALID_TOKEN;
736 params.context = context_handle->handle;
737 params.data_length = message->pBuffers[data_idx].cbBuffer;
738 params.data = message->pBuffers[data_idx].pvBuffer;
739 params.token_length = message->pBuffers[token_idx].cbBuffer;
740 params.token = message->pBuffers[token_idx].pvBuffer;
741 params.qop = quality_of_protection;
743 return KRB5_CALL( unseal_message, &params );
745 else return SEC_E_INVALID_HANDLE;
748 static SECPKG_USER_FUNCTION_TABLE kerberos_user_table =
750 kerberos_SpInstanceInit,
751 NULL, /* SpInitUserModeContext */
752 kerberos_SpMakeSignature,
753 kerberos_SpVerifySignature,
754 kerberos_SpSealMessage,
755 kerberos_SpUnsealMessage,
756 NULL, /* SpGetContextToken */
757 NULL, /* SpQueryContextAttributes */
758 NULL, /* SpCompleteAuthToken */
759 NULL, /* SpDeleteContext */
760 NULL, /* SpFormatCredentialsFn */
761 NULL, /* SpMarshallSupplementalCreds */
762 NULL, /* SpExportSecurityContext */
763 NULL /* SpImportSecurityContext */
766 NTSTATUS NTAPI SpUserModeInitialize(ULONG lsa_version, PULONG package_version,
767 PSECPKG_USER_FUNCTION_TABLE *table, PULONG table_count)
769 TRACE("%#lx, %p, %p, %p\n", lsa_version, package_version, table, table_count);
771 *package_version = SECPKG_INTERFACE_VERSION;
772 *table = &kerberos_user_table;
773 *table_count = 1;
774 return STATUS_SUCCESS;