When you use the Security Support Provider Interface (SSPI) API to validate a user's credentials, the server ends up with a security context handle.
You can then use the QueryContextAttributes
function to query for information about the security context handle:
QueryContextAttributes(handle,
SECPKG_ATTR_LIFESPAN
)
- tsStart: Time at which the context was established.
- tsExpiry: Time at which the context will expire.
QueryContextAttributes(handle,
SECPKG_ATTR_AUTHORITY
)
- sAuthorityName: the name of the authenticating authority, if available.
QueryContextAttributes(handle,
SECPKG_ATTR_PASSWORD_EXPIRY
)
- tsPasswordExpires: when the credentials for the security context expire.
QueryContextAttributes(handle,
SECPKG_ATTR_PACKAGE_INFO
)
- Name: the name of the security package.
- Comment: This can be any additional string passed back by the package.
QueryContextAttributes(handle,
SECPKG_ATTR_NATIVE_NAMES
)
- sClientName: the principal name for the client in the outbound ticket.
- sServerName: the principal name for the server in the outbound ticket
QueryContextAttributes(handle,
SECPKG_ATTR_CLIENT_SPECIFIED_TARGET
)
- sTargetName: The SPN of the initial target.
When i use SSPI to validate my credentials, the server gets a set of information about me, one of the items fails:
- Context Handle:
0x04CC9F4000AC8B80
- Username:
STACKOVERFLOW\ian
- Native Client Name:
ian@STACKOVERFLOW.COM
- Native Server Name:
ian@STACKOVERFLOW.COM
- User SID:
S-1-5-21-1708537768-844245398-2146844275-1109
- Client Specified Target:
ian
- Authority:
The function requested is not supported (80090302)
- Password Expires (UTC):
- Lifespan Start:
10/23/2019 11:03 ᴀᴍ
- Lifespan Expiry:
10/23/2019 7:32 ᴘᴍ
- Package Name:
Kerberos
- Package Comment:
Microsoft Kerberos V1.0
- Package Capabilities:
0x028F3BBF
- Package Version:
0001
- Package Rpc ID:
0010
- Package Max Token Length:
48000
Credential authority
I want to know the authority who validated (or vouched for the cached) credentials.
Except calling QueryContextAttributes (and QueryContextAttributesEx) with SECPKG_ATTR_AUTHORITY
fails with the error:
// MessageId: SEC_E_UNSUPPORTED_FUNCTION
//
// MessageText:
//
// The function requested is not supported
//
SEC_E_UNSUPPORTED_FUNCTION = HRESULT($80090302);
What's doing?
I can find it using the command line:
C:\Users\Ian>SET
LOGONSERVER=\\HYDROGEN
But i'm using APIs.
Background: How SSPI works
SSPI was designed as a generic wrapper around different security algorithms. The way to use the API is pretty simple:
- Client:
- calls
InitializeSecurityContext
and is given a blob - client sends that blob to the server
- calls
- Server:
- calls
AcceptSecurityContext(blob)
, and is given a blob back - server sends that blob back to the client
- calls
- Client:
- calls
InitializeSecurityContext(blob)
, and is given back a blob - client sends that blob back to the server
- calls
- Server:
- calls
AcceptSecurityContext(blob)
, and is given a blob back - ...keep repeating until told to stop...
- calls
Both sides keep going back and forth, until the function stops returning a blob that needs to be sent to the other side:
And so the with SSPI you do this ping-ponging back and forth until you're told to stop. And so they were able to shoe-horn every authentication scheme into that ping-pong-until-told-to-stop high level abstraction.
And how do you transmit the blobs?
You transmit the blobs over whatever communication channel you're using.
If you're talking to a remote server over TCP/IP, then you'd probably use that:
// Open connection to server
sockConnect(162.210.196.166, 1433);
blob = null;
Boolean bContinue = InitializeSecurityContext(ref blob);
while (bContinue)
{
sockWrite(blob); //send the blob to the server
blob = sockRead(); //wait for the server to return a blob
bContinue = InitializeSecurityContext(ref blob);
}
If you're doing it over http:
blob = null;
Boolean bContinue = InitializeSecurityContext(ref blob);
while (bContinue)
{
http = new HttpRequest("http://4chan.org/default.aspx");
http.AddHeader("X-SSPI-Blob", blob.ToBase64());
http.Send();
blob = http.ReasponseHeader["X-SSPI-Blob"];
if (blob.IsEmpty())
break;
bContinue = InitializeSecurityContext(ref blob);
}
You can even send them over carrier pigeon!
Bonus Reading
SSPI is the name of the Windows implementation of RFC4121
Generic Security Service Application Program Interface (GSS-API)
Bonus Bonus
- "What am i supposed to set TargetName to?: https://stackoverflow.com/a/49411527/12597