Error calling api lsacallauthenticationpackage ticket granting ticket substatus 1312

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:
  • 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): 1312

    klist 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

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)

clip_image002[4]   

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

clip_image004[4]

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.

clip_image006[4]

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.

clip_image008[4]

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

clip_image010[4]

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)

clip_image012[4]

}

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.

clip_image014[4]

}

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

@vijaykota

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

@iamjasonp

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.

@vijaykota



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.

@vijaykota



Copy link


Contributor

Author

Looks like this requires User2User protocol support. We need to figure out if the MIT Kerberos implementation has this support

@karelz

The scenario seems to be rather corner-case.
@zhenlan @mconnew is it something you guys use in WCF?

@davidsh

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.

@mconnew

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.

@davidsh

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?

@mconnew

@davidsh, that is exactly the case. Linux client connecting to a Windows WCF service.

davidsh

referenced
this issue
in davidsh/runtime

Dec 3, 2019

@davidsh

@msftgits
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
        }

Понравилась статья? Поделить с друзьями:
  • Error callback angular
  • Error call to undefined function tests feature factory
  • Error call to nonexistent function ahk
  • Error call to non static member function without an object argument
  • Error call to abs is ambiguous