PSOpenAD
PSOpenAD copied to clipboard
gss_init_sec_context failed - Ticket expired
Hello Jordan, I'm back. After a certain amount of idle time I came back to show off your awesome module to a colleague and ran into this error.
gss_init_sec_context failed (Major Status 851968 - Unspecified GSS failure. Minor code may provide m
ore information) (Minor Status 100001 - Ticket expired)
I saw on issue 43 you said PR 45 resolved an issue where the connection timed out. I thought this might be similar. Here is the output of Get-Error
Exception :
Type : PSOpenAD.Native.GSSAPIException
MajorStatus : 851968
MinorStatus : 100001
TargetSite :
Name : InitSecContext
DeclaringType : PSOpenAD.Native.GSSAPI, PSOpenAD, Version=0.5.0.0, Culture=neutral, PublicKeyToken=null
MemberType : Method
Module : PSOpenAD.dll
Message : gss_init_sec_context failed (Major Status 851968 - Unspecified GSS failure. Minor code may provide m
ore information) (Minor Status 100001 - Ticket expired)
Source : PSOpenAD
HResult : -2146233087
StackTrace :
at PSOpenAD.Native.GSSAPI.InitSecContext(SafeGssapiCred cred, SafeGssapiSecContext context, SafeGssapiName targetNam
e, Byte[] mechType, GssapiContextFlags reqFlags, Int32 ttl, ChannelBindings chanBindings, Byte[] inputToken) in /_/src/
PSOpenAD/Native/GSSAPI.cs:line 504
at PSOpenAD.GssapiContext.Step(Byte[] inputToken) in /_/src/PSOpenAD/Authentication.cs:line 194
at PSOpenAD.Module.OpenADSessionFactory.SaslAuth(IADConnection connection, SecurityContext context, String saslMech,
Boolean integrity, Boolean confidentiality, CancellationToken cancelToken) in /_/src/PSOpenAD.Module/OpenADSessionFact
ory.cs:line 487
at PSOpenAD.Module.OpenADSessionFactory.Authenticate(IADConnection connection, Uri uri, AuthenticationMethod auth, P
SCredential credential, ChannelBindings channelBindings, Boolean transportIsTls, OpenADSessionOptions sessionOptions, C
ancellationToken cancelToken, PSCmdlet cmdlet, Boolean& signed, Boolean& encrypted) in /_/src/PSOpenAD.Module/OpenADSes
sionFactory.cs:line 423
at PSOpenAD.Module.OpenADSessionFactory.Create(Uri uri, PSCredential credential, AuthenticationMethod auth, Boolean
startTls, OpenADSessionOptions sessionOptions, CancellationToken cancelToken, PSCmdlet cmdlet) in /_/src/PSOpenAD.Modul
e/OpenADSessionFactory.cs:line 151
at PSOpenAD.Module.OpenADSessionFactory.CreateOrUseDefault(String server, PSCredential credential, AuthenticationMet
hod auth, Boolean startTls, OpenADSessionOptions sessionOptions, CancellationToken cancelToken, PSCmdlet cmdlet, Boolea
n skipCache) in /_/src/PSOpenAD.Module/OpenADSessionFactory.cs:line 84
CategoryInfo : AuthenticationError: (:) [Get-OpenADComputer], GSSAPIException
FullyQualifiedErrorId : AuthError,PSOpenAD.Module.Commands.GetOpenADComputer
InvocationInfo :
MyCommand : Get-OpenADComputer
ScriptLineNumber : 1
OffsetInLine : 1
HistoryId : 1
Line : Get-OpenADComputer | ft
Statement : Get-OpenADComputer
PositionMessage : At line:1 char:1
+ Get-OpenADComputer | ft
+ ~~~~~~~~~~~~~~~~~~
InvocationName : Get-OpenADComputer
CommandOrigin : Internal
ScriptStackTrace : at <ScriptBlock>, <No file>: line 1
PipelineIterationInfo :
Restarting powershell did not have any effect. The commands Get/New-OpenADSession
received the same error without explicit credentials. I was able to create a session with explicit credentials. The cmdlets still gave the same gss error with or without specifying the server (name/fqdn) but with explicit credentials they work fine. Restarting the ubuntu wsl app and completing shutting down wsl (wsl --shutdown
) has not made a difference. My uneducated guess is it seems the anonymous "session" is broken?
GSSAPI (in reality Kerberos here) is very susceptible to time skew but based on the error I can see 2 possible issues
- The cached Kerberos TGT in the ccache is expired, this is what would have been retrieved through
kinit
- The time on the client differs from the time on the target server or the KDC (which is likely the target server in this scenario)
Based on the error id I would say it's the first problem as I believe the error returned for the latter specifically say clock skew. Running klist
can show the expiration time of the TGT
$ klist
Ticket cache: FILE:/tmp/krb5cc_1000
Default principal: [email protected]
Valid starting Expires Service principal
28/03/24 20:36:58 29/03/24 06:36:58 krbtgt/[email protected]
renew until 29/03/24 20:36:52
28/03/24 20:37:46 29/03/24 06:36:58 ldap/dc01.domain.test@
renew until 29/03/24 20:36:52
Ticket server: ldap/[email protected]
The krbtgt/*
ticket is the TGT ticket retrieved by kinit
and is used to get the subsequent service tickets. The ldap/*
ticket is the service ticket specifically for the LDAP host that is retrieved through the TGT. If there is no service ticket for the host then gss_init_sec_context
is going to use your TGT to get that service ticket. If either are expired I would expect this error, personally I would expect if the service ticket is expired it would automatically retrieve a new one but I've never tested that assertion.
OK I'm thinking maybe I'm confused about how it should work. After successfully querying with
$cred = Get-Credential domainuser
Get-OpenADComputer -Server dc01.domain.com -Credential $cred
Then the following commands work
Get-OpenADComputer -Server dc01 -AuthType Anonymous
Get-OpenADComputer -Server dc01
Get-OpenADComputer -Server dc01.domain.com -AuthType Anonymous
Get-OpenADComputer -Server dc01.domain.com
When querying another dc, I got this error
Get-OpenADComputer: Operations error - 000004DC: LdapErr: DSID-0C090ACD, comment: In order to perform this operation a successful bind must be completed on the connection., data 0, v4563
Interestingly, this command succeeded
Get-OpenADComputer -Server dc02.domain.com -Credential $cred
While this one does not
Get-OpenADComputer -Server dc02 -Credential $cred
Afterwards these work
Get-OpenADComputer -Server dc02.domain.com
Get-OpenADComputer -Server dc02.domain.com -AuthType Anonymous
while these end with the same bind must be completed error
Get-OpenADComputer -Server dc02 -AuthType Anonymous
Get-OpenADComputer -Server dc02 -Credential $cred
Get-OpenADComputer -Server dc02
What makes the short/fqdn work with dc01 but not allow the short name to work with dc02? If it matters, currently all FSMO roles are held by dc02.
The time on the client and server are just a few seconds off, so should be good there. (I also assume the kdc is the same as the target server, but both dcs time are practically the same)
Here is the output of klist, and it does show expired.
PS /home/doug> klist
Ticket cache: FILE:/tmp/krb5cc_1000
Default principal: [email protected]
Valid starting Expires Service principal
03/26/24 16:45:11 03/27/24 02:45:11 krbtgt/[email protected]
renew until 03/27/24 16:45:07
03/26/24 20:12:59 03/27/24 02:45:11 ldap/[email protected]
renew until 03/27/24 16:45:07
If connecting back with a session/explicit credentials doesn't refresh this ticket and it doesn't refresh automatically, how can I manually refresh it? I assume you desire this to work when picked back up like the AD module does? I'm pretty sure I've seen the ad cmdlets after a certain amount of time have to start up the AD psdrive. Is there some similar functionality we can add to make this easier for noobs like me. :)
BTW I have to say, your quick responses and extreme willingness to share your knowledge across many platforms is very much appreciated.
If connecting back with a session/explicit credentials doesn't refresh this ticket and it doesn't refresh automatically, how can I manually refresh it?
If the TGT ticket (krbtgt
) is expired then there's not much I can do AFAIK. It requires the caller to either provide explicit credentials or run kinit
again to get a new TGT. If the service ticket is expired I would have hoped GSSAPI would be automatically ignoring it and getting a new one. I'll definitely have to test out this scenario a bit more to see what's happening and what I could potentially do to improve the scenario. As for cleaning existing sessions you should be able to do Get-OpenADSession | Remove-OpenADSession
to get and clear all existing sessions.
I definitely need to look into the whole session setup part a bit more. It's been a while since I've last checked how it works and how the module selects the session to use if one wasn't explicitly provided. There's definitely some more work that needs to be done there on the module side.
BTW I have to say, your quick responses and extreme willingness to share your knowledge across many platforms is very much appreciated.
Thanks, it definitely can be a bit hairy especially when it comes to Kerberos. I can also sometimes assume people have knowledge about some things here so it's nice when those assumptions are challenged. It might be information overload but if you start pwsh like KRB5_TRACE=/dev/stdout pwsh
you'll also see verbose logging from the Kerberos library. You can set it to any path if you don't want to see it on the console.