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
27 #define WIN32_NO_STATUS
37 #include "wine/debug.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 \
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
=
67 RPC_C_AUTHN_GSS_KERBEROS
,
73 static ULONG kerberos_package_id
;
74 static LSA_DISPATCH_TABLE lsa_dispatch
;
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
;
96 return (LSA_SEC_HANDLE
)ctx
;
99 static int get_buffer_index( const SecBufferDesc
*desc
, DWORD type
)
102 if (!desc
) return -1;
103 for (i
= 0; i
< desc
->cBuffers
; i
++)
105 if (desc
->pBuffers
[i
].BufferType
== type
) return i
;
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
)
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
)
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
));
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
)
165 KERB_QUERY_TKT_CACHE_RESPONSE
*client_resp
;
167 status
= lsa_dispatch
.AllocateClientBuffer(lsa_req
, size
, out
);
168 if (status
!= STATUS_SUCCESS
) return status
;
171 status
= lsa_dispatch
.CopyToClientBuffer(lsa_req
, offsetof(KERB_QUERY_TKT_CACHE_RESPONSE
, Tickets
),
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
;
203 lsa_dispatch
.FreeClientBuffer(lsa_req
, client_resp
);
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
;
219 case KerbQueryTicketCacheMessage
:
221 KERB_QUERY_TKT_CACHE_REQUEST
*query
= (KERB_QUERY_TKT_CACHE_REQUEST
*)in_buf
;
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
;
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
, ¶ms
);
233 if (status
== STATUS_SUCCESS
) status
= copy_to_client( req
, resp
, out_buf
, *out_buf_len
);
235 if (status
!= STATUS_BUFFER_TOO_SMALL
) break;
237 *ret_status
= status
;
240 case KerbRetrieveTicketMessage
:
241 FIXME("KerbRetrieveTicketMessage stub\n");
242 *ret_status
= STATUS_NOT_IMPLEMENTED
;
245 case KerbPurgeTicketCacheMessage
:
246 FIXME("KerbPurgeTicketCacheMessage stub\n");
247 *ret_status
= STATUS_NOT_IMPLEMENTED
;
250 default: /* All other requests should call LsaApCallPackage */
251 WARN("%u => access denied\n", msg
);
252 *ret_status
= STATUS_ACCESS_DENIED
;
259 static NTSTATUS NTAPI
kerberos_SpGetInfo(SecPkgInfoW
*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.
268 return STATUS_SUCCESS
;
271 static char *get_str_unixcp( const UNICODE_STRING
*str
)
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
);
281 static char *get_username_unixcp( const WCHAR
*user
, ULONG user_len
, const WCHAR
*domain
, ULONG domain_len
)
283 int len_user
, len_domain
;
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
);
292 WideCharToMultiByte( CP_UNIXCP
, 0, domain
, domain_len
, ret
+ len_user
+ 1, len_domain
, NULL
, NULL
);
293 ret
[len_user
+ len_domain
+ 1] = 0;
297 static char *get_password_unixcp( const WCHAR
*passwd
, ULONG passwd_len
)
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
);
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
;
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
;
325 if (id
->Flags
& SEC_WINNT_AUTH_IDENTITY_ANSI
)
327 FIXME( "ANSI identity not supported\n" );
328 status
= SEC_E_UNSUPPORTED_FUNCTION
;
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
;
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
, ¶ms
)))
345 *credential
= (LSA_SEC_HANDLE
)cred_handle
;
348 expiry_to_timestamp( exptime
, expiry
);
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
;
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
, ¶ms
);
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
;
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
;
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;
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
);
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
, ¶ms
);
421 if (status
== SEC_E_OK
|| status
== SEC_I_CONTINUE_NEEDED
)
422 *new_context
= create_context_handle( context_handle
, new_context_handle
);
425 *mapped_context
= TRUE
;
426 expiry_to_timestamp( exptime
, expiry
);
429 /* FIXME: initialize context_data */
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
;
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
;
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
, ¶ms
);
471 if (status
== SEC_E_OK
|| status
== SEC_I_CONTINUE_NEEDED
)
472 *new_context
= create_context_handle( context_handle
, new_context_handle
);
475 *mapped_context
= TRUE
;
476 expiry_to_timestamp( exptime
, expiry
);
478 /* FIXME: initialize context_data */
483 static NTSTATUS NTAPI
kerberos_SpDeleteContext( LSA_SEC_HANDLE context
)
485 struct context_handle
*context_handle
= (void *)context
;
486 struct delete_context_params params
;
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
, ¶ms
);
495 free( context_handle
);
499 static SecPkgInfoW
*build_package_info( const SecPkgInfoW
*info
)
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
);
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
;
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
, ¶ms
);
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
;
554 FIXME( "unknown attribute %lu\n", attribute
);
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)
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
,
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
;
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
);
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
, ¶ms
);
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
);
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
, ¶ms
);
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
);
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
, ¶ms
);
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
);
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
, ¶ms
);
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
;
774 return STATUS_SUCCESS
;