- Remove From My Forums
-
Question
-
I’m trying to figure out what might be causing one of the servers in a resource domain (trusting) not to authenticate using Kerberos. This is the second of two servers just created in this environment. The first server is working correctly and
kerberos tickets look correct using klist. When you log into this second server, you get the following:Using the klist utility returns:
Current LogonId is 0:0x19ea7c
Error calling API LsaCallAuthenticationPackage (Ticket Granting Ticket substatus): 1312klist failed with 0x8009030e/-2146893042: No credentials are available in the security package
On the domain controller, I see this event logged which seems to be using NTLM instead of kerberos
Event ID: 540
Logon Type: 3
Logon Process: NtLmSsp
Authentication Package: NTLM
Answers
-
In general, it is recommended to create matching site names when operating in multi-forest environment. The primary benefit of this confgiuration is ability to localize cross-forest authentication — i.e. a user from Domain B who logs on to a computer in
Domain A will be authetnicated by a DC from domain B that resides in the same site as the local computer.I’d expect Kerberos auth to work regardless whether this is in place or not (although not in the optimal manner). The change you made likely led to a different domain controller from trusted domain performing authentication — so if you want
to investigate this further, I’d suggest focusing on checking DNS name resolution/communication between the server and the previously authenticating DC…hth
Marcin-
Marked as answer by
Friday, September 17, 2010 7:57 AM
-
Marked as answer by
I’m investigating a domain where logon does not seem to produce a TGT.
After logon with a test account, klist tgt
outputs this:
Current LogonId is 0:0x71647be1
Error calling API LsaCallAuthenticationPackage (Ticket Granting Ticket substatus): 1312
klist failed with 0x8009030e/-2146893042: No credentials are available in the security package
I. e. the same output you get on a non-domain member. However, the hosts are
definitely joined just that they seem to fall back on NTLM to authenticate to
services. DNS is set up correctly. In fact, it is possible to obtain service
tickets manually using klist get $SPN
, even without being asked for
preauth credentials. So Kerberos as such seems functional, just that
applications like IE refuse to use it.
Likewise, klist tickets
yields zero cached tickets. klist sessions
spits out errors of the form “Error calling API LsaGetLogonSessionData on
LogonId”.
Any ideas what could be the cause of this? Suggestions what I should check?
This is not a domain I have control over. The behavior is the same when logged
on directly to the machine and when connecting through RDP. Note though that
apparently this domain has grown over decades, probably even goes back to an
NT4 domain originally. I wonder whether at some point years ago they disabled Kerberos
auth for the whole domain (via GPO?) because it caused interop issues and then
forgot about it.
Microsoft already provides a set of scripts for this. So, you don’t have to write this from scratch. Viewing and Purging Cached Kerberos Tickets and yes they have klist in the mix. Otherwise, you end up trying to leverage …
[System.Security.Principal.WindowsIdentity]
… and then doing SID translations and the like or you end up going down the same discussion in this Q&A.
How to programmatically clear the Kerberos ticket cache
Or leveraging these resources and tweaking as needed.
Kerberos Module
The module gives access to the Kerberos ticket cache. It can read and purge tickets of the current logon session.
A Managed Code validator for Kerberos tickets
The Point of Kerberos.NET is to make Kerberos much easier to work with
in such scenarios. This is done by removing any hard dependencies on
Windows and moving all ticket processing to the application itself.
This of course means you don’t need the application to be on a
domain-joined machine, and it probably doesn’t need to be on Windows
either.Install-Package Kerberos.NET
Using the Library
Ticket authentication occurs in two stages. The first stage validates
the ticket for correctness via an IKerberosValidator with a default
implementation of KerberosValidator. The second stage involves
converting the ticket in to a usable ClaimsIdentity, which occurs in
the KerberosAuthenticator.The easiest way to get started is to create a new
KerberosAuthenticator and calling Authenticate. If you need to tweak
the behavior of the conversion, you can do so by overriding the
ConvertTicket(DecryptedData data) method.var authenticator = new KerberosAuthenticator(new KeyTable(File.ReadAllBytes("sample.keytab"))); var identity = authenticator.Authenticate("YIIHCAYGKwYBBQUCoIIG..."); Assert.IsNotNull(identity); var name = identity.Name; Assert.IsFalse(string.IsNullOrWhitespace(name));
Note that the constructor parameter for the authenticator is a
KeyTable. The KeyTable is a common format used to store keys on other
platforms. You can either use a file created by a tool like ktpass, or
you can just pass a KerberosKey during instantiation and it’ll have
the same effect.
List All Cached Kerberos Tickets
When administering or troubleshooting authentication in a domain there are times when you need to know whether a ticket for a user and service are cached on a computer. This script exports all user’s cached tickets on a computer to a text file for review.
Download : GetKerbTix.ps1
Purge All Kerberos Tickets
There are situations where an administrator may want to clear the cached Kerberos tickets on a server. For example, user Bob left the company. In situations like that you can run this script to clear all cached Kerberos tickets and TGTs for all sessions on the computer.
Download : PurgeAllKerbTickets.ps1
#************************************************
# GetKerbTix.ps1
# Version 1.0
# Date: 6-11-2014
# Author: Tim Springston [MSFT]
# Description: On a specific computer the script is ran on,
# this script finds all logon sessions which have Kerberos
# tickets cached and enumerates the tickets and any ticket granting tickets.
# The tickets may be from remote or interactive users and may be
# any logon type session (network, batch, interactive, remote interactive...).
# This script will run on Windows Server 2008/Vista and later.
#************************************************
cls
$FormatEnumerationLimit = -1
$ComputerName = $env:COMPUTERNAME
$UserName = [Security.Principal.WindowsIdentity]::GetCurrent().name
$ComputerDomain = [System.DirectoryServices.ActiveDirectory.Domain]::GetComputerDomain().name
$Date = Get-Date
#Prepare an output file to place info into.
$ExportFile = "C:windowstemp" + $ComputerName + "_CachedKerberosTickets.txt"
"Cached Kerberos Tickets" | Out-File $ExportFile -Encoding utf8
"Logged on User:$UserName" | Out-File $ExportFile -Append -Encoding utf8
"Computer name: $ComputerName" | Out-File $ExportFile -Append -Encoding utf8
"Computer Domain: $ComputerDomain" | Out-File $ExportFile -Append -Encoding utf8
"Date: $Date" | Out-File $ExportFile -Append -Encoding utf8
"************************************" | Out-File $ExportFile -Append -Encoding utf8
function GetKerbSessions
{
$Sessions = @()
$WMILogonSessions = gwmi win32_LogonSession
foreach ($WMILogonSession in $WMILogonSessions)
{
$LUID = [Convert]::ToString($WMILogonSession.LogonID, 16)
$LUID = '0x' + $LUID
$Sessions += $LUID
}
return $sessions
}
function GetKerbSessionInfo
{
$OS = gwmi win32_operatingsystem
$sessions = New-Object PSObject
if ($OS.Buildnumber -ge 9200)
{
$KlistSessions = klist sessions
$Counter = 0
foreach ($item in $KlistSessions)
{
if ($item -match "^[.*]")
{
$LogonId = $item.split(' ')[3]
$LogonId = $LogonId.Replace('0:','')
$Identity = $item.split(' ')[4]
$Token5 = $item.Split(' ')[5]
$AuthnMethod = $Token5.Split(':')[0]
$LogonType = $Token5.Split(':')[1]
$Session = New-Object PSObject
Add-Member -InputObject $Session -MemberType NoteProperty -Name "SessionID" -Value $LogonId
Add-Member -InputObject $Session -MemberType NoteProperty -Name "Identity" -Value $Identity
Add-Member -InputObject $Session -MemberType NoteProperty -Name "Authentication Method" -Value $AuthnMethod
Add-Member -InputObject $Session -MemberType NoteProperty -Name "Logon Type" -Value $LogonType
Add-Member -InputObject $sessions -MemberType NoteProperty -Name $LogonId -Value $Session
$Session = $null
}
}
}
if ($OS.Buildnumber -lt 9200)
{
$WMILogonSessions = gwmi win32_LogonSession
foreach ($WMILogonSession in $WMILogonSessions)
{
$LUID = [Convert]::ToString($WMILogonSession.LogonID, 16)
$LUID = '0x' + $LUID
$Session = New-Object PSObject
Add-Member -InputObject $Session -MemberType NoteProperty -Name "SessionID" -Value $LUID
Add-Member -InputObject $Session -MemberType NoteProperty -Name "Identity" -Value "Not available"
Add-Member -InputObject $Session -MemberType NoteProperty -Name "Authentication Method" -Value $WMILogonSession.AuthenticationPackage
Add-Member -InputObject $Session -MemberType NoteProperty -Name "Logon Type" -Value $WMILogonSession.LogonType
Add-Member -InputObject $sessions -MemberType NoteProperty -Name $LUID -Value $Session
$Session = $null
}
}
return $sessions
}
function ReturnSessionTGTs
{
param ($SessionID = $null)
if ($SessionID -eq $null)
{
$RawTGT = klist.exe tgt
}
else
{
$RawTGT = klist.exe tgt -li $sessionID
}
$TGT = @()
foreach ($Line in $RawTGT)
{
if ($Line.length -ge 1)
{
$TGT += $Line
}
}
if ($TGT -contains 'Error calling API LsaCallAuthenticationPackage (Ticket Granting Ticket substatus): 1312')
{$TGT = 'No ticket granting ticket cached in session.'}
return $TGT
}
function ReturnSessionTickets
{
param ($SessionID = $null)
$OS = gwmi win32_operatingsystem
if ($SessionID -eq $null)
{
$TicketsArray = klist.exe tickets
}
else
{
$TicketsArray = klist.exe tickets -li $sessionID
}
$Counter = 0
$TicketsObject = New-Object PSObject
foreach ($line in $TicketsArray)
{
if ($line -match "^#d")
{
$Ticket = New-Object PSObject
$Number = $Line.Split('>')[0]
$Line1 = $Line.Split('>')[1]
$TicketNumber = "Ticket " + $Number
$Client = $Line1 ; $Client = $Client.Replace('Client:','') ; $Client = $Client.Substring(2)
$Server = $TicketsArray[$Counter+1]; $Server = $Server.Replace('Server:','') ;$Server = $Server.substring(2)
$KerbTicketEType = $TicketsArray[$Counter+2];$KerbTicketEType = $KerbTicketEType.Replace('KerbTicket Encryption Type:','');$KerbTicketEType = $KerbTicketEType.substring(2)
$TickFlags = $TicketsArray[$Counter+3];$TickFlags = $TickFlags.Replace('Ticket Flags','');$TickFlags = $TickFlags.substring(2)
$StartTime = $TicketsArray[$Counter+4];$StartTime = $StartTime.Replace('Start Time:','');$StartTime = $StartTime.substring(2)
$EndTime = $TicketsArray[$Counter+5];$EndTime = $EndTime.Replace('End Time:','');$EndTime = $EndTime.substring(4)
$RenewTime = $TicketsArray[$Counter+6];$RenewTime = $RenewTime.Replace('Renew Time:','');$RenewTime = $RenewTime.substring(2)
$SessionKey = $TicketsArray[$Counter+7];$SessionKey = $SessionKey.Replace('Session Key Type:','');$SessionKey = $SessionKey.substring(2)
Add-Member -InputObject $Ticket -MemberType NoteProperty -Name "Client" -Value $Client
Add-Member -InputObject $Ticket -MemberType NoteProperty -Name "Server" -Value $Server
Add-Member -InputObject $Ticket -MemberType NoteProperty -Name "KerbTicket Encryption Type" -Value $KerbTicketEType
Add-Member -InputObject $Ticket -MemberType NoteProperty -Name "Ticket Flags" -Value $TickFlags
Add-Member -InputObject $Ticket -MemberType NoteProperty -Name "Start Time" -Value $StartTime
Add-Member -InputObject $Ticket -MemberType NoteProperty -Name "End Time" -Value $EndTime
Add-Member -InputObject $Ticket -MemberType NoteProperty -Name "Renew Time" -Value $RenewTime
Add-Member -InputObject $Ticket -MemberType NoteProperty -Name "Session Key Type" -Value $SessionKey
if ($OS.BuildNumber -ge 9200)
{
$CacheFlags = $TicketsArray[$Counter+8];$CacheFlags = $CacheFlags.Replace('Cache Flags:','');$CacheFlags = $CacheFlags.substring(2)
$KDCCalled = $TicketsArray[$Counter+9];$KDCCalled = $KDCCalled.Replace('Kdc Called:','');$KDCCalled = $KDCCalled.substring(2)
Add-Member -InputObject $Ticket -MemberType NoteProperty -Name "Cache Flags" -Value $CacheFlags
Add-Member -InputObject $Ticket -MemberType NoteProperty -Name "KDC Called" -Value $KDCCalled
}
Add-Member -InputObject $TicketsObject -MemberType NoteProperty -Name $TicketNumber -Value $Ticket
$Ticket = $null
}
$Counter++
}
return $TicketsObject
}
$OS = gwmi win32_operatingsystem
$sessions = getkerbsessions
$sessioninfo = GetKerbSessionInfo
foreach ($Session in $sessions)
{
#Get Session details as well
$currentsessioninfo = $sessioninfo.$session
$ID = $currentsessioninfo.identity
$SessionID = $currentsessioninfo.SessionID
$LogonType = $currentsessioninfo.'Logon Type'
$AuthMethod = $currentsessioninfo.'Authentication Method'
if ($OS.Buildnumber -lt 9200)
{
Write-Host "Kerberos Tickets for LogonID $SessionID"
"Kerberos Tickets for LogonID $SessionID" | Out-File $ExportFile -Append -Encoding utf8
}
else
{
Write-Host "Kerberos Tickets for $ID"
"Kerberos Tickets for $ID" | Out-File $ExportFile -Append -Encoding utf8
}
Write-Host "*****************************"
"*****************************" | Out-File $ExportFile -Append -Encoding utf8
Write-Host "Logon Type: $LogonType"
"Logon Type: $LogonType" | Out-File $ExportFile -Append -Encoding utf8
Write-host "Session ID: $SessionID"
"Session ID: $SessionID" | Out-File $ExportFile -Append -Encoding utf8
Write-host "Auth Method: $AuthMethod"
"Auth Method: $AuthMethod" | Out-File $ExportFile -Append -Encoding utf8
$SessionTickets = ReturnSessionTickets $Session
$TGT = ReturnSessionTGTs $SessionID
$TGT | FL *
$TGT | Out-File $ExportFile -Append -Encoding utf8
if ($SessionTickets -notmatch 'Ticket')
{
Write-Host "Session TGT: No tickets for this session in cache."
"Session TGT: No tickets for this session in cache." | Out-File $ExportFile -Append -Encoding utf8
}
else
{
$SessionTickets | FL *
$SessionTickets | Out-File $ExportFile -Append -Encoding utf8
}
Write-Host "`n"
"`n" | Out-File $ExportFile -Append -Encoding utf8
}
#************************************************
# PurgeAllKerbTickets.ps1
# Version 1.0
# Date: 6-12-2014
# Author: Tim Springston [MSFT]
# Description: On a specific computer the script is ran on,
# this script finds all logon sessions which have Kerberos
# tickets cached and for each session purges the ticket granting
# tickets and the tickets using klist.exe.
#************************************************
cls
function GetKerbSessions
{
$Sessions = @()
$WMILogonSessions = gwmi win32_LogonSession
foreach ($WMILogonSession in $WMILogonSessions)
{
$LUID = [Convert]::ToString($WMILogonSession.LogonID, 16)
$LUID = '0x' + $LUID
$Sessions += $LUID
}
return $sessions
}
Write-Host "WARNING: This script will purge all cached Kerberos tickets on the local computer for all sessions (whether interactive, network or other sessions)." -backgroundcolor Red
Write-Host "In a well-connected environment clients will request and obtain Kerberos tickets on demand without interruption. If not well-connected to a domain controller (remote network) then further network resource authentication may fail or use NTLM if tickets are purged." -BackgroundColor red
Write-Host "Confirm whether to purge by entering YES"
$Response = Read-Host
if ($Response -match 'YES')
{
$sessions = GetKerbSessions
foreach ($Session in $sessions)
{
$PurgedTix = klist.exe -li $Session purge
}
Write-Host "All tickets purged!" -backgroundcolor green
}
else
{
Write-Host "Confirmation not received. NOT purging tickets." -backgroundcolor yellow
}
Thank you. Here is the output for the commands from within the container. Look like there is a trust issue?
PS C:> whoami /all
USER INFORMATION
User Name SID
=================================== ============
user managercontaineradministrator S-1-5-93-2-1
GROUP INFORMATION
Group Name Type SID Attributes
==================================== ================ ============ =====================================================
Mandatory LabelHigh Mandatory Level Label S-1-16-12288
Everyone Well-known group S-1-1-0 Mandatory group, Enabled by default, Enabled group
BUILTINUsers Alias S-1-5-32-545 Mandatory group, Enabled by default, Enabled group
NT AUTHORITYSERVICE Well-known group S-1-5-6 Mandatory group, Enabled by default, Enabled group
CONSOLE LOGON Well-known group S-1-2-1 Mandatory group, Enabled by default, Enabled group
NT AUTHORITYAuthenticated Users Well-known group S-1-5-11 Mandatory group, Enabled by default, Enabled group
NT AUTHORITYThis Organization Well-known group S-1-5-15 Mandatory group, Enabled by default, Enabled group
LOCAL Well-known group S-1-2-0 Mandatory group, Enabled by default, Enabled group
BUILTINAdministrators Alias S-1-5-32-544 Mandatory group, Enabled by default, Enabled group, G
roup owner
Unknown SID type S-1-5-93-0 Mandatory group, Enabled by default, Enabled group
NT AUTHORITYThis Organization Well-known group S-1-5-15 Mandatory group, Enabled by default, Enabled group
LOCAL Well-known group S-1-2-0 Mandatory group, Enabled by default, Enabled group
BUILTINAdministrators Alias S-1-5-32-544 Mandatory group, Enabled by default, Enabled group,
roup owner G
Unknown SID type S-1-5-93-0 Mandatory group, Enabled by default, Enabled group
PRIVILEGES INFORMATION
Privilege Name Description State
========================================= ================================================================== ========
SeIncreaseQuotaPrivilege Adjust memory quotas for a process Disabled
SeSecurityPrivilege Manage auditing and security log Disabled
SeTakeOwnershipPrivilege Take ownership of files or other objects Disabled
SeLoadDriverPrivilege Load and unload device drivers Disabled
SeSystemProfilePrivilege Profile system performance Disabled
SeSystemtimePrivilege Change the system time Disabled
SeProfileSingleProcessPrivilege Profile single process Disabled
SeIncreaseBasePriorityPrivilege Increase scheduling priority Disabled
SeCreatePagefilePrivilege Create a pagefile Disabled
SeBackupPrivilege Back up files and directories Disabled
SeRestorePrivilege Restore files and directories Disabled
SeShutdownPrivilege Shut down the system Disabled
SeDebugPrivilege Debug programs Enabled
SeSystemEnvironmentPrivilege Modify firmware environment values Disabled
SeChangeNotifyPrivilege Bypass traverse checking Enabled
SeRemoteShutdownPrivilege Force shutdown from a remote system Disabled
SeUndockPrivilege Remove computer from docking station Disabled
SeManageVolumePrivilege Perform volume maintenance tasks Disabled
SeImpersonatePrivilege Impersonate a client after authentication Enabled
SeCreateGlobalPrivilege Create global objects Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set Disabled
SeTimeZonePrivilege Change the time zone Disabled
SeCreateSymbolicLinkPrivilege Create symbolic links Disabled
SeDelegateSessionUserImpersonatePrivilege Obtain an impersonation token for another user in the same session Disabled
USER CLAIMS INFORMATION
User claims unknown.
Kerberos support for Dynamic Access Control on this device has been disabled.
PS C:> klist get ldap/contoso.com
Current LogonId is 0:0xe34097
Error calling API LsaCallAuthenticationPackage (GetTicket substatus): 0x6fb
klist failed with 0xc000018b/-1073741429: The SAM database on the Windows Server does not have a computer account for th
is workstation trust relationship.
I am trying to and failing to authenticate my Kerberos credentials when doing ssh from a Windows 11 client joined to a Windows Server 2019 domain (let’s call it AD.LOCAL
) to a Linux host joined to a domain managed by FreeIPA (let’s call it IPA.LOCAL
).
I already have the trust relationship established as «Forest» trust, and to break down the issues I verified that if I change the client (to Linux), or the destination (to a host on the same domain) it works.
To demonstrate the problem, the command output is trimmed for brevity and the host and IPs anonymized.
❌ From Windows to IPA host:
PS C:Usersuser> ssh -v -K -l user@ad.local host02.ipa.local
OpenSSH_for_Windows_8.1p1, LibreSSL 3.0.2
...
debug1: Authenticating to host02.ipa.local:22 as 'user@ad.local'
...
debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic,password,keyboard-interactive
debug1: Next authentication method: gssapi-with-mic
debug1: GSS_S_FAILURE
debug1: Next authentication method: publickey
...
✅ From Windows to AD host:
PS C:Usersuser> ssh -v -K -l user@ad.local host01.ad.local
OpenSSH_for_Windows_8.1p1, LibreSSL 3.0.2
...
debug1: Authenticating to host01.ad.local:22 as 'user@ad.local'
...
debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic,password,keyboard-interactive
debug1: Next authentication method: gssapi-with-mic
debug1: Delegating credentials
debug1: sspi delegation was requested but not fulfilled
debug1: Delegating credentials
debug1: sspi delegation was requested but not fulfilled
debug1: Authentication succeeded (gssapi-with-mic).
Authenticated to host01.ad.local ([192.168.0.62]:22).
...
✅ From Linux to IPA host:
$ ssh -v -K -l user@ad.local host02.ipa.local
OpenSSH_8.0p1, OpenSSL 1.1.1k FIPS 25 Mar 2021
...
debug1: Authenticating to host02.ipa.local:22 as 'user@ad.local'
...
debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic,password,keyboard-interactive
debug1: Next authentication method: gssapi-with-mic
debug1: Delegating credentials
debug1: Delegating credentials
debug1: Authentication succeeded (gssapi-with-mic).
Authenticated to host02.ipa.local ([192.168.0.181]:22).
...
✅ From Linux to AD host:
$ ssh -v -K -l user@ad.local host01.ad.local
OpenSSH_8.0p1, OpenSSL 1.1.1k FIPS 25 Mar 2021
...
debug1: Authenticating to host01.ad.local:22 as 'user@ad.local'
...
debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic,password,keyboard-interactive
debug1: Next authentication method: gssapi-with-mic
debug1: Delegating credentials
debug1: Delegating credentials
debug1: Authentication succeeded (gssapi-with-mic).
Authenticated to host01.ad.local ([192.168.0.62]:22).
...
My tickets after running the above commands:
Windows ticket:
PS C:Usersuser> klist
Current LogonId is 0:0xe934d3
Cached Tickets: (2)
#0> Client: user @ AD.LOCAL
Server: krbtgt/AD.LOCAL @ AD.LOCAL
KerbTicket Encryption Type: RSADSI RC4-HMAC(NT)
Ticket Flags 0x40e10000 -> forwardable renewable initial pre_authent name_canonicalize
Start Time: 6/17/2022 14:55:54 (local)
End Time: 6/18/2022 0:55:54 (local)
Renew Time: 6/24/2022 14:55:54 (local)
Session Key Type: AES-256-CTS-HMAC-SHA1-96
Cache Flags: 0x1 -> PRIMARY
Kdc Called: dc02.ad.local
#1> Client: user @ AD.LOCAL
Server: host/host01.ad.local @ AD.LOCAL
KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
Ticket Flags 0x40a10000 -> forwardable renewable pre_authent name_canonicalize
Start Time: 6/17/2022 14:55:54 (local)
End Time: 6/18/2022 0:55:54 (local)
Renew Time: 6/24/2022 14:55:54 (local)
Session Key Type: AES-256-CTS-HMAC-SHA1-96
Cache Flags: 0
Kdc Called: dc02.ad.local
Linux ticket:
$ klist
Ticket cache: KEYRING:persistent:1000:1000
Default principal: user@AD.LOCAL
Valid starting Expires Service principal
06/17/2022 14:31:40 06/18/2022 00:30:36 host/host02.ipa.local@
renew until 06/18/2022 14:30:34
Ticket server: host/host02.ipa.local@IPA.LOCAL
06/17/2022 14:31:39 06/18/2022 00:30:36 krbtgt/IPA.LOCAL@AD.LOCAL
renew until 06/18/2022 14:30:34
06/17/2022 14:31:09 06/18/2022 00:30:36 host/host01.ad.local@
renew until 06/18/2022 14:30:34
Ticket server: host/host01.ad.local@AD.LOCAL
06/17/2022 14:30:36 06/18/2022 00:30:36 krbtgt/AD.LOCAL@AD.LOCAL
renew until 06/18/2022 14:30:34
And for completeness, I have nothing of interest in /etc/krb5.conf
on the Linux box, I intentionally commented out pretty much everything.
$ grep -v # /etc/krb5.conf
[libdefaults]
default_ccache_name = KEYRING:persistent:%{uid}
OS versions
Windows client:
PS C:Usersuser> cmd /c ver
Microsoft Windows [Version 10.0.22000.675]
Linux client:
$ lsb_release -a
LSB Version: :core-4.1-amd64:core-4.1-noarch
Distributor ID: Rocky
Description: Rocky Linux release 8.6 (Green Obsidian)
Release: 8.6
Codename: GreenObsidian
Update to answer questions in a comment:
Windows client:
$ klist get host/host02.ipa.local
Current LogonId is 0:0xe934d3
Error calling API LsaCallAuthenticationPackage (GetTicket substatus): 0x6fb
klist failed with 0xc000018b/-1073741429: The SAM database on the Windows Server does not have a computer account for this workstation trust relationship.
Note: The trust is configured as «External» type.
Linux client does not have sssd installed at all.
$ rpm -qa sss* | grep . ; echo $?
1
But for completeness:
$ env SSSD_KRB5_LOCATOR_DISABLE=1 kvno host/host02.ipa.local
kvno: Configuration file does not specify default realm while parsing principal name host/host02.ipa.local
Now, this makes me think that the Linux client tools simply behave differently in respect to resolving hostname credentials. E.g., the following command, when told that the wanted credential is a hostname, it succeeds and it goes gets a krbtgt
for IPA.LOCAL from AD.LOCAL, then goes to the IPA.LOCAL servers to get the ticket:
$ env SSSD_KRB5_LOCATOR_DISABLE=1 kvno -S host host02.ipa.local
host/host02.ipa.local@: kvno = 1
$ klist
Ticket cache: KEYRING:persistent:1000:1000
Default principal: user@AD.LOCAL
Valid starting Expires Service principal
06/20/2022 11:57:32 06/20/2022 21:56:38 host/host02.ipa.local@
renew until 06/21/2022 11:56:34
Ticket server: host/host02.ipa.local@IPA.LOCAL
06/20/2022 11:57:32 06/20/2022 21:56:38 krbtgt/IPA.LOCAL@AD.LOCAL
renew until 06/21/2022 11:56:34
06/20/2022 11:56:38 06/20/2022 21:56:38 krbtgt/AD.LOCAL@AD.LOCAL
renew until 06/21/2022 11:56:34
P.S. Updated the description as we upgraded the trust from «External» type to «Forest» type. Still the same problem.
SQL Server connectivity, Kerberos authentication and SQL Server SPN (SQL Server Service Principal Name )
Most of you would already be aware of Kerberos authentication in SQL Server (http://technet.microsoft.com/en-us/library/cc280744%28v=sql.105%29.aspx) It is mandate for delegation and highly secured method for client server authentication.
Connection failures caused by Kerberos authentication issues drives majority of questions in MSDN and other SQL Server forums. Some of the common errors you would get when Kerberos authentication fails include.
{
Cannot generate SSPI context
login failed for user NT Authority Anonymous
Login failed for user ‘NT AUTHORITYANONYMOUS LOGON’. (Microsoft SQL Server, Error: 18456)
Login failed for user ‘(null)’
Login failed for user ”
Login failed. The login is from an untrusted domain and cannot be used with Windows authentication.
Linked server connections failing
SSPI handshake failed with error code 0x80090311 while establishing a connection with integrated security; the connection has been closed
SSPI handshake failed with error code 0x80090304 while establishing a connection with integrated security; the connection has been closed
Note: For the last two errors error code translates to
Error -2146893039 (0x80090311): No authority could be contacted for authentication
Error -2146893052 (0x80090304): The Local Security Authority cannot be contacted
So it is pretty much clear that if you get last two errors then it means secure session could not be established with you domain controller. So you can use nltest /SC_QUERY:YourDomainName to check the domain connection status.
You will also see below event from netlogon session in system event log when your SQL Server connection fails with last two errors in the above list
Log Name: System
Source: NETLOGON
Event ID: 5719
Task Category: None
Level: Error
Keywords: Classic
User: N/A
Computer: client.Contoso.com
Description: This computer was not able to set up a secure session with a domain controller in domain CONTOSO due to the following:
There are currently no logon servers available to service the logon request.
This may lead to authentication problems. Make sure that this computer is connected to the network. If the problem persists, please contact your domain administrator.
}
Before we jump into troubleshooting Connection failures caused by Kerberos authentication let see how to force SQL Server to use Named pipes protocol when you get above errors and workaround the problem till you fix the Kerberos authentication with TCP/IP. To force SQL Server to use NP protocol you can use any one of the below methods.
1. Prefix the SQL Server instance name with np: Ex: If your server name is MssqlwikiInstance1 , modify the connection string to np: MssqlwikiInstance1
2. Change the order of client protocols and bring Named pipes before the TCP/IP protocol (SQL Server configuration manager -> SQL Server native client configuration -> Client protocols -> Order – >Bring Named pipes above TCP/IP)
Note: You have to do the change both in 32-Bit and 64-Bit SQL Server native client configuration in your client systems.
3. Create a named pipe Alias
When you get Kerberos authentications errors or if you notice SQL Server is failing back to NTLM authentication you can follow below steps to troubleshoot Kerberos failures.
1. How to check If SQL Server is suing Kerberos authentication?
SELECT net_transport, auth_scheme FROM sys.dm_exec_connections WHERE session_id = @@spid
For the Kerberos authentication to work in SQL Server, SPN (Service principal name) has to be registered for SQL Server service. SPN is automatically registered by SQL Server using the startup account of SQL Server when SQL Server starts and deregistered when SQL Server is stopped. Kerberos authentication would fail when the SPN is not registered (or) when there is duplicate SPN’s registered in Active directory (or) client system is not able to get the Kerberos ticket (or) DNS is not configured properly.
2. How to Check if SPN’s are successfully registered in the active directory?
When SPN’s is registered in active directory during the startup of SQL Server by startup account of SQL Server, a message similar to one below is logged in SQL Server error log.
2013-12-05 22:21:47.030 Server The SQL Server Network Interface library successfully registered the Service Principal Name (SPN) [ MSSQLSvc/node2.mssqlwiki.com ] for the SQL Server service.
2013-12-05 22:21:47.030 Server The SQL Server Network Interface library successfully registered the Service Principal Name (SPN) [ MSSQLSvc/node2.mssqlwiki.com:1433 ] for the SQL Server service.
When SQL Server could not register SPN’s during the startup below error message is logged in SQL Server error log?
Server The SQL Server Network Interface library could not register the Service Principal Name (SPN) [ MSSQLSvc/node2.mssqlwiki.com ] for the SQL Server service. Windows return code: 0xffffffff, state: 53. Failure to register a SPN might cause integrated authentication to use NTLM instead of Kerberos. This is an informational message. Further action is only required if Kerberos authentication is required by authentication policies and if the SPN has not been manually registered.
Server The SQL Server Network Interface library could not register the Service Principal Name (SPN) [ MSSQLSvc/node2.mssqlwiki.com:1433 ] for the SQL Server service. Windows return code: 0xffffffff, state: 53. Failure to register a SPN might cause integrated authentication to use NTLM instead of Kerberos. This is an informational message. Further action is only required if Kerberos authentication is required by authentication policies and if the SPN has not been manually registered.
3. I see SQL Server could not register SPN error message in SQL Server errorlog. How do I make SQL Server register SPN’s automatically?
If your Domain controller is windows2008R2 or lower grant Read servicePrincipalName and Write servicePrincipalName privilege for startup account of SQL Server using ADSIEDIT.msc tool
Launch the ADSI Edit -> Domain -> DC=DCNAME,DC=com -> CN=Users -> CN=SQLServer_ServiceAccount -> Properties -> security tab-> advanced ->Add self -> Edit ->in permissions ->Click properties -> grant ->Read servicePrincipalName and -> Write servicePrincipalName
If your domain controller is Windows2012 grant Validate write to service principal name for startup account of SQL Server using Active directory user and computers snap in
4. From SQL Server error log I see SPN’s are registered successfully but still Kerberos authentication is failing. What is next?
Check if there are duplicate SPN’s registered in Ad using the LDIFDE tool. Below query will fetch all the SQL Server SPN’s from active directory and print in c:tempspnlist.txt.
Ldifde -f c:tempspnlist.txt -s YourDomainName -t 3268 -d «» -r «(serviceprincipalname= MSSQLSvc/*)»
Search for duplicate SPN in the output file (spnlist.txt). In our case SPN name is MSSQLSvc/node2.mssqlwiki.com:1433 .So if there are more than one entry in the output file for MSSQLSvc/node2.mssqlwiki.com:1433 then there is a duplicate SPN’s which has to be deleted.
5. How do I identify which SPN is duplicate?
In the output of the LDIFDE you will find the SAM accountName which registered the SPN, just above the ServicePrincipalName (Refer the sample below). If the SAM account is not the startup account of SQL Server then it as duplicate SPN.
{
sAMAccountName: NODE2$
sAMAccountType: 805306369
dNSHostName: NODE2.mssqlwiki.com
servicePrincipalName: MSSQLSvc/node2.mssqlwiki.com
servicePrincipalName: MSSQLSvc/node2.mssqlwiki.com:1433
}
6. There is a duplicate SPN in active directory how do I delete?
Use the setspn tool
Syntax: Setspn -D «MSSQLSvc/FQDN:port» «SAMAccount name which has duplicate SPN «
Setspn -D » MSSQLSvc/node2.mssqlwiki.com:1433″ «DOMAINAccountname»
7. SPN’s are registered properly, there is no duplicate SPN but still the Kerberos authentication is not working ?
Run the KLIST exe from the client and check if it is able to get the ticket
Example:
Klist get MSSQLSvc/node2.mssqlwiki.com:1433
If the client is able to get the ticket then you should see a output similar to one below
{
c:WindowsSystem32>Klist get MSSQLSvc/node2.mssqlwiki.com:1433
Current LogonId is 0:0x2de9f6
A ticket to MSSQLSvc/node2.mssqlwiki.com:1433 has been retrieved successfully.
Cached Tickets: (10)
}
If the client is unable to get the ticket then you should see an error similar to one below.
{
c:WindowsSystem32>Klist get MSSQLSvc/node2.mssqlwiki.com:1433
Current LogonId is 0:0x2de9f6
Error calling API LsaCallAuthenticationPackage (GetTicket substatus): 0x6fb
klist failed with 0xc000018b/-1073741429: The SAM database on the Windows Server
does not have a computer account for this workstation trust relationship.
}
If the client is unable to get the ticket check if it not able to retrieve the ticket only the ticket for SQL Server (or) not able to get any tickets. You can use below commands
Klist get Host/FQDN of DC where SQLServer is installed
Klist get Host/FQDN of SQLServer Machine name
If all the tickets are failing then most probably the issue should be with DNS/Network setting, you can troubleshoot further based on the error you receive from klist or collect Netmon traces to troubleshoot further.
8. If the client is able to get the ticket and still Kerberos authentication fails?
Ping the SQL Server name and IP address (with –a ) and identify if it is able to resolved to fully qualified name DNS name, If it is not able to resolve to FQDN of SQL Server then fix the DNS settings
9. How to Collect Netmon traces and identify Kerberos authentication failure?
Wait for my next blog
If you liked this post, do like us on Facebook at https://www.facebook.com/mssqlwiki and join our Facebook group
Thank you,
Karthick P.K |My Facebook Page |My Site| Blog space| Twitter
Disclaimer:
The views expressed on this website/blog are mine alone and do not reflect the views of my company or anyone else. All postings on this blog are provided “AS IS” with no warranties, and confers no rights
Comments
The xplat NegotiateStream implementation is able to successfully use Kerberos auth when the target of AuthenticateAsClientAsync
is a service principal eg. HOST/machine, HTTP@machine etc. However, if the target is a user like foo@domainfqdn, the auth is failing. Perhaps in this case, the gss_import_name
needs to be called with some OID other than GSS_KRB5_NT_PRINCIPAL_NAME
Awesome, thanks @vijaykota.
Should we also be considering whether or not to translate the domain part of the UPN into uppercase as well? In our testing, we have found that the UPN must be in uppercase for the scenario to work.
Not sure if that would be a safe operation though.
Copy link
Contributor
Author
Translation of domain would not be safe since the Linux default is to be case-sensitive.
This seems like a complex issue to solve on Linux:
kinit -S $user $user
foo@DOMAIN.CORP.MICROSOFT.COM's Password:
kinit: krb5_get_init_creds: Server (foo@DOMAIN.CORP.MICROSOFT.COM) unknown
On a Windows server I see failure like:
e:>klist get %user%
Current LogonId is 0:0x28e0ff
Error calling API LsaCallAuthenticationPackage (GetTicket substatus): 0x52e
klist failed with 0xc0000408/-1073740792: Kerberos sub-protocol User2User is required.
But Windows NegotiateStream is able to successfully get a ticket.
Copy link
Contributor
Author
Looks like this requires User2User protocol support. We need to figure out if the MIT Kerberos implementation has this support
The scenario seems to be rather corner-case.
@zhenlan @mconnew is it something you guys use in WCF?
User2User protocol support is unlikely to be needed in cloud scenarios.
User-to-user authentication is a special Kerberos application protocol, that allows users to host secure application services on their desktop machines. It is increasingly common for users to offer desktop services that merit secure authentication, such as nfs and ftp. When users configure their desktop servers with a long-lived srvtab key, this long-lived key becomes a very attractive target for theft. User-to-user authentication enables a user to run a server without keeping a long-lived key on disk. Instead, the user’s short-lived TGS session-key takes the place of the usual srvtab secret key, in the server’s authentication handshakes.
Closing this for now until we get more customer feedback.
I just saw this issue. This is a scenario that WCF uses quite extensively and is NOT a corner case for us. If you run a server as non-system (ie self-hosted), then you must use a non-default service identity. As configurating a custom SPN requires additional domain permissions and isn’t very friendly for quickly setting something up, most users will use a UPN instead.
Edit:
This issue is also related to issue dotnet/corefx#27745. Once WCF is able to set a custom SPN, we will be able to be a client to console hosted WCF servers using Windows auth. This is a broken scenario for us right now and have been waiting several years for this support. Once issue dotnet/corefx#27745 has be completed, this issue will affect HTTP Negotiate authentication too.
This is a scenario that WCF uses quite extensively and is NOT a corner case for us. If you run a server as non-system (ie self-hosted), then you must use a non-default service identity. As configurating a custom SPN requires additional domain permissions and isn’t very friendly for quickly setting something up, most users will use a UPN instead.
.NET Core doesn’t support NegotiateStream as a server on Linux. So, are you referring to a scenario where NegotiateStream (acting as a server) is being used on a Windows machine? And your requirement is that Linux clients be able to connect to it?
@davidsh, that is exactly the case. Linux client connecting to a Windows WCF service.
davidsh
referenced
this issue
in davidsh/runtime
Dec 3, 2019
msftgits
transferred this issue from dotnet/corefx
Jan 31, 2020
Microsoft уже предоставляет для этого набор скриптов. Таким образом, вам не нужно писать это с нуля. Просмотр и очистка кэшированных билетов Kerberos и да, у них есть klist в миксе. В противном случае вы закончите тем, что попытаетесь использовать…
[System.Security.Principal.WindowsIdentity]
… а затем выполнять переводы SID и тому подобное, или вы в конечном итоге перейдете к тому же обсуждению в этом разделе вопросов и ответов.
Как программно очистить кеш билетов Kerberos
Или использовать эти ресурсы и настраивать по мере необходимости.
Модуль Kerberos
Модуль предоставляет доступ к кешу билетов Kerberos. Он может считывать и очищать билеты текущего сеанса входа в систему.
Валидатор управляемого кода для билетов Kerberos
The Point of Kerberos.NET is to make Kerberos much easier to work with
in such scenarios. This is done by removing any hard dependencies on
Windows and moving all ticket processing to the application itself.
This of course means you don’t need the application to be on a
domain-joined machine, and it probably doesn’t need to be on Windows
either.Install-Package Kerberos.NET
Using the Library
Ticket authentication occurs in two stages. The first stage validates
the ticket for correctness via an IKerberosValidator with a default
implementation of KerberosValidator. The second stage involves
converting the ticket in to a usable ClaimsIdentity, which occurs in
the KerberosAuthenticator.The easiest way to get started is to create a new
KerberosAuthenticator and calling Authenticate. If you need to tweak
the behavior of the conversion, you can do so by overriding the
ConvertTicket(DecryptedData data) method.var authenticator = new KerberosAuthenticator(new KeyTable(File.ReadAllBytes(«sample.keytab»)));
var identity = authenticator.Authenticate(«YIIHCAYGKwYBBQUCoIIG…»);
Assert.IsNotNull(identity);
var name = identity.Name;
Assert.IsFalse(string.IsNullOrWhitespace(name));
Note that the constructor parameter for the authenticator is a
KeyTable. The KeyTable is a common format used to store keys on other
platforms. You can either use a file created by a tool like ktpass, or
you can just pass a KerberosKey during instantiation and it’ll have
the same effect.
Список всех кэшированных билетов Kerberos
При администрировании или устранении неполадок проверки подлинности в домене бывают случаи, когда вам необходимо знать, кэшируются ли на компьютере билеты для пользователя и службы. Этот сценарий экспортирует все кэшированные билеты пользователя на компьютере в текстовый файл для просмотра.
Скачать : GetKerbTix.ps1
Очистить все билеты Kerberos
Бывают ситуации, когда администратору может потребоваться очистить кэшированные билеты Kerberos на сервере. Например, пользователь Боб покинул компанию. В подобных ситуациях вы можете запустить этот сценарий, чтобы очистить все кэшированные билеты Kerberos и TGT для всех сеансов на компьютере.
Скачать : PurgeAllKerbTickets.ps1
#************************************************
# GetKerbTix.ps1
# Version 1.0
# Date: 6-11-2014
# Author: Tim Springston [MSFT]
# Description: On a specific computer the script is ran on,
# this script finds all logon sessions which have Kerberos
# tickets cached and enumerates the tickets and any ticket granting tickets.
# The tickets may be from remote or interactive users and may be
# any logon type session (network, batch, interactive, remote interactive...).
# This script will run on Windows Server 2008/Vista and later.
#************************************************
cls
$FormatEnumerationLimit = -1
$ComputerName = $env:COMPUTERNAME
$UserName = [Security.Principal.WindowsIdentity]::GetCurrent().name
$ComputerDomain = [System.DirectoryServices.ActiveDirectory.Domain]::GetComputerDomain().name
$Date = Get-Date
#Prepare an output file to place info into.
$ExportFile = "C:windowstemp" + $ComputerName + "_CachedKerberosTickets.txt"
"Cached Kerberos Tickets" | Out-File $ExportFile -Encoding utf8
"Logged on User:$UserName" | Out-File $ExportFile -Append -Encoding utf8
"Computer name: $ComputerName" | Out-File $ExportFile -Append -Encoding utf8
"Computer Domain: $ComputerDomain" | Out-File $ExportFile -Append -Encoding utf8
"Date: $Date" | Out-File $ExportFile -Append -Encoding utf8
"************************************" | Out-File $ExportFile -Append -Encoding utf8
function GetKerbSessions
{
$Sessions = @()
$WMILogonSessions = gwmi win32_LogonSession
foreach ($WMILogonSession in $WMILogonSessions)
{
$LUID = [Convert]::ToString($WMILogonSession.LogonID, 16)
$LUID = '0x' + $LUID
$Sessions += $LUID
}
return $sessions
}
function GetKerbSessionInfo
{
$OS = gwmi win32_operatingsystem
$sessions = New-Object PSObject
if ($OS.Buildnumber -ge 9200)
{
$KlistSessions = klist sessions
$Counter = 0
foreach ($item in $KlistSessions)
{
if ($item -match "^[.*]")
{
$LogonId = $item.split(' ')[3]
$LogonId = $LogonId.Replace('0:','')
$Identity = $item.split(' ')[4]
$Token5 = $item.Split(' ')[5]
$AuthnMethod = $Token5.Split(':')[0]
$LogonType = $Token5.Split(':')[1]
$Session = New-Object PSObject
Add-Member -InputObject $Session -MemberType NoteProperty -Name "SessionID" -Value $LogonId
Add-Member -InputObject $Session -MemberType NoteProperty -Name "Identity" -Value $Identity
Add-Member -InputObject $Session -MemberType NoteProperty -Name "Authentication Method" -Value $AuthnMethod
Add-Member -InputObject $Session -MemberType NoteProperty -Name "Logon Type" -Value $LogonType
Add-Member -InputObject $sessions -MemberType NoteProperty -Name $LogonId -Value $Session
$Session = $null
}
}
}
if ($OS.Buildnumber -lt 9200)
{
$WMILogonSessions = gwmi win32_LogonSession
foreach ($WMILogonSession in $WMILogonSessions)
{
$LUID = [Convert]::ToString($WMILogonSession.LogonID, 16)
$LUID = '0x' + $LUID
$Session = New-Object PSObject
Add-Member -InputObject $Session -MemberType NoteProperty -Name "SessionID" -Value $LUID
Add-Member -InputObject $Session -MemberType NoteProperty -Name "Identity" -Value "Not available"
Add-Member -InputObject $Session -MemberType NoteProperty -Name "Authentication Method" -Value $WMILogonSession.AuthenticationPackage
Add-Member -InputObject $Session -MemberType NoteProperty -Name "Logon Type" -Value $WMILogonSession.LogonType
Add-Member -InputObject $sessions -MemberType NoteProperty -Name $LUID -Value $Session
$Session = $null
}
}
return $sessions
}
function ReturnSessionTGTs
{
param ($SessionID = $null)
if ($SessionID -eq $null)
{
$RawTGT = klist.exe tgt
}
else
{
$RawTGT = klist.exe tgt -li $sessionID
}
$TGT = @()
foreach ($Line in $RawTGT)
{
if ($Line.length -ge 1)
{
$TGT += $Line
}
}
if ($TGT -contains 'Error calling API LsaCallAuthenticationPackage (Ticket Granting Ticket substatus): 1312')
{$TGT = 'No ticket granting ticket cached in session.'}
return $TGT
}
function ReturnSessionTickets
{
param ($SessionID = $null)
$OS = gwmi win32_operatingsystem
if ($SessionID -eq $null)
{
$TicketsArray = klist.exe tickets
}
else
{
$TicketsArray = klist.exe tickets -li $sessionID
}
$Counter = 0
$TicketsObject = New-Object PSObject
foreach ($line in $TicketsArray)
{
if ($line -match "^#d")
{
$Ticket = New-Object PSObject
$Number = $Line.Split('>')[0]
$Line1 = $Line.Split('>')[1]
$TicketNumber = "Ticket " + $Number
$Client = $Line1 ; $Client = $Client.Replace('Client:','') ; $Client = $Client.Substring(2)
$Server = $TicketsArray[$Counter+1]; $Server = $Server.Replace('Server:','') ;$Server = $Server.substring(2)
$KerbTicketEType = $TicketsArray[$Counter+2];$KerbTicketEType = $KerbTicketEType.Replace('KerbTicket Encryption Type:','');$KerbTicketEType = $KerbTicketEType.substring(2)
$TickFlags = $TicketsArray[$Counter+3];$TickFlags = $TickFlags.Replace('Ticket Flags','');$TickFlags = $TickFlags.substring(2)
$StartTime = $TicketsArray[$Counter+4];$StartTime = $StartTime.Replace('Start Time:','');$StartTime = $StartTime.substring(2)
$EndTime = $TicketsArray[$Counter+5];$EndTime = $EndTime.Replace('End Time:','');$EndTime = $EndTime.substring(4)
$RenewTime = $TicketsArray[$Counter+6];$RenewTime = $RenewTime.Replace('Renew Time:','');$RenewTime = $RenewTime.substring(2)
$SessionKey = $TicketsArray[$Counter+7];$SessionKey = $SessionKey.Replace('Session Key Type:','');$SessionKey = $SessionKey.substring(2)
Add-Member -InputObject $Ticket -MemberType NoteProperty -Name "Client" -Value $Client
Add-Member -InputObject $Ticket -MemberType NoteProperty -Name "Server" -Value $Server
Add-Member -InputObject $Ticket -MemberType NoteProperty -Name "KerbTicket Encryption Type" -Value $KerbTicketEType
Add-Member -InputObject $Ticket -MemberType NoteProperty -Name "Ticket Flags" -Value $TickFlags
Add-Member -InputObject $Ticket -MemberType NoteProperty -Name "Start Time" -Value $StartTime
Add-Member -InputObject $Ticket -MemberType NoteProperty -Name "End Time" -Value $EndTime
Add-Member -InputObject $Ticket -MemberType NoteProperty -Name "Renew Time" -Value $RenewTime
Add-Member -InputObject $Ticket -MemberType NoteProperty -Name "Session Key Type" -Value $SessionKey
if ($OS.BuildNumber -ge 9200)
{
$CacheFlags = $TicketsArray[$Counter+8];$CacheFlags = $CacheFlags.Replace('Cache Flags:','');$CacheFlags = $CacheFlags.substring(2)
$KDCCalled = $TicketsArray[$Counter+9];$KDCCalled = $KDCCalled.Replace('Kdc Called:','');$KDCCalled = $KDCCalled.substring(2)
Add-Member -InputObject $Ticket -MemberType NoteProperty -Name "Cache Flags" -Value $CacheFlags
Add-Member -InputObject $Ticket -MemberType NoteProperty -Name "KDC Called" -Value $KDCCalled
}
Add-Member -InputObject $TicketsObject -MemberType NoteProperty -Name $TicketNumber -Value $Ticket
$Ticket = $null
}
$Counter++
}
return $TicketsObject
}
$OS = gwmi win32_operatingsystem
$sessions = getkerbsessions
$sessioninfo = GetKerbSessionInfo
foreach ($Session in $sessions)
{
#Get Session details as well
$currentsessioninfo = $sessioninfo.$session
$ID = $currentsessioninfo.identity
$SessionID = $currentsessioninfo.SessionID
$LogonType = $currentsessioninfo.'Logon Type'
$AuthMethod = $currentsessioninfo.'Authentication Method'
if ($OS.Buildnumber -lt 9200)
{
Write-Host "Kerberos Tickets for LogonID $SessionID"
"Kerberos Tickets for LogonID $SessionID" | Out-File $ExportFile -Append -Encoding utf8
}
else
{
Write-Host "Kerberos Tickets for $ID"
"Kerberos Tickets for $ID" | Out-File $ExportFile -Append -Encoding utf8
}
Write-Host "*****************************"
"*****************************" | Out-File $ExportFile -Append -Encoding utf8
Write-Host "Logon Type: $LogonType"
"Logon Type: $LogonType" | Out-File $ExportFile -Append -Encoding utf8
Write-host "Session ID: $SessionID"
"Session ID: $SessionID" | Out-File $ExportFile -Append -Encoding utf8
Write-host "Auth Method: $AuthMethod"
"Auth Method: $AuthMethod" | Out-File $ExportFile -Append -Encoding utf8
$SessionTickets = ReturnSessionTickets $Session
$TGT = ReturnSessionTGTs $SessionID
$TGT | FL *
$TGT | Out-File $ExportFile -Append -Encoding utf8
if ($SessionTickets -notmatch 'Ticket')
{
Write-Host "Session TGT: No tickets for this session in cache."
"Session TGT: No tickets for this session in cache." | Out-File $ExportFile -Append -Encoding utf8
}
else
{
$SessionTickets | FL *
$SessionTickets | Out-File $ExportFile -Append -Encoding utf8
}
Write-Host "`n"
"`n" | Out-File $ExportFile -Append -Encoding utf8
}
#************************************************
# PurgeAllKerbTickets.ps1
# Version 1.0
# Date: 6-12-2014
# Author: Tim Springston [MSFT]
# Description: On a specific computer the script is ran on,
# this script finds all logon sessions which have Kerberos
# tickets cached and for each session purges the ticket granting
# tickets and the tickets using klist.exe.
#************************************************
cls
function GetKerbSessions
{
$Sessions = @()
$WMILogonSessions = gwmi win32_LogonSession
foreach ($WMILogonSession in $WMILogonSessions)
{
$LUID = [Convert]::ToString($WMILogonSession.LogonID, 16)
$LUID = '0x' + $LUID
$Sessions += $LUID
}
return $sessions
}
Write-Host "WARNING: This script will purge all cached Kerberos tickets on the local computer for all sessions (whether interactive, network or other sessions)." -backgroundcolor Red
Write-Host "In a well-connected environment clients will request and obtain Kerberos tickets on demand without interruption. If not well-connected to a domain controller (remote network) then further network resource authentication may fail or use NTLM if tickets are purged." -BackgroundColor red
Write-Host "Confirm whether to purge by entering YES"
$Response = Read-Host
if ($Response -match 'YES')
{
$sessions = GetKerbSessions
foreach ($Session in $sessions)
{
$PurgedTix = klist.exe -li $Session purge
}
Write-Host "All tickets purged!" -backgroundcolor green
}
else
{
Write-Host "Confirmation not received. NOT purging tickets." -backgroundcolor yellow
}