Vanara/PInvoke/Security/Secur32/Sspi.cs

8008 lines
406 KiB
C#
Raw Normal View History

2018-09-30 17:37:25 -04:00
using System;
using System.Collections.Generic;
using System.Linq;
2018-09-30 17:37:25 -04:00
using System.Runtime.InteropServices;
using Vanara.Extensions;
using Vanara.InteropServices;
using static Vanara.PInvoke.AdvApi32;
using static Vanara.PInvoke.Crypt32;
using static Vanara.PInvoke.Schannel;
using TimeStamp = System.Runtime.InteropServices.ComTypes.FILETIME;
2018-09-30 17:37:25 -04:00
namespace Vanara.PInvoke
{
/// <summary>Functions and definitions from Secur32.dll</summary>
public static partial class Secur32
{
/// <summary>Undocumented.</summary>
/// <param name="Arg">Argument passed in</param>
/// <param name="Principal">Principal ID</param>
/// <param name="KeyVer">Key Version</param>
/// <param name="Key">Returned ptr to key.</param>
/// <param name="Status">returned status.</param>
[PInvokeData("sspi.h")]
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
public delegate void SEC_GET_KEY_FN(IntPtr Arg, IntPtr Principal, uint KeyVer, out IntPtr Key, out int Status);
/// <summary>Bit flags that specify the attributes required by the server to establish the context.</summary>
[PInvokeData("sspi.h", MSDNShortId = "a53f733e-b646-4431-b021-a2c446308849")]
[Flags]
public enum ASC_REQ : uint
{
/// <summary>The server is allowed to impersonate the client. Ignore this flag for constrained delegation.</summary>
ASC_REQ_DELEGATE = 0x00000001,
/// <summary>The mutual authentication policy of the service will be satisfied.</summary>
ASC_REQ_MUTUAL_AUTH = 0x00000002,
/// <summary>Detect replayed packets.</summary>
ASC_REQ_REPLAY_DETECT = 0x00000004,
/// <summary>Detect messages received out of sequence.</summary>
ASC_REQ_SEQUENCE_DETECT = 0x00000008,
/// <summary>Encrypt messages by using the EncryptMessage function.</summary>
ASC_REQ_CONFIDENTIALITY = 0x00000010,
/// <summary>A new session key must be negotiated. This value is supported only by the Kerberos security package.</summary>
ASC_REQ_USE_SESSION_KEY = 0x00000020,
2020-03-13 17:43:39 -04:00
/// <summary/>
ASC_REQ_SESSION_TICKET = 0x00000040,
/// <summary>
/// Credential Security Support Provider (CredSSP) will allocate output buffers. When you have finished using the output buffers,
/// free them by calling the FreeContextBuffer function.
/// </summary>
ASC_REQ_ALLOCATE_MEMORY = 0x00000100,
2020-03-13 17:43:39 -04:00
/// <summary/>
ASC_REQ_USE_DCE_STYLE = 0x00000200,
2020-03-13 17:43:39 -04:00
/// <summary/>
ASC_REQ_DATAGRAM = 0x00000400,
/// <summary>The security context will not handle formatting messages.</summary>
ASC_REQ_CONNECTION = 0x00000800,
2020-03-13 17:43:39 -04:00
/// <summary/>
ASC_REQ_CALL_LEVEL = 0x00001000,
2020-03-13 17:43:39 -04:00
/// <summary/>
ASC_REQ_FRAGMENT_SUPPLIED = 0x00002000,
/// <summary>When errors occur, the remote party will be notified.</summary>
ASC_REQ_EXTENDED_ERROR = 0x00008000,
/// <summary>Support a stream-oriented connection.</summary>
ASC_REQ_STREAM = 0x00010000,
/// <summary>Sign messages and verify signatures by using the EncryptMessage and MakeSignature functions.</summary>
ASC_REQ_INTEGRITY = 0x00020000,
2020-03-13 17:43:39 -04:00
/// <summary/>
ASC_REQ_LICENSING = 0x00040000,
2020-03-13 17:43:39 -04:00
/// <summary/>
ASC_REQ_IDENTIFY = 0x00080000,
2020-03-13 17:43:39 -04:00
/// <summary/>
ASC_REQ_ALLOW_NULL_SESSION = 0x00100000,
2020-03-13 17:43:39 -04:00
/// <summary/>
ASC_REQ_ALLOW_NON_USER_LOGONS = 0x00200000,
2020-03-13 17:43:39 -04:00
/// <summary/>
ASC_REQ_ALLOW_CONTEXT_REPLAY = 0x00400000,
2020-03-13 17:43:39 -04:00
/// <summary/>
ASC_REQ_FRAGMENT_TO_FIT = 0x00800000,
2020-03-13 17:43:39 -04:00
/// <summary/>
ASC_REQ_NO_TOKEN = 0x01000000,
2020-03-13 17:43:39 -04:00
/// <summary/>
ASC_REQ_PROXY_BINDINGS = 0x04000000,
2020-03-13 17:43:39 -04:00
/// <summary/>
ASC_REQ_ALLOW_MISSING_BINDINGS = 0x10000000,
}
/// <summary>A set of bit flags that indicate the attributes of the established context.</summary>
[PInvokeData("sspi.h", MSDNShortId = "a53f733e-b646-4431-b021-a2c446308849")]
[Flags]
public enum ASC_RET : uint
{
/// <summary>
/// The server in the transport application can build new security contexts impersonating the client that will be accepted by
/// other servers as the client's contexts. Delegate works only if MUTUAL_AUTH is set. DELEGATE is currently supported only by
/// Kerberos. Further, Kerberos will delegate only to a server that has the flag TRUSTED_FOR_DELEGATION. Do not use this flag for
/// constrained delegation.
/// </summary>
ASC_RET_DELEGATE = 0x00000001,
/// <summary>
/// The communicating parties must authenticate their identities to each other. Without MUTUAL_AUTH, the client authenticates its
/// identity to the server. With MUTUAL_AUTH, the server also must authenticate its identity to the client.
/// <para>
/// When using the Schannel security package, the server sets the ASC_RET_MUTUAL_AUTH constant only in the last call to
/// AcceptSecurityContext(Negotiate), after certificate mapping has successfully completed.
/// </para>
/// </summary>
ASC_RET_MUTUAL_AUTH = 0x00000002,
/// <summary>
/// The security package detects replayed packets and notifies the caller if a packet has been replayed. The use of this flag
/// implies all of the conditions specified by the INTEGRITY flag.
/// </summary>
ASC_RET_REPLAY_DETECT = 0x00000004,
/// <summary>
/// The context must be allowed to detect out-of-order delivery of packets later through the message support functions. Use of
/// this flag implies all of the conditions specified by the INTEGRITY flag.
/// </summary>
ASC_RET_SEQUENCE_DETECT = 0x00000008,
/// <summary>
/// The context can protect data while in transit using the EncryptMessage (General) and DecryptMessage (General) functions. The
/// CONFIDENTIALITY flag does not work if the generated context is for the Guest account.
/// </summary>
ASC_RET_CONFIDENTIALITY = 0x00000010,
/// <summary>A new session key must be negotiated.</summary>
ASC_RET_USE_SESSION_KEY = 0x00000020,
/// <summary></summary>
ASC_RET_SESSION_TICKET = 0x00000040,
/// <summary>
/// The security package must allocate memory. The caller must eventually call the FreeContextBuffer function to free memory
/// allocated by the security package.
/// </summary>
ASC_RET_ALLOCATED_MEMORY = 0x00000100,
/// <summary>The caller expects a three-leg authentication transaction.</summary>
ASC_RET_USED_DCE_STYLE = 0x00000200,
/// <summary>Datagram semantics must be used. For more information, see Datagram Contexts.</summary>
ASC_RET_DATAGRAM = 0x00000400,
/// <summary>Connection semantics must be used. For more information, see Connection-Oriented Contexts.</summary>
ASC_RET_CONNECTION = 0x00000800,
/// <summary></summary>
ASC_RET_CALL_LEVEL = 0x00002000,
/// <summary></summary>
ASC_RET_THIRD_LEG_FAILED = 0x00004000,
/// <summary>Error reply messages for the peer must be generated if the context fails.</summary>
ASC_RET_EXTENDED_ERROR = 0x00008000,
/// <summary>Stream semantics must be used. For more information, see Stream Contexts.</summary>
ASC_RET_STREAM = 0x00010000,
/// <summary>Buffer integrity can be verified but no sequencing or reply detection is enabled.</summary>
ASC_RET_INTEGRITY = 0x00020000,
/// <summary></summary>
ASC_RET_LICENSING = 0x00040000,
/// <summary>
/// When a server impersonates a context that has this flag set, that impersonation yields extremely limited access.
/// Impersonation with IDENTIFY set is used to verify the client's identity.
/// </summary>
ASC_RET_IDENTIFY = 0x00080000,
/// <summary></summary>
ASC_RET_NULL_SESSION = 0x00100000,
/// <summary></summary>
ASC_RET_ALLOW_NON_USER_LOGONS = 0x00200000,
/// <summary></summary>
ASC_RET_ALLOW_CONTEXT_REPLAY = 0x00400000,
/// <summary></summary>
ASC_RET_FRAGMENT_ONLY = 0x00800000,
/// <summary></summary>
ASC_RET_NO_TOKEN = 0x01000000,
/// <summary></summary>
ASC_RET_NO_ADDITIONAL_TOKEN = 0x02000000,
}
/// <summary>The data representation, such as byte ordering, on the target.</summary>
[PInvokeData("sspi.h", MSDNShortId = "a53f733e-b646-4431-b021-a2c446308849")]
[Flags]
public enum DREP
{
/// <summary></summary>
SECURITY_NATIVE_DREP = 0x00000010,
/// <summary></summary>
SECURITY_NETWORK_DREP = 0x00000000
}
/// <summary>Property to return from the SASL context.</summary>
[PInvokeData("sspi.h", MSDNShortId = "c9c424d3-07e6-4ed0-9189-c932af0475d9")]
public enum SASL_OPTION
{
/// <summary>
/// Data type of buffer: ULONG
/// <para>
/// State of SASL processing of the Authz value provided by the SASL application. The valid states for processing are
/// Sasl_AuthZIDForbidden and Sasl_AuthZIDProcessed.
/// </para>
/// </summary>
SASL_OPTION_AUTHZ_PROCESSING = 4,
/// <summary>
/// Data type of buffer: Array of binary characters
/// <para>
/// String of characters passed from the SASL client to the server. If the AuthZ_Processing state is Sasl_AuthZIDForbidden, the
/// return value SEC_E_UNSUPPORTED_FUNCTION is returned.
/// </para>
/// </summary>
SASL_OPTION_AUTHZ_STRING = 3,
/// <summary>
/// Data type of buffer: ULONG
/// <para>Maximum size of the receiving buffer on the local computer.</para>
/// </summary>
SASL_OPTION_RECV_SIZE = 2,
/// <summary>
/// Data type of buffer: ULONG
/// <para>
/// Maximum message data size that can be transmitted. This value is the maximum buffer size that can be transmitted to the
/// remote SASL process minus the block size, the trailer size, and the maximum signature size.
/// </para>
/// </summary>
SASL_OPTION_SEND_SIZE = 1,
}
/// <summary>En/Decryption options.</summary>
[PInvokeData("sspi.h", MSDNShortId = "86598BAA-0E87-46A9-AA1A-BF04BF0CDAFA")]
public enum SEC_WINNT_AUTH_IDENTITY_ENCRYPT
{
/// <summary>
/// The encrypted structure can only be decrypted by a security context in the same logon session. This option is used to protect
/// an identity buffer that is being sent over a local RPC.
/// </summary>
SEC_WINNT_AUTH_IDENTITY_ENCRYPT_SAME_LOGON = 0x1,
/// <summary>
/// The encrypted structure can only be decrypted by the same process. Calling the function with this option is equivalent to
/// calling SspiEncryptAuthIdentity. This option is used to protect an identity buffer that is being persisted in a process's
/// private memory for an extended period.
/// </summary>
SEC_WINNT_AUTH_IDENTITY_ENCRYPT_SAME_PROCESS = 0x2
}
/// <summary>The type used by negotiable security packages.</summary>
[PInvokeData("sspi.h", MSDNShortId = "a6083d76-1774-428c-85ca-fea817827d6a")]
[Flags]
public enum SEC_WINNT_AUTH_IDENTITY_FLAGS
{
/// <summary>Credentials are in ANSI form.</summary>
SEC_WINNT_AUTH_IDENTITY_ANSI = 0x1,
/// <summary>Credentials are in Unicode form.</summary>
SEC_WINNT_AUTH_IDENTITY_UNICODE = 0x2,
/// <summary>All data is in one buffer.</summary>
SEC_WINNT_AUTH_IDENTITY_MARSHALLED = 0x4,
/// <summary>
/// Used with the Kerberos security support provider (SSP). Credentials are for identity only. The Kerberos package is directed
/// to not include authorization data in the ticket.
/// </summary>
SEC_WINNT_AUTH_IDENTITY_ONLY = 0x8,
/// <summary>
/// The structure is encrypted by the SspiEncryptAuthIdentity function or by the SspiEncryptAuthIdentityEx function with the
/// SEC_WINNT_AUTH_IDENTITY_ENCRYPT_SAME_PROCESS option. It can only be decrypted by the same process.
/// <para>Windows Server 2008 R2 and Windows 7: This flag is not supported.</para>
/// </summary>
SEC_WINNT_AUTH_IDENTITY_FLAGS_PROCESS_ENCRYPTED = 0x10,
/// <summary>
/// The structure is encrypted by the SspiEncryptAuthIdentityEx function with the SEC_WINNT_AUTH_IDENTITY_ENCRYPT_SAME_LOGON
/// option under the SYSTEM security context. It can only be decrypted by a thread running as SYSTEM.
/// <para>Windows Server 2008 R2 and Windows 7: This flag is not supported.</para>
/// </summary>
SEC_WINNT_AUTH_IDENTITY_FLAGS_SYSTEM_PROTECTED = 0x20,
/// <summary>
/// The structure is encrypted by the SspiEncryptAuthIdentityEx function with the SEC_WINNT_AUTH_IDENTITY_ENCRYPT_SAME_LOGON
/// option under a non-SYSTEM security context. It can only be decrypted by a thread running in the same logon session in which
/// it was encrypted.
/// <para>Windows Server 2008 R2 and Windows 7: This flag is not supported.</para>
/// </summary>
SEC_WINNT_AUTH_IDENTITY_FLAGS_USER_PROTECTED = 0x40,
/// <summary>
/// The authentication identity buffer is cbStructureLength + 8 padding bytes that are necessary for in-place encryption or
/// decryption of the identity.
/// <para>
/// The authentication identity buffer is cbStructureLength + 8 padding bytes that are necessary for in-place encryption or
/// decryption of the identity.
/// </para>
/// </summary>
SEC_WINNT_AUTH_IDENTITY_FLAGS_RESERVED = 0x10000,
/// <summary>Undocumented.</summary>
SEC_WINNT_AUTH_IDENTITY_FLAGS_NULL_USER = 0x20000,
/// <summary>Undocumented.</summary>
SEC_WINNT_AUTH_IDENTITY_FLAGS_NULL_DOMAIN = 0x40000,
/// <summary>
/// When the credential type is password, the presence of this flag specifies that the structure is an online ID credential. The
/// DomainOffset and DomainLength members correspond to the online ID provider name.
/// <para>Windows Server 2008 R2 and Windows 7: This flag is not supported.</para>
/// </summary>
SEC_WINNT_AUTH_IDENTITY_FLAGS_ID_PROVIDER = 0x80000,
}
2020-03-13 17:43:39 -04:00
/// <summary/>
[Flags]
public enum SecBufferType : uint
{
/// <summary>The buffer contains an alert message.</summary>
SECBUFFER_ALERT = 0x11,
/// <summary>The buffer contains a bitmask for a SECBUFFER_READONLY_WITH_CHECKSUM buffer.</summary>
SECBUFFER_ATTRMASK = 0xF0000000,
/// <summary>The buffer contains channel binding information.</summary>
SECBUFFER_CHANNEL_BINDINGS = 0xE,
/// <summary>The buffer contains a DOMAIN_PASSWORD_INFORMATION structure.</summary>
//[CorrespondingType(typeof(DOMAIN_PASSWORD_INFORMATION))]
SECBUFFER_CHANGE_PASS_RESPONSE = 0xF,
/// <summary>
/// The buffer contains common data. The security package can read and write this data, for example, to encrypt some or all of it.
/// </summary>
SECBUFFER_DATA = 0x1,
/// <summary>
/// The buffer contains the setting for the maximum transmission unit (MTU) size for DTLS only. The default value is 1096 and the
/// valid configurable range is between 200 and 64*1024.
/// </summary>
SECBUFFER_DTLS_MTU = 0x18,
/// <summary>
/// This is a placeholder in the buffer array. The caller can supply several such entries in the array, and the security package
/// can return information in them. For more information, see SSPI Context Semantics.
/// </summary>
SECBUFFER_EMPTY = 0x0,
/// <summary>The security package uses this value to indicate the number of extra or unprocessed bytes in a message.</summary>
SECBUFFER_EXTRA = 0x5,
/// <summary>
/// The buffer contains a protocol-specific list of object identifiers (OIDs). It is not usually of interest to callers.
/// </summary>
SECBUFFER_MECHLIST = 0xB,
/// <summary>The buffer contains a signature of a SECBUFFER_MECHLIST buffer. It is not usually of interest to callers.</summary>
SECBUFFER_MECHLIST_SIGNATURE = 0xC,
/// <summary>
/// The security package uses this value to indicate the number of missing bytes in a particular message. The pvBuffer member is
/// ignored in this type.
/// </summary>
SECBUFFER_MISSING = 0x4,
/// <summary>
/// These are transport-to-packagespecific parameters. For example, the NetWare redirector may supply the server object
/// identifier, while DCE RPC can supply an association UUID, and so on.
/// </summary>
SECBUFFER_PKG_PARAMS = 0x3,
/// <summary>The buffer contains the preshared key. The maximum allowed PSK buffer size is 256 bytes.</summary>
SECBUFFER_PRESHARED_KEY = 0x16,
/// <summary>The buffer contains the preshared key identity.</summary>
SECBUFFER_PRESHARED_KEY_IDENTITY = 0x17,
/// <summary>The buffer contains the SRTP master key identifier.</summary>
SECBUFFER_SRTP_MASTER_KEY_IDENTIFIER = 0x14,
/// <summary>The buffer contains the list of SRTP protection profiles, in descending order of preference.</summary>
SECBUFFER_SRTP_PROTECTION_PROFILES = 0x13,
/// <summary>The buffer contains a protocol-specific header for a particular record. It is not usually of interest to callers.</summary>
SECBUFFER_STREAM_HEADER = 0x7,
/// <summary>The buffer contains a protocol-specific trailer for a particular record. It is not usually of interest to callers.</summary>
SECBUFFER_STREAM_TRAILER = 0x6,
/// <summary>This flag is reserved. Do not use it.</summary>
SECBUFFER_TARGET = 0xD,
/// <summary>
/// The buffer specifies the service principal name (SPN) of the target.
/// <para>This value is supported by the Digest security package when used with channel bindings.</para>
/// <para>Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP: This value is not supported.</para>
/// </summary>
SECBUFFER_TARGET_HOST = 0x10,
/// <summary>
/// The buffer contains the security token portion of the message. This is read-only for input parameters or read/write for
/// output parameters.
/// </summary>
SECBUFFER_TOKEN = 0x2,
/// <summary>
/// The buffer contains the supported token binding protocol version and key parameters, in descending order of preference.
/// </summary>
SECBUFFER_TOKEN_BINDING = 0x15,
/// <summary>
/// The buffer contains a list of application protocol IDs, one list per application protocol negotiation extension type to be enabled.
/// </summary>
SECBUFFER_APPLICATION_PROTOCOLS = 18,
/// <summary>Undocumented.</summary>
SECBUFFER_NEGOTIATION_INFO = 8,
/// <summary>Undocumented.</summary>
SECBUFFER_PADDING = 9,
/// <summary>
/// The buffer is read-only with no checksum. This flag is intended for sending header information to the security package for
/// computing the checksum. The package can read this buffer, but cannot modify it.
/// </summary>
SECBUFFER_READONLY = 0x80000000,
/// <summary>The buffer is read-only with a checksum.</summary>
SECBUFFER_READONLY_WITH_CHECKSUM = 0x10000000,
/// <summary>Undocumented.</summary>
SECBUFFER_RESERVED = 0x60000000,
/// <summary>Undocumented.</summary>
SECBUFFER_STREAM = 10,
}
/// <summary>Specifies the attribute of the context to be returned.</summary>
[PInvokeData("sspi.h", MSDNShortId = "FD91EE99-F94E-44CE-9331-933D0CAA5F75")]
public enum SECPKG_ATTR : uint
{
/// <summary>
/// The pBuffer parameter contains a pointer to a SecPkgContext_AccessToken structure.
/// <para>Returns a handle to the access token.</para>
/// </summary>
[CorrespondingType(typeof(SecPkgContext_AccessToken), CorrespondingAction.Get)]
SECPKG_ATTR_ACCESS_TOKEN = 18,
/// <summary>
/// The pBuffer parameter contains a pointer to a SecPkgContext_SessionAppData structure.
/// <para>Returns or specifies application data for the session.</para>
/// <para>This attribute is supported only by the Schannel security package.</para>
/// </summary>
[CorrespondingType(typeof(SecPkgContext_SessionAppData), CorrespondingAction.GetSet)]
SECPKG_ATTR_APP_DATA = 0x5e,
/// <summary>
/// The pBuffer parameter contains a pointer to a SecPkgContext_Authority structure.
/// <para>Queries the name of the authenticating authority.</para>
/// </summary>
[CorrespondingType(typeof(SecPkgContext_Authority), CorrespondingAction.Get)]
SECPKG_ATTR_AUTHORITY = 6,
/// <summary>
/// The pBuffer parameter contains a pointer to a SecPkgContext_ClientSpecifiedTarget structure that represents the service
/// principal name (SPN) of the initial target supplied by the client.
/// <para>Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP: This value is not supported.</para>
/// </summary>
[CorrespondingType(typeof(SecPkgContext_ClientSpecifiedTarget), CorrespondingAction.Get)]
SECPKG_ATTR_CLIENT_SPECIFIED_TARGET = 27,
/// <summary>
/// The pBuffer parameter contains a pointer to a SecPkgContext_ConnectionInfo structure.
/// <para>Returns detailed information on the established connection.</para>
/// <para>This attribute is supported only by the Schannel security package.</para>
/// </summary>
[CorrespondingType(typeof(SecPkgContext_ConnectionInfo), CorrespondingAction.Get)]
SECPKG_ATTR_CONNECTION_INFO = 0x5a,
/// <summary>
/// The pBuffer parameter contains a pointer to a SecPkgContext_ClientCreds structure that specifies client credentials.
/// <para>If the client credential is user name and password, the buffer is a packed KERB_INTERACTIVE_LOGON structure.</para>
/// <para>If the client credential is user name and smart card PIN, the buffer is a packed KERB_CERTIFICATE_LOGON structure.</para>
/// <para>If the client credential is an online identity credential, the buffer is a marshaled SEC_WINNT_AUTH_IDENTITY_EX2 structure.</para>
/// <para>This attribute is supported only on the CredSSP server.</para>
/// <para>
/// Windows Server 2008 R2, Windows 7, Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP: This value is not supported.
/// </para>
/// </summary>
[CorrespondingType(typeof(SecPkgContext_ClientCreds), CorrespondingAction.Get)]
SECPKG_ATTR_CREDS_2 = 0x80000086,
/// <summary>
/// The pBuffer parameter contains a pointer to a SecPkgContext_DceInfo structure.
/// <para>Queries for authorization data used by DCE services.</para>
/// </summary>
[CorrespondingType(typeof(SecPkgContext_DceInfo), CorrespondingAction.Get)]
SECPKG_ATTR_DCE_INFO = 3,
/// <summary>
/// The pBuffer parameter contains a pointer to a SecPkgContext_Bindings structure that specifies channel binding information.
/// <para>This attribute is supported only by the Schannel security package.</para>
/// <para>Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP: This value is not supported.</para>
/// </summary>
[CorrespondingType(typeof(SecPkgContext_Bindings), CorrespondingAction.Get)]
SECPKG_ATTR_ENDPOINT_BINDINGS = 26,
/// <summary>
/// The pBuffer parameter contains a pointer to a SecPkgContext_EapKeyBlock structure.
/// <para>Queries for key data used by the EAP TLS protocol.</para>
/// <para>This attribute is supported only by the Schannel security package.</para>
/// </summary>
[CorrespondingType(typeof(SecPkgContext_EapKeyBlock), CorrespondingAction.Get)]
SECPKG_ATTR_EAP_KEY_BLOCK = 0x5b,
/// <summary>
/// The pBuffer parameter contains a pointer to a SecPkgContext_Flags structure.
/// <para>Returns information about the negotiated context flags.</para>
/// </summary>
[CorrespondingType(typeof(SecPkgContext_Flags), CorrespondingAction.Get)]
SECPKG_ATTR_FLAGS = 14,
/// <summary>
/// The pBuffer parameter contains a pointer to a SecPkgContext_IssuerListInfoEx structure.
/// <para>Returns a list of certificate issuers that are accepted by the server.</para>
/// <para>This attribute is supported only by the Schannel security package.</para>
/// </summary>
[CorrespondingType(typeof(SecPkgContext_IssuerListInfoEx), CorrespondingAction.Get)]
SECPKG_ATTR_ISSUER_LIST_EX = 0x59,
/// <summary>
/// The pBuffer parameter contains a pointer to a SecPkgContext_KeyInfo structure.
/// <para>Queries information about the keys used in a security context.</para>
/// </summary>
[CorrespondingType(typeof(SecPkgContext_KeyInfo), CorrespondingAction.Get)]
SECPKG_ATTR_KEY_INFO = 5,
/// <summary>
/// The pBuffer parameter contains a pointer to a SecPkgContext_LastClientTokenStatus structure that specifies whether the token
/// from the most recent call to the InitializeSecurityContext function is the last token from the client.
/// <para>This value is supported only by the Negotiate, Kerberos, and NTLM security packages.</para>
/// <para>Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP: This value is not supported.</para>
/// </summary>
[CorrespondingType(typeof(SecPkgContext_LastClientTokenStatus), CorrespondingAction.Get)]
SECPKG_ATTR_LAST_CLIENT_TOKEN_STATUS = 30,
/// <summary>
/// The pBuffer parameter contains a pointer to a SecPkgContext_Lifespan structure.
/// <para>Queries the life span of the context.</para>
/// </summary>
[CorrespondingType(typeof(SecPkgContext_Lifespan), CorrespondingAction.Get)]
SECPKG_ATTR_LIFESPAN = 2,
/// <summary>
/// The pBuffer parameter contains a pointer to a PCCERT_CONTEXTstructure.
/// <para>Finds a certificate context that contains a local end certificate.</para>
/// <para>This attribute is supported only by the Schannel security package.</para>
/// </summary>
SECPKG_ATTR_LOCAL_CERT_CONTEXT = 0x54,
/// <summary>
/// The pBuffer parameter contains a pointer to a SecPkgContext_Names structure.
/// <para>Queries the name associated with the context.</para>
/// </summary>
[CorrespondingType(typeof(SecPkgContext_Names), CorrespondingAction.Get)]
SECPKG_ATTR_NAMES = 1,
/// <summary>
/// The pBuffer parameter contains a pointer to a SecPkgContext_NativeNames structure.
/// <para>Returns the principal name (CNAME) from the outbound ticket.</para>
/// </summary>
[CorrespondingType(typeof(SecPkgContext_NativeNames), CorrespondingAction.Get)]
SECPKG_ATTR_NATIVE_NAMES = 13,
/// <summary>
/// The pBuffer parameter contains a pointer to a SecPkgContext_NegotiationInfo structure.
/// <para>
/// Returns information about the security package to be used with the negotiation process and the current state of the
/// negotiation for the use of that package.
/// </para>
/// </summary>
[CorrespondingType(typeof(SecPkgContext_NegotiationInfo), CorrespondingAction.Get)]
SECPKG_ATTR_NEGOTIATION_INFO = 12,
/// <summary>
/// The pBuffer parameter contains a pointer to a SecPkgContext_PackageInfostructure.
/// <para>Returns information on the SSP in use.</para>
/// </summary>
[CorrespondingType(typeof(SecPkgContext_PackageInfo), CorrespondingAction.Get)]
SECPKG_ATTR_PACKAGE_INFO = 10,
/// <summary>
/// The pBuffer parameter contains a pointer to a SecPkgContext_PasswordExpiry structure.
/// <para>Returns password expiration information.</para>
/// </summary>
[CorrespondingType(typeof(SecPkgContext_PasswordExpiry), CorrespondingAction.Get)]
SECPKG_ATTR_PASSWORD_EXPIRY = 8,
/// <summary>
/// The pBuffer parameter contains a pointer to a PCCERT_CONTEXTstructure.
/// <para>Finds a certificate context that contains the end certificate supplied by the server.</para>
/// <para>This attribute is supported only by the Schannel security package.</para>
/// </summary>
[CorrespondingType(typeof(CERT_CONTEXT), CorrespondingAction.Get)]
SECPKG_ATTR_REMOTE_CERT_CONTEXT = 0x53,
/// <summary>
/// The pBuffer parameter contains a pointer to a HCERTCONTEXT. Finds a certificate context that contains a certificate supplied
/// by the Root store.
/// </summary>
SECPKG_ATTR_ROOT_STORE = 0x55,
/// <summary>
/// The pBuffer parameter contains a pointer to a SecPkgContext_SessionKey structure.
/// <para>Returns information about the session keys.</para>
/// </summary>
[CorrespondingType(typeof(SecPkgContext_SessionKey), CorrespondingAction.Get)]
SECPKG_ATTR_SESSION_KEY = 9,
/// <summary>
/// The pBuffer parameter contains a pointer to a SecPkgContext_SessionInfo structure.
/// <para>Returns information about the session.</para>
/// <para>Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP: This value is not supported.</para>
/// <para>This attribute is supported only by the Schannel security package.</para>
/// </summary>
[CorrespondingType(typeof(SecPkgContext_SessionInfo), CorrespondingAction.Get)]
SECPKG_ATTR_SESSION_INFO = 0x5d,
/// <summary>
/// The pBuffer parameter contains a pointer to a SecPkgContext_Sizes structure.
/// <para>Queries the sizes of the structures used in the per-message functions.</para>
/// </summary>
[CorrespondingType(typeof(SecPkgContext_Sizes))]
SECPKG_ATTR_SIZES = 0,
/// <summary>
/// The pBuffer parameter contains a pointer to a SecPkgContext_StreamSizes structure.
/// <para>Queries the sizes of the various parts of a stream used in the per-message functions.</para>
/// <para>This attribute is supported only by the Schannel security package.</para>
/// </summary>
[CorrespondingType(typeof(SecPkgContext_StreamSizes), CorrespondingAction.Get)]
SECPKG_ATTR_STREAM_SIZES = 4,
/// <summary>
/// The pBuffer parameter contains a pointer to a SecPkgContext_SubjectAttributes structure.
/// <para>This value returns information about the security attributes for the connection.</para>
/// <para>This value is supported only on the CredSSP server.</para>
/// <para>Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP: This value is not supported.</para>
/// </summary>
[CorrespondingType(typeof(SecPkgContext_SubjectAttributes), CorrespondingAction.Get)]
SECPKG_ATTR_SUBJECT_SECURITY_ATTRIBUTES = 124,
/// <summary>
/// The pBuffer parameter contains a pointer to a SecPkgContext_SupportedSignatures structure.
/// <para>This value returns information about the signature types that are supported for the connection.</para>
/// <para>This value is supported only by the Schannel security package.</para>
/// <para>Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP: This value is not supported.</para>
/// </summary>
[CorrespondingType(typeof(SecPkgContext_SupportedSignatures), CorrespondingAction.Get)]
SECPKG_ATTR_SUPPORTED_SIGNATURES = 0x66,
/// <summary>
/// The pBuffer parameter contains a pointer to a SecPkgContext_TargetInformation structure.
/// <para>Returns information about the name of the remote server.</para>
/// </summary>
[CorrespondingType(typeof(SecPkgContext_TargetInformation), CorrespondingAction.Get)]
SECPKG_ATTR_TARGET_INFORMATION = 17,
/// <summary>
/// The pBuffer parameter contains a pointer to a SecPkgContext_Bindings structure that specifies channel binding information.
/// <para>This value is supported only by the Schannel security package.</para>
/// <para>Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP: This value is not supported.</para>
/// </summary>
[CorrespondingType(typeof(SecPkgContext_Bindings), CorrespondingAction.Get)]
SECPKG_ATTR_UNIQUE_BINDINGS = 25,
/// <summary>
/// The pBuffer parameter contains a pointer to a SecPkgContext_AccessToken structure that specifies the access token for the
/// current security context.
/// <para>This attribute is supported only on the server.</para>
/// </summary>
[CorrespondingType(typeof(SecPkgContext_AccessToken), CorrespondingAction.Get)]
SECPKG_ATTR_C_ACCESS_TOKEN = 0x80000012,
/// <summary>
/// The pBuffer parameter contains a pointer to a SecPkgContext_AccessToken structure that specifies the access token for the
/// current security context.
/// <para>This attribute is supported only on the server.</para>
/// </summary>
[CorrespondingType(typeof(SecPkgContext_AccessToken), CorrespondingAction.Get)]
SECPKG_ATTR_C_FULL_ACCESS_TOKEN = 0x80000082,
/// <summary>
/// The pBuffer parameter contains a pointer to a CERT_TRUST_STATUS structure that specifies trust information about the certificate.
/// <para>This attribute is supported only on the client.</para>
/// </summary>
[CorrespondingType(typeof(CERT_TRUST_STATUS), CorrespondingAction.Get)]
SECPKG_ATTR_CERT_TRUST_STATUS = 0x80000084,
/// <summary>
/// The pBuffer parameter contains a pointer to a SecPkgContext_ClientCreds structure that specifies client credentials.
/// <para>The client credentials can be either user name and password or user name and smart card PIN.</para>
/// <para>This attribute is supported only on the server.</para>
/// </summary>
[CorrespondingType(typeof(SecPkgContext_ClientCreds), CorrespondingAction.Get)]
SECPKG_ATTR_CREDS = 0x80000080,
/// <summary>
/// The pBuffer parameter contains a pointer to a SecPkgContext_PackageInfo structure that specifies the name of the
/// authentication package negotiated by the Microsoft Negotiate provider.
/// </summary>
[CorrespondingType(typeof(SecPkgContext_PackageInfo), CorrespondingAction.Get)]
SECPKG_ATTR_NEGOTIATION_PACKAGE = 0x80000081,
/// <summary>
/// The pBuffer parameter contains a pointer to a SecPkgContext_Flags structure that specifies information about the flags in the
/// current security context.
/// <para>This attribute is supported only on the client.</para>
/// </summary>
[CorrespondingType(typeof(SecPkgContext_Flags), CorrespondingAction.Get)]
SECPKG_ATTR_SERVER_AUTH_FLAGS = 0x80000083,
/// <summary>
/// The pBuffer parameter contains a pointer to a SecPkgContext_EapPrfInfo structure.
/// <para>
/// Sets the pseudo-random function (PRF) used by the Extensible Authentication Protocol (EAP). This is the value that is
/// returned by a call to the QueryContextAttributes (Schannel) function when SECPKG_ATTR_EAP_KEY_BLOCK is passed as the value of
/// the ulAttribute parameter.
/// </para>
/// <para>This attribute is supported only by the Schannel security package.</para>
/// </summary>
[CorrespondingType(typeof(SecPkgContext_EapPrfInfo), CorrespondingAction.Set)]
SECPKG_ATTR_EAP_PRF_INFO = 101,
/// <summary>
/// The pBuffer parameter contains a pointer to a SecPkgContext_EarlyStart structure.
/// <para>Sets the False Start feature. See the Building a faster and more secure web blog post for information on this feature.</para>
/// </summary>
[CorrespondingType(typeof(SecPkgContext_EarlyStart), CorrespondingAction.Set)]
SECPKG_ATTR_EARLY_START = 105,
/// <summary>
/// Sets and retrieves the MTU (maximum transmission unit) value for use with DTLS. If DTLS is not enabled in a security context,
/// this attribute is not supported.
/// <para>Valid values are between 200 bytes and 64 kilobytes. The default DTLS MTU value in Schannel is 1096 bytes.</para>
/// </summary>
[CorrespondingType(typeof(ushort), CorrespondingAction.Set)]
SECPKG_ATTR_DTLS_MTU = 34,
/// <summary>
/// The pBuffer parameter contains a pointer to a SecPkgContext_KeyingMaterialInfo structure. The keying material export feature
/// follows the RFC 5705 standard.
/// <para>This attribute is supported only by the Schannel security package in Windows 10 and Windows Server 2016 or later versions.</para>
/// </summary>
[CorrespondingType(typeof(SecPkgContext_KeyingMaterialInfo), CorrespondingAction.Set)]
SECPKG_ATTR_KEYING_MATERIAL_INFO = 106,
}
/// <summary>
/// <para>
/// Indicates whether the token from the most recent call to the InitializeSecurityContext function is the last token from the client.
/// </para>
/// <para>This enumeration is used in the SecPkgContext_LastClientTokenStatus structure.</para>
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/ne-sspi-secpkg_attr_lct_status typedef enum _SECPKG_ATTR_LCT_STATUS {
// SecPkgAttrLastClientTokenYes, SecPkgAttrLastClientTokenNo, SecPkgAttrLastClientTokenMaybe } SECPKG_ATTR_LCT_STATUS, *PSECPKG_ATTR_LCT_STATUS;
[PInvokeData("sspi.h", MSDNShortId = "b9067862-2339-4543-a8cd-610e6f921bfd")]
public enum SECPKG_ATTR_LCT_STATUS
{
/// <summary>The token is the last token from the client.</summary>
SecPkgAttrLastClientTokenYes,
/// <summary>The token is not the last token from the client.</summary>
SecPkgAttrLastClientTokenNo,
/// <summary>It is not known whether the token is the last token from the client.</summary>
SecPkgAttrLastClientTokenMaybe,
}
/// <summary>Bit flags that describe the capabilities of the security package.</summary>
[PInvokeData("sspi.h", MSDNShortId = "d0bff3d8-63f1-4a4e-851f-177040af6bd2")]
[Flags]
public enum SECPKG_CALLFLAGS
{
/// <summary>The caller is an app container.</summary>
SECPKG_CALLFLAGS_APPCONTAINER = 0x00000001,
/// <summary>The caller can use default credentials.</summary>
SECPKG_CALLFLAGS_AUTHCAPABLE = 0x00000002,
/// <summary>The caller can only use supplied credentials.</summary>
SECPKG_CALLFLAGS_FORCE_SUPPLIED = 0x00000004,
/// <summary/>
SECPKG_CALLFLAGS_APPCONTAINER_UPNCAPABLE = 0x00000008,
}
/// <summary>Flags for <c>ExportSecurityContext</c>.</summary>
[PInvokeData("sspi.h", MSDNShortId = "4ebc7f37-b948-4c78-973f-0a74e55c7ee2")]
[Flags]
public enum SECPKG_CONTEXT_EXPORT
{
/// <summary>The new security context is reset to its initial state.</summary>
SECPKG_CONTEXT_EXPORT_RESET_NEW = 1,
/// <summary>The old security context is deleted.</summary>
SECPKG_CONTEXT_EXPORT_DELETE_OLD = 2,
/// <summary>
/// This value is not supported.
/// <para>
/// Windows Server 2003 and Windows XP/2000: The security context is to be exported to the kernel.This value is supported only in
/// Schannel kernel mode.
/// </para>
/// </summary>
SECPKG_CONTEXT_EXPORT_TO_KERNEL = 4,
}
/// <summary>A flag that indicates how credentials will be used.</summary>
[PInvokeData("sspi.h", MSDNShortId = "3b73decf-75d4-4bc4-b7ca-5f16aaadff29")]
public enum SECPKG_CRED
{
/// <summary>Allow a local client credential to prepare an outgoing token.</summary>
SECPKG_CRED_OUTBOUND = 0x2,
/// <summary>
/// Validate an incoming server credential. Inbound credentials might be validated by using an authenticating authority when
/// InitializeSecurityContext (CredSSP) or AcceptSecurityContext (CredSSP) is called. If such an authority is not available, the
/// function will fail and return SEC_E_NO_AUTHENTICATING_AUTHORITY. Validation is package specific.
/// </summary>
SECPKG_CRED_INBOUND = 0x1,
/// <summary/>
SECPKG_CRED_BOTH = 0x3,
/// <summary/>
SECPKG_CRED_DEFAULT = 0x4
}
/// <summary>Specifies the attribute to query.</summary>
[PInvokeData("sspi.h", MSDNShortId = "a8ba6f73-8469-431b-b185-183b45b2c533")]
public enum SECPKG_CRED_ATTR
{
/// <summary>
/// Returns the certificate thumbprint in a pbuffer of type SecPkgCredentials_Cert.
/// <para>This attribute is only supported by Kerberos.</para>
/// <para>
/// Windows Server 2008 R2, Windows 7, Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP: This attribute is
/// not available.
/// </para>
/// </summary>
[CorrespondingType(typeof(SecPkgCredentials_Cert), CorrespondingAction.Get)]
SECPKG_CRED_ATTR_CERT = 4,
/// <summary>
/// Returns the name of a credential in a pbuffer of type SecPkgCredentials_Names.
/// <para>This attribute is not supported by Schannel in WOW64 mode.</para>
/// </summary>
[CorrespondingType(typeof(SecPkgCredentials_Names))]
SECPKG_CRED_ATTR_NAMES = 1,
/// <summary>
/// Returns the supported algorithms in a pbuffer of type SecPkgCred_SupportedAlgs. All supported algorithms are included,
/// regardless of whether they are supported by the provided certificate or enabled on the local computer.
/// <para>This attribute is supported only by Schannel.</para>
/// </summary>
[CorrespondingType(typeof(SecPkgCred_SupportedAlgs))]
SECPKG_ATTR_SUPPORTED_ALGS = 0x56,
/// <summary>
/// Returns the cipher strengths in a pbuffer of type SecPkgCred_CipherStrengths.
/// <para>This attribute is supported only by Schannel.</para>
/// </summary>
[CorrespondingType(typeof(SecPkgCred_CipherStrengths))]
SECPKG_ATTR_CIPHER_STRENGTHS = 0x57,
/// <summary>
/// Returns the supported algorithms in a pbuffer of type SecPkgCred_SupportedProtocols. All supported protocols are included,
/// regardless of whether they are supported by the provided certificate or enabled on the local computer.
/// <para>This attribute is supported only by Schannel.</para>
/// </summary>
[CorrespondingType(typeof(SecPkgCred_SupportedProtocols))]
SECPKG_ATTR_SUPPORTED_PROTOCOLS = 0x58,
}
/// <summary>
/// Indicates the type of credential used in a client context. The <c>SECPKG_CRED_CLASS</c> enumeration is used in the
/// SecPkgContext_CredInfo structure.
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/ne-sspi-_secpkg_cred_class typedef enum _SECPKG_CRED_CLASS {
// SecPkgCredClass_None, SecPkgCredClass_Ephemeral, SecPkgCredClass_PersistedGeneric, SecPkgCredClass_PersistedSpecific,
// SecPkgCredClass_Explicit } SECPKG_CRED_CLASS, *PSECPKG_CRED_CLASS;
[PInvokeData("sspi.h", MSDNShortId = "2f5f9be2-e7b5-4d34-a2ad-89a99db78ad0")]
public enum SECPKG_CRED_CLASS
{
/// <summary>No credentials are supplied.</summary>
SecPkgCredClass_None = 0,
/// <summary>Indicates the credentials used to log on to the system.</summary>
SecPkgCredClass_Ephemeral = 10,
/// <summary>Indicates saved credentials that are not target specific.</summary>
SecPkgCredClass_PersistedGeneric = 20,
/// <summary>Indicates saved credentials that are target specific.</summary>
SecPkgCredClass_PersistedSpecific = 30,
/// <summary>The sec PKG cred class explicit</summary>
SecPkgCredClass_Explicit = 40,
}
/// <summary>Bit flags that describe the capabilities of the security package.</summary>
[PInvokeData("sspi.h", MSDNShortId = "d0bff3d8-63f1-4a4e-851f-177040af6bd2")]
[Flags]
public enum SECPKG_FLAG : uint
{
/// <summary>The security package supports the MakeSignature and VerifySignature functions.</summary>
SECPKG_FLAG_INTEGRITY = 0x1,
/// <summary>The security package supports the EncryptMessage (General) and DecryptMessage (General) functions.</summary>
SECPKG_FLAG_PRIVACY = 0x2,
/// <summary>
/// The package is interested only in the security-token portion of messages, and will ignore any other buffers. This is a
/// performance-related issue.
/// </summary>
SECPKG_FLAG_TOKEN_ONLY = 0x4,
/// <summary>
/// Supports datagram-style authentication. For more information, see SSPI Context Semantics.
/// <para>Important The Microsoft Kerberos package does not support datagram contexts in user-to-user mode.</para>
/// </summary>
SECPKG_FLAG_DATAGRAM = 0x8,
/// <summary>Supports connection-oriented style authentication. For more information, see SSPI Context Semantics.</summary>
SECPKG_FLAG_CONNECTION = 0x10,
/// <summary>Multiple legs are required for authentication.</summary>
SECPKG_FLAG_MULTI_REQUIRED = 0x20,
/// <summary>Server authentication support is not provided.</summary>
SECPKG_FLAG_CLIENT_ONLY = 0x40,
/// <summary>Supports extended error handling. For more information, see Extended Error Information.</summary>
SECPKG_FLAG_EXTENDED_ERROR = 0x80,
/// <summary>Supports Windows impersonation in server contexts.</summary>
SECPKG_FLAG_IMPERSONATION = 0x100,
/// <summary>Understands Windows principal and target names.</summary>
SECPKG_FLAG_ACCEPT_WIN32_NAME = 0x200,
/// <summary>Supports stream semantics. For more information, see SSPI Context Semantics.</summary>
SECPKG_FLAG_STREAM = 0x400,
/// <summary>Can be used by the Microsoft Negotiate security package.</summary>
SECPKG_FLAG_NEGOTIABLE = 0x800,
/// <summary>Supports GSS compatibility.</summary>
SECPKG_FLAG_GSS_COMPATIBLE = 0x1000,
/// <summary>Supports LsaLogonUser.</summary>
SECPKG_FLAG_LOGON = 0x2000,
/// <summary>Token buffers are in ASCII characters format.</summary>
SECPKG_FLAG_ASCII_BUFFERS = 0x4000,
/// <summary>
/// Supports separating large tokens into smaller buffers so that applications can make repeated calls to
/// InitializeSecurityContext (General) and AcceptSecurityContext (General) with the smaller buffers to complete authentication.
/// </summary>
SECPKG_FLAG_FRAGMENT = 0x8000,
/// <summary>Supports mutual authentication.</summary>
SECPKG_FLAG_MUTUAL_AUTH = 0x10000,
/// <summary>Supports delegation.</summary>
SECPKG_FLAG_DELEGATION = 0x20000,
/// <summary>
/// The security package supports using a checksum instead of in-place encryption when calling the EncryptMessage function.
/// </summary>
SECPKG_FLAG_READONLY_WITH_CHECKSUM = 0x40000,
/// <summary>Supports callers with restricted tokens.</summary>
SECPKG_FLAG_RESTRICTED_TOKENS = 0x80000,
/// <summary>
/// The security package extends the Microsoft Negotiate security package. There can be at most one package of this type.
/// </summary>
SECPKG_FLAG_NEGO_EXTENDER = 0x00100000,
/// <summary>This package is negotiated by the package of type SECPKG_FLAG_NEGO_EXTENDER.</summary>
SECPKG_FLAG_NEGOTIABLE2 = 0x00200000,
/// <summary>This package receives all calls from app container apps.</summary>
SECPKG_FLAG_APPCONTAINER_PASSTHROUGH = 0x00400000,
/// <summary>
/// This package receives calls from app container apps if one of the following checks succeeds.
/// <list type="bullet">
/// <item>
/// <term>Caller has default credentials capability.</term>
/// </item>
/// <item>
/// <term>The target is a proxy server.</term>
/// </item>
/// <item>
/// <term>The caller has supplied credentials.</term>
/// </item>
/// </list>
/// </summary>
SECPKG_FLAG_APPCONTAINER_CHECKS = 0x00800000,
/// <summary>This package is running with Credential Guard enabled.</summary>
SECPKG_FLAG_CREDENTIAL_ISOLATION_ENABLED = 0x01000000,
/// <summary/>
SECPKG_FLAG_UNDOCUMENTED1 = 0x02000000,
}
/// <summary>The type of security package.</summary>
[PInvokeData("sspi.h", MSDNShortId = "2e9f65ec-72a5-4d6f-aa63-f83369f0dd07")]
public enum SECPKG_OPTIONS_TYPE
{
/// <summary>The package type is not known.</summary>
SECPKG_OPTIONS_TYPE_UNKNOWN = 0,
/// <summary>The security package is an LSA authentication package.</summary>
SECPKG_OPTIONS_TYPE_LSA = 1,
/// <summary>The security package is a Security Support Provider Interface (SSPI) package.</summary>
SECPKG_OPTIONS_TYPE_SSPI = 2,
}
/// <summary>Package-specific flags that indicate the quality of protection.</summary>
[PInvokeData("Sspi.h", MSDNShortId = "aa375348")]
[Flags]
public enum SECQOP : uint
{
/// <summary>The message is not encrypted, but a header or trailer is present.</summary>
SECQOP_WRAP_NO_ENCRYPT = 0x80000001,
/// <summary>
/// Send an Schannel alert message. In this case, the pMessage parameter must contain a standard two-byte SSL/TLS event code.
/// This value is supported only by the Schannel SSP.
/// </summary>
SECQOP_WRAP_OOB_DATA = 0x40000000,
}
/// <summary>
/// The <c>AcceptSecurityContext (CredSSP)</c> function lets the server component of a transport application establish a security
/// context between the server and a remote client. The remote client calls the InitializeSecurityContext (CredSSP) function to start
/// the process of establishing a security context. The server can require one or more reply tokens from the remote client to
/// complete establishing the security context.
/// </summary>
/// <param name="phCredential">
/// A handle to the server credentials. To retrieve this handle, the server calls the AcquireCredentialsHandle (CredSSP) function
/// with either the SECPKG_CRED_INBOUND or SECPKG_CRED_BOTH flag set.
/// </param>
/// <param name="phContext">
/// A pointer to a CtxtHandle structure. On the first call to <c>AcceptSecurityContext (CredSSP)</c>, this pointer is <c>NULL</c>. On
/// subsequent calls, phContext specifies the partially formed context returned in the phNewContext parameter by the first call.
/// </param>
/// <param name="pInput">
/// <para>
/// A pointer to a SecBufferDesc structure generated by a client call to InitializeSecurityContext (CredSSP). The structure contains
/// the input buffer descriptor.
/// </para>
/// <para>
/// The first buffer must be of type <c>SECBUFFER_TOKEN</c> and contain the security token received from the client. The second
/// buffer should be of type <c>SECBUFFER_EMPTY</c>.
/// </para>
/// </param>
/// <param name="fContextReq">
/// <para>
/// -Bit flags that specify the attributes required by the server to establish the context. Bit flags can be combined by using
/// bitwise- <c>OR</c> operations. This parameter can be one or more of the following values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ASC_REQ_ALLOCATE_MEMORY</term>
/// <term>
/// Credential Security Support Provider (CredSSP) will allocate output buffers. When you have finished using the output buffers,
/// free them by calling the FreeContextBuffer function.
/// </term>
/// </item>
/// <item>
/// <term>ASC_REQ_CONNECTION</term>
/// <term>The security context will not handle formatting messages.</term>
/// </item>
/// <item>
/// <term>ASC_REQ_DELEGATE</term>
/// <term>The server is allowed to impersonate the client. Ignore this flag for constrained delegation.</term>
/// </item>
/// <item>
/// <term>ASC_REQ_EXTENDED_ERROR</term>
/// <term>When errors occur, the remote party will be notified.</term>
/// </item>
/// <item>
/// <term>ASC_REQ_REPLAY_DETECT</term>
/// <term>Detect replayed packets.</term>
/// </item>
/// <item>
/// <term>ASC_REQ_SEQUENCE_DETECT</term>
/// <term>Detect messages received out of sequence.</term>
/// </item>
/// <item>
/// <term>ASC_REQ_STREAM</term>
/// <term>Support a stream-oriented connection.</term>
/// </item>
/// </list>
/// <para>
/// For possible attribute flags and their meanings, see Context Requirements. Flags used for this parameter are prefixed with
/// ASC_REQ, for example, ASC_REQ_DELEGATE.
/// </para>
/// <para>The requested attributes may not be supported by the client. For more information, see the pfContextAttr parameter.</para>
/// </param>
/// <param name="TargetDataRep">
/// The data representation, such as byte ordering, on the target. This parameter can be either <c>SECURITY_NATIVE_DREP</c> or <c>SECURITY_NETWORK_DREP</c>.
/// </param>
/// <param name="phNewContext">
/// A pointer to a CtxtHandle structure. On the first call to <c>AcceptSecurityContext (CredSSP)</c>, this pointer receives the new
/// context handle. On subsequent calls, phNewContext can be the same as the handle specified in the phContext parameter.
/// </param>
/// <param name="pOutput">
/// <para>
/// A pointer to a SecBufferDesc structure that contains the output buffer descriptor. This buffer is sent to the client for input
/// into additional calls to InitializeSecurityContext (CredSSP). An output buffer may be generated even if the function returns
/// SEC_E_OK. Any buffer generated must be sent back to the client application.
/// </para>
/// <para>
/// On output, this buffer receives a token for the security context. The token must be sent to the client. The function can also
/// return a buffer of type SECBUFFER_EXTRA.
/// </para>
/// </param>
/// <param name="pfContextAttr">
/// <para>
/// A pointer to a set of bit flags that indicate the attributes of the established context. For a description of the various
/// attributes, see Context Requirements. Flags used for this parameter are prefixed with ASC_RET, for example, ASC_RET_DELEGATE.
/// </para>
/// <para>
/// Do not check for security-related attributes until the final function call returns successfully. Attribute flags not related to
/// security, such as the ASC_RET_ALLOCATED_MEMORY flag, can be checked before the final return.
/// </para>
/// </param>
/// <param name="ptsTimeStamp">The PTS time stamp.</param>
/// <returns>
/// <para>This function returns one of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code/value</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>SEC_E_INCOMPLETE_MESSAGE 0x80090318L</term>
/// <term>
/// The function succeeded. The data in the input buffer is incomplete. The application must read additional data from the client and
/// call AcceptSecurityContext (CredSSP) again.
/// </term>
/// </item>
/// <item>
/// <term>SEC_E_INSUFFICIENT_MEMORY 0x80090300L</term>
/// <term>The function failed. There is not enough memory available to complete the requested action.</term>
/// </item>
/// <item>
/// <term>SEC_E_INTERNAL_ERROR 0x80090304L</term>
/// <term>The function failed. An error occurred that did not map to an SSPI error code.</term>
/// </item>
/// <item>
/// <term>SEC_E_INVALID_HANDLE 0x80100003L</term>
/// <term>The function failed. The handle passed to the function is not valid.</term>
/// </item>
/// <item>
/// <term>SEC_E_INVALID_TOKEN 0x80090308L</term>
/// <term>The function failed. The token passed to the function is not valid.</term>
/// </item>
/// <item>
/// <term>SEC_E_LOGON_DENIED 0x8009030CL</term>
/// <term>The logon failed.</term>
/// </item>
/// <item>
/// <term>SEC_E_NO_AUTHENTICATING_AUTHORITY 0x80090311L</term>
/// <term>The function failed. No authority could be contacted for authentication. This could be due to the following conditions:</term>
/// </item>
/// <item>
/// <term>SEC_E_NO_CREDENTIALS 0x8009030EL</term>
/// <term>The function failed. The credentials handle specified in the phCredential parameter is not valid.</term>
/// </item>
/// <item>
/// <term>SEC_E_OK 0x00000000L</term>
/// <term>
/// The function succeeded. The security context received from the client was accepted. If the function generated an output token,
/// the token must be sent to the client process.
/// </term>
/// </item>
/// <item>
/// <term>SEC_E_UNSUPPORTED_FUNCTION 0x80090302L</term>
/// <term>
/// The function failed. The fContextReq parameter specified a context attribute flag (ASC_REQ_DELEGATE or ASC_REQ_PROMPT_FOR_CREDS)
/// that was not valid.
/// </term>
/// </item>
/// <item>
/// <term>SEC_I_COMPLETE_AND_CONTINUE 0x00090314L</term>
/// <term>
/// The function succeeded. The server must call CompleteAuthToken and pass the output token to the client. The server must then wait
/// for a return token from the client before making another call to AcceptSecurityContext (CredSSP).
/// </term>
/// </item>
/// <item>
/// <term>SEC_I_COMPLETE_NEEDED 0x00090313L</term>
/// <term>The function succeeded. The server must finish building the message from the client before calling CompleteAuthToken.</term>
/// </item>
/// <item>
/// <term>SEC_I_CONTINUE_NEEDED 0x00090312L</term>
/// <term>
/// The function succeeded. The server must send the output token to the client and wait for a returned token. The returned token
/// should be passed in pInput for another call to AcceptSecurityContext (CredSSP).
/// </term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// The <c>AcceptSecurityContext (CredSSP)</c> function is the server counterpart to the InitializeSecurityContext (CredSSP) function.
/// </para>
/// <para>
/// When the server receives a request from a client, it uses the fContextReq parameter to specify what it requires of the session.
/// In this fashion, a server can require that clients be capable of using a confidential or integrity-checked session; it can reject
/// clients that cannot meet that demand. Alternatively, a server can require nothing; whatever the client requires or can provide is
/// returned in the pfContextAttr parameter.
/// </para>
/// <para>
/// The fContextReq and pfContextAttr parameters are bitmasks that represent various context attributes. For a description of the
/// various attributes, see Context Requirements.
/// </para>
/// <para>
/// <c>Note</c> While the pfContextAttr parameter is valid on any successful return, you should examine the flags pertaining to
/// security aspects of the context only on the final successful return. Intermediate returns can set, for example, the
/// ISC_RET_ALLOCATED_MEMORY flag.
/// </para>
/// <para>
/// The caller is responsible for determining whether the final context attributes are sufficient. For example, if confidentiality
/// (encryption) was requested but could not be established, some applications may choose to shut down the connection immediately. If
/// the security context cannot be established, the server must free the partially created context by calling the
/// DeleteSecurityContext function. For information about when to call the <c>DeleteSecurityContext</c> function, see <c>DeleteSecurityContext</c>.\
/// </para>
/// <para>
/// After the security context has been established, the server application can use the QuerySecurityContextToken function to
/// retrieve a handle to the user account to which the client certificate was mapped. Also, the server can use the
/// ImpersonateSecurityContext function to impersonate the user.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-acceptsecuritycontext KSECDDDECLSPEC SECURITY_STATUS SEC_ENTRY
// AcceptSecurityContext( PCredHandle phCredential, PCtxtHandle phContext, PSecBufferDesc pInput, unsigned long fContextReq, unsigned
// long TargetDataRep, PCtxtHandle phNewContext, PSecBufferDesc pOutput, unsigned long *pfContextAttr, PTimeStamp ptsExpiry );
[DllImport(Lib.Secur32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("sspi.h", MSDNShortId = "a53f733e-b646-4431-b021-a2c446308849")]
public static unsafe extern HRESULT AcceptSecurityContext([Optional] CredHandle* phCredential, CtxtHandle* phContext, [In, Optional] SecBufferDesc* pInput, ASC_REQ fContextReq, DREP TargetDataRep,
out CtxtHandle phNewContext, [Optional] SecBufferDesc* pOutput, out ASC_RET pfContextAttr, out TimeStamp ptsTimeStamp);
/// <summary>
/// <para>
/// The <c>AcquireCredentialsHandle (CredSSP)</c> function acquires a handle to preexisting credentials of a security principal. This
/// handle is required by the InitializeSecurityContext (CredSSP) and AcceptSecurityContext (CredSSP) functions. These can be either
/// preexisting credentials, which are established through a system logon that is not described here, or the caller can provide
/// alternative credentials.
/// </para>
/// <para><c>Note</c> This is not a "log on to the network" and does not imply gathering of credentials.</para>
/// </summary>
/// <param name="pszPrincipal">
/// <para>A pointer to a null-terminated string that specifies the name of the principal whose credentials the handle will reference.</para>
/// <para>
/// <c>Note</c> If the process that requests the handle does not have access to the credentials, the function returns an error. A
/// null string indicates that the process requires a handle to the credentials of the user under whose security context it is executing.
/// </para>
/// </param>
/// <param name="pszPackage">
/// A pointer to a null-terminated string that specifies the name of the security package with which these credentials will be used.
/// This is a security package name returned in the <c>Name</c> member of a SecPkgInfo structure returned by the
/// EnumerateSecurityPackages function. After a context is established, QueryContextAttributes (CredSSP) can be called with
/// ulAttribute set to <c>SECPKG_ATTR_PACKAGE_INFO</c> to return information on the security package in use.
/// </param>
/// <param name="fCredentialUse">
/// <para>A flag that indicates how these credentials will be used. This parameter can be one of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>SECPKG_CRED_INBOUND 0x1</term>
/// <term>
/// Validate an incoming server credential. Inbound credentials might be validated by using an authenticating authority when
/// InitializeSecurityContext (CredSSP) or AcceptSecurityContext (CredSSP) is called. If such an authority is not available, the
/// function will fail and return SEC_E_NO_AUTHENTICATING_AUTHORITY. Validation is package specific.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_CRED_OUTBOUND 0x0</term>
/// <term>Allow a local client credential to prepare an outgoing token.</term>
/// </item>
/// </list>
/// </param>
/// <param name="pvLogonId">
/// A pointer to a locally unique identifier (LUID) that identifies the user. This parameter is provided for file-system processes
/// such as network redirectors. This parameter can be <c>NULL</c>.
/// </param>
/// <param name="pAuthData">
/// A pointer to a CREDSSP_CRED structure that specifies authentication data for both Schannel and Negotiate packages.
/// </param>
/// <param name="pGetKeyFn">Reserved. This parameter is not used and should be set to <c>NULL</c>.</param>
/// <param name="pvGetKeyArgument">Reserved. This parameter must be set to <c>NULL</c>.</param>
/// <param name="phCredential">A pointer to the CredHandle structure that will receive the credential handle.</param>
/// <param name="ptsExpiry">
/// A pointer to a TimeStamp structure that receives the time at which the returned credentials expire. The structure value received
/// depends on the security package, which must specify the value in local time.
/// </param>
/// <returns>
/// <para>If the function succeeds, it returns <c>SEC_E_OK</c>.</para>
/// <para>If the function fails, it returns one of the following error codes.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>SEC_E_INSUFFICIENT_MEMORY</term>
/// <term>There is insufficient memory available to complete the requested action.</term>
/// </item>
/// <item>
/// <term>SEC_E_INTERNAL_ERROR</term>
/// <term>An error occurred that did not map to an SSPI error code.</term>
/// </item>
/// <item>
/// <term>SEC_E_NO_CREDENTIALS</term>
/// <term>No credentials are available in the security package.</term>
/// </item>
/// <item>
/// <term>SEC_E_NOT_OWNER</term>
/// <term>The caller of the function does not have the necessary credentials.</term>
/// </item>
/// <item>
/// <term>SEC_E_SECPKG_NOT_FOUND</term>
/// <term>The requested security package does not exist.</term>
/// </item>
/// <item>
/// <term>SEC_E_UNKNOWN_CREDENTIALS</term>
/// <term>The credentials supplied to the package were not recognized.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// The <c>AcquireCredentialsHandle (CredSSP)</c> function returns a handle to the credentials of a principal, such as a user or
/// client, as used by a specific security package. The function can return the handle to either preexisting credentials or newly
/// created credentials and return it. This handle can be used in subsequent calls to the AcceptSecurityContext (CredSSP) and
/// InitializeSecurityContext (CredSSP) functions.
/// </para>
/// <para>
/// In general, <c>AcquireCredentialsHandle (CredSSP)</c> does not provide the credentials of other users logged on to the same
/// computer. However, a caller with SE_TCB_NAME privilege can obtain the credentials of an existing logon session by specifying the
/// logon identifier (LUID) of that session. Typically, this is used by kernel-mode modules that must act on behalf of a logged-on user.
/// </para>
/// <para>
/// A package might call the function in pGetKeyFn provided by the RPC run-time transport. If the transport does not support the
/// notion of callback to retrieve credentials, this parameter must be <c>NULL</c>.
/// </para>
/// <para>For kernel mode callers, the following differences must be noted:</para>
/// <list type="bullet">
/// <item>
/// <term>The two string parameters must be Unicode strings.</term>
/// </item>
/// <item>
/// <term>The buffer values must be allocated in process virtual memory, not from the pool.</term>
/// </item>
/// </list>
/// <para>
/// When you have finished using the returned credentials, free the memory used by the credentials by calling the
/// FreeCredentialsHandle function.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-acquirecredentialshandlea SECURITY_STATUS SEC_ENTRY
// AcquireCredentialsHandleA( LPSTR pszPrincipal, LPSTR pszPackage, unsigned long fCredentialUse, void *pvLogonId, void *pAuthData,
// SEC_GET_KEY_FN pGetKeyFn, void *pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry );
[DllImport(Lib.Secur32, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("sspi.h", MSDNShortId = "3b73decf-75d4-4bc4-b7ca-5f16aaadff29")]
public static extern HRESULT AcquireCredentialsHandle([Optional] string pszPrincipal, string pszPackage, SECPKG_CRED fCredentialUse, [In, Optional] IntPtr pvLogonId, [In, Optional] IntPtr pAuthData, [In, Optional] IntPtr pGetKeyFn,
[In, Optional] IntPtr pvGetKeyArgument, out CredHandle phCredential, out TimeStamp ptsExpiry);
/// <summary>
/// <para>
/// The <c>AcquireCredentialsHandle (CredSSP)</c> function acquires a handle to preexisting credentials of a security principal. This
/// handle is required by the InitializeSecurityContext (CredSSP) and AcceptSecurityContext (CredSSP) functions. These can be either
/// preexisting credentials, which are established through a system logon that is not described here, or the caller can provide
/// alternative credentials.
/// </para>
/// <para><c>Note</c> This is not a "log on to the network" and does not imply gathering of credentials.</para>
/// </summary>
/// <param name="pszPrincipal">
/// <para>A pointer to a null-terminated string that specifies the name of the principal whose credentials the handle will reference.</para>
/// <para>
/// <c>Note</c> If the process that requests the handle does not have access to the credentials, the function returns an error. A
/// null string indicates that the process requires a handle to the credentials of the user under whose security context it is executing.
/// </para>
/// </param>
/// <param name="pszPackage">
/// A pointer to a null-terminated string that specifies the name of the security package with which these credentials will be used.
/// This is a security package name returned in the <c>Name</c> member of a SecPkgInfo structure returned by the
/// EnumerateSecurityPackages function. After a context is established, QueryContextAttributes (CredSSP) can be called with
/// ulAttribute set to <c>SECPKG_ATTR_PACKAGE_INFO</c> to return information on the security package in use.
/// </param>
/// <param name="fCredentialUse">
/// <para>A flag that indicates how these credentials will be used. This parameter can be one of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>SECPKG_CRED_INBOUND 0x1</term>
/// <term>
/// Validate an incoming server credential. Inbound credentials might be validated by using an authenticating authority when
/// InitializeSecurityContext (CredSSP) or AcceptSecurityContext (CredSSP) is called. If such an authority is not available, the
/// function will fail and return SEC_E_NO_AUTHENTICATING_AUTHORITY. Validation is package specific.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_CRED_OUTBOUND 0x0</term>
/// <term>Allow a local client credential to prepare an outgoing token.</term>
/// </item>
/// </list>
/// </param>
/// <param name="pvLogonId">
/// A pointer to a locally unique identifier (LUID) that identifies the user. This parameter is provided for file-system processes
/// such as network redirectors. This parameter can be <c>NULL</c>.
/// </param>
/// <param name="pAuthData">
/// A pointer to a CREDSSP_CRED structure that specifies authentication data for both Schannel and Negotiate packages.
/// </param>
/// <param name="pGetKeyFn">Reserved. This parameter is not used and should be set to <c>NULL</c>.</param>
/// <param name="pvGetKeyArgument">Reserved. This parameter must be set to <c>NULL</c>.</param>
/// <param name="phCredential">A pointer to the CredHandle structure that will receive the credential handle.</param>
/// <param name="ptsExpiry">
/// A pointer to a TimeStamp structure that receives the time at which the returned credentials expire. The structure value received
/// depends on the security package, which must specify the value in local time.
/// </param>
/// <returns>
/// <para>If the function succeeds, it returns <c>SEC_E_OK</c>.</para>
/// <para>If the function fails, it returns one of the following error codes.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>SEC_E_INSUFFICIENT_MEMORY</term>
/// <term>There is insufficient memory available to complete the requested action.</term>
/// </item>
/// <item>
/// <term>SEC_E_INTERNAL_ERROR</term>
/// <term>An error occurred that did not map to an SSPI error code.</term>
/// </item>
/// <item>
/// <term>SEC_E_NO_CREDENTIALS</term>
/// <term>No credentials are available in the security package.</term>
/// </item>
/// <item>
/// <term>SEC_E_NOT_OWNER</term>
/// <term>The caller of the function does not have the necessary credentials.</term>
/// </item>
/// <item>
/// <term>SEC_E_SECPKG_NOT_FOUND</term>
/// <term>The requested security package does not exist.</term>
/// </item>
/// <item>
/// <term>SEC_E_UNKNOWN_CREDENTIALS</term>
/// <term>The credentials supplied to the package were not recognized.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// The <c>AcquireCredentialsHandle (CredSSP)</c> function returns a handle to the credentials of a principal, such as a user or
/// client, as used by a specific security package. The function can return the handle to either preexisting credentials or newly
/// created credentials and return it. This handle can be used in subsequent calls to the AcceptSecurityContext (CredSSP) and
/// InitializeSecurityContext (CredSSP) functions.
/// </para>
/// <para>
/// In general, <c>AcquireCredentialsHandle (CredSSP)</c> does not provide the credentials of other users logged on to the same
/// computer. However, a caller with SE_TCB_NAME privilege can obtain the credentials of an existing logon session by specifying the
/// logon identifier (LUID) of that session. Typically, this is used by kernel-mode modules that must act on behalf of a logged-on user.
/// </para>
/// <para>
/// A package might call the function in pGetKeyFn provided by the RPC run-time transport. If the transport does not support the
/// notion of callback to retrieve credentials, this parameter must be <c>NULL</c>.
/// </para>
/// <para>For kernel mode callers, the following differences must be noted:</para>
/// <list type="bullet">
/// <item>
/// <term>The two string parameters must be Unicode strings.</term>
/// </item>
/// <item>
/// <term>The buffer values must be allocated in process virtual memory, not from the pool.</term>
/// </item>
/// </list>
/// <para>
/// When you have finished using the returned credentials, free the memory used by the credentials by calling the
/// FreeCredentialsHandle function.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-acquirecredentialshandlea SECURITY_STATUS SEC_ENTRY
// AcquireCredentialsHandleA( LPSTR pszPrincipal, LPSTR pszPackage, unsigned long fCredentialUse, void *pvLogonId, void *pAuthData,
// SEC_GET_KEY_FN pGetKeyFn, void *pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry );
[DllImport(Lib.Secur32, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("sspi.h", MSDNShortId = "3b73decf-75d4-4bc4-b7ca-5f16aaadff29")]
public static extern HRESULT AcquireCredentialsHandle([Optional] string pszPrincipal, string pszPackage, SECPKG_CRED fCredentialUse, in LUID pvLogonId, in CREDSSP_CRED pAuthData, [In, Optional] SEC_GET_KEY_FN pGetKeyFn,
[In, Optional] IntPtr pvGetKeyArgument, out CredHandle phCredential, out TimeStamp ptsExpiry);
/// <summary>Adds a security support provider to the list of providers supported by Microsoft Negotiate.</summary>
/// <param name="pszPackageName">The name of the package to add.</param>
/// <param name="pOptions">
/// A pointer to a SECURITY_PACKAGE_OPTIONS structure that specifies additional information about the security package.
/// </param>
/// <returns>
/// <para>If the function succeeds, it returns <c>SEC_E_OK</c>.</para>
/// <para>If the function fails, it returns a nonzero error code.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-addsecuritypackagea SECURITY_STATUS SEC_ENTRY
// AddSecurityPackageA( LPSTR pszPackageName, PSECURITY_PACKAGE_OPTIONS pOptions );
[DllImport(Lib.Secur32, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("sspi.h", MSDNShortId = "35b993d2-87a0-46d0-991f-88358b0cc5e6")]
public static extern HRESULT AddSecurityPackage(string pszPackageName, in SECURITY_PACKAGE_OPTIONS pOptions);
/// <summary>Adds a security support provider to the list of providers supported by Microsoft Negotiate.</summary>
/// <param name="pszPackageName">The name of the package to add.</param>
/// <param name="pOptions">
/// A pointer to a SECURITY_PACKAGE_OPTIONS structure that specifies additional information about the security package.
/// </param>
/// <returns>
/// <para>If the function succeeds, it returns <c>SEC_E_OK</c>.</para>
/// <para>If the function fails, it returns a nonzero error code.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-addsecuritypackagea SECURITY_STATUS SEC_ENTRY
// AddSecurityPackageA( LPSTR pszPackageName, PSECURITY_PACKAGE_OPTIONS pOptions );
[DllImport(Lib.Secur32, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("sspi.h", MSDNShortId = "35b993d2-87a0-46d0-991f-88358b0cc5e6")]
public static extern HRESULT AddSecurityPackage(string pszPackageName, [Optional] IntPtr pOptions);
/// <summary>
/// <para>
/// The <c>ApplyControlToken</c> function provides a way to apply a control token to a security context. A token can be received when
/// the security context is being established by a call to the InitializeSecurityContext (Schannel) function or with a per-message
/// security service, such as verify or unseal.
/// </para>
/// <para>This function is supported only by the Schannel security support provider (SSP).</para>
/// <para>This function is not supported in kernel mode.</para>
/// <para>This function allows additional or replacement tokens to be applied to a context.</para>
/// </summary>
/// <param name="phContext">
/// <para>A handle to the context to which the token is applied.</para>
/// <para>
/// For information about the way the Schannel SSP notifies the remote party of the shutdown, see the Remarks section of
/// DecryptMessage (Schannel). For additional information on the use of this function, see Shutting Down an Schannel Connection.
/// </para>
/// </param>
/// <param name="pInput">
/// A pointer to a SecBufferDesc structure that contains a pointer to a SecBuffer structure that contains the input token to apply to
/// the context.
/// </param>
/// <returns>
/// <para>If the function succeeds, the function returns SEC_E_OK.</para>
/// <para>
/// If the function fails, it returns a nonzero error code. The following error code is one of the possible error codes that can be returned.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>SEC_E_UNSUPPORTED_FUNCTION</term>
/// <term>This value is returned by Schannel kernel mode to indicate that this function is not supported.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// The <c>ApplyControlToken</c> function can modify the context based on this token. Among the tokens that this function can add to
/// the client context are SCHANNEL_ALERT_TOKEN and SCHANNEL_SESSION_TOKEN.
/// </para>
/// <para>
/// This function can be used to shut down the security context that underlies an existing Schannel connection. For information about
/// how to do this, see Shutting Down an Schannel Connection.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-applycontroltoken KSECDDDECLSPEC SECURITY_STATUS SEC_ENTRY
// ApplyControlToken( PCtxtHandle phContext, PSecBufferDesc pInput );
[DllImport(Lib.Secur32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("sspi.h", MSDNShortId = "5ce13a05-874c-4e1a-9be8-aed98609791e")]
public static extern HRESULT ApplyControlToken(in CtxtHandle phContext, in SecBufferDesc pInput);
/// <summary>
/// <para>
/// The <c>ChangeAccountPassword</c> function changes the password for a Windows domain account by using the specified Security
/// Support Provider.
/// </para>
/// <para>This function is supported only by the Microsoft Kerberos, Microsoft Negotiate, and Microsoft NTLM providers.</para>
/// </summary>
/// <param name="pszPackageName">
/// The name of the provider to use. The value of this parameter must be either "Kerberos", "Negotiate", or "NTLM".
/// </param>
/// <param name="pszDomainName">The domain of the account for which to change the password.</param>
/// <param name="pszAccountName">The user name of the account for which to change the password.</param>
/// <param name="pszOldPassword">The old password to be changed.</param>
/// <param name="pszNewPassword">The new password for the specified account.</param>
/// <param name="bImpersonating"><c>TRUE</c> if the calling process is running as the client; otherwise, <c>FALSE</c>.</param>
/// <param name="dwReserved">Reserved. Must be set to zero.</param>
/// <param name="pOutput">
/// On input, a pointer to a SecBufferDesc structure. The <c>SecBufferDesc</c> structure must contain a single buffer of type
/// <c>SECBUFFER_CHANGE_PASS_RESPONSE</c>. On output, the <c>pvBuffer</c> member of that structure points to a
/// DOMAIN_PASSWORD_INFORMATION structure.
/// </param>
/// <returns>
/// <para>If the function succeeds, the function returns SEC_E_OK.</para>
/// <para>If the function fails, it returns an error code.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-changeaccountpassworda SECURITY_STATUS SEC_ENTRY
// ChangeAccountPasswordA( SEC_CHAR *pszPackageName, SEC_CHAR *pszDomainName, SEC_CHAR *pszAccountName, SEC_CHAR *pszOldPassword,
// SEC_CHAR *pszNewPassword, BOOLEAN bImpersonating, unsigned long dwReserved, PSecBufferDesc pOutput );
[DllImport(Lib.Secur32, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("sspi.h", MSDNShortId = "a1d1e315-d1a2-499a-b552-83180508271f")]
public static extern HRESULT ChangeAccountPassword(string pszPackageName, string pszDomainName, string pszAccountName, string pszOldPassword, string pszNewPassword, [MarshalAs(UnmanagedType.U1)] bool bImpersonating,
[Optional] uint dwReserved, ref SecBufferDesc pOutput);
/// <summary>
/// <para>
/// The <c>CompleteAuthToken</c> function completes an authentication token. This function is used by protocols, such as DCE, that
/// need to revise the security information after the transport application has updated some message parameters.
/// </para>
/// <para>This function is supported only by the Digest security support provider (SSP).</para>
/// <para><c>CompleteAuthToken</c> is used on the server side only.</para>
/// </summary>
/// <param name="phContext">A handle of the context that needs to be completed.</param>
/// <param name="pToken">A pointer to a SecBufferDesc structure that contains the buffer descriptor for the entire message.</param>
/// <returns>
/// <para>If the function succeeds, the function returns SEC_E_OK.</para>
/// <para>If the function fails, it returns one of the following error codes.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>SEC_E_INVALID_HANDLE</term>
/// <term>The handle that was passed to the function is not valid.</term>
/// </item>
/// <item>
/// <term>SEC_E_INVALID_TOKEN</term>
/// <term>The token that was passed to the function is not valid.</term>
/// </item>
/// <item>
/// <term>SEC_E_OUT_OF_SEQUENCE</term>
/// <term>
/// The client's security context was located, but the message number is incorrect. This return value is used with the Digest SSP.
/// </term>
/// </item>
/// <item>
/// <term>SEC_E_MESSAGE_ALTERED</term>
/// <term>
/// The client's security context was located, but the client's message has been tampered with. This return value is used with the
/// Digest SSP.
/// </term>
/// </item>
/// <item>
/// <term>SEC_E_INTERNAL_ERROR</term>
/// <term>An error occurred that did not map to an SSPI error code.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// The client of a transport application calls the <c>CompleteAuthToken</c> function to allow the security package to update a
/// checksum or similar operation after all the protocol headers have been updated by the transport application. The client calls
/// this function only if the InitializeSecurityContext (Digest) call returned SEC_I_COMPLETE_NEEDED or SEC_I_COMPLETE_AND_CONTINUE.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-completeauthtoken SECURITY_STATUS SEC_ENTRY CompleteAuthToken(
// PCtxtHandle phContext, PSecBufferDesc pToken );
[DllImport(Lib.Secur32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("sspi.h", MSDNShortId = "a404d0a3-d1ea-4708-87d7-2d216e9a5f5f")]
public static extern HRESULT CompleteAuthToken(in CtxtHandle phContext, in SecBufferDesc pToken);
/// <summary>
/// <para>
/// The <c>DecryptMessage (Digest)</c> function decrypts a message. Some packages do not encrypt and decrypt messages but rather
/// perform and check an integrity hash.
/// </para>
/// <para>
/// The Digest security support provider (SSP) provides encryption and decryption confidentiality for messages exchanged between
/// client and server as a SASL mechanism only.
/// </para>
/// <para>
/// <c>Note</c> EncryptMessage (Digest) and <c>DecryptMessage (Digest)</c> can be called at the same time from two different threads
/// in a single Security Support Provider Interface (SSPI) context if one thread is encrypting and the other is decrypting. If more
/// than one thread is encrypting, or more than one thread is decrypting, each thread should obtain a unique context.
/// </para>
/// </summary>
/// <param name="phContext">A handle to the security context to be used to decrypt the message.</param>
/// <param name="pMessage">
/// <para>
/// A pointer to a SecBufferDesc structure. On input, the structure references one or more SecBuffer structures. At least one of
/// these must be of type SECBUFFER_DATA. That buffer contains the encrypted message. The encrypted message is decrypted in place,
/// overwriting the original contents of its buffer.
/// </para>
/// <para>
/// When using the Digest SSP, on input, the structure references one or more SecBuffer structures. One of these must be of type
/// SECBUFFER_DATA or SECBUFFER_STREAM, and it must contain the encrypted message.
/// </para>
/// </param>
/// <param name="MessageSeqNo">
/// <para>
/// The sequence number expected by the transport application, if any. If the transport application does not maintain sequence
/// numbers, this parameter must be set to zero.
/// </para>
/// <para>When using the Digest SSP, this parameter must be set to zero. The Digest SSP manages sequence numbering internally.</para>
/// </param>
/// <param name="pfQOP">
/// <para>A pointer to a variable of type <c>ULONG</c> that receives package-specific flags that indicate the quality of protection.</para>
/// <para>This parameter can be one of the following flags.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>SECQOP_WRAP_NO_ENCRYPT</term>
/// <term>The message was not encrypted, but a header or trailer was produced.</term>
/// </item>
/// <item>
/// <term>SIGN_ONLY</term>
/// <term>
/// When using the Digest SSP, use this flag when the security context is set to verify the signature only. For more information, see
/// Quality of Protection.
/// </term>
/// </item>
/// </list>
/// </param>
/// <returns>
/// <para>If the function verifies that the message was received in the correct sequence, the function returns SEC_E_OK.</para>
/// <para>If the function fails to decrypt the message, it returns one of the following error codes.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>SEC_E_BUFFER_TOO_SMALL</term>
/// <term>The message buffer is too small. Used with the Digest SSP.</term>
/// </item>
/// <item>
/// <term>SEC_E_CRYPTO_SYSTEM_INVALID</term>
/// <term>The cipher chosen for the security context is not supported. Used with the Digest SSP.</term>
/// </item>
/// <item>
/// <term>SEC_E_INCOMPLETE_MESSAGE</term>
/// <term>
/// The data in the input buffer is incomplete. The application needs to read more data from the server and call DecryptMessage
/// (Digest) again.
/// </term>
/// </item>
/// <item>
/// <term>SEC_E_INVALID_HANDLE</term>
/// <term>A context handle that is not valid was specified in the phContext parameter. Used with the Digest SSP.</term>
/// </item>
/// <item>
/// <term>SEC_E_MESSAGE_ALTERED</term>
/// <term>The message has been altered. Used with the Digest SSP.</term>
/// </item>
/// <item>
/// <term>SEC_E_OUT_OF_SEQUENCE</term>
/// <term>The message was not received in the correct sequence.</term>
/// </item>
/// <item>
/// <term>SEC_E_QOP_NOT_SUPPORTED</term>
/// <term>Neither confidentiality nor integrity are supported by the security context. Used with the Digest SSP.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// Sometimes an application will read data from the remote party, attempt to decrypt it by using <c>DecryptMessage (Digest)</c>, and
/// discover that <c>DecryptMessage (Digest)</c> succeeded but the output buffers are empty. This is normal behavior, and
/// applications must be able to deal with it.
/// </para>
/// <para>
/// <c>Windows XP:</c> This function was also known as <c>UnsealMessage</c>. Applications should now use <c>DecryptMessage
/// (Digest)</c> only.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-decryptmessage SECURITY_STATUS SEC_ENTRY DecryptMessage(
// PCtxtHandle phContext, PSecBufferDesc pMessage, unsigned long MessageSeqNo, unsigned long *pfQOP );
[DllImport(Lib.Secur32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("sspi.h", MSDNShortId = "46d45f59-33fa-434a-b329-20b6257c9a19")]
public static extern HRESULT DecryptMessage(in CtxtHandle phContext, ref SecBufferDesc pMessage, uint MessageSeqNo, out SECQOP pfQOP);
/// <summary>
/// The <c>DeleteSecurityContext</c> function deletes the local data structures associated with the specified security context
/// initiated by a previous call to the InitializeSecurityContext (General) function or the AcceptSecurityContext (General) function.
/// </summary>
/// <param name="phContext">Handle of the security context to delete.</param>
/// <returns>
/// <para>If the function succeeds or the handle has already been deleted, the return value is <c>SEC_E_OK</c>.</para>
/// <para>If the function fails, the return value can be the following error code.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>SEC_E_INVALID_HANDLE</term>
/// <term>The handle passed to the function is not valid.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>The <c>DeleteSecurityContext</c> function terminates a security context and frees associated resources.</para>
/// <para>
/// The caller must call this function for a security context when that security context is no longer needed. This is true if the
/// security context is partial, incomplete, rejected, or failed. After the security context is successfully deleted, further use of
/// that security context is not permitted and the handle is no longer valid.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-deletesecuritycontext KSECDDDECLSPEC SECURITY_STATUS SEC_ENTRY
// DeleteSecurityContext( PCtxtHandle phContext );
[DllImport(Lib.Secur32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("sspi.h", MSDNShortId = "2a4dd697-ef90-4c37-ab74-0e5ab92794cd")]
public static extern HRESULT DeleteSecurityContext(in CtxtHandle phContext);
/// <summary>Deletes a security support provider from the list of providers supported by Microsoft Negotiate.</summary>
/// <param name="pszPackageName">The name of the security provider to delete.</param>
/// <returns>
/// <para>If the function succeeds, it returns <c>SEC_E_OK</c>.</para>
/// <para>If the function fails, it returns a nonzero error code.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-deletesecuritypackagea SECURITY_STATUS SEC_ENTRY
// DeleteSecurityPackageA( LPSTR pszPackageName );
[DllImport(Lib.Secur32, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("sspi.h", MSDNShortId = "7a9a2c64-92a4-419b-8b20-d0f5cba64147")]
public static extern HRESULT DeleteSecurityPackage(string pszPackageName);
/// <summary>
/// <para>
/// The <c>EncryptMessage (Digest)</c> function encrypts a message to provide privacy. <c>EncryptMessage (Digest)</c> allows the
/// application to choose among cryptographic algorithms supported by the chosen mechanism. The <c>EncryptMessage (Digest)</c>
/// function uses the security context referenced by the context handle. Some packages do not have messages to be encrypted or
/// decrypted but rather provide an integrity hash that can be checked.
/// </para>
/// <para>This function is available as a SASL mechanism only.</para>
/// <para>
/// <c>Note</c><c>EncryptMessage (Digest)</c> and DecryptMessage (Digest) can be called at the same time from two different threads
/// in a single Security Support Provider Interface (SSPI) context if one thread is encrypting and the other is decrypting. If more
/// than one thread is encrypting, or more than one thread is decrypting, each thread should obtain a unique context.
/// </para>
/// </summary>
/// <param name="phContext">A handle to the security context to be used to encrypt the message.</param>
/// <param name="fQOP">
/// <para>
/// Package-specific flags that indicate the quality of protection. A security package can use this parameter to enable the selection
/// of cryptographic algorithms.
/// </para>
/// <para>When using the Digest SSP, this parameter must be set to zero.</para>
/// </param>
/// <param name="pMessage">
/// <para>
/// A pointer to a SecBufferDesc structure. On input, the structure references one or more SecBuffer structures that can be of type
/// SECBUFFER_DATA. That buffer contains the message to be encrypted. The message is encrypted in place, overwriting the original
/// contents of the structure.
/// </para>
/// <para>The function does not process buffers with the SECBUFFER_READONLY attribute.</para>
/// <para>
/// The length of the SecBuffer structure that contains the message must be no greater than <c>cbMaximumMessage</c>, which is
/// obtained from the QueryContextAttributes (Digest) (SECPKG_ATTR_STREAM_SIZES) function.
/// </para>
/// <para>
/// When using the Digest SSP, there must be a second buffer of type SECBUFFER_PADDING or SEC_BUFFER_DATA to hold signature
/// information. To get the size of the output buffer, call the QueryContextAttributes (Digest) function and specify
/// SECPKG_ATTR_SIZES. The function will return a SecPkgContext_Sizes structure. The size of the output buffer is the sum of the
/// values in the <c>cbMaxSignature</c> and <c>cbBlockSize</c> members.
/// </para>
/// <para>Applications that do not use SSL must supply a SecBuffer of type SECBUFFER_PADDING.</para>
/// </param>
/// <param name="MessageSeqNo">
/// <para>
/// The sequence number that the transport application assigned to the message. If the transport application does not maintain
/// sequence numbers, this parameter must be zero.
/// </para>
/// <para>When using the Digest SSP, this parameter must be set to zero. The Digest SSP manages sequence numbering internally.</para>
/// </param>
/// <returns>
/// <para>If the function succeeds, the function returns SEC_E_OK.</para>
/// <para>If the function fails, it returns one of the following error codes.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>SEC_E_BUFFER_TOO_SMALL</term>
/// <term>The output buffer is too small. For more information, see Remarks.</term>
/// </item>
/// <item>
/// <term>SEC_E_CONTEXT_EXPIRED</term>
/// <term>
/// The application is referencing a context that has already been closed. A properly written application should not receive this error.
/// </term>
/// </item>
/// <item>
/// <term>SEC_E_CRYPTO_SYSTEM_INVALID</term>
/// <term>The cipher chosen for the security context is not supported.</term>
/// </item>
/// <item>
/// <term>SEC_E_INSUFFICIENT_MEMORY</term>
/// <term>There is not enough memory available to complete the requested action.</term>
/// </item>
/// <item>
/// <term>SEC_E_INVALID_HANDLE</term>
/// <term>A context handle that is not valid was specified in the phContext parameter.</term>
/// </item>
/// <item>
/// <term>SEC_E_INVALID_TOKEN</term>
/// <term>No SECBUFFER_DATA type buffer was found.</term>
/// </item>
/// <item>
/// <term>SEC_E_QOP_NOT_SUPPORTED</term>
/// <term>Neither confidentiality nor integrity are supported by the security context.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// The <c>EncryptMessage (Digest)</c> function encrypts a message based on the message and the session key from a security context.
/// </para>
/// <para>
/// If the transport application created the security context to support sequence detection and the caller provides a sequence
/// number, the function includes this information with the encrypted message. Including this information protects against replay,
/// insertion, and suppression of messages. The security package incorporates the sequence number passed down from the transport application.
/// </para>
/// <para>
/// When you use the Digest SSP, get the size of the output buffer by calling the QueryContextAttributes (Digest) function and
/// specifying SECPKG_ATTR_SIZES. The function will return a SecPkgContext_Sizes structure. The size of the output buffer is the sum
/// of the values in the <c>cbMaxSignature</c> and <c>cbBlockSize</c> members.
/// </para>
/// <para><c>Note</c> These buffers must be supplied in the order shown.</para>
/// <list type="table">
/// <listheader>
/// <term>Buffer type</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>SECBUFFER_STREAM_HEADER</term>
/// <term>Used internally. No initialization required.</term>
/// </item>
/// <item>
/// <term>SECBUFFER_DATA</term>
/// <term>Contains the plaintext message to be encrypted.</term>
/// </item>
/// <item>
/// <term>SECBUFFER_STREAM_TRAILER</term>
/// <term>Used internally. No initialization required.</term>
/// </item>
/// <item>
/// <term>SECBUFFER_EMPTY</term>
/// <term>Used internally. No initialization required. Size can be zero.</term>
/// </item>
/// </list>
/// <para>For optimal performance, the pMessage structures should be allocated from contiguous memory.</para>
/// <para>
/// <c>Windows XP:</c> This function was also known as <c>SealMessage</c>. Applications should now use <c>EncryptMessage (Digest)</c> only.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-encryptmessage SECURITY_STATUS SEC_ENTRY EncryptMessage(
// PCtxtHandle phContext, unsigned long fQOP, PSecBufferDesc pMessage, unsigned long MessageSeqNo );
[DllImport(Lib.Secur32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("sspi.h", MSDNShortId = "0045e931-929b-40c4-a524-5664d2fc5170")]
public static extern HRESULT EncryptMessage(in CtxtHandle phContext, SECQOP fQOP, ref SecBufferDesc pMessage, uint MessageSeqNo);
/// <summary>
/// The <c>EnumerateSecurityPackages</c> function returns an array of SecPkgInfo structures that provide information about the
/// security packages available to the client.
/// </summary>
/// <param name="pcPackages">
/// A pointer to a <c>ULONG</c> variable that receives the number of packages available on the system. This includes packages that
/// are already loaded and packages available on demand.
/// </param>
/// <param name="ppPackageInfo">
/// <para>
/// A pointer to a variable that receives a pointer to an array of SecPkgInfo structures. Each structure contains information from
/// the security support provider (SSP) that describes the capabilities of the security package available within that SSP.
/// </para>
/// <para>When you have finished using the array, free the memory by calling the FreeContextBuffer function.</para>
/// </param>
/// <returns>
/// <para>If the function succeeds, the function returns <c>SEC_E_OK</c>.</para>
/// <para>
/// If the function fails, it returns a nonzero error code. Possible values include, but are not limited to, those in the following table.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code/value</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>SEC_E_INSUFFICIENT_MEMORY 0x80090300L</term>
/// <term>There was not sufficient memory to allocate one or more of the buffers.</term>
/// </item>
/// <item>
/// <term>SEC_E_INVALID_HANDLE 0x80090301L</term>
/// <term>An invalid handle was specified.</term>
/// </item>
/// <item>
/// <term>SEC_E_SECPKG_NOT_FOUND 0x80090305L</term>
/// <term>The specified package was not found.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// The caller can use the <c>Name</c> member of a SecPkgInfo structure to specify a security package in a call to the
/// AcquireCredentialsHandle (General) function.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-enumeratesecuritypackagesa SECURITY_STATUS SEC_ENTRY
// EnumerateSecurityPackagesA( unsigned long *pcPackages, PSecPkgInfoA *ppPackageInfo );
[DllImport(Lib.Secur32, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("sspi.h", MSDNShortId = "900790a6-111d-43f5-9316-e85aab03a3bc")]
public static extern HRESULT EnumerateSecurityPackages(out uint pcPackages, out SafeContextBuffer ppPackageInfo);
/// <summary>
/// The <c>ExportSecurityContext</c> function creates a serialized representation of a security context that can later be imported
/// into a different process by calling ImportSecurityContext. The process that imports the security context must be running on the
/// same computer as the process that called <c>ExportSecurityContext</c>.
/// </summary>
/// <param name="phContext">A handle of the security context to be exported.</param>
/// <param name="fFlags">
/// <para>This parameter can be a bitwise- <c>OR</c> combination of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>SECPKG_CONTEXT_EXPORT_RESET_NEW 1 (0x1)</term>
/// <term>The new security context is reset to its initial state.</term>
/// </item>
/// <item>
/// <term>SECPKG_CONTEXT_EXPORT_DELETE_OLD 2 (0x2)</term>
/// <term>The old security context is deleted.</term>
/// </item>
/// <item>
/// <term>SECPKG_CONTEXT_EXPORT_TO_KERNEL 4 (0x4)</term>
/// <term>
/// This value is not supported. Windows Server 2003 and Windows XP/2000: The security context is to be exported to the kernel.This
/// value is supported only in Schannel kernel mode.
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="pPackedContext">
/// A pointer to a buffer of type <c>SECBUFFER_EMPTY</c> that receives the serialized security context. When you have finished using
/// this context, free it by calling the FreeContextBuffer function.
/// </param>
/// <param name="pToken">
/// <para>A pointer to receive the handle of the context's token.</para>
/// <para>When you have finished using the user token, release the handle by calling the CloseHandle function.</para>
/// </param>
/// <returns>
/// <para>If the function succeeds, the function returns SEC_E_OK.</para>
/// <para>If the function fails, it returns one of the following error codes.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>SEC_E_INSUFFICIENT_MEMORY</term>
/// <term>There is not enough memory available to complete the requested action.</term>
/// </item>
/// <item>
/// <term>SEC_E_INVALID_HANDLE</term>
/// <term>The phContext parameter does not point to a valid handle.</term>
/// </item>
/// <item>
/// <term>SEC_E_NOT_SUPPORTED</term>
/// <term>Schannel kernel mode does not support this function.</term>
/// </item>
/// </list>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-exportsecuritycontext KSECDDDECLSPEC SECURITY_STATUS SEC_ENTRY
// ExportSecurityContext( PCtxtHandle phContext, ULONG fFlags, PSecBuffer pPackedContext, void **pToken );
[DllImport(Lib.Secur32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("sspi.h", MSDNShortId = "4ebc7f37-b948-4c78-973f-0a74e55c7ee2")]
public static extern HRESULT ExportSecurityContext(in CtxtHandle phContext, SECPKG_CONTEXT_EXPORT fFlags, ref SecBuffer pPackedContext, out SafeHTOKEN pToken);
/// <summary>
/// The <c>FreeContextBuffer</c> function enables callers of security package functions to free memory buffers allocated by the
/// security package.
/// </summary>
/// <param name="pvContextBuffer">A pointer to memory to be freed.</param>
/// <returns>
/// <para>If the function succeeds, the function returns SEC_E_OK.</para>
/// <para>If the function fails, it returns a nonzero error code.</para>
/// </returns>
/// <remarks>
/// <para>
/// Memory buffers are typically allocated by the InitializeSecurityContext (General) and AcceptSecurityContext (General) functions.
/// </para>
/// <para>The <c>FreeContextBuffer</c> function can free any memory allocated by a security package.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-freecontextbuffer SECURITY_STATUS SEC_ENTRY FreeContextBuffer(
// PVOID pvContextBuffer );
[DllImport(Lib.Secur32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("sspi.h", MSDNShortId = "3c3d27bb-4f9a-4979-b679-1e10fa1ff221")]
public static extern HRESULT FreeContextBuffer(IntPtr pvContextBuffer);
/// <summary>
/// <para>
/// The <c>FreeCredentialsHandle</c> function notifies the security system that the credentials are no longer needed. An application
/// calls this function to free the credential handle acquired in the call to the AcquireCredentialsHandle (General) function after
/// calling the DeleteSecurityContext function to free any context handles associated with the credential. When all references to
/// this credential set have been removed, the credentials themselves can be removed.
/// </para>
/// <para>Failure to free credentials handles will result in memory leaks.</para>
/// </summary>
/// <param name="phCredential">A pointer to the CredHandle handle obtained by using the AcquireCredentialsHandle (General) function.</param>
/// <returns>
/// <para>If the function succeeds, the function returns SEC_E_OK.</para>
/// <para>If the function fails, it returns the following error code.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>SEC_E_INVALID_HANDLE</term>
/// <term>The handle passed to the function is not valid.</term>
/// </item>
/// </list>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-freecredentialshandle KSECDDDECLSPEC SECURITY_STATUS SEC_ENTRY
// FreeCredentialsHandle( PCredHandle phCredential );
[DllImport(Lib.Secur32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("sspi.h", MSDNShortId = "e089618c-8233-475a-9725-39265c6427ab")]
public static extern HRESULT FreeCredentialsHandle(ref CredHandle phCredential);
/// <summary>
/// The <c>ImpersonateSecurityContext</c> function allows a server to impersonate a client by using a token previously obtained by a
/// call to AcceptSecurityContext (General) or QuerySecurityContextToken. This function allows the application server to act as the
/// client, and thus all necessary access controls are enforced.
/// </summary>
/// <param name="phContext">
/// The handle of the context to impersonate. This handle must have been obtained by a call to the AcceptSecurityContext (General) function.
/// </param>
/// <returns>
/// <para>If the function succeeds, the function returns SEC_E_OK.</para>
/// <para>If the function fails, it returns the following error code.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>SEC_E_INVALID_HANDLE</term>
/// <term>The handle passed to the function is not valid.</term>
/// </item>
/// <item>
/// <term>SEC_E_NO_IMPERSONATION</term>
/// <term>The client could not be impersonated.</term>
/// </item>
/// <item>
/// <term>SEC_E_UNSUPPORTED_FUNCTION</term>
/// <term>This value is returned by Schannel kernel mode to indicate that this function is not supported.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// The server application calls the <c>ImpersonateSecurityContext</c> function when it needs to impersonate the client. Before doing
/// so, the server must have obtained a valid context handle. To obtain the context handle, the server must call
/// AcceptSecurityContext (General) to submit the client's incoming security token to the security system. The server gets a context
/// handle if the inbound context is validated. The function creates an impersonation token and allows the thread or process to run
/// with the impersonation context.
/// </para>
/// <para>
/// When using the Schannel security support provider (SSP), the server application must pass the <c>ASC_REQ_MUTUAL_AUTH</c> flag
/// when calling AcceptSecurityContext (General). This ensures that the client is asked for a client certificate during the SSL/TLS
/// handshake. When a client certificate is received, the Schannel package verifies the client certificate and attempts to map it to
/// a user account. When this mapping is successful, then a client user token is created and this function succeeds.
/// </para>
/// <para>
/// The application server must call the RevertSecurityContext function when it finishes or when it needs to restore its own security context.
/// </para>
/// <para>
/// <c>ImpersonateSecurityContext</c> is not available with all security packages on all platforms. Typically, it is implemented only
/// on platforms and with security packages that support impersonation. To learn whether a security package supports impersonation,
/// call the QuerySecurityPackageInfo function.
/// </para>
/// <para>
/// <c>Note</c> If the <c>ImpersonateSecurityContext</c> function fails, the client is not impersonated, and all subsequent client
/// requests are made in the security context of the process that called the function. If the calling process is running as a
/// privileged account, it can perform actions that the client would not be allowed to perform. To avoid security risks, the calling
/// process should always check the return value. If the return value indicates that the function call failed, no client requests
/// should be executed.
/// </para>
/// <para>
/// All impersonate functions, including <c>ImpersonateSecurityContext</c> allow the requested impersonation if one of the following
/// is true:
/// </para>
/// <list type="bullet">
/// <item>
/// <term>
/// The requested impersonation level of the token is less than <c>SecurityImpersonation</c>, such as <c>SecurityIdentification</c>
/// or <c>SecurityAnonymous</c>.
/// </term>
/// </item>
/// <item>
/// <term>The caller has the <c>SeImpersonatePrivilege</c> privilege.</term>
/// </item>
/// <item>
/// <term>
/// A process (or another process in the caller's logon session) created the token using explicit credentials through LogonUser or
/// LsaLogonUser function.
/// </term>
/// </item>
/// <item>
/// <term>The authenticated identity is same as the caller.</term>
/// </item>
/// </list>
/// <para><c>Windows XP with SP1 and earlier:</c> The <c>SeImpersonatePrivilege</c> privilege is not supported.</para>
/// <para><c>Windows XP:</c> The SeImpersonatePrivilege privilege is not supported until Windows XP with Service Pack 2 (SP2).</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-impersonatesecuritycontext KSECDDDECLSPEC SECURITY_STATUS
// SEC_ENTRY ImpersonateSecurityContext( PCtxtHandle phContext );
[DllImport(Lib.Secur32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("sspi.h", MSDNShortId = "167eaf3b-b794-4587-946d-fa596f1f9411")]
public static extern HRESULT ImpersonateSecurityContext(in CtxtHandle phContext);
/// <summary>
/// The <c>ImportSecurityContext</c> function imports a security context. The security context must have been exported to the process
/// calling <c>ImportSecurityContext</c> by a previous call to ExportSecurityContext.
/// </summary>
/// <param name="pszPackage">A string that contains the name of the security package to which the security context was exported.</param>
/// <param name="pPackedContext">A pointer to a buffer that contains the serialized security context created by ExportSecurityContext.</param>
/// <param name="Token">A handle to the context's token.</param>
/// <param name="phContext">
/// A handle of the new security context created from pPackedContext. When you have finished using the context, delete it by calling
/// the DeleteSecurityContext function.
/// </param>
/// <returns>
/// <para>If the function succeeds, the function returns SEC_E_OK.</para>
/// <para>If the function fails, it returns one of the following error codes.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>SEC_E_UNKNOWN_CREDENTIALS</term>
/// <term>The credentials supplied to the package were not recognized.</term>
/// </item>
/// <item>
/// <term>SEC_E_NO_CREDENTIALS</term>
/// <term>No credentials are available in the security package.</term>
/// </item>
/// <item>
/// <term>SEC_E_NOT_OWNER</term>
/// <term>The caller of the function does not have the necessary credentials.</term>
/// </item>
/// <item>
/// <term>SEC_E_INSUFFICIENT_MEMORY</term>
/// <term>There is not enough memory available to complete the requested action.</term>
/// </item>
/// <item>
/// <term>SEC_E_INTERNAL_ERROR</term>
/// <term>An error occurred that did not map to an SSPI error code.</term>
/// </item>
/// </list>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-importsecuritycontexta SECURITY_STATUS SEC_ENTRY
// ImportSecurityContextA( LPSTR pszPackage, PSecBuffer pPackedContext, VOID *Token, PCtxtHandle phContext );
[DllImport(Lib.Secur32, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("sspi.h", MSDNShortId = "0f8e65d0-69cf-42ba-a903-1922d731e5ec")]
public static extern HRESULT ImportSecurityContext(string pszPackage, ref SecBuffer pPackedContext, HTOKEN Token, out SafeCtxtHandle phContext);
/// <summary>
/// <para>
/// The <c>InitializeSecurityContext (General)</c> function initiates the client side, outbound security context from a credential
/// handle. The function is used to build a security context between the client application and a remote peer.
/// <c>InitializeSecurityContext (General)</c> returns a token that the client must pass to the remote peer, which the peer in turn
/// submits to the local security implementation through the AcceptSecurityContext (General) call. The token generated should be
/// considered opaque by all callers.
/// </para>
/// <para>
/// Typically, the <c>InitializeSecurityContext (General)</c> function is called in a loop until a sufficient security context is established.
/// </para>
/// <para>For information about using this function with a specific security support provider (SSP), see the following topics.</para>
/// <list type="table">
/// <listheader>
/// <term>Topic</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>InitializeSecurityContext (CredSSP)</term>
/// <term>
/// Initiates the client side, outbound security context from a credential handle by using the Credential Security Support Provider (CredSSP).
/// </term>
/// </item>
/// <item>
/// <term>InitializeSecurityContext (Digest)</term>
/// <term>Initiates the client side, outbound security context from a credential handle by using the Digest security package.</term>
/// </item>
/// <item>
/// <term>InitializeSecurityContext (Kerberos)</term>
/// <term>Initiates the client side, outbound security context from a credential handle by using the Kerberos security package.</term>
/// </item>
/// <item>
/// <term>InitializeSecurityContext (Negotiate)</term>
/// <term>Initiates the client side, outbound security context from a credential handle by using the Negotiate security package.</term>
/// </item>
/// <item>
/// <term>InitializeSecurityContext (NTLM)</term>
/// <term>Initiates the client side, outbound security context from a credential handle by using the NTLM security package.</term>
/// </item>
/// <item>
/// <term>InitializeSecurityContext (Schannel)</term>
/// <term>Initiates the client side, outbound security context from a credential handle by using the Schannel security package.</term>
/// </item>
/// </list>
/// </summary>
/// <param name="phCredential">
/// A handle to the credentials returned by AcquireCredentialsHandle (General). This handle is used to build the security context.
/// The <c>InitializeSecurityContext (General)</c> function requires at least OUTBOUND credentials.
/// </param>
/// <param name="phContext">
/// <para>
/// A pointer to a CtxtHandle structure. On the first call to <c>InitializeSecurityContext (General)</c>, this pointer is
/// <c>NULL</c>. On the second call, this parameter is a pointer to the handle to the partially formed context returned in the
/// phNewContext parameter by the first call.
/// </para>
/// <para>This parameter is optional with the Microsoft Digest SSP and can be set to <c>NULL</c>.</para>
/// <para>
/// When using the Schannel SSP, on the first call to <c>InitializeSecurityContext (General)</c>, specify <c>NULL</c>. On future
/// calls, specify the token received in the phNewContext parameter after the first call to this function.
/// </para>
/// </param>
/// <param name="pszTargetName">TBD</param>
/// <param name="fContextReq">
/// <para>
/// Bit flags that indicate requests for the context. Not all packages can support all requirements. Flags used for this parameter
/// are prefixed with ISC_REQ_, for example, ISC_REQ_DELEGATE. This parameter can be one or more of the following attributes flags.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ISC_REQ_ALLOCATE_MEMORY</term>
/// <term>
/// The security package allocates output buffers for you. When you have finished using the output buffers, free them by calling the
/// FreeContextBuffer function.
/// </term>
/// </item>
/// <item>
/// <term>ISC_REQ_CONFIDENTIALITY</term>
/// <term>Encrypt messages by using the EncryptMessage function.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_CONNECTION</term>
/// <term>
/// The security context will not handle formatting messages. This value is the default for the Kerberos, Negotiate, and NTLM
/// security packages.
/// </term>
/// </item>
/// <item>
/// <term>ISC_REQ_DELEGATE</term>
/// <term>
/// The server can use the context to authenticate to other servers as the client. The ISC_REQ_MUTUAL_AUTH flag must be set for this
/// flag to work. Valid for Kerberos. Ignore this flag for constrained delegation.
/// </term>
/// </item>
/// <item>
/// <term>ISC_REQ_EXTENDED_ERROR</term>
/// <term>When errors occur, the remote party will be notified.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_HTTP</term>
/// <term>Use Digest for HTTP. Omit this flag to use Digest as a SASL mechanism.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_INTEGRITY</term>
/// <term>Sign messages and verify signatures by using the EncryptMessage and MakeSignature functions.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_MANUAL_CRED_VALIDATION</term>
/// <term>Schannel must not authenticate the server automatically.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_MUTUAL_AUTH</term>
/// <term>The mutual authentication policy of the service will be satisfied.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_NO_INTEGRITY</term>
/// <term>
/// If this flag is set, the ISC_REQ_INTEGRITY flag is ignored. This value is supported only by the Negotiate and Kerberos security packages.
/// </term>
/// </item>
/// <item>
/// <term>ISC_REQ_REPLAY_DETECT</term>
/// <term>Detect replayed messages that have been encoded by using the EncryptMessage or MakeSignature functions.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_SEQUENCE_DETECT</term>
/// <term>Detect messages received out of sequence.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_STREAM</term>
/// <term>Support a stream-oriented connection.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_USE_SESSION_KEY</term>
/// <term>A new session key must be negotiated. This value is supported only by the Kerberos security package.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_USE_SUPPLIED_CREDS</term>
/// <term>Schannel must not attempt to supply credentials for the client automatically.</term>
/// </item>
/// </list>
/// <para>The requested attributes may not be supported by the client. For more information, see the pfContextAttr parameter.</para>
/// <para>For further descriptions of the various attributes, see Context Requirements.</para>
/// </param>
/// <param name="Reserved1">This parameter is reserved and must be set to zero.</param>
/// <param name="TargetDataRep">
/// <para>The data representation, such as byte ordering, on the target. This parameter can be either SECURITY_NATIVE_DREP or SECURITY_NETWORK_DREP.</para>
/// <para>This parameter is not used with Digest or Schannel. Set it to zero.</para>
/// </param>
/// <param name="pInput">
/// A pointer to a SecBufferDesc structure that contains pointers to the buffers supplied as input to the package. Unless the client
/// context was initiated by the server, the value of this parameter must be <c>NULL</c> on the first call to the function. On
/// subsequent calls to the function or when the client context was initiated by the server, the value of this parameter is a pointer
/// to a buffer allocated with enough memory to hold the token returned by the remote computer.
/// </param>
/// <param name="Reserved2">This parameter is reserved and must be set to zero.</param>
/// <param name="phNewContext">
/// <para>
/// A pointer to a CtxtHandle structure. On the first call to <c>InitializeSecurityContext (General)</c>, this pointer receives the
/// new context handle. On the second call, phNewContext can be the same as the handle specified in the phContext parameter.
/// </para>
/// <para>
/// When using the Schannel SSP, on calls after the first call, pass the handle returned here as the phContext parameter and specify
/// <c>NULL</c> for phNewContext.
/// </para>
/// </param>
/// <param name="pOutput">
/// <para>
/// A pointer to a SecBufferDesc structure that contains pointers to the SecBuffer structure that receives the output data. If a
/// buffer was typed as SEC_READWRITE in the input, it will be there on output. The system will allocate a buffer for the security
/// token if requested (through ISC_REQ_ALLOCATE_MEMORY) and fill in the address in the buffer descriptor for the security token.
/// </para>
/// <para>When using the Microsoft Digest SSP, this parameter receives the challenge response that must be sent to the server.</para>
/// <para>
/// When using the Schannel SSP, if the ISC_REQ_ALLOCATE_MEMORY flag is specified, the Schannel SSP will allocate memory for the
/// buffer and put the appropriate information in the SecBufferDesc. In addition, the caller must pass in a buffer of type
/// <c>SECBUFFER_ALERT</c>. On output, if an alert is generated, this buffer contains information about that alert, and the function fails.
/// </para>
/// </param>
/// <param name="pfContextAttr">
/// <para>
/// A pointer to a variable to receive a set of bit flags that indicate the attributes of the established context. For a description
/// of the various attributes, see Context Requirements.
/// </para>
/// <para>Flags used for this parameter are prefixed with ISC_RET, such as ISC_RET_DELEGATE.</para>
/// <para>For a list of valid values, see the fContextReq parameter.</para>
/// <para>
/// Do not check for security-related attributes until the final function call returns successfully. Attribute flags that are not
/// related to security, such as the ASC_RET_ALLOCATED_MEMORY flag, can be checked before the final return.
/// </para>
/// <para><c>Note</c> Particular context attributes can change during negotiation with a remote peer.</para>
/// </param>
/// <param name="ptsExpiry">
/// <para>
/// A pointer to a TimeStamp structure that receives the expiration time of the context. It is recommended that the security package
/// always return this value in local time. This parameter is optional and <c>NULL</c> should be passed for short-lived clients.
/// </para>
/// <para>There is no expiration time for Microsoft Digest SSP security contexts or credentials.</para>
/// </param>
/// <returns>
/// <para>If the function succeeds, the function returns one of the following success codes.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>SEC_I_COMPLETE_AND_CONTINUE</term>
/// <term>
/// The client must call CompleteAuthToken and then pass the output to the server. The client then waits for a returned token and
/// passes it, in another call, to InitializeSecurityContext (General).
/// </term>
/// </item>
/// <item>
/// <term>SEC_I_COMPLETE_NEEDED</term>
/// <term>The client must finish building the message and then call the CompleteAuthToken function.</term>
/// </item>
/// <item>
/// <term>SEC_I_CONTINUE_NEEDED</term>
/// <term>
/// The client must send the output token to the server and wait for a return token. The returned token is then passed in another
/// call to InitializeSecurityContext (General). The output token can be empty.
/// </term>
/// </item>
/// <item>
/// <term>SEC_I_INCOMPLETE_CREDENTIALS</term>
/// <term>
/// Use with Schannel. The server has requested client authentication, and the supplied credentials either do not include a
/// certificate or the certificate was not issued by a certification authority that is trusted by the server. For more information,
/// see Remarks.
/// </term>
/// </item>
/// <item>
/// <term>SEC_E_INCOMPLETE_MESSAGE</term>
/// <term>
/// Use with Schannel. Data for the whole message was not read from the wire. When this value is returned, the pInput buffer contains
/// a SecBuffer structure with a BufferType member of SECBUFFER_MISSING. The cbBuffer member of SecBuffer contains a value that
/// indicates the number of additional bytes that the function must read from the client before this function succeeds. While this
/// number is not always accurate, using it can help improve performance by avoiding multiple calls to this function.
/// </term>
/// </item>
/// <item>
/// <term>SEC_E_OK</term>
/// <term>
/// The security context was successfully initialized. There is no need for another InitializeSecurityContext (General) call. If the
/// function returns an output token, that is, if the SECBUFFER_TOKEN in pOutput is of nonzero length, that token must be sent to the server.
/// </term>
/// </item>
/// </list>
/// <para>If the function fails, the function returns one of the following error codes.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>SEC_E_INSUFFICIENT_MEMORY</term>
/// <term>There is not enough memory available to complete the requested action.</term>
/// </item>
/// <item>
/// <term>SEC_E_INTERNAL_ERROR</term>
/// <term>An error occurred that did not map to an SSPI error code.</term>
/// </item>
/// <item>
/// <term>SEC_E_INVALID_HANDLE</term>
/// <term>The handle passed to the function is not valid.</term>
/// </item>
/// <item>
/// <term>SEC_E_INVALID_TOKEN</term>
/// <term>
/// The error is due to a malformed input token, such as a token corrupted in transit, a token of incorrect size, or a token passed
/// into the wrong security package. Passing a token to the wrong package can happen if the client and server did not negotiate the
/// proper security package.
/// </term>
/// </item>
/// <item>
/// <term>SEC_E_LOGON_DENIED</term>
/// <term>The logon failed.</term>
/// </item>
/// <item>
/// <term>SEC_E_NO_AUTHENTICATING_AUTHORITY</term>
/// <term>
/// No authority could be contacted for authentication. The domain name of the authenticating party could be wrong, the domain could
/// be unreachable, or there might have been a trust relationship failure.
/// </term>
/// </item>
/// <item>
/// <term>SEC_E_NO_CREDENTIALS</term>
/// <term>No credentials are available in the security package.</term>
/// </item>
/// <item>
/// <term>SEC_E_TARGET_UNKNOWN</term>
/// <term>The target was not recognized.</term>
/// </item>
/// <item>
/// <term>SEC_E_UNSUPPORTED_FUNCTION</term>
/// <term>
/// A context attribute flag that is not valid (ISC_REQ_DELEGATE or ISC_REQ_PROMPT_FOR_CREDS) was specified in the fContextReq parameter.
/// </term>
/// </item>
/// <item>
/// <term>SEC_E_WRONG_PRINCIPAL</term>
/// <term>
/// The principal that received the authentication request is not the same as the one passed into the pszTargetName parameter. This
/// indicates a failure in mutual authentication.
/// </term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// The caller is responsible for determining whether the final context attributes are sufficient. If, for example, confidentiality
/// was requested, but could not be established, some applications may choose to shut down the connection immediately.
/// </para>
/// <para>
/// If attributes of the security context are not sufficient, the client must free the partially created context by calling the
/// DeleteSecurityContext function.
/// </para>
/// <para>The <c>InitializeSecurityContext (General)</c> function is used by a client to initialize an outbound context.</para>
/// <para>For a two-leg security context, the calling sequence is as follows:</para>
/// <list type="number">
/// <item>
/// <term>The client calls the function with phContext set to <c>NULL</c> and fills in the buffer descriptor with the input message.</term>
/// </item>
/// <item>
/// <term>
/// The security package examines the parameters and constructs an opaque token, placing it in the TOKEN element in the buffer array.
/// If the fContextReq parameter includes the ISC_REQ_ALLOCATE_MEMORY flag, the security package allocates the memory and returns the
/// pointer in the TOKEN element.
/// </term>
/// </item>
/// <item>
/// <term>
/// The client sends the token returned in the pOutput buffer to the target server. The server then passes the token as an input
/// argument in a call to the AcceptSecurityContext (General) function.
/// </term>
/// </item>
/// <item>
/// <term>
/// AcceptSecurityContext (General) may return a token, which the server sends to the client for a second call to
/// <c>InitializeSecurityContext (General)</c> if the first call returned SEC_I_CONTINUE_NEEDED.
/// </term>
/// </item>
/// </list>
/// <para>For multiple-leg security contexts, such as mutual authentication, the calling sequence is as follows:</para>
/// <list type="number">
/// <item>
/// <term>The client calls the function as described earlier, but the package returns the SEC_I_CONTINUE_NEEDED success code.</term>
/// </item>
/// <item>
/// <term>The client sends the output token to the server and waits for the server's reply.</term>
/// </item>
/// <item>
/// <term>
/// Upon receipt of the server's response, the client calls <c>InitializeSecurityContext (General)</c> again, with phContext set to
/// the handle that was returned from the last call. The token received from the server is supplied in the pInput parameter.
/// </term>
/// </item>
/// </list>
/// <para>If the server has successfully responded, the security package returns SEC_E_OK and a secure session is established.</para>
/// <para>If the function returns one of the error responses, the server's response is not accepted, and the session is not established.</para>
/// <para>
/// If the function returns SEC_I_CONTINUE_NEEDED, SEC_I_COMPLETE_NEEDED, or SEC_I_COMPLETE_AND_CONTINUE, steps 2 and 3 are repeated.
/// </para>
/// <para>
/// To initialize a security context, more than one call to this function may be required, depending on the underlying authentication
/// mechanism as well as the choices specified in the fContextReq parameter.
/// </para>
/// <para>
/// The fContextReq and pfContextAttributes parameters are bitmasks that represent various context attributes. For a description of
/// the various attributes, see Context Requirements. The pfContextAttributes parameter is valid on any successful return, but only
/// on the final successful return should you examine the flags that pertain to security aspects of the context. Intermediate returns
/// can set, for example, the ISC_RET_ALLOCATED_MEMORY flag.
/// </para>
/// <para>
/// If the ISC_REQ_USE_SUPPLIED_CREDS flag is set, the security package must look for a SECBUFFER_PKG_PARAMS buffer type in the
/// pInput input buffer. This is not a generic solution, but it allows for a strong pairing of security package and application when appropriate.
/// </para>
/// <para>If ISC_REQ_ALLOCATE_MEMORY was specified, the caller must free the memory by calling the FreeContextBuffer function.</para>
/// <para>
/// For example, the input token could be the challenge from a LAN Manager. In this case, the output token would be the
/// NTLM-encrypted response to the challenge.
/// </para>
/// <para>
/// The action the client takes depends on the return code from this function. If the return code is SEC_E_OK, there will be no
/// second <c>InitializeSecurityContext (General)</c> call, and no response from the server is expected. If the return code is
/// SEC_I_CONTINUE_NEEDED, the client expects a token in response from the server and passes it in a second call to
/// <c>InitializeSecurityContext (General)</c>. The SEC_I_COMPLETE_NEEDED return code indicates that the client must finish building
/// the message and call the CompleteAuthToken function. The SEC_I_COMPLETE_AND_CONTINUE code incorporates both of these actions.
/// </para>
/// <para>
/// If <c>InitializeSecurityContext (General)</c> returns success on the first (or only) call, then the caller must eventually call
/// the DeleteSecurityContext function on the returned handle, even if the call fails on a later leg of the authentication exchange.
/// </para>
/// <para>
/// The client may call <c>InitializeSecurityContext (General)</c> again after it has completed successfully. This indicates to the
/// security package that a reauthentication is wanted.
/// </para>
/// <para>
/// Kernel mode callers have the following differences: the target name is a Unicode string that must be allocated in virtual memory
/// by using VirtualAlloc; it must not be allocated from the pool. Buffers passed and supplied in pInput and pOutput must be in
/// virtual memory, not in the pool.
/// </para>
/// <para>
/// When using the Schannel SSP, if the function returns SEC_I_INCOMPLETE_CREDENTIALS, check that you specified a valid and trusted
/// certificate in your credentials. The certificate is specified when calling the AcquireCredentialsHandle (General) function. The
/// certificate must be a client authentication certificate issued by a certification authority (CA) trusted by the server. To obtain
/// a list of the CAs trusted by the server, call the QueryContextAttributes (General) function and specify the
/// SECPKG_ATTR_ISSUER_LIST_EX attribute.
/// </para>
/// <para>
/// When using the Schannel SSP, after a client application receives an authentication certificate from a CA that is trusted by the
/// server, the application creates a new credential by calling the AcquireCredentialsHandle (General) function and then calling
/// <c>InitializeSecurityContext (General)</c> again, specifying the new credential in the phCredential parameter.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-initializesecuritycontexta SECURITY_STATUS SEC_ENTRY
// InitializeSecurityContextA( PCredHandle phCredential, PCtxtHandle phContext, SEC_CHAR *pszTargetName, unsigned long fContextReq,
// unsigned long Reserved1, unsigned long TargetDataRep, PSecBufferDesc pInput, unsigned long Reserved2, PCtxtHandle phNewContext,
// PSecBufferDesc pOutput, unsigned long *pfContextAttr, PTimeStamp ptsExpiry );
[DllImport(Lib.Secur32, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("sspi.h", MSDNShortId = "21d965d4-3c03-4e29-a70d-4538c5c366b0")]
public static unsafe extern HRESULT InitializeSecurityContext([In, Optional] CredHandle* phCredential, [In, Optional] CtxtHandle* phContext, [Optional] string pszTargetName, ASC_REQ fContextReq, [Optional] uint Reserved1, DREP TargetDataRep,
[In, Optional] SecBufferDesc* pInput, [Optional] uint Reserved2, ref CtxtHandle phNewContext, [Optional] SecBufferDesc* pOutput, out ASC_RET pfContextAttr, out TimeStamp ptsExpiry);
/// <summary>
/// <para>
/// The <c>InitializeSecurityContext (General)</c> function initiates the client side, outbound security context from a credential
/// handle. The function is used to build a security context between the client application and a remote peer.
/// <c>InitializeSecurityContext (General)</c> returns a token that the client must pass to the remote peer, which the peer in turn
/// submits to the local security implementation through the AcceptSecurityContext (General) call. The token generated should be
/// considered opaque by all callers.
/// </para>
/// <para>
/// Typically, the <c>InitializeSecurityContext (General)</c> function is called in a loop until a sufficient security context is established.
/// </para>
/// <para>For information about using this function with a specific security support provider (SSP), see the following topics.</para>
/// <list type="table">
/// <listheader>
/// <term>Topic</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>InitializeSecurityContext (CredSSP)</term>
/// <term>
/// Initiates the client side, outbound security context from a credential handle by using the Credential Security Support Provider (CredSSP).
/// </term>
/// </item>
/// <item>
/// <term>InitializeSecurityContext (Digest)</term>
/// <term>Initiates the client side, outbound security context from a credential handle by using the Digest security package.</term>
/// </item>
/// <item>
/// <term>InitializeSecurityContext (Kerberos)</term>
/// <term>Initiates the client side, outbound security context from a credential handle by using the Kerberos security package.</term>
/// </item>
/// <item>
/// <term>InitializeSecurityContext (Negotiate)</term>
/// <term>Initiates the client side, outbound security context from a credential handle by using the Negotiate security package.</term>
/// </item>
/// <item>
/// <term>InitializeSecurityContext (NTLM)</term>
/// <term>Initiates the client side, outbound security context from a credential handle by using the NTLM security package.</term>
/// </item>
/// <item>
/// <term>InitializeSecurityContext (Schannel)</term>
/// <term>Initiates the client side, outbound security context from a credential handle by using the Schannel security package.</term>
/// </item>
/// </list>
/// </summary>
/// <param name="phCredential">
/// A handle to the credentials returned by AcquireCredentialsHandle (General). This handle is used to build the security context.
/// The <c>InitializeSecurityContext (General)</c> function requires at least OUTBOUND credentials.
/// </param>
/// <param name="phContext">
/// <para>
/// A pointer to a CtxtHandle structure. On the first call to <c>InitializeSecurityContext (General)</c>, this pointer is
/// <c>NULL</c>. On the second call, this parameter is a pointer to the handle to the partially formed context returned in the
/// phNewContext parameter by the first call.
/// </para>
/// <para>This parameter is optional with the Microsoft Digest SSP and can be set to <c>NULL</c>.</para>
/// <para>
/// When using the Schannel SSP, on the first call to <c>InitializeSecurityContext (General)</c>, specify <c>NULL</c>. On future
/// calls, specify the token received in the phNewContext parameter after the first call to this function.
/// </para>
/// </param>
/// <param name="pszTargetName">TBD</param>
/// <param name="fContextReq">
/// <para>
/// Bit flags that indicate requests for the context. Not all packages can support all requirements. Flags used for this parameter
/// are prefixed with ISC_REQ_, for example, ISC_REQ_DELEGATE. This parameter can be one or more of the following attributes flags.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ISC_REQ_ALLOCATE_MEMORY</term>
/// <term>
/// The security package allocates output buffers for you. When you have finished using the output buffers, free them by calling the
/// FreeContextBuffer function.
/// </term>
/// </item>
/// <item>
/// <term>ISC_REQ_CONFIDENTIALITY</term>
/// <term>Encrypt messages by using the EncryptMessage function.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_CONNECTION</term>
/// <term>
/// The security context will not handle formatting messages. This value is the default for the Kerberos, Negotiate, and NTLM
/// security packages.
/// </term>
/// </item>
/// <item>
/// <term>ISC_REQ_DELEGATE</term>
/// <term>
/// The server can use the context to authenticate to other servers as the client. The ISC_REQ_MUTUAL_AUTH flag must be set for this
/// flag to work. Valid for Kerberos. Ignore this flag for constrained delegation.
/// </term>
/// </item>
/// <item>
/// <term>ISC_REQ_EXTENDED_ERROR</term>
/// <term>When errors occur, the remote party will be notified.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_HTTP</term>
/// <term>Use Digest for HTTP. Omit this flag to use Digest as a SASL mechanism.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_INTEGRITY</term>
/// <term>Sign messages and verify signatures by using the EncryptMessage and MakeSignature functions.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_MANUAL_CRED_VALIDATION</term>
/// <term>Schannel must not authenticate the server automatically.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_MUTUAL_AUTH</term>
/// <term>The mutual authentication policy of the service will be satisfied.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_NO_INTEGRITY</term>
/// <term>
/// If this flag is set, the ISC_REQ_INTEGRITY flag is ignored. This value is supported only by the Negotiate and Kerberos security packages.
/// </term>
/// </item>
/// <item>
/// <term>ISC_REQ_REPLAY_DETECT</term>
/// <term>Detect replayed messages that have been encoded by using the EncryptMessage or MakeSignature functions.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_SEQUENCE_DETECT</term>
/// <term>Detect messages received out of sequence.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_STREAM</term>
/// <term>Support a stream-oriented connection.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_USE_SESSION_KEY</term>
/// <term>A new session key must be negotiated. This value is supported only by the Kerberos security package.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_USE_SUPPLIED_CREDS</term>
/// <term>Schannel must not attempt to supply credentials for the client automatically.</term>
/// </item>
/// </list>
/// <para>The requested attributes may not be supported by the client. For more information, see the pfContextAttr parameter.</para>
/// <para>For further descriptions of the various attributes, see Context Requirements.</para>
/// </param>
/// <param name="Reserved1">This parameter is reserved and must be set to zero.</param>
/// <param name="TargetDataRep">
/// <para>The data representation, such as byte ordering, on the target. This parameter can be either SECURITY_NATIVE_DREP or SECURITY_NETWORK_DREP.</para>
/// <para>This parameter is not used with Digest or Schannel. Set it to zero.</para>
/// </param>
/// <param name="pInput">
/// A pointer to a SecBufferDesc structure that contains pointers to the buffers supplied as input to the package. Unless the client
/// context was initiated by the server, the value of this parameter must be <c>NULL</c> on the first call to the function. On
/// subsequent calls to the function or when the client context was initiated by the server, the value of this parameter is a pointer
/// to a buffer allocated with enough memory to hold the token returned by the remote computer.
/// </param>
/// <param name="Reserved2">This parameter is reserved and must be set to zero.</param>
/// <param name="phNewContext">
/// <para>
/// A pointer to a CtxtHandle structure. On the first call to <c>InitializeSecurityContext (General)</c>, this pointer receives the
/// new context handle. On the second call, phNewContext can be the same as the handle specified in the phContext parameter.
/// </para>
/// <para>
/// When using the Schannel SSP, on calls after the first call, pass the handle returned here as the phContext parameter and specify
/// <c>NULL</c> for phNewContext.
/// </para>
/// </param>
/// <param name="pOutput">
/// <para>
/// A pointer to a SecBufferDesc structure that contains pointers to the SecBuffer structure that receives the output data. If a
/// buffer was typed as SEC_READWRITE in the input, it will be there on output. The system will allocate a buffer for the security
/// token if requested (through ISC_REQ_ALLOCATE_MEMORY) and fill in the address in the buffer descriptor for the security token.
/// </para>
/// <para>When using the Microsoft Digest SSP, this parameter receives the challenge response that must be sent to the server.</para>
/// <para>
/// When using the Schannel SSP, if the ISC_REQ_ALLOCATE_MEMORY flag is specified, the Schannel SSP will allocate memory for the
/// buffer and put the appropriate information in the SecBufferDesc. In addition, the caller must pass in a buffer of type
/// <c>SECBUFFER_ALERT</c>. On output, if an alert is generated, this buffer contains information about that alert, and the function fails.
/// </para>
/// </param>
/// <param name="pfContextAttr">
/// <para>
/// A pointer to a variable to receive a set of bit flags that indicate the attributes of the established context. For a description
/// of the various attributes, see Context Requirements.
/// </para>
/// <para>Flags used for this parameter are prefixed with ISC_RET, such as ISC_RET_DELEGATE.</para>
/// <para>For a list of valid values, see the fContextReq parameter.</para>
/// <para>
/// Do not check for security-related attributes until the final function call returns successfully. Attribute flags that are not
/// related to security, such as the ASC_RET_ALLOCATED_MEMORY flag, can be checked before the final return.
/// </para>
/// <para><c>Note</c> Particular context attributes can change during negotiation with a remote peer.</para>
/// </param>
/// <param name="ptsExpiry">
/// <para>
/// A pointer to a TimeStamp structure that receives the expiration time of the context. It is recommended that the security package
/// always return this value in local time. This parameter is optional and <c>NULL</c> should be passed for short-lived clients.
/// </para>
/// <para>There is no expiration time for Microsoft Digest SSP security contexts or credentials.</para>
/// </param>
/// <returns>
/// <para>If the function succeeds, the function returns one of the following success codes.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>SEC_I_COMPLETE_AND_CONTINUE</term>
/// <term>
/// The client must call CompleteAuthToken and then pass the output to the server. The client then waits for a returned token and
/// passes it, in another call, to InitializeSecurityContext (General).
/// </term>
/// </item>
/// <item>
/// <term>SEC_I_COMPLETE_NEEDED</term>
/// <term>The client must finish building the message and then call the CompleteAuthToken function.</term>
/// </item>
/// <item>
/// <term>SEC_I_CONTINUE_NEEDED</term>
/// <term>
/// The client must send the output token to the server and wait for a return token. The returned token is then passed in another
/// call to InitializeSecurityContext (General). The output token can be empty.
/// </term>
/// </item>
/// <item>
/// <term>SEC_I_INCOMPLETE_CREDENTIALS</term>
/// <term>
/// Use with Schannel. The server has requested client authentication, and the supplied credentials either do not include a
/// certificate or the certificate was not issued by a certification authority that is trusted by the server. For more information,
/// see Remarks.
/// </term>
/// </item>
/// <item>
/// <term>SEC_E_INCOMPLETE_MESSAGE</term>
/// <term>
/// Use with Schannel. Data for the whole message was not read from the wire. When this value is returned, the pInput buffer contains
/// a SecBuffer structure with a BufferType member of SECBUFFER_MISSING. The cbBuffer member of SecBuffer contains a value that
/// indicates the number of additional bytes that the function must read from the client before this function succeeds. While this
/// number is not always accurate, using it can help improve performance by avoiding multiple calls to this function.
/// </term>
/// </item>
/// <item>
/// <term>SEC_E_OK</term>
/// <term>
/// The security context was successfully initialized. There is no need for another InitializeSecurityContext (General) call. If the
/// function returns an output token, that is, if the SECBUFFER_TOKEN in pOutput is of nonzero length, that token must be sent to the server.
/// </term>
/// </item>
/// </list>
/// <para>If the function fails, the function returns one of the following error codes.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>SEC_E_INSUFFICIENT_MEMORY</term>
/// <term>There is not enough memory available to complete the requested action.</term>
/// </item>
/// <item>
/// <term>SEC_E_INTERNAL_ERROR</term>
/// <term>An error occurred that did not map to an SSPI error code.</term>
/// </item>
/// <item>
/// <term>SEC_E_INVALID_HANDLE</term>
/// <term>The handle passed to the function is not valid.</term>
/// </item>
/// <item>
/// <term>SEC_E_INVALID_TOKEN</term>
/// <term>
/// The error is due to a malformed input token, such as a token corrupted in transit, a token of incorrect size, or a token passed
/// into the wrong security package. Passing a token to the wrong package can happen if the client and server did not negotiate the
/// proper security package.
/// </term>
/// </item>
/// <item>
/// <term>SEC_E_LOGON_DENIED</term>
/// <term>The logon failed.</term>
/// </item>
/// <item>
/// <term>SEC_E_NO_AUTHENTICATING_AUTHORITY</term>
/// <term>
/// No authority could be contacted for authentication. The domain name of the authenticating party could be wrong, the domain could
/// be unreachable, or there might have been a trust relationship failure.
/// </term>
/// </item>
/// <item>
/// <term>SEC_E_NO_CREDENTIALS</term>
/// <term>No credentials are available in the security package.</term>
/// </item>
/// <item>
/// <term>SEC_E_TARGET_UNKNOWN</term>
/// <term>The target was not recognized.</term>
/// </item>
/// <item>
/// <term>SEC_E_UNSUPPORTED_FUNCTION</term>
/// <term>
/// A context attribute flag that is not valid (ISC_REQ_DELEGATE or ISC_REQ_PROMPT_FOR_CREDS) was specified in the fContextReq parameter.
/// </term>
/// </item>
/// <item>
/// <term>SEC_E_WRONG_PRINCIPAL</term>
/// <term>
/// The principal that received the authentication request is not the same as the one passed into the pszTargetName parameter. This
/// indicates a failure in mutual authentication.
/// </term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// The caller is responsible for determining whether the final context attributes are sufficient. If, for example, confidentiality
/// was requested, but could not be established, some applications may choose to shut down the connection immediately.
/// </para>
/// <para>
/// If attributes of the security context are not sufficient, the client must free the partially created context by calling the
/// DeleteSecurityContext function.
/// </para>
/// <para>The <c>InitializeSecurityContext (General)</c> function is used by a client to initialize an outbound context.</para>
/// <para>For a two-leg security context, the calling sequence is as follows:</para>
/// <list type="number">
/// <item>
/// <term>The client calls the function with phContext set to <c>NULL</c> and fills in the buffer descriptor with the input message.</term>
/// </item>
/// <item>
/// <term>
/// The security package examines the parameters and constructs an opaque token, placing it in the TOKEN element in the buffer array.
/// If the fContextReq parameter includes the ISC_REQ_ALLOCATE_MEMORY flag, the security package allocates the memory and returns the
/// pointer in the TOKEN element.
/// </term>
/// </item>
/// <item>
/// <term>
/// The client sends the token returned in the pOutput buffer to the target server. The server then passes the token as an input
/// argument in a call to the AcceptSecurityContext (General) function.
/// </term>
/// </item>
/// <item>
/// <term>
/// AcceptSecurityContext (General) may return a token, which the server sends to the client for a second call to
/// <c>InitializeSecurityContext (General)</c> if the first call returned SEC_I_CONTINUE_NEEDED.
/// </term>
/// </item>
/// </list>
/// <para>For multiple-leg security contexts, such as mutual authentication, the calling sequence is as follows:</para>
/// <list type="number">
/// <item>
/// <term>The client calls the function as described earlier, but the package returns the SEC_I_CONTINUE_NEEDED success code.</term>
/// </item>
/// <item>
/// <term>The client sends the output token to the server and waits for the server's reply.</term>
/// </item>
/// <item>
/// <term>
/// Upon receipt of the server's response, the client calls <c>InitializeSecurityContext (General)</c> again, with phContext set to
/// the handle that was returned from the last call. The token received from the server is supplied in the pInput parameter.
/// </term>
/// </item>
/// </list>
/// <para>If the server has successfully responded, the security package returns SEC_E_OK and a secure session is established.</para>
/// <para>If the function returns one of the error responses, the server's response is not accepted, and the session is not established.</para>
/// <para>
/// If the function returns SEC_I_CONTINUE_NEEDED, SEC_I_COMPLETE_NEEDED, or SEC_I_COMPLETE_AND_CONTINUE, steps 2 and 3 are repeated.
/// </para>
/// <para>
/// To initialize a security context, more than one call to this function may be required, depending on the underlying authentication
/// mechanism as well as the choices specified in the fContextReq parameter.
/// </para>
/// <para>
/// The fContextReq and pfContextAttributes parameters are bitmasks that represent various context attributes. For a description of
/// the various attributes, see Context Requirements. The pfContextAttributes parameter is valid on any successful return, but only
/// on the final successful return should you examine the flags that pertain to security aspects of the context. Intermediate returns
/// can set, for example, the ISC_RET_ALLOCATED_MEMORY flag.
/// </para>
/// <para>
/// If the ISC_REQ_USE_SUPPLIED_CREDS flag is set, the security package must look for a SECBUFFER_PKG_PARAMS buffer type in the
/// pInput input buffer. This is not a generic solution, but it allows for a strong pairing of security package and application when appropriate.
/// </para>
/// <para>If ISC_REQ_ALLOCATE_MEMORY was specified, the caller must free the memory by calling the FreeContextBuffer function.</para>
/// <para>
/// For example, the input token could be the challenge from a LAN Manager. In this case, the output token would be the
/// NTLM-encrypted response to the challenge.
/// </para>
/// <para>
/// The action the client takes depends on the return code from this function. If the return code is SEC_E_OK, there will be no
/// second <c>InitializeSecurityContext (General)</c> call, and no response from the server is expected. If the return code is
/// SEC_I_CONTINUE_NEEDED, the client expects a token in response from the server and passes it in a second call to
/// <c>InitializeSecurityContext (General)</c>. The SEC_I_COMPLETE_NEEDED return code indicates that the client must finish building
/// the message and call the CompleteAuthToken function. The SEC_I_COMPLETE_AND_CONTINUE code incorporates both of these actions.
/// </para>
/// <para>
/// If <c>InitializeSecurityContext (General)</c> returns success on the first (or only) call, then the caller must eventually call
/// the DeleteSecurityContext function on the returned handle, even if the call fails on a later leg of the authentication exchange.
/// </para>
/// <para>
/// The client may call <c>InitializeSecurityContext (General)</c> again after it has completed successfully. This indicates to the
/// security package that a reauthentication is wanted.
/// </para>
/// <para>
/// Kernel mode callers have the following differences: the target name is a Unicode string that must be allocated in virtual memory
/// by using VirtualAlloc; it must not be allocated from the pool. Buffers passed and supplied in pInput and pOutput must be in
/// virtual memory, not in the pool.
/// </para>
/// <para>
/// When using the Schannel SSP, if the function returns SEC_I_INCOMPLETE_CREDENTIALS, check that you specified a valid and trusted
/// certificate in your credentials. The certificate is specified when calling the AcquireCredentialsHandle (General) function. The
/// certificate must be a client authentication certificate issued by a certification authority (CA) trusted by the server. To obtain
/// a list of the CAs trusted by the server, call the QueryContextAttributes (General) function and specify the
/// SECPKG_ATTR_ISSUER_LIST_EX attribute.
/// </para>
/// <para>
/// When using the Schannel SSP, after a client application receives an authentication certificate from a CA that is trusted by the
/// server, the application creates a new credential by calling the AcquireCredentialsHandle (General) function and then calling
/// <c>InitializeSecurityContext (General)</c> again, specifying the new credential in the phCredential parameter.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-initializesecuritycontexta SECURITY_STATUS SEC_ENTRY
// InitializeSecurityContextA( PCredHandle phCredential, PCtxtHandle phContext, SEC_CHAR *pszTargetName, unsigned long fContextReq,
// unsigned long Reserved1, unsigned long TargetDataRep, PSecBufferDesc pInput, unsigned long Reserved2, PCtxtHandle phNewContext,
// PSecBufferDesc pOutput, unsigned long *pfContextAttr, PTimeStamp ptsExpiry );
[DllImport(Lib.Secur32, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("sspi.h", MSDNShortId = "21d965d4-3c03-4e29-a70d-4538c5c366b0")]
public static extern HRESULT InitializeSecurityContext(in CredHandle phCredential, [In, Optional] IntPtr phContext, string pszTargetName, [In] ASC_REQ fContextReq, [Optional] int Reserved1, [In] DREP TargetDataRep,
[In, Optional] IntPtr pInput, [Optional] int Reserved2, ref CtxtHandle phNewContext, ref SecBufferDesc pOutput, out ASC_RET pfContextAttr, out TimeStamp ptsExpiry);
2020-03-13 17:43:39 -04:00
/// <summary>
/// <para>
/// The <c>InitializeSecurityContext (General)</c> function initiates the client side, outbound security context from a credential
/// handle. The function is used to build a security context between the client application and a remote peer.
/// <c>InitializeSecurityContext (General)</c> returns a token that the client must pass to the remote peer, which the peer in turn
/// submits to the local security implementation through the AcceptSecurityContext (General) call. The token generated should be
/// considered opaque by all callers.
/// </para>
/// <para>
/// Typically, the <c>InitializeSecurityContext (General)</c> function is called in a loop until a sufficient security context is established.
/// </para>
/// <para>For information about using this function with a specific security support provider (SSP), see the following topics.</para>
/// <list type="table">
/// <listheader>
/// <term>Topic</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>InitializeSecurityContext (CredSSP)</term>
/// <term>
/// Initiates the client side, outbound security context from a credential handle by using the Credential Security Support Provider (CredSSP).
/// </term>
/// </item>
/// <item>
/// <term>InitializeSecurityContext (Digest)</term>
/// <term>Initiates the client side, outbound security context from a credential handle by using the Digest security package.</term>
/// </item>
/// <item>
/// <term>InitializeSecurityContext (Kerberos)</term>
/// <term>Initiates the client side, outbound security context from a credential handle by using the Kerberos security package.</term>
/// </item>
/// <item>
/// <term>InitializeSecurityContext (Negotiate)</term>
/// <term>Initiates the client side, outbound security context from a credential handle by using the Negotiate security package.</term>
/// </item>
/// <item>
/// <term>InitializeSecurityContext (NTLM)</term>
/// <term>Initiates the client side, outbound security context from a credential handle by using the NTLM security package.</term>
/// </item>
/// <item>
/// <term>InitializeSecurityContext (Schannel)</term>
/// <term>Initiates the client side, outbound security context from a credential handle by using the Schannel security package.</term>
/// </item>
/// </list>
/// </summary>
/// <param name="phCredential">A handle to the credentials returned by AcquireCredentialsHandle (General). This handle is used to build the security context.
/// The <c>InitializeSecurityContext (General)</c> function requires at least OUTBOUND credentials.</param>
/// <param name="phContext"><para>
/// A pointer to a CtxtHandle structure. On the first call to <c>InitializeSecurityContext (General)</c>, this pointer is
/// <c>NULL</c>. On the second call, this parameter is a pointer to the handle to the partially formed context returned in the
/// phNewContext parameter by the first call.
/// </para>
/// <para>This parameter is optional with the Microsoft Digest SSP and can be set to <c>NULL</c>.</para>
/// <para>
/// When using the Schannel SSP, on the first call to <c>InitializeSecurityContext (General)</c>, specify <c>NULL</c>. On future
/// calls, specify the token received in the phNewContext parameter after the first call to this function.
/// </para></param>
/// <param name="pszTargetName">TBD</param>
/// <param name="fContextReq"><para>
/// Bit flags that indicate requests for the context. Not all packages can support all requirements. Flags used for this parameter
/// are prefixed with ISC_REQ_, for example, ISC_REQ_DELEGATE. This parameter can be one or more of the following attributes flags.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ISC_REQ_ALLOCATE_MEMORY</term>
/// <term>
/// The security package allocates output buffers for you. When you have finished using the output buffers, free them by calling the
/// FreeContextBuffer function.
/// </term>
/// </item>
/// <item>
/// <term>ISC_REQ_CONFIDENTIALITY</term>
/// <term>Encrypt messages by using the EncryptMessage function.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_CONNECTION</term>
/// <term>
/// The security context will not handle formatting messages. This value is the default for the Kerberos, Negotiate, and NTLM
/// security packages.
/// </term>
/// </item>
/// <item>
/// <term>ISC_REQ_DELEGATE</term>
/// <term>
/// The server can use the context to authenticate to other servers as the client. The ISC_REQ_MUTUAL_AUTH flag must be set for this
/// flag to work. Valid for Kerberos. Ignore this flag for constrained delegation.
/// </term>
/// </item>
/// <item>
/// <term>ISC_REQ_EXTENDED_ERROR</term>
/// <term>When errors occur, the remote party will be notified.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_HTTP</term>
/// <term>Use Digest for HTTP. Omit this flag to use Digest as a SASL mechanism.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_INTEGRITY</term>
/// <term>Sign messages and verify signatures by using the EncryptMessage and MakeSignature functions.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_MANUAL_CRED_VALIDATION</term>
/// <term>Schannel must not authenticate the server automatically.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_MUTUAL_AUTH</term>
/// <term>The mutual authentication policy of the service will be satisfied.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_NO_INTEGRITY</term>
/// <term>
/// If this flag is set, the ISC_REQ_INTEGRITY flag is ignored. This value is supported only by the Negotiate and Kerberos security packages.
/// </term>
/// </item>
/// <item>
/// <term>ISC_REQ_REPLAY_DETECT</term>
/// <term>Detect replayed messages that have been encoded by using the EncryptMessage or MakeSignature functions.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_SEQUENCE_DETECT</term>
/// <term>Detect messages received out of sequence.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_STREAM</term>
/// <term>Support a stream-oriented connection.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_USE_SESSION_KEY</term>
/// <term>A new session key must be negotiated. This value is supported only by the Kerberos security package.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_USE_SUPPLIED_CREDS</term>
/// <term>Schannel must not attempt to supply credentials for the client automatically.</term>
/// </item>
/// </list>
/// <para>The requested attributes may not be supported by the client. For more information, see the pfContextAttr parameter.</para>
/// <para>For further descriptions of the various attributes, see Context Requirements.</para></param>
/// <param name="TargetDataRep"><para>The data representation, such as byte ordering, on the target. This parameter can be either SECURITY_NATIVE_DREP or SECURITY_NETWORK_DREP.</para>
/// <para>This parameter is not used with Digest or Schannel. Set it to zero.</para></param>
/// <param name="pInput">A pointer to a SecBufferDesc structure that contains pointers to the buffers supplied as input to the package. Unless the client
/// context was initiated by the server, the value of this parameter must be <c>NULL</c> on the first call to the function. On
/// subsequent calls to the function or when the client context was initiated by the server, the value of this parameter is a pointer
/// to a buffer allocated with enough memory to hold the token returned by the remote computer.</param>
/// <param name="outputType">Type of the output.</param>
/// <param name="pOutput"><para>
/// A pointer to a SecBufferDesc structure that contains pointers to the SecBuffer structure that receives the output data. If a
/// buffer was typed as SEC_READWRITE in the input, it will be there on output. The system will allocate a buffer for the security
/// token if requested (through ISC_REQ_ALLOCATE_MEMORY) and fill in the address in the buffer descriptor for the security token.
/// </para>
/// <para>When using the Microsoft Digest SSP, this parameter receives the challenge response that must be sent to the server.</para>
/// <para>
/// When using the Schannel SSP, if the ISC_REQ_ALLOCATE_MEMORY flag is specified, the Schannel SSP will allocate memory for the
/// buffer and put the appropriate information in the SecBufferDesc. In addition, the caller must pass in a buffer of type
/// <c>SECBUFFER_ALERT</c>. On output, if an alert is generated, this buffer contains information about that alert, and the function fails.
/// </para></param>
/// <param name="pfContextAttr"><para>
/// A pointer to a variable to receive a set of bit flags that indicate the attributes of the established context. For a description
/// of the various attributes, see Context Requirements.
/// </para>
/// <para>Flags used for this parameter are prefixed with ISC_RET, such as ISC_RET_DELEGATE.</para>
/// <para>For a list of valid values, see the fContextReq parameter.</para>
/// <para>
/// Do not check for security-related attributes until the final function call returns successfully. Attribute flags that are not
/// related to security, such as the ASC_RET_ALLOCATED_MEMORY flag, can be checked before the final return.
/// </para>
/// <para>
/// <c>Note</c> Particular context attributes can change during negotiation with a remote peer.</para></param>
/// <param name="ptsExpiry"><para>
/// A pointer to a TimeStamp structure that receives the expiration time of the context. It is recommended that the security package
/// always return this value in local time. This parameter is optional and <c>NULL</c> should be passed for short-lived clients.
/// </para>
/// <para>There is no expiration time for Microsoft Digest SSP security contexts or credentials.</para></param>
/// <returns>
/// <para>If the function succeeds, the function returns one of the following success codes.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>SEC_I_COMPLETE_AND_CONTINUE</term>
/// <term>
/// The client must call CompleteAuthToken and then pass the output to the server. The client then waits for a returned token and
/// passes it, in another call, to InitializeSecurityContext (General).
/// </term>
/// </item>
/// <item>
/// <term>SEC_I_COMPLETE_NEEDED</term>
/// <term>The client must finish building the message and then call the CompleteAuthToken function.</term>
/// </item>
/// <item>
/// <term>SEC_I_CONTINUE_NEEDED</term>
/// <term>
/// The client must send the output token to the server and wait for a return token. The returned token is then passed in another
/// call to InitializeSecurityContext (General). The output token can be empty.
/// </term>
/// </item>
/// <item>
/// <term>SEC_I_INCOMPLETE_CREDENTIALS</term>
/// <term>
/// Use with Schannel. The server has requested client authentication, and the supplied credentials either do not include a
/// certificate or the certificate was not issued by a certification authority that is trusted by the server. For more information,
/// see Remarks.
/// </term>
/// </item>
/// <item>
/// <term>SEC_E_INCOMPLETE_MESSAGE</term>
/// <term>
/// Use with Schannel. Data for the whole message was not read from the wire. When this value is returned, the pInput buffer contains
/// a SecBuffer structure with a BufferType member of SECBUFFER_MISSING. The cbBuffer member of SecBuffer contains a value that
/// indicates the number of additional bytes that the function must read from the client before this function succeeds. While this
/// number is not always accurate, using it can help improve performance by avoiding multiple calls to this function.
/// </term>
/// </item>
/// <item>
/// <term>SEC_E_OK</term>
/// <term>
/// The security context was successfully initialized. There is no need for another InitializeSecurityContext (General) call. If the
/// function returns an output token, that is, if the SECBUFFER_TOKEN in pOutput is of nonzero length, that token must be sent to the server.
/// </term>
/// </item>
/// </list>
/// <para>If the function fails, the function returns one of the following error codes.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>SEC_E_INSUFFICIENT_MEMORY</term>
/// <term>There is not enough memory available to complete the requested action.</term>
/// </item>
/// <item>
/// <term>SEC_E_INTERNAL_ERROR</term>
/// <term>An error occurred that did not map to an SSPI error code.</term>
/// </item>
/// <item>
/// <term>SEC_E_INVALID_HANDLE</term>
/// <term>The handle passed to the function is not valid.</term>
/// </item>
/// <item>
/// <term>SEC_E_INVALID_TOKEN</term>
/// <term>
/// The error is due to a malformed input token, such as a token corrupted in transit, a token of incorrect size, or a token passed
/// into the wrong security package. Passing a token to the wrong package can happen if the client and server did not negotiate the
/// proper security package.
/// </term>
/// </item>
/// <item>
/// <term>SEC_E_LOGON_DENIED</term>
/// <term>The logon failed.</term>
/// </item>
/// <item>
/// <term>SEC_E_NO_AUTHENTICATING_AUTHORITY</term>
/// <term>
/// No authority could be contacted for authentication. The domain name of the authenticating party could be wrong, the domain could
/// be unreachable, or there might have been a trust relationship failure.
/// </term>
/// </item>
/// <item>
/// <term>SEC_E_NO_CREDENTIALS</term>
/// <term>No credentials are available in the security package.</term>
/// </item>
/// <item>
/// <term>SEC_E_TARGET_UNKNOWN</term>
/// <term>The target was not recognized.</term>
/// </item>
/// <item>
/// <term>SEC_E_UNSUPPORTED_FUNCTION</term>
/// <term>
/// A context attribute flag that is not valid (ISC_REQ_DELEGATE or ISC_REQ_PROMPT_FOR_CREDS) was specified in the fContextReq parameter.
/// </term>
/// </item>
/// <item>
/// <term>SEC_E_WRONG_PRINCIPAL</term>
/// <term>
/// The principal that received the authentication request is not the same as the one passed into the pszTargetName parameter. This
/// indicates a failure in mutual authentication.
/// </term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// The caller is responsible for determining whether the final context attributes are sufficient. If, for example, confidentiality
/// was requested, but could not be established, some applications may choose to shut down the connection immediately.
/// </para>
/// <para>
/// If attributes of the security context are not sufficient, the client must free the partially created context by calling the
/// DeleteSecurityContext function.
/// </para>
/// <para>The <c>InitializeSecurityContext (General)</c> function is used by a client to initialize an outbound context.</para>
/// <para>For a two-leg security context, the calling sequence is as follows:</para>
/// <list type="number">
/// <item>
/// <term>The client calls the function with phContext set to <c>NULL</c> and fills in the buffer descriptor with the input message.</term>
/// </item>
/// <item>
/// <term>
/// The security package examines the parameters and constructs an opaque token, placing it in the TOKEN element in the buffer array.
/// If the fContextReq parameter includes the ISC_REQ_ALLOCATE_MEMORY flag, the security package allocates the memory and returns the
/// pointer in the TOKEN element.
/// </term>
/// </item>
/// <item>
/// <term>
/// The client sends the token returned in the pOutput buffer to the target server. The server then passes the token as an input
/// argument in a call to the AcceptSecurityContext (General) function.
/// </term>
/// </item>
/// <item>
/// <term>
/// AcceptSecurityContext (General) may return a token, which the server sends to the client for a second call to
/// <c>InitializeSecurityContext (General)</c> if the first call returned SEC_I_CONTINUE_NEEDED.
/// </term>
/// </item>
/// </list>
/// <para>For multiple-leg security contexts, such as mutual authentication, the calling sequence is as follows:</para>
/// <list type="number">
/// <item>
/// <term>The client calls the function as described earlier, but the package returns the SEC_I_CONTINUE_NEEDED success code.</term>
/// </item>
/// <item>
/// <term>The client sends the output token to the server and waits for the server's reply.</term>
/// </item>
/// <item>
/// <term>
/// Upon receipt of the server's response, the client calls <c>InitializeSecurityContext (General)</c> again, with phContext set to
/// the handle that was returned from the last call. The token received from the server is supplied in the pInput parameter.
/// </term>
/// </item>
/// </list>
/// <para>If the server has successfully responded, the security package returns SEC_E_OK and a secure session is established.</para>
/// <para>If the function returns one of the error responses, the server's response is not accepted, and the session is not established.</para>
/// <para>
/// If the function returns SEC_I_CONTINUE_NEEDED, SEC_I_COMPLETE_NEEDED, or SEC_I_COMPLETE_AND_CONTINUE, steps 2 and 3 are repeated.
/// </para>
/// <para>
/// To initialize a security context, more than one call to this function may be required, depending on the underlying authentication
/// mechanism as well as the choices specified in the fContextReq parameter.
/// </para>
/// <para>
/// The fContextReq and pfContextAttributes parameters are bitmasks that represent various context attributes. For a description of
/// the various attributes, see Context Requirements. The pfContextAttributes parameter is valid on any successful return, but only
/// on the final successful return should you examine the flags that pertain to security aspects of the context. Intermediate returns
/// can set, for example, the ISC_RET_ALLOCATED_MEMORY flag.
/// </para>
/// <para>
/// If the ISC_REQ_USE_SUPPLIED_CREDS flag is set, the security package must look for a SECBUFFER_PKG_PARAMS buffer type in the
/// pInput input buffer. This is not a generic solution, but it allows for a strong pairing of security package and application when appropriate.
/// </para>
/// <para>If ISC_REQ_ALLOCATE_MEMORY was specified, the caller must free the memory by calling the FreeContextBuffer function.</para>
/// <para>
/// For example, the input token could be the challenge from a LAN Manager. In this case, the output token would be the
/// NTLM-encrypted response to the challenge.
/// </para>
/// <para>
/// The action the client takes depends on the return code from this function. If the return code is SEC_E_OK, there will be no
/// second <c>InitializeSecurityContext (General)</c> call, and no response from the server is expected. If the return code is
/// SEC_I_CONTINUE_NEEDED, the client expects a token in response from the server and passes it in a second call to
/// <c>InitializeSecurityContext (General)</c>. The SEC_I_COMPLETE_NEEDED return code indicates that the client must finish building
/// the message and call the CompleteAuthToken function. The SEC_I_COMPLETE_AND_CONTINUE code incorporates both of these actions.
/// </para>
/// <para>
/// If <c>InitializeSecurityContext (General)</c> returns success on the first (or only) call, then the caller must eventually call
/// the DeleteSecurityContext function on the returned handle, even if the call fails on a later leg of the authentication exchange.
/// </para>
/// <para>
/// The client may call <c>InitializeSecurityContext (General)</c> again after it has completed successfully. This indicates to the
/// security package that a reauthentication is wanted.
/// </para>
/// <para>
/// Kernel mode callers have the following differences: the target name is a Unicode string that must be allocated in virtual memory
/// by using VirtualAlloc; it must not be allocated from the pool. Buffers passed and supplied in pInput and pOutput must be in
/// virtual memory, not in the pool.
/// </para>
/// <para>
/// When using the Schannel SSP, if the function returns SEC_I_INCOMPLETE_CREDENTIALS, check that you specified a valid and trusted
/// certificate in your credentials. The certificate is specified when calling the AcquireCredentialsHandle (General) function. The
/// certificate must be a client authentication certificate issued by a certification authority (CA) trusted by the server. To obtain
/// a list of the CAs trusted by the server, call the QueryContextAttributes (General) function and specify the
/// SECPKG_ATTR_ISSUER_LIST_EX attribute.
/// </para>
/// <para>
/// When using the Schannel SSP, after a client application receives an authentication certificate from a CA that is trusted by the
/// server, the application creates a new credential by calling the AcquireCredentialsHandle (General) function and then calling
/// <c>InitializeSecurityContext (General)</c> again, specifying the new credential in the phCredential parameter.
/// </para>
/// </remarks>
public static HRESULT InitializeSecurityContext(in CredHandle phCredential, [In, Out] SafeCtxtHandle phContext, string pszTargetName, ASC_REQ fContextReq, DREP TargetDataRep,
[In, Optional] SecBufferDesc? pInput, SecBufferType outputType, out SafeSecBufferDesc pOutput, out ASC_RET pfContextAttr, out TimeStamp ptsExpiry)
{
pOutput = new SafeSecBufferDesc(outputType);
return InitializeSecurityContext(phCredential, phContext, pszTargetName, fContextReq, TargetDataRep, pInput, pOutput, out pfContextAttr, out ptsExpiry);
}
2020-03-13 17:43:39 -04:00
/// <summary>
/// <para>
/// The <c>InitializeSecurityContext (General)</c> function initiates the client side, outbound security context from a credential
/// handle. The function is used to build a security context between the client application and a remote peer.
/// <c>InitializeSecurityContext (General)</c> returns a token that the client must pass to the remote peer, which the peer in turn
/// submits to the local security implementation through the AcceptSecurityContext (General) call. The token generated should be
/// considered opaque by all callers.
/// </para>
/// <para>
/// Typically, the <c>InitializeSecurityContext (General)</c> function is called in a loop until a sufficient security context is established.
/// </para>
/// <para>For information about using this function with a specific security support provider (SSP), see the following topics.</para>
/// <list type="table">
/// <listheader>
/// <term>Topic</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>InitializeSecurityContext (CredSSP)</term>
/// <term>
/// Initiates the client side, outbound security context from a credential handle by using the Credential Security Support Provider (CredSSP).
/// </term>
/// </item>
/// <item>
/// <term>InitializeSecurityContext (Digest)</term>
/// <term>Initiates the client side, outbound security context from a credential handle by using the Digest security package.</term>
/// </item>
/// <item>
/// <term>InitializeSecurityContext (Kerberos)</term>
/// <term>Initiates the client side, outbound security context from a credential handle by using the Kerberos security package.</term>
/// </item>
/// <item>
/// <term>InitializeSecurityContext (Negotiate)</term>
/// <term>Initiates the client side, outbound security context from a credential handle by using the Negotiate security package.</term>
/// </item>
/// <item>
/// <term>InitializeSecurityContext (NTLM)</term>
/// <term>Initiates the client side, outbound security context from a credential handle by using the NTLM security package.</term>
/// </item>
/// <item>
/// <term>InitializeSecurityContext (Schannel)</term>
/// <term>Initiates the client side, outbound security context from a credential handle by using the Schannel security package.</term>
/// </item>
/// </list>
/// </summary>
/// <param name="phCredential">A handle to the credentials returned by AcquireCredentialsHandle (General). This handle is used to build the security context.
/// The <c>InitializeSecurityContext (General)</c> function requires at least OUTBOUND credentials.</param>
/// <param name="phContext"><para>
/// A pointer to a CtxtHandle structure. On the first call to <c>InitializeSecurityContext (General)</c>, this pointer is
/// <c>NULL</c>. On the second call, this parameter is a pointer to the handle to the partially formed context returned in the
/// phNewContext parameter by the first call.
/// </para>
/// <para>This parameter is optional with the Microsoft Digest SSP and can be set to <c>NULL</c>.</para>
/// <para>
/// When using the Schannel SSP, on the first call to <c>InitializeSecurityContext (General)</c>, specify <c>NULL</c>. On future
/// calls, specify the token received in the phNewContext parameter after the first call to this function.
/// </para></param>
/// <param name="pszTargetName">TBD</param>
/// <param name="fContextReq"><para>
/// Bit flags that indicate requests for the context. Not all packages can support all requirements. Flags used for this parameter
/// are prefixed with ISC_REQ_, for example, ISC_REQ_DELEGATE. This parameter can be one or more of the following attributes flags.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ISC_REQ_ALLOCATE_MEMORY</term>
/// <term>
/// The security package allocates output buffers for you. When you have finished using the output buffers, free them by calling the
/// FreeContextBuffer function.
/// </term>
/// </item>
/// <item>
/// <term>ISC_REQ_CONFIDENTIALITY</term>
/// <term>Encrypt messages by using the EncryptMessage function.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_CONNECTION</term>
/// <term>
/// The security context will not handle formatting messages. This value is the default for the Kerberos, Negotiate, and NTLM
/// security packages.
/// </term>
/// </item>
/// <item>
/// <term>ISC_REQ_DELEGATE</term>
/// <term>
/// The server can use the context to authenticate to other servers as the client. The ISC_REQ_MUTUAL_AUTH flag must be set for this
/// flag to work. Valid for Kerberos. Ignore this flag for constrained delegation.
/// </term>
/// </item>
/// <item>
/// <term>ISC_REQ_EXTENDED_ERROR</term>
/// <term>When errors occur, the remote party will be notified.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_HTTP</term>
/// <term>Use Digest for HTTP. Omit this flag to use Digest as a SASL mechanism.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_INTEGRITY</term>
/// <term>Sign messages and verify signatures by using the EncryptMessage and MakeSignature functions.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_MANUAL_CRED_VALIDATION</term>
/// <term>Schannel must not authenticate the server automatically.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_MUTUAL_AUTH</term>
/// <term>The mutual authentication policy of the service will be satisfied.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_NO_INTEGRITY</term>
/// <term>
/// If this flag is set, the ISC_REQ_INTEGRITY flag is ignored. This value is supported only by the Negotiate and Kerberos security packages.
/// </term>
/// </item>
/// <item>
/// <term>ISC_REQ_REPLAY_DETECT</term>
/// <term>Detect replayed messages that have been encoded by using the EncryptMessage or MakeSignature functions.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_SEQUENCE_DETECT</term>
/// <term>Detect messages received out of sequence.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_STREAM</term>
/// <term>Support a stream-oriented connection.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_USE_SESSION_KEY</term>
/// <term>A new session key must be negotiated. This value is supported only by the Kerberos security package.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_USE_SUPPLIED_CREDS</term>
/// <term>Schannel must not attempt to supply credentials for the client automatically.</term>
/// </item>
/// </list>
/// <para>The requested attributes may not be supported by the client. For more information, see the pfContextAttr parameter.</para>
/// <para>For further descriptions of the various attributes, see Context Requirements.</para></param>
/// <param name="TargetDataRep"><para>The data representation, such as byte ordering, on the target. This parameter can be either SECURITY_NATIVE_DREP or SECURITY_NETWORK_DREP.</para>
/// <para>This parameter is not used with Digest or Schannel. Set it to zero.</para></param>
/// <param name="pInput">A pointer to a SecBufferDesc structure that contains pointers to the buffers supplied as input to the package. Unless the client
/// context was initiated by the server, the value of this parameter must be <c>NULL</c> on the first call to the function. On
/// subsequent calls to the function or when the client context was initiated by the server, the value of this parameter is a pointer
/// to a buffer allocated with enough memory to hold the token returned by the remote computer.</param>
/// <param name="pOutput"><para>
/// A pointer to a SecBufferDesc structure that contains pointers to the SecBuffer structure that receives the output data. If a
/// buffer was typed as SEC_READWRITE in the input, it will be there on output. The system will allocate a buffer for the security
/// token if requested (through ISC_REQ_ALLOCATE_MEMORY) and fill in the address in the buffer descriptor for the security token.
/// </para>
/// <para>When using the Microsoft Digest SSP, this parameter receives the challenge response that must be sent to the server.</para>
/// <para>
/// When using the Schannel SSP, if the ISC_REQ_ALLOCATE_MEMORY flag is specified, the Schannel SSP will allocate memory for the
/// buffer and put the appropriate information in the SecBufferDesc. In addition, the caller must pass in a buffer of type
/// <c>SECBUFFER_ALERT</c>. On output, if an alert is generated, this buffer contains information about that alert, and the function fails.
/// </para></param>
/// <param name="pfContextAttr"><para>
/// A pointer to a variable to receive a set of bit flags that indicate the attributes of the established context. For a description
/// of the various attributes, see Context Requirements.
/// </para>
/// <para>Flags used for this parameter are prefixed with ISC_RET, such as ISC_RET_DELEGATE.</para>
/// <para>For a list of valid values, see the fContextReq parameter.</para>
/// <para>
/// Do not check for security-related attributes until the final function call returns successfully. Attribute flags that are not
/// related to security, such as the ASC_RET_ALLOCATED_MEMORY flag, can be checked before the final return.
/// </para>
/// <para>
/// <c>Note</c> Particular context attributes can change during negotiation with a remote peer.</para></param>
/// <param name="ptsExpiry"><para>
/// A pointer to a TimeStamp structure that receives the expiration time of the context. It is recommended that the security package
/// always return this value in local time. This parameter is optional and <c>NULL</c> should be passed for short-lived clients.
/// </para>
/// <para>There is no expiration time for Microsoft Digest SSP security contexts or credentials.</para></param>
/// <returns>
/// <para>If the function succeeds, the function returns one of the following success codes.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>SEC_I_COMPLETE_AND_CONTINUE</term>
/// <term>
/// The client must call CompleteAuthToken and then pass the output to the server. The client then waits for a returned token and
/// passes it, in another call, to InitializeSecurityContext (General).
/// </term>
/// </item>
/// <item>
/// <term>SEC_I_COMPLETE_NEEDED</term>
/// <term>The client must finish building the message and then call the CompleteAuthToken function.</term>
/// </item>
/// <item>
/// <term>SEC_I_CONTINUE_NEEDED</term>
/// <term>
/// The client must send the output token to the server and wait for a return token. The returned token is then passed in another
/// call to InitializeSecurityContext (General). The output token can be empty.
/// </term>
/// </item>
/// <item>
/// <term>SEC_I_INCOMPLETE_CREDENTIALS</term>
/// <term>
/// Use with Schannel. The server has requested client authentication, and the supplied credentials either do not include a
/// certificate or the certificate was not issued by a certification authority that is trusted by the server. For more information,
/// see Remarks.
/// </term>
/// </item>
/// <item>
/// <term>SEC_E_INCOMPLETE_MESSAGE</term>
/// <term>
/// Use with Schannel. Data for the whole message was not read from the wire. When this value is returned, the pInput buffer contains
/// a SecBuffer structure with a BufferType member of SECBUFFER_MISSING. The cbBuffer member of SecBuffer contains a value that
/// indicates the number of additional bytes that the function must read from the client before this function succeeds. While this
/// number is not always accurate, using it can help improve performance by avoiding multiple calls to this function.
/// </term>
/// </item>
/// <item>
/// <term>SEC_E_OK</term>
/// <term>
/// The security context was successfully initialized. There is no need for another InitializeSecurityContext (General) call. If the
/// function returns an output token, that is, if the SECBUFFER_TOKEN in pOutput is of nonzero length, that token must be sent to the server.
/// </term>
/// </item>
/// </list>
/// <para>If the function fails, the function returns one of the following error codes.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>SEC_E_INSUFFICIENT_MEMORY</term>
/// <term>There is not enough memory available to complete the requested action.</term>
/// </item>
/// <item>
/// <term>SEC_E_INTERNAL_ERROR</term>
/// <term>An error occurred that did not map to an SSPI error code.</term>
/// </item>
/// <item>
/// <term>SEC_E_INVALID_HANDLE</term>
/// <term>The handle passed to the function is not valid.</term>
/// </item>
/// <item>
/// <term>SEC_E_INVALID_TOKEN</term>
/// <term>
/// The error is due to a malformed input token, such as a token corrupted in transit, a token of incorrect size, or a token passed
/// into the wrong security package. Passing a token to the wrong package can happen if the client and server did not negotiate the
/// proper security package.
/// </term>
/// </item>
/// <item>
/// <term>SEC_E_LOGON_DENIED</term>
/// <term>The logon failed.</term>
/// </item>
/// <item>
/// <term>SEC_E_NO_AUTHENTICATING_AUTHORITY</term>
/// <term>
/// No authority could be contacted for authentication. The domain name of the authenticating party could be wrong, the domain could
/// be unreachable, or there might have been a trust relationship failure.
/// </term>
/// </item>
/// <item>
/// <term>SEC_E_NO_CREDENTIALS</term>
/// <term>No credentials are available in the security package.</term>
/// </item>
/// <item>
/// <term>SEC_E_TARGET_UNKNOWN</term>
/// <term>The target was not recognized.</term>
/// </item>
/// <item>
/// <term>SEC_E_UNSUPPORTED_FUNCTION</term>
/// <term>
/// A context attribute flag that is not valid (ISC_REQ_DELEGATE or ISC_REQ_PROMPT_FOR_CREDS) was specified in the fContextReq parameter.
/// </term>
/// </item>
/// <item>
/// <term>SEC_E_WRONG_PRINCIPAL</term>
/// <term>
/// The principal that received the authentication request is not the same as the one passed into the pszTargetName parameter. This
/// indicates a failure in mutual authentication.
/// </term>
/// </item>
/// </list>
/// </returns>
/// <exception cref="System.ArgumentNullException">phContext</exception>
/// <remarks>
/// <para>
/// The caller is responsible for determining whether the final context attributes are sufficient. If, for example, confidentiality
/// was requested, but could not be established, some applications may choose to shut down the connection immediately.
/// </para>
/// <para>
/// If attributes of the security context are not sufficient, the client must free the partially created context by calling the
/// DeleteSecurityContext function.
/// </para>
/// <para>The <c>InitializeSecurityContext (General)</c> function is used by a client to initialize an outbound context.</para>
/// <para>For a two-leg security context, the calling sequence is as follows:</para>
/// <list type="number">
/// <item>
/// <term>The client calls the function with phContext set to <c>NULL</c> and fills in the buffer descriptor with the input message.</term>
/// </item>
/// <item>
/// <term>
/// The security package examines the parameters and constructs an opaque token, placing it in the TOKEN element in the buffer array.
/// If the fContextReq parameter includes the ISC_REQ_ALLOCATE_MEMORY flag, the security package allocates the memory and returns the
/// pointer in the TOKEN element.
/// </term>
/// </item>
/// <item>
/// <term>
/// The client sends the token returned in the pOutput buffer to the target server. The server then passes the token as an input
/// argument in a call to the AcceptSecurityContext (General) function.
/// </term>
/// </item>
/// <item>
/// <term>
/// AcceptSecurityContext (General) may return a token, which the server sends to the client for a second call to
/// <c>InitializeSecurityContext (General)</c> if the first call returned SEC_I_CONTINUE_NEEDED.
/// </term>
/// </item>
/// </list>
/// <para>For multiple-leg security contexts, such as mutual authentication, the calling sequence is as follows:</para>
/// <list type="number">
/// <item>
/// <term>The client calls the function as described earlier, but the package returns the SEC_I_CONTINUE_NEEDED success code.</term>
/// </item>
/// <item>
/// <term>The client sends the output token to the server and waits for the server's reply.</term>
/// </item>
/// <item>
/// <term>
/// Upon receipt of the server's response, the client calls <c>InitializeSecurityContext (General)</c> again, with phContext set to
/// the handle that was returned from the last call. The token received from the server is supplied in the pInput parameter.
/// </term>
/// </item>
/// </list>
/// <para>If the server has successfully responded, the security package returns SEC_E_OK and a secure session is established.</para>
/// <para>If the function returns one of the error responses, the server's response is not accepted, and the session is not established.</para>
/// <para>
/// If the function returns SEC_I_CONTINUE_NEEDED, SEC_I_COMPLETE_NEEDED, or SEC_I_COMPLETE_AND_CONTINUE, steps 2 and 3 are repeated.
/// </para>
/// <para>
/// To initialize a security context, more than one call to this function may be required, depending on the underlying authentication
/// mechanism as well as the choices specified in the fContextReq parameter.
/// </para>
/// <para>
/// The fContextReq and pfContextAttributes parameters are bitmasks that represent various context attributes. For a description of
/// the various attributes, see Context Requirements. The pfContextAttributes parameter is valid on any successful return, but only
/// on the final successful return should you examine the flags that pertain to security aspects of the context. Intermediate returns
/// can set, for example, the ISC_RET_ALLOCATED_MEMORY flag.
/// </para>
/// <para>
/// If the ISC_REQ_USE_SUPPLIED_CREDS flag is set, the security package must look for a SECBUFFER_PKG_PARAMS buffer type in the
/// pInput input buffer. This is not a generic solution, but it allows for a strong pairing of security package and application when appropriate.
/// </para>
/// <para>If ISC_REQ_ALLOCATE_MEMORY was specified, the caller must free the memory by calling the FreeContextBuffer function.</para>
/// <para>
/// For example, the input token could be the challenge from a LAN Manager. In this case, the output token would be the
/// NTLM-encrypted response to the challenge.
/// </para>
/// <para>
/// The action the client takes depends on the return code from this function. If the return code is SEC_E_OK, there will be no
/// second <c>InitializeSecurityContext (General)</c> call, and no response from the server is expected. If the return code is
/// SEC_I_CONTINUE_NEEDED, the client expects a token in response from the server and passes it in a second call to
/// <c>InitializeSecurityContext (General)</c>. The SEC_I_COMPLETE_NEEDED return code indicates that the client must finish building
/// the message and call the CompleteAuthToken function. The SEC_I_COMPLETE_AND_CONTINUE code incorporates both of these actions.
/// </para>
/// <para>
/// If <c>InitializeSecurityContext (General)</c> returns success on the first (or only) call, then the caller must eventually call
/// the DeleteSecurityContext function on the returned handle, even if the call fails on a later leg of the authentication exchange.
/// </para>
/// <para>
/// The client may call <c>InitializeSecurityContext (General)</c> again after it has completed successfully. This indicates to the
/// security package that a reauthentication is wanted.
/// </para>
/// <para>
/// Kernel mode callers have the following differences: the target name is a Unicode string that must be allocated in virtual memory
/// by using VirtualAlloc; it must not be allocated from the pool. Buffers passed and supplied in pInput and pOutput must be in
/// virtual memory, not in the pool.
/// </para>
/// <para>
/// When using the Schannel SSP, if the function returns SEC_I_INCOMPLETE_CREDENTIALS, check that you specified a valid and trusted
/// certificate in your credentials. The certificate is specified when calling the AcquireCredentialsHandle (General) function. The
/// certificate must be a client authentication certificate issued by a certification authority (CA) trusted by the server. To obtain
/// a list of the CAs trusted by the server, call the QueryContextAttributes (General) function and specify the
/// SECPKG_ATTR_ISSUER_LIST_EX attribute.
/// </para>
/// <para>
/// When using the Schannel SSP, after a client application receives an authentication certificate from a CA that is trusted by the
/// server, the application creates a new credential by calling the AcquireCredentialsHandle (General) function and then calling
/// <c>InitializeSecurityContext (General)</c> again, specifying the new credential in the phCredential parameter.
/// </para>
/// </remarks>
public static HRESULT InitializeSecurityContext(in CredHandle phCredential, [In, Out] SafeCtxtHandle phContext, string pszTargetName, ASC_REQ fContextReq, DREP TargetDataRep,
SecBufferDesc? pInput, [In, Out] SafeSecBufferDesc pOutput, out ASC_RET pfContextAttr, out TimeStamp ptsExpiry)
{
if (phContext is null) throw new ArgumentNullException(nameof(phContext));
unsafe
{
using (var pinnedInput = PinnedObject.FromNullable(pInput))
{
var hCtxt = CtxtHandle.Null;
HRESULT hr = 0;
fixed (CredHandle* pphCred = &phCredential)
hr = InitializeSecurityContext(pphCred, phContext, pszTargetName, fContextReq | ASC_REQ.ASC_REQ_ALLOCATE_MEMORY, 0, TargetDataRep, (SecBufferDesc*)(IntPtr)pinnedInput, 0, ref hCtxt, pOutput, out pfContextAttr, out ptsExpiry);
if (hr.Succeeded)
{
if (phContext.DangerousGetHandle().IsNull)
phContext.SetHandle(hCtxt);
}
return hr;
}
}
}
/// <summary>
/// The <c>InitSecurityInterface</c> function returns a pointer to an SSPI dispatch table. This function enables clients to use SSPI
/// without binding directly to an implementation of the interface.
/// </summary>
/// <returns>
/// <para>If the function succeeds, the return value is a pointer to a SecurityFunctionTable structure.</para>
/// <para>If the function fails, the return value is <c>NULL</c>.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-initsecurityinterfacea PSecurityFunctionTableA SEC_ENTRY
// InitSecurityInterfaceA( );
[DllImport(Lib.Secur32, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("sspi.h", MSDNShortId = "1026eeab-e2d6-45f2-9677-82d6cfbf4e12")]
public static unsafe extern SecurityFunctionTable* InitSecurityInterface();
/// <summary>
/// <para>
/// The <c>MakeSignature</c> function generates a cryptographic checksum of the message, and also includes sequencing information to
/// prevent message loss or insertion. <c>MakeSignature</c> allows the application to choose between several cryptographic
/// algorithms, if supported by the chosen mechanism. The <c>MakeSignature</c> function uses the security context referenced by the
/// context handle.
/// </para>
/// <para>This function is not supported by the Schannel security support provider (SSP).</para>
/// </summary>
/// <param name="phContext">A handle to the security context to use to sign the message.</param>
/// <param name="fQOP">
/// <para>
/// Package-specific flags that indicate the quality of protection. A security package can use this parameter to enable the selection
/// of cryptographic algorithms.
/// </para>
/// <para>When using the Digest SSP, this parameter must be set to zero.</para>
/// </param>
/// <param name="pMessage">
/// <para>
/// A pointer to a SecBufferDesc structure. On input, the structure references one or more SecBuffer structures that contain the
/// message to be signed. The function does not process buffers with the SECBUFFER_READONLY_WITH_CHECKSUM attribute.
/// </para>
/// <para>The SecBufferDesc structure also references a SecBuffer structure of type SECBUFFER_TOKEN that receives the signature.</para>
/// <para>When the Digest SSP is used as an HTTP authentication protocol, the buffers should be configured as follows.</para>
/// <list type="table">
/// <listheader>
/// <term>Buffer #/buffer type</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>0 SECBUFFER_TOKEN</term>
/// <term>Empty.</term>
/// </item>
/// <item>
/// <term>1 SECBUFFER_PKG_PARAMS</term>
/// <term>Method.</term>
/// </item>
/// <item>
/// <term>2 SECBUFFER_PKG_PARAMS</term>
/// <term>URL.</term>
/// </item>
/// <item>
/// <term>3 SECBUFFER_PKG_PARAMS</term>
/// <term>HEntity. For more information, see Input Buffers for the Digest Challenge Response.</term>
/// </item>
/// <item>
/// <term>4 SECBUFFER_PADDING</term>
/// <term>Empty. Receives the signature.</term>
/// </item>
/// </list>
/// <para>When the Digest SSP is used as an SASL mechanism, the buffers should be configured as follows.</para>
/// <list type="table">
/// <listheader>
/// <term>Buffer #/buffer type</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>0 SECBUFFER_TOKEN</term>
/// <term>
/// Empty. Receives the signature. This buffer must be large enough to hold the largest possible signature. Determine the size
/// required by calling the QueryContextAttributes (General) function and specifying SECPKG_ATTR_SIZES. Check the returned
/// SecPkgContext_Sizes structure member cbMaxSignature.
/// </term>
/// </item>
/// <item>
/// <term>1 SECBUFFER_DATA</term>
/// <term>Message to be signed.</term>
/// </item>
/// <item>
/// <term>2 SECBUFFER_PADDING</term>
/// <term>Empty.</term>
/// </item>
/// </list>
/// </param>
/// <param name="MessageSeqNo">
/// <para>
/// The sequence number that the transport application assigned to the message. If the transport application does not maintain
/// sequence numbers, this parameter is zero.
/// </para>
/// <para>When using the Digest SSP, this parameter must be set to zero. The Digest SSP manages sequence numbering internally.</para>
/// </param>
/// <returns>
/// <para>If the function succeeds, the function returns SEC_E_OK.</para>
/// <para>If the function fails, it returns one of the following error codes.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>SEC_I_RENEGOTIATE</term>
/// <term>
/// The remote party requires a new handshake sequence or the application has just initiated a shutdown. Return to the negotiation
/// loop and call AcceptSecurityContext (General) or InitializeSecurityContext (General) again. An empty input buffer is passed in
/// the first call.
/// </term>
/// </item>
/// <item>
/// <term>SEC_E_INVALID_HANDLE</term>
/// <term>The context handle specified by phContext is not valid.</term>
/// </item>
/// <item>
/// <term>SEC_E_INVALID_TOKEN</term>
/// <term>pMessage did not contain a valid SECBUFFER_TOKEN buffer or contained too few buffers.</term>
/// </item>
/// <item>
/// <term>SEC_E_OUT_OF_SEQUENCE</term>
/// <term>The nonce count is out of sequence.</term>
/// </item>
/// <item>
/// <term>SEC_E_NO_AUTHENTICATING_AUTHORITY</term>
/// <term>The security context (phContext) must be revalidated.</term>
/// </item>
/// <item>
/// <term>STATUS_INVALID_PARAMETER</term>
/// <term>The nonce count is not numeric.</term>
/// </item>
/// <item>
/// <term>SEC_E_QOP_NOT_SUPPORTED</term>
/// <term>The quality of protection negotiated between the client and server did not include integrity checking.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>The <c>MakeSignature</c> function generates a signature that is based on the message and the session key for the context.</para>
/// <para>The VerifySignature function verifies the messages signed by the <c>MakeSignature</c> function.</para>
/// <para>
/// If the transport application created the security context to support sequence detection and the caller provides a sequence
/// number, the function includes this information in the signature. This protects against reply, insertion, and suppression of
/// messages. The security package incorporates the sequence number passed down from the transport application.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-makesignature KSECDDDECLSPEC SECURITY_STATUS SEC_ENTRY
// MakeSignature( PCtxtHandle phContext, unsigned long fQOP, PSecBufferDesc pMessage, unsigned long MessageSeqNo );
[DllImport(Lib.Secur32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("sspi.h", MSDNShortId = "d17824b0-6121-48a3-b19b-d4fae3e1348e")]
public static extern HRESULT MakeSignature(in CtxtHandle phContext, SECQOP fQOP, ref SecBufferDesc pMessage, uint MessageSeqNo);
/// <summary>
/// The <c>QueryContextAttributes (CredSSP)</c> function lets a transport application query the Credential Security Support Provider
/// (CredSSP) security package for certain attributes of a security context.
/// </summary>
/// <param name="phContext">A handle to the security context to be queried.</param>
/// <param name="ulAttribute">
/// <para>
/// The attribute of the context to be returned. This parameter can be one of the following values. Unless otherwise specified, the
/// attributes are applicable to both client and server.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>SECPKG_ATTR_C_ACCESS_TOKEN 0x80000012</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_AccessToken structure that specifies the access token for the current
/// security context. This attribute is supported only on the server.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_C_FULL_ACCESS_TOKEN 0x80000082</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_AccessToken structure that specifies the access token for the current
/// security context. This attribute is supported only on the server.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_CERT_TRUST_STATUS 0x80000084</term>
/// <term>
/// The pBuffer parameter contains a pointer to a CERT_TRUST_STATUS structure that specifies trust information about the certificate.
/// This attribute is supported only on the client.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_CREDS 0x80000080</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_ClientCreds structure that specifies client credentials. The client
/// credentials can be either user name and password or user name and smart card PIN. This attribute is supported only on the server.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_CREDS_2 0x80000086</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_ClientCreds structure that specifies client credentials. If the
/// client credential is user name and password, the buffer is a packed KERB_INTERACTIVE_LOGON structure. If the client credential is
/// user name and smart card PIN, the buffer is a packed KERB_CERTIFICATE_LOGON structure. If the client credential is an online
/// identity credential, the buffer is a marshaled SEC_WINNT_AUTH_IDENTITY_EX2 structure. This attribute is supported only on the
/// CredSSP server. Windows Server 2008 R2, Windows 7, Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP: This
/// value is not supported.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_NEGOTIATION_PACKAGE 0x80000081</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_PackageInfo structure that specifies the name of the authentication
/// package negotiated by the Microsoft Negotiate provider.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_PACKAGE_INFO 10</term>
/// <term>The pBuffer parameter contains a pointer to a SecPkgContext_PackageInfostructure. Returns information on the SSP in use.</term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_SERVER_AUTH_FLAGS 0x80000083</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_Flags structure that specifies information about the flags in the
/// current security context. This attribute is supported only on the client.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_SIZES 0x0</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_Sizes structure. Queries the sizes of the structures used in the
/// per-message functions and authentication exchanges.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_SUBJECT_SECURITY_ATTRIBUTES 124</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_SubjectAttributes structure. This value returns information about the
/// security attributes for the connection. This value is supported only on the CredSSP server. Windows Server 2008, Windows Vista,
/// Windows Server 2003 and Windows XP: This value is not supported.
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="pBuffer">
/// A pointer to a structure that receives the attributes. The structure type depends on the value of the ulAttribute parameter.
/// </param>
/// <returns>
/// <para>If the function succeeds, it returns SEC_E_OK.</para>
/// <para>If the function fails, it can return the following error codes.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code/value</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>SEC_E_INVALID_HANDLE 0x80100003</term>
/// <term>The function failed. The phContext parameter specifies a handle to an incomplete context.</term>
/// </item>
/// <item>
/// <term>SEC_E_UNSUPPORTED_FUNCTION 0x80090302</term>
/// <term>The function failed. The value of the ulAttribute parameter is not valid.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>The structure pointed to by the pBuffer parameter varies depending on the attribute being queried.</para>
/// <para>
/// While the caller must allocate the pBuffer structure itself, the SSP allocates any memory required to hold variable-sized members
/// of the pBuffer structure. Memory allocated by the SSP must be freed by calling the FreeContextBuffer function.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-querycontextattributesw KSECDDDECLSPEC SECURITY_STATUS SEC_ENTRY
// QueryContextAttributesW( PCtxtHandle phContext, unsigned long ulAttribute, void *pBuffer );
[DllImport(Lib.Secur32, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("sspi.h", MSDNShortId = "4956c4ab-b71e-4960-b750-f3a79b87baac")]
public static extern HRESULT QueryContextAttributes(in CtxtHandle phContext, SECPKG_ATTR ulAttribute, IntPtr pBuffer);
/// <summary>
/// The <c>QueryContextAttributes (CredSSP)</c> function lets a transport application query the Credential Security Support Provider
/// (CredSSP) security package for certain attributes of a security context.
/// </summary>
/// <param name="phContext">A handle to the security context to be queried.</param>
/// <param name="ulAttribute">
/// <para>
/// The attribute of the context to be returned. This parameter can be one of the following values. Unless otherwise specified, the
/// attributes are applicable to both client and server.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>SECPKG_ATTR_C_ACCESS_TOKEN 0x80000012</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_AccessToken structure that specifies the access token for the current
/// security context. This attribute is supported only on the server.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_C_FULL_ACCESS_TOKEN 0x80000082</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_AccessToken structure that specifies the access token for the current
/// security context. This attribute is supported only on the server.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_CERT_TRUST_STATUS 0x80000084</term>
/// <term>
/// The pBuffer parameter contains a pointer to a CERT_TRUST_STATUS structure that specifies trust information about the certificate.
/// This attribute is supported only on the client.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_CREDS 0x80000080</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_ClientCreds structure that specifies client credentials. The client
/// credentials can be either user name and password or user name and smart card PIN. This attribute is supported only on the server.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_CREDS_2 0x80000086</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_ClientCreds structure that specifies client credentials. If the
/// client credential is user name and password, the buffer is a packed KERB_INTERACTIVE_LOGON structure. If the client credential is
/// user name and smart card PIN, the buffer is a packed KERB_CERTIFICATE_LOGON structure. If the client credential is an online
/// identity credential, the buffer is a marshaled SEC_WINNT_AUTH_IDENTITY_EX2 structure. This attribute is supported only on the
/// CredSSP server. Windows Server 2008 R2, Windows 7, Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP: This
/// value is not supported.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_NEGOTIATION_PACKAGE 0x80000081</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_PackageInfo structure that specifies the name of the authentication
/// package negotiated by the Microsoft Negotiate provider.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_PACKAGE_INFO 10</term>
/// <term>The pBuffer parameter contains a pointer to a SecPkgContext_PackageInfostructure. Returns information on the SSP in use.</term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_SERVER_AUTH_FLAGS 0x80000083</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_Flags structure that specifies information about the flags in the
/// current security context. This attribute is supported only on the client.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_SIZES 0x0</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_Sizes structure. Queries the sizes of the structures used in the
/// per-message functions and authentication exchanges.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_SUBJECT_SECURITY_ATTRIBUTES 124</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_SubjectAttributes structure. This value returns information about the
/// security attributes for the connection. This value is supported only on the CredSSP server. Windows Server 2008, Windows Vista,
/// Windows Server 2003 and Windows XP: This value is not supported.
/// </term>
/// </item>
/// </list>
/// </param>
/// <returns>A structure that receives the attributes. The structure type depends on the value of the ulAttribute parameter.</returns>
/// <remarks>
/// <para>The structure pointed to by the pBuffer parameter varies depending on the attribute being queried.</para>
/// <para>
/// While the caller must allocate the pBuffer structure itself, the SSP allocates any memory required to hold variable-sized members
/// of the pBuffer structure. Memory allocated by the SSP must be freed by calling the FreeContextBuffer function.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-querycontextattributesw KSECDDDECLSPEC SECURITY_STATUS SEC_ENTRY
// QueryContextAttributesW( PCtxtHandle phContext, unsigned long ulAttribute, void *pBuffer );
[PInvokeData("sspi.h", MSDNShortId = "4956c4ab-b71e-4960-b750-f3a79b87baac")]
public static T QueryContextAttributes<T>(in CtxtHandle phContext, SECPKG_ATTR ulAttribute) where T : struct
{
if (!CorrespondingTypeAttribute.CanGet(ulAttribute, typeof(T))) throw new ArgumentException($"{typeof(T).GetType().Name} cannot be retrieved using {ulAttribute}.");
using (var mem = SafeHGlobalHandle.CreateFromStructure<T>())
{
if (Environment.OSVersion.Version > new Version(6, 0))
QueryContextAttributesEx(phContext, ulAttribute, (IntPtr)mem, (uint)mem.Size).ThrowIfFailed();
else
QueryContextAttributes(phContext, ulAttribute, (IntPtr)mem).ThrowIfFailed();
return mem.ToStructure<T>();
}
}
/// <summary>Enables a transport application to query a security package for certain attributes of a security context.</summary>
/// <param name="phContext">A handle to the security context to be queried.</param>
/// <param name="ulAttribute">
/// <para>Specifies the attribute of the context to be returned. This parameter can be one of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>SECPKG_ATTR_ACCESS_TOKEN 18</term>
/// <term>The pBuffer parameter contains a pointer to a SecPkgContext_AccessToken structure. Returns a handle to the access token.</term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_APP_DATA 0x5e</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_SessionAppData structure. Returns or specifies application data for
/// the session. This attribute is supported only by the Schannel security package.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_AUTHORITY 6</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_Authority structure. Queries the name of the authenticating authority.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_CLIENT_SPECIFIED_TARGET 27</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_ClientSpecifiedTarget structure that represents the service principal
/// name (SPN) of the initial target supplied by the client. Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP:
/// This value is not supported.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_CONNECTION_INFO 0x5a</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_ConnectionInfo structure. Returns detailed information on the
/// established connection. This attribute is supported only by the Schannel security package.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_CREDS_2 0x80000086</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_ClientCreds structure that specifies client credentials. If the
/// client credential is user name and password, the buffer is a packed KERB_INTERACTIVE_LOGON structure. If the client credential is
/// user name and smart card PIN, the buffer is a packed KERB_CERTIFICATE_LOGON structure. If the client credential is an online
/// identity credential, the buffer is a marshaled SEC_WINNT_AUTH_IDENTITY_EX2 structure. This attribute is supported only on the
/// CredSSP server. Windows Server 2008 R2, Windows 7, Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP: This
/// value is not supported.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_DCE_INFO 3</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_DceInfo structure. Queries for authorization data used by DCE services.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_ENDPOINT_BINDINGS 26</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_Bindings structure that specifies channel binding information. This
/// attribute is supported only by the Schannel security package. Windows Server 2008, Windows Vista, Windows Server 2003 and Windows
/// XP: This value is not supported.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_EAP_KEY_BLOCK 0x5b</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_EapKeyBlock structure. Queries for key data used by the EAP TLS
/// protocol. This attribute is supported only by the Schannel security package.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_FLAGS 14</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_Flags structure. Returns information about the negotiated context flags.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_ISSUER_LIST_EX 0x59</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_IssuerListInfoEx structure. Returns a list of certificate issuers
/// that are accepted by the server. This attribute is supported only by the Schannel security package.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_KEY_INFO 5</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_KeyInfo structure. Queries information about the keys used in a
/// security context.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_LAST_CLIENT_TOKEN_STATUS 30</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_LastClientTokenStatus structure that specifies whether the token from
/// the most recent call to the InitializeSecurityContext function is the last token from the client. This value is supported only by
/// the Negotiate, Kerberos, and NTLM security packages. Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP: This
/// value is not supported.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_LIFESPAN 2</term>
/// <term>The pBuffer parameter contains a pointer to a SecPkgContext_Lifespan structure. Queries the life span of the context.</term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_LOCAL_CERT_CONTEXT 0x54</term>
/// <term>
/// The pBuffer parameter contains a pointer to a PCCERT_CONTEXTstructure. Finds a certificate context that contains a local end
/// certificate. This attribute is supported only by the Schannel security package.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_LOCAL_CRED</term>
/// <term>The pBuffer parameter contains a pointer to a SecPkgContext_LocalCredentialInfo structure. (obsolete) Superseded by SECPKG_ATTR_LOCAL_CERT_CONTEXT.</term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_NAMES 1</term>
/// <term>The pBuffer parameter contains a pointer to a SecPkgContext_Names structure. Queries the name associated with the context.</term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_NATIVE_NAMES 13</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_NativeNames structure. Returns the principal name (CNAME) from the
/// outbound ticket.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_NEGOTIATION_INFO 12</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_NegotiationInfo structure. Returns information about the security
/// package to be used with the negotiation process and the current state of the negotiation for the use of that package.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_PACKAGE_INFO 10</term>
/// <term>The pBuffer parameter contains a pointer to a SecPkgContext_PackageInfostructure. Returns information on the SSP in use.</term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_PASSWORD_EXPIRY 8</term>
/// <term>The pBuffer parameter contains a pointer to a SecPkgContext_PasswordExpiry structure. Returns password expiration information.</term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_REMOTE_CERT_CONTEXT 0x53</term>
/// <term>
/// The pBuffer parameter contains a pointer to a PCCERT_CONTEXTstructure. Finds a certificate context that contains the end
/// certificate supplied by the server. This attribute is supported only by the Schannel security package.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_ROOT_STORE 0x55</term>
/// <term>
/// The pBuffer parameter contains a pointer to a HCERTCONTEXT. Finds a certificate context that contains a certificate supplied by
/// the Root store.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_SESSION_KEY 9</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_SessionKey structure. Returns information about the session keys.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_SESSION_INFO 0x5d</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_SessionInfo structure. Returns information about the session. Windows
/// Server 2008, Windows Vista, Windows Server 2003 and Windows XP: This value is not supported. This attribute is supported only by
/// the Schannel security package.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_SIZES 0</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_Sizes structure. Queries the sizes of the structures used in the
/// per-message functions.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_STREAM_SIZES 4</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_StreamSizes structure. Queries the sizes of the various parts of a
/// stream used in the per-message functions. This attribute is supported only by the Schannel security package.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_SUBJECT_SECURITY_ATTRIBUTES 124</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_SubjectAttributes structure. This value returns information about the
/// security attributes for the connection. This value is supported only on the CredSSP server. Windows Server 2008, Windows Vista,
/// Windows Server 2003 and Windows XP: This value is not supported.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_SUPPORTED_SIGNATURES 0x66</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_SupportedSignatures structure. This value returns information about
/// the signature types that are supported for the connection. This value is supported only by the Schannel security package. Windows
/// Server 2008, Windows Vista, Windows Server 2003 and Windows XP: This value is not supported.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_TARGET_INFORMATION 17</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_TargetInformation structure. Returns information about the name of
/// the remote server.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_UNIQUE_BINDINGS 25</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_Bindings structure that specifies channel binding information. This
/// value is supported only by the Schannel security package. Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP:
/// This value is not supported.
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="pBuffer">
/// A pointer to a structure that receives the attributes. The type of structure pointed to depends on the value specified in the
/// ulAttribute parameter.
/// </param>
/// <param name="cbBuffer">The size, in bytes, of the pBuffer parameter.</param>
/// <returns>
/// <para>If the function succeeds, the return value is SEC_E_OK.</para>
/// <para>If the function fails, the return value is a nonzero error code.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-querycontextattributesexw SECURITY_STATUS SEC_ENTRY
// QueryContextAttributesExW( PCtxtHandle phContext, unsigned long ulAttribute, void *pBuffer, unsigned long cbBuffer );
[DllImport(Lib.SspiCli, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("sspi.h", MSDNShortId = "FD91EE99-F94E-44CE-9331-933D0CAA5F75", MinClient = PInvokeClient.Windows7)]
public static extern HRESULT QueryContextAttributesEx(in CtxtHandle phContext, SECPKG_ATTR ulAttribute, IntPtr pBuffer, uint cbBuffer);
/// <summary>
/// Retrieves the attributes of a credential, such as the name associated with the credential. The information is valid for any
/// security context created with the specified credential.
/// </summary>
/// <param name="phCredential">A handle of the credentials to be queried.</param>
/// <param name="ulAttribute">
/// <para>Specifies the attribute to query. This parameter can be any of the following attributes.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>SECPKG_CRED_ATTR_CERT</term>
/// <term>
/// Returns the certificate thumbprint in a pbuffer of type SecPkgCredentials_Cert. This attribute is only supported by Kerberos.
/// Windows Server 2008 R2, Windows 7, Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP: This attribute is not available.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_CRED_ATTR_NAMES</term>
/// <term>
/// Returns the name of a credential in a pbuffer of type SecPkgCredentials_Names. This attribute is not supported by Schannel in
/// WOW64 mode.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_SUPPORTED_ALGS</term>
/// <term>
/// Returns the supported algorithms in a pbuffer of type SecPkgCred_SupportedAlgs. All supported algorithms are included, regardless
/// of whether they are supported by the provided certificate or enabled on the local computer. This attribute is supported only by Schannel.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_CIPHER_STRENGTHS</term>
/// <term>Returns the cipher strengths in a pbuffer of type SecPkgCred_CipherStrengths. This attribute is supported only by Schannel.</term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_SUPPORTED_PROTOCOLS</term>
/// <term>
/// Returns the supported algorithms in a pbuffer of type SecPkgCred_SupportedProtocols. All supported protocols are included,
/// regardless of whether they are supported by the provided certificate or enabled on the local computer. This attribute is
/// supported only by Schannel.
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="pBuffer">
/// A pointer to a buffer that receives the requested attribute. The type of structure returned depends on the value of ulAttribute.
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is SEC_E_OK.</para>
/// <para>If the function fails, the return value may be one of the following error codes.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>SEC_E_INVALID_HANDLE</term>
/// <term>The handle passed to the function is not valid.</term>
/// </item>
/// <item>
/// <term>SEC_E_UNSUPPORTED_FUNCTION</term>
/// <term>
/// The specified attribute is not supported by Schannel. This return value will only be returned when the Schannel SSP is being used.
/// </term>
/// </item>
/// <item>
/// <term>SEC_E_INSUFFICIENT_MEMORY</term>
/// <term>The memory that is available is not sufficient to complete the request.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// The <c>QueryCredentialsAttributes</c> function allows an application to determine several characteristics of a credential,
/// including the name associated with the specified credentials.
/// </para>
/// <para>
/// Querying the SECPKG_ATTR_CIPHER_STRENGTHS attribute returns a SecPkgCred_CipherStrengths structure. The cipher strength in this
/// structure is the same as the cipher strength in the SCHANNEL_CRED structure used when a credential was created.
/// </para>
/// <para>
/// <c>Note</c> An application can find the system default cipher strength by querying this attribute with a default credential. A
/// default credential is created by calling AcquireCredentialsHandle with a <c>NULL</c> pAuthData parameter.
/// </para>
/// <para>
/// Querying the SECPKG_ATTR_SUPPORTED_ALGS attribute returns a SecPkgCred_SupportedAlgs structure. The algorithms in this structure
/// are compatible with those indicated in the SCHANNEL_CRED structure used when a credential was created.
/// </para>
/// <para>
/// Querying the SECPKG_ATTR_SUPPORTED_PROTOCOLS attribute returns a SecPkgCred_SupportedProtocols structure that contains a bit
/// array compatible with the grbitEnabledProtocols field of the SCHANNEL_CRED structure.
/// </para>
/// <para>
/// The caller must allocate the structure pointed to by the pBuffer parameter. The security package allocates the buffer for any
/// pointer returned in the pBuffer structure. The caller can call the FreeContextBuffer function to free any pointers allocated by
/// the security package.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-querycredentialsattributesa SECURITY_STATUS SEC_ENTRY
// QueryCredentialsAttributesA( PCredHandle phCredential, unsigned long ulAttribute, void *pBuffer );
[DllImport(Lib.Secur32, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("sspi.h", MSDNShortId = "a8ba6f73-8469-431b-b185-183b45b2c533")]
public static extern HRESULT QueryCredentialsAttributes(in CredHandle phCredential, SECPKG_CRED_ATTR ulAttribute, IntPtr pBuffer);
/// <summary>
/// Retrieves the attributes of a credential, such as the name associated with the credential. The information is valid for any
/// security context created with the specified credential.
/// </summary>
/// <param name="phCredential">A handle of the credentials to be queried.</param>
/// <param name="ulAttribute">
/// <para>Specifies the attribute to query. This parameter can be any of the following attributes.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>SECPKG_CRED_ATTR_CERT</term>
/// <term>
/// Returns the certificate thumbprint in a pbuffer of type SecPkgCredentials_Cert. This attribute is only supported by Kerberos.
/// Windows Server 2008 R2, Windows 7, Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP: This attribute is not available.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_CRED_ATTR_NAMES</term>
/// <term>
/// Returns the name of a credential in a pbuffer of type SecPkgCredentials_Names. This attribute is not supported by Schannel in
/// WOW64 mode.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_SUPPORTED_ALGS</term>
/// <term>
/// Returns the supported algorithms in a pbuffer of type SecPkgCred_SupportedAlgs. All supported algorithms are included, regardless
/// of whether they are supported by the provided certificate or enabled on the local computer. This attribute is supported only by Schannel.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_CIPHER_STRENGTHS</term>
/// <term>Returns the cipher strengths in a pbuffer of type SecPkgCred_CipherStrengths. This attribute is supported only by Schannel.</term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_SUPPORTED_PROTOCOLS</term>
/// <term>
/// Returns the supported algorithms in a pbuffer of type SecPkgCred_SupportedProtocols. All supported protocols are included,
/// regardless of whether they are supported by the provided certificate or enabled on the local computer. This attribute is
/// supported only by Schannel.
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="pBuffer">
/// A pointer to a buffer that receives the requested attribute. The type of structure returned depends on the value of ulAttribute.
/// </param>
/// <param name="cbBuffer">The size, in bytes, of the pBuffer parameter.</param>
/// <returns>
/// <para>If the function succeeds, the return value is SEC_E_OK.</para>
/// <para>If the function fails, the return value may be one of the following error codes.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>SEC_E_INVALID_HANDLE</term>
/// <term>The handle passed to the function is not valid.</term>
/// </item>
/// <item>
/// <term>SEC_E_UNSUPPORTED_FUNCTION</term>
/// <term>
/// The specified attribute is not supported by Schannel. This return value will only be returned when the Schannel SSP is being used.
/// </term>
/// </item>
/// <item>
/// <term>SEC_E_INSUFFICIENT_MEMORY</term>
/// <term>The memory that is available is not sufficient to complete the request.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
2018-09-30 17:37:25 -04:00
/// <para>
/// The <c>QueryCredentialsAttributes</c> function allows an application to determine several characteristics of a credential,
/// including the name associated with the specified credentials.
2018-09-30 17:37:25 -04:00
/// </para>
/// <para>
/// Querying the SECPKG_ATTR_CIPHER_STRENGTHS attribute returns a SecPkgCred_CipherStrengths structure. The cipher strength in this
/// structure is the same as the cipher strength in the SCHANNEL_CRED structure used when a credential was created.
2018-09-30 17:37:25 -04:00
/// </para>
/// <para>
/// <c>Note</c> An application can find the system default cipher strength by querying this attribute with a default credential. A
/// default credential is created by calling AcquireCredentialsHandle with a <c>NULL</c> pAuthData parameter.
/// </para>
/// <para>
/// Querying the SECPKG_ATTR_SUPPORTED_ALGS attribute returns a SecPkgCred_SupportedAlgs structure. The algorithms in this structure
/// are compatible with those indicated in the SCHANNEL_CRED structure used when a credential was created.
/// </para>
/// <para>
/// Querying the SECPKG_ATTR_SUPPORTED_PROTOCOLS attribute returns a SecPkgCred_SupportedProtocols structure that contains a bit
/// array compatible with the grbitEnabledProtocols field of the SCHANNEL_CRED structure.
/// </para>
/// <para>
/// The caller must allocate the structure pointed to by the pBuffer parameter. The security package allocates the buffer for any
/// pointer returned in the pBuffer structure. The caller can call the FreeContextBuffer function to free any pointers allocated by
/// the security package.
/// </para>
/// </remarks>
[DllImport(Lib.SspiCli, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("sspi.h", MinClient = PInvokeClient.Windows7)]
public static extern HRESULT QueryCredentialsAttributesEx(in CredHandle phCredential, SECPKG_CRED_ATTR ulAttribute, IntPtr pBuffer, uint cbBuffer);
/// <summary>Obtains the access token for a client security context and uses it directly.</summary>
/// <param name="phContext">Handle of the context to query.</param>
/// <param name="Token">Returned handle to the access token.</param>
2018-09-30 17:37:25 -04:00
/// <returns>
/// <para>If the function succeeds, the function returns SEC_E_OK.</para>
/// <para>If the function fails, it returns a nonzero error code. One possible error code return is SEC_E_INVALID_HANDLE.</para>
2018-09-30 17:37:25 -04:00
/// </returns>
/// <remarks>
/// This function is called by a server application to control impersonation outside the SSPI layer, such as when launching a child
/// process. The handle returned must be closed with CloseHandle when the handle is no longer needed.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-querysecuritycontexttoken KSECDDDECLSPEC SECURITY_STATUS
// SEC_ENTRY QuerySecurityContextToken( PCtxtHandle phContext, void **Token );
2018-09-30 17:37:25 -04:00
[DllImport(Lib.Secur32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("sspi.h", MSDNShortId = "5dc23608-9ce3-4fee-8161-2e409cef4063")]
public static extern HRESULT QuerySecurityContextToken(in CtxtHandle phContext, out SafeHTOKEN Token);
2018-09-30 17:37:25 -04:00
/// <summary>
/// Retrieves information about a specified security package. This information includes the bounds on sizes of authentication
/// information, credentials, and contexts.
2018-09-30 17:37:25 -04:00
/// </summary>
/// <param name="pszPackageName">Pointer to a null-terminated string that specifies the name of the security package.</param>
/// <param name="ppPackageInfo">
/// Pointer to a variable that receives a pointer to a SecPkgInfo structure containing information about the specified security package.
2018-09-30 17:37:25 -04:00
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is SEC_E_OK.</para>
/// <para>If the function fails, the return value is a nonzero error code.</para>
/// </returns>
/// <remarks>The caller must call the FreeContextBuffer function to free the buffer returned in ppPackageInfo.</remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-querysecuritypackageinfoa SECURITY_STATUS SEC_ENTRY
// QuerySecurityPackageInfoA( LPSTR pszPackageName, PSecPkgInfoA *ppPackageInfo );
[DllImport(Lib.Secur32, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("sspi.h", MSDNShortId = "130ef0fe-bb13-4a65-b476-cd25ed234da1")]
public static extern HRESULT QuerySecurityPackageInfo(string pszPackageName, out SafeContextBuffer ppPackageInfo);
/// <summary>Allows a security package to discontinue the impersonation of the caller and restore its own security context.</summary>
/// <param name="phContext">
/// Handle of the security context being impersonated. This handle must have been obtained in the call to the AcceptSecurityContext
/// (General) function and used in the call to the ImpersonateSecurityContext function.
2018-09-30 17:37:25 -04:00
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is SEC_E_OK.</para>
/// <para>If the function fails, the return value can be one of the following error codes.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>SEC_E_INVALID_HANDLE</term>
/// <term>The handle passed to the function is not valid.</term>
/// </item>
/// </list>
2018-09-30 17:37:25 -04:00
/// </returns>
/// <remarks>
/// <c>RevertSecurityContext</c> is not available with all security packages on all platforms. Typically, it is implemented only on
/// platforms and with security packages for which a call to the QuerySecurityPackageInfo function indicates impersonation support.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-revertsecuritycontext KSECDDDECLSPEC SECURITY_STATUS SEC_ENTRY
// RevertSecurityContext( PCtxtHandle phContext );
2018-09-30 17:37:25 -04:00
[DllImport(Lib.Secur32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("sspi.h", MSDNShortId = "d4ed1fe9-2e0a-4648-a010-1eae49ba03ee")]
public static extern HRESULT RevertSecurityContext(in CtxtHandle phContext);
2018-09-30 17:37:25 -04:00
/// <summary>
/// The <c>SaslAcceptSecurityContext</c> function wraps a standard call to the Security Support Provider Interface
/// AcceptSecurityContext (General) function and includes creation of SASL server cookies.
2018-09-30 17:37:25 -04:00
/// </summary>
/// <param name="phCredential">
/// A handle to the server's credentials. The server calls the AcquireCredentialsHandle function with the INBOUND flag set to
/// retrieve this handle.
/// </param>
/// <param name="phContext">
/// Pointer to a CtxtHandle structure. On the first call to AcceptSecurityContext (General), this pointer is <c>NULL</c>. On
/// subsequent calls, phContext is the handle to the partially formed context that was returned in the phNewContext parameter by the
/// first call.
/// </param>
/// <param name="pInput">
2018-09-30 17:37:25 -04:00
/// <para>
/// Pointer to a SecBufferDesc structure generated by a client call to the InitializeSecurityContext (General) function that contains
/// the input buffer descriptor.
/// </para>
/// <para>
/// SASL requires a single buffer of type <c>SECBUFFER_TOKEN</c>. The buffer is empty for the first call to the AcceptSecurityContext
/// (General) function and contains the challenge response received from the client for the second call.
2018-09-30 17:37:25 -04:00
/// </para>
/// </param>
/// <param name="fContextReq">
/// <para>
/// Bit flags that specify the attributes required by the server to establish the context. Bit flags can be combined using bitwise-
/// <c>OR</c> operations. The following table shows the possible values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ASC_REQ_CONFIDENTIALITY</term>
/// <term>Encrypt and decrypt messages. Valid with the Digest SSP for SASL only.</term>
/// </item>
/// <item>
/// <term>ASC_REQ_HTTP</term>
/// <term>Use Digest for HTTP. Omit this flag to use Digest as an SASL mechanism.</term>
/// </item>
/// </list>
/// </param>
/// <param name="TargetDataRep">
/// Indicates the data representation, such as byte ordering, on the target. This value can be either SECURITY_NATIVE_DREP or SECURITY_NETWORK_DREP.
2018-09-30 17:37:25 -04:00
/// </param>
/// <param name="phNewContext">
/// Pointer to a CtxtHandle structure. On the first call to AcceptSecurityContext (General), this pointer receives the new context
/// handle. On subsequent calls, phNewContext can be the same as the handle specified in the phContext parameter.
2018-09-30 17:37:25 -04:00
/// </param>
/// <param name="pOutput">
/// Pointer to a SecBufferDesc structure that contains the output buffer descriptor. This buffer is sent to the client for input into
/// additional calls to InitializeSecurityContext (General). An output buffer may be generated even if the function returns SEC_E_OK.
/// Any buffer generated must be sent back to the client application.
2018-09-30 17:37:25 -04:00
/// </param>
/// <param name="pfContextAttr">
/// <para>
/// Pointer to a variable that receives a set of bit flags indicating the attributes of the established context. For a description of
/// the various attributes, see Context Requirements. Flags used for this parameter are prefixed with ASC_RET, such as ASC_RET_DELEGATE.
/// </para>
/// <para>
/// Do not check for security-related attributes until the final function call returns successfully. Attribute flags not related to
/// security, such as the ASC_RET_ALLOCATED_MEMORY flag, can be checked before the final return.
/// </para>
/// </param>
/// <param name="ptsExpiry">
/// <para>
/// Pointer to a <c>TimeStamp</c> structure that receives the expiration time of the context. It is recommended that the security
/// package always return this value in local time.
/// </para>
/// <para>
/// <c>Note</c> Until the last call of the authentication process, the expiration time for the context can be incorrect because more
/// information will be provided during later stages of the negotiation. Therefore, ptsTimeStamp must be <c>NULL</c> until the last
/// call to the function.
/// </para>
2018-09-30 17:37:25 -04:00
/// </param>
/// <returns>
/// <para>
/// If the call is completed successfully, this function returns SEC_E_OK. The following table shows some possible failure return values.
2018-09-30 17:37:25 -04:00
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
2018-09-30 17:37:25 -04:00
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>SEC_E_ALGORITHM_MISMATCH</term>
/// <term>Authz processing is not permitted.</term>
/// </item>
/// <item>
/// <term>SEC_E_INSUFFICIENT_MEMORY</term>
/// <term>Not enough memory is available to complete the request.</term>
/// </item>
/// <item>
/// <term>SEC_E_INVALID_TOKEN</term>
/// <term>No Token buffer is located in the pOutput parameter, or the message failed to decrypt.</term>
2018-09-30 17:37:25 -04:00
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// The final call of the AcceptSecurityContext (General) function that returns SEC_E_OK is identified. If a return token is
/// produced, SASL processing is suspended for one round trip back to the client to allow the final token to be processed. After the
/// exchange is completed, SEC_E_CONTINUE_NEEDED is returned to the application with an additional SASL server cookie encrypted with
/// SSPI message functions. The initial server cookie indicates if INTEGRITY and PRIVACY are supported. This initial server cookie is
/// processed by the client, and the client returns a client cookie to indicate which services the client requests. The client cookie
/// is then decrypted by the server and the final services are determined for the following message traffic.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-saslacceptsecuritycontext SECURITY_STATUS SEC_ENTRY
// SaslAcceptSecurityContext( PCredHandle phCredential, PCtxtHandle phContext, PSecBufferDesc pInput, unsigned long fContextReq,
// unsigned long TargetDataRep, PCtxtHandle phNewContext, PSecBufferDesc pOutput, unsigned long *pfContextAttr, PTimeStamp ptsExpiry );
[DllImport(Lib.Secur32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("sspi.h", MSDNShortId = "39ef6522-ff70-4066-a34d-f2af2174f6ee")]
public static unsafe extern HRESULT SaslAcceptSecurityContext([In, Optional] CredHandle* phCredential, [In, Optional] CtxtHandle* phContext, [In, Optional] SecBufferDesc* pInput, ASC_REQ fContextReq, DREP TargetDataRep,
out CtxtHandle phNewContext, [Optional] SecBufferDesc* pOutput, out ASC_RET pfContextAttr, out TimeStamp ptsExpiry);
2018-09-30 17:37:25 -04:00
/// <summary>The <c>SaslEnumerateProfiles</c> function lists the packages that provide a SASL interface.</summary>
/// <param name="ProfileList">
/// Pointer to a list of Unicode or ANSI strings that contain the names of the packages with SASL wrapper support.
2018-09-30 17:37:25 -04:00
/// </param>
/// <param name="ProfileCount">
/// Pointer to an unsigned <c>LONG</c> value that contains the number of packages with SASL wrapper support.
2018-09-30 17:37:25 -04:00
/// </param>
/// <returns>
/// <para>If the call is completed successfully, this function returns SEC_E_OK.</para>
/// <para>If the function fails, the return value is a nonzero error code.</para>
2018-09-30 17:37:25 -04:00
/// </returns>
/// <remarks>
/// <para>The current list is maintained in the registry under</para>
/// <para>A terminating <c>NULL</c> character is appended to the end of the list.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-saslenumerateprofilesa SECURITY_STATUS SEC_ENTRY
// SaslEnumerateProfilesA( LPSTR *ProfileList, ULONG *ProfileCount );
[DllImport(Lib.Secur32, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("sspi.h", MSDNShortId = "0c11e0e3-2538-4703-bc32-31c73d65a498")]
public static extern HRESULT SaslEnumerateProfiles([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(NullTermStringArrayMarshaler), MarshalCookie = "Auto")] out string[] ProfileList, out uint ProfileCount);
2018-09-30 17:37:25 -04:00
/// <summary>The <c>SaslGetContextOption</c> function retrieves the specified property of the specified SASL context.</summary>
/// <param name="ContextHandle">Handle of the SASL context.</param>
/// <param name="Option">
/// <para>Property to return from the SASL context. The following table lists the possible values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>SASL_OPTION_AUTHZ_PROCESSING</term>
/// <term>
/// Data type of buffer: ULONG State of SASL processing of the Authz value provided by the SASL application. The valid states for
/// processing are Sasl_AuthZIDForbidden and Sasl_AuthZIDProcessed.
/// </term>
/// </item>
/// <item>
/// <term>SASL_OPTION_AUTHZ_STRING</term>
/// <term>
/// Data type of buffer: Array of binary characters String of characters passed from the SASL client to the server. If the
/// AuthZ_Processing state is Sasl_AuthZIDForbidden, the return value SEC_E_UNSUPPORTED_FUNCTION is returned.
/// </term>
/// </item>
/// <item>
/// <term>SASL_OPTION_RECV_SIZE</term>
/// <term>Data type of buffer: ULONG Maximum size of the receiving buffer on the local computer.</term>
/// </item>
/// <item>
/// <term>SASL_OPTION_SEND_SIZE</term>
/// <term>
/// Data type of buffer: ULONG Maximum message data size that can be transmitted. This value is the maximum buffer size that can be
/// transmitted to the remote SASL process minus the block size, the trailer size, and the maximum signature size.
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="Value">
/// A pointer to a buffer that receives the requested property. For the data type of the buffer for each value of the Option
/// parameter, see the Option parameter.
/// </param>
/// <param name="Size">The size, in bytes, of the buffer specified by the Value parameter.</param>
/// <param name="Needed">
/// A pointer to an unsigned <c>LONG</c> value that returns the value if the buffer specified by the Value parameter is not large
/// enough to contain the data value of the property specified by the Option parameter.
/// </param>
/// <returns>
2018-09-30 17:37:25 -04:00
/// <para>
/// If the call is completed successfully, this function returns SEC_E_OK. The following table shows some possible error return values.
2018-09-30 17:37:25 -04:00
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>SEC_E_BUFFER_TOO_SMALL</term>
/// <term>
/// The buffer specified by the Value parameter is not large enough to contain the data value of the property specified by the Option parameter.
/// </term>
/// </item>
/// <item>
/// <term>SEC_E_INVALID_HANDLE</term>
/// <term>The SASL context handle specified by the ContextHandle parameter was not found in the SASL list.</term>
/// </item>
/// <item>
/// <term>SEC_E_UNSUPPORTED_FUNCTION</term>
/// <term>The option specified in the Option parameter is not valid.</term>
/// </item>
/// </list>
2018-09-30 17:37:25 -04:00
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-saslgetcontextoption SECURITY_STATUS SEC_ENTRY
// SaslGetContextOption( PCtxtHandle ContextHandle, ULONG Option, PVOID Value, ULONG Size, PULONG Needed );
2018-09-30 17:37:25 -04:00
[DllImport(Lib.Secur32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("sspi.h", MSDNShortId = "c9c424d3-07e6-4ed0-9189-c932af0475d9")]
public static extern HRESULT SaslGetContextOption(in CtxtHandle ContextHandle, SASL_OPTION Option, [Out] IntPtr Value, uint Size, out uint Needed);
2018-09-30 17:37:25 -04:00
/// <summary>The <c>SaslGetProfilePackage</c> function returns the package information for the specified package.</summary>
/// <param name="ProfileName">Unicode or ANSI string that contains the name of the SASL package.</param>
/// <param name="PackageInfo">
/// Pointer to a pointer to a SecPkgInfo structure that returns the package information for the package specified by the ProfileName parameter.
2018-09-30 17:37:25 -04:00
/// </param>
/// <returns>
/// <para>
/// If the call is completed successfully, this function returns SEC_E_OK. The following table shows some possible failure return values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>SEC_E_SECPKG_NOT_FOUND</term>
/// <term>The SASL profile specified by the ProfileName parameter could not be found.</term>
/// </item>
/// <item>
/// <term>SEC_E_INSUFFICIENT_MEMORY</term>
/// <term>Memory could not be allocated for the SecPkgInfo structure.</term>
/// </item>
/// </list>
2018-09-30 17:37:25 -04:00
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-saslgetprofilepackagew SECURITY_STATUS SEC_ENTRY
// SaslGetProfilePackageW( LPWSTR ProfileName, PSecPkgInfoW *PackageInfo );
[DllImport(Lib.Secur32, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("sspi.h", MSDNShortId = "b7cecc5f-775f-40ba-abfc-27d51b3f5395")]
public static extern HRESULT SaslGetProfilePackage(string ProfileName, out SafeContextBuffer PackageInfo);
2018-09-30 17:37:25 -04:00
/// <summary>
/// The <c>SaslIdentifyPackage</c> function returns the negotiate prefix that matches the specified SASL negotiation buffer.
2018-09-30 17:37:25 -04:00
/// </summary>
/// <param name="pInput">
/// Pointer to a SecBufferDesc structure that specifies the SASL negotiation buffer for which to find the negotiate prefix.
2018-09-30 17:37:25 -04:00
/// </param>
/// <param name="PackageInfo">
/// Pointer to a pointer to a SecPkgInfo structure that returns the negotiate prefix for the negotiation buffer specified by the
/// pInput parameter.
2018-09-30 17:37:25 -04:00
/// </param>
/// <returns>
/// <para>If the call is completed successfully, this function returns SEC_E_OK.</para>
/// <para>If the function fails, the return value is a nonzero error code.</para>
2018-09-30 17:37:25 -04:00
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-saslidentifypackagea SECURITY_STATUS SEC_ENTRY
// SaslIdentifyPackageA( PSecBufferDesc pInput, PSecPkgInfoA *PackageInfo );
[DllImport(Lib.Secur32, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("sspi.h", MSDNShortId = "df6f4749-8f28-4ee5-8165-f7aeb3bea7ab")]
public static extern HRESULT SaslIdentifyPackage(ref SecBufferDesc pInput, out SafeContextBuffer PackageInfo);
2018-09-30 17:37:25 -04:00
/// <summary>
/// The <c>SaslInitializeSecurityContext</c> function wraps a standard call to the Security Support Provider Interface
/// InitializeSecurityContext (General) function and processes SASL server cookies from the server.
2018-09-30 17:37:25 -04:00
/// </summary>
/// <param name="phCredential">
/// A handle to the credentials returned by the AcquireCredentialsHandle function used to build the security context. Using the
/// <c>SaslInitializeSecurityContext</c> function requires at least OUTBOUND credentials.
2018-09-30 17:37:25 -04:00
/// </param>
/// <param name="phContext">
/// Pointer to a <c>CtxtHandle</c> structure. On the first call to the <c>SaslInitializeSecurityContext</c> function, this pointer is
/// <c>NULL</c>. On the second call, this parameter is a pointer to the handle to the partially formed context returned in the
/// phNewContext parameter by the first call.
2018-09-30 17:37:25 -04:00
/// </param>
/// <param name="pszTargetName">Pointer to a Unicode or ANSI string that indicates the target of the context.</param>
/// <param name="fContextReq">
/// <para>
/// Bit flags that indicate the requirements of the context. Flags used for this parameter are prefixed with ISC_REQ_; for example:
/// ISC_REQ_DELEGATE. Specify combinations of the following attributes flags.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ISC_REQ_REPLAY_DETECT</term>
/// <term>Detect replayed packets.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_SEQUENCE_DETECT</term>
/// <term>Detect messages received out of sequence.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_CONFIDENTIALITY</term>
/// <term>Encrypt messages.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_STREAM</term>
/// <term>Support a stream-oriented connection.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_EXTENDED_ERROR</term>
/// <term>When errors occur, the remote party will be notified.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_CONNECTION</term>
/// <term>The security context will not handle formatting messages.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_MUTUAL_AUTH</term>
/// <term>Client and server will be authenticated.</term>
/// </item>
/// <item>
/// <term>ISC_REQ_INTEGRITY</term>
/// <term>Sign messages and verify signatures.</term>
/// </item>
/// </list>
/// <para>For further descriptions of the various attributes, see Context Requirements.</para>
2018-09-30 17:37:25 -04:00
/// </param>
/// <param name="Reserved1">Reserved value; must be zero.</param>
/// <param name="TargetDataRep">
/// Indicates the data representation, such as byte ordering, on the target. Can be either SECURITY_NATIVE_DREP or SECURITY_NETWORK_DREP.
/// </param>
/// <param name="pInput">
2018-09-30 17:37:25 -04:00
/// <para>
/// Pointer to a SecBufferDesc structure that contains pointers to the buffers supplied as input to the package. The pointer must be
/// <c>NULL</c> on the first call to the function. On subsequent calls to the function, it is a pointer to a buffer allocated with
/// enough memory to hold the token returned by the remote peer.
2018-09-30 17:37:25 -04:00
/// </para>
/// <para>SASL requires a single buffer of type <c>SECBUFFER_TOKEN</c> that contains the challenge received from the server.</para>
2018-09-30 17:37:25 -04:00
/// </param>
/// <param name="Reserved2">Reserved value; must be zero.</param>
/// <param name="phNewContext">
/// Pointer to a CtxtHandle structure. On the first call to the <c>SaslInitializeSecurityContext</c> function, this pointer receives
/// the new context handle. On the second call, phNewContext can be the same as the handle specified in the phContext parameter.
2018-09-30 17:37:25 -04:00
/// </param>
/// <param name="pOutput">
/// Pointer to a SecBufferDesc structure that contains pointers to the SecBuffer structure that receives the output data. If a buffer
/// was typed as SEC_READWRITE in the input, it will be there on output. The system will allocate a buffer for the security token if
/// requested (through ISC_REQ_ALLOCATE_MEMORY) and fill in the address in the buffer descriptor for the security token.
2018-09-30 17:37:25 -04:00
/// </param>
/// <param name="pfContextAttr">
/// <para>
/// Pointer to a variable to receive a set of bit flags that indicate the attributes of the established context. For a description of
/// the various attributes, see Context Requirements.
/// </para>
/// <para>Flags used for this parameter are prefixed with ISC_RET_, such as ISC_RET_DELEGATE.</para>
/// <para>For a list of valid values, see the fContextReq parameter.</para>
/// <para>
/// Do not check for security-related attributes until the final function call returns successfully. Attribute flags not related to
/// security, such as the ASC_RET_ALLOCATED_MEMORY flag, can be checked before the final return.
/// </para>
/// <para><c>Note</c> Particular context attributes can change during a negotiation with a remote peer.</para>
/// </param>
/// <param name="ptsExpiry">
/// Pointer to a <c>TimeStamp</c> structure that receives the expiration time of the context. It is recommended that the security
/// package always return this value in local time. This parameter is optional and <c>NULL</c> should be passed for short-lived clients.
2018-09-30 17:37:25 -04:00
/// </param>
/// <returns>
/// <para>
/// If the call is completed successfully, this function returns SEC_E_OK. The following table shows some possible failure return values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>SEC_E_ALGORITHM_MISMATCH</term>
/// <term>Authz processing is not permitted.</term>
/// </item>
/// <item>
/// <term>SEC_E_INSUFFICIENT_MEMORY</term>
/// <term>Not enough memory is available to complete the request.</term>
/// </item>
/// <item>
/// <term>SEC_E_INVALID_TOKEN</term>
/// <term>No Token buffer is located in the pOutput parameter, or the message failed to decrypt.</term>
/// </item>
/// </list>
2018-09-30 17:37:25 -04:00
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-saslinitializesecuritycontextw SECURITY_STATUS SEC_ENTRY
// SaslInitializeSecurityContextW( PCredHandle phCredential, PCtxtHandle phContext, LPWSTR pszTargetName, unsigned long fContextReq,
// unsigned long Reserved1, unsigned long TargetDataRep, PSecBufferDesc pInput, unsigned long Reserved2, PCtxtHandle phNewContext,
// PSecBufferDesc pOutput, unsigned long *pfContextAttr, PTimeStamp ptsExpiry );
[DllImport(Lib.Secur32, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("sspi.h", MSDNShortId = "9cc661b7-f1b0-4fb1-b799-5b318d87fd4d")]
public static unsafe extern HRESULT SaslInitializeSecurityContext([In, Optional] CredHandle* phCredential, [In, Optional] CtxtHandle* phContext, [Optional] string pszTargetName, ASC_REQ fContextReq, [Optional] uint Reserved1, DREP TargetDataRep,
[In, Optional] SecBufferDesc* pInput, [Optional] uint Reserved2, out SafeCtxtHandle phNewContext, [Optional] SecBufferDesc* pOutput, out ASC_RET pfContextAttr, out TimeStamp ptsExpiry);
/// <summary>The <c>SaslSetContextOption</c> function sets the value of the specified property for the specified SASL context.</summary>
/// <param name="ContextHandle">Handle of the SASL context.</param>
/// <param name="Option">
/// <para>Property to set for the SASL context. The following table lists the possible values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>SASL_OPTION_AUTHZ_PROCESSING</term>
/// <term>
/// Data type of buffer: ULONG State of SASL processing of the Authz value provided by the SASL application. The valid states for
/// processing are Sasl_AuthZIDForbidden and Sasl_AuthZIDProcessed. The default value is Sasl_AuthZIDProcessed.
/// </term>
/// </item>
/// <item>
/// <term>SASL_OPTION_AUTHZ_STRING</term>
/// <term>
/// Data type of buffer: Array of binary characters String of characters passed from the SASL client to the server. If the
/// AuthZ_Processing state is Sasl_AuthZIDForbidden, the return value SEC_E_UNSUPPORTED_FUNCTION is returned.
/// </term>
/// </item>
/// <item>
/// <term>SASL_OPTION_RECV_SIZE</term>
/// <term>Data type of buffer: ULONG Maximum size of the receiving buffer on the local computer. The default value is 0x0FFFF bytes.</term>
/// </item>
/// <item>
/// <term>SASL_OPTION_SEND_SIZE</term>
/// <term>
/// Data type of buffer: ULONG Maximum message data size that can be transmitted. This value is the maximum buffer size that can be
/// transmitted to the remote SASL process minus the block size, the trailer size, and the maximum signature size. The default value
/// is 0x0FFFF bytes.
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="Value">
/// A pointer to a buffer that contains the value to set to the requested property. For the data type of the buffer for each value of
/// the Option parameter, see the Option parameter.
/// </param>
/// <param name="Size">The size, in bytes, of the buffer specified by the Value parameter.</param>
/// <returns>
/// <para>
/// If the call is completed successfully, this function returns SEC_E_OK. The following table shows some possible error return values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>SEC_E_BUFFER_TOO_SMALL</term>
/// <term>
/// The buffer specified by the Value parameter is not large enough to contain the data value of the property specified by the Option parameter.
/// </term>
/// </item>
/// <item>
/// <term>SEC_E_INVALID_HANDLE</term>
/// <term>The SASL context handle specified by the ContextHandle parameter was not found in the SASL list.</term>
/// </item>
/// <item>
/// <term>SEC_E_UNSUPPORTED_FUNCTION</term>
/// <term>The option specified in the Option parameter is not valid.</term>
/// </item>
/// </list>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-saslsetcontextoption SECURITY_STATUS SEC_ENTRY
// SaslSetContextOption( PCtxtHandle ContextHandle, ULONG Option, PVOID Value, ULONG Size );
[DllImport(Lib.Secur32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("sspi.h", MSDNShortId = "3c3b1209-b0de-4100-8dfe-53ea314b790b")]
public static extern HRESULT SaslSetContextOption(in CtxtHandle ContextHandle, SASL_OPTION Option, [MarshalAs(UnmanagedType.LPWStr)] string Value, uint Size);
/// <summary>The <c>SaslSetContextOption</c> function sets the value of the specified property for the specified SASL context.</summary>
/// <param name="ContextHandle">Handle of the SASL context.</param>
/// <param name="Option">
/// <para>Property to set for the SASL context. The following table lists the possible values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>SASL_OPTION_AUTHZ_PROCESSING</term>
/// <term>
/// Data type of buffer: ULONG State of SASL processing of the Authz value provided by the SASL application. The valid states for
/// processing are Sasl_AuthZIDForbidden and Sasl_AuthZIDProcessed. The default value is Sasl_AuthZIDProcessed.
/// </term>
/// </item>
/// <item>
/// <term>SASL_OPTION_AUTHZ_STRING</term>
/// <term>
/// Data type of buffer: Array of binary characters String of characters passed from the SASL client to the server. If the
/// AuthZ_Processing state is Sasl_AuthZIDForbidden, the return value SEC_E_UNSUPPORTED_FUNCTION is returned.
/// </term>
/// </item>
/// <item>
/// <term>SASL_OPTION_RECV_SIZE</term>
/// <term>Data type of buffer: ULONG Maximum size of the receiving buffer on the local computer. The default value is 0x0FFFF bytes.</term>
/// </item>
/// <item>
/// <term>SASL_OPTION_SEND_SIZE</term>
/// <term>
/// Data type of buffer: ULONG Maximum message data size that can be transmitted. This value is the maximum buffer size that can be
/// transmitted to the remote SASL process minus the block size, the trailer size, and the maximum signature size. The default value
/// is 0x0FFFF bytes.
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="Value">
/// A pointer to a buffer that contains the value to set to the requested property. For the data type of the buffer for each value of
/// the Option parameter, see the Option parameter.
/// </param>
/// <param name="Size">The size, in bytes, of the buffer specified by the Value parameter.</param>
/// <returns>
/// <para>
/// If the call is completed successfully, this function returns SEC_E_OK. The following table shows some possible error return values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>SEC_E_BUFFER_TOO_SMALL</term>
/// <term>
/// The buffer specified by the Value parameter is not large enough to contain the data value of the property specified by the Option parameter.
/// </term>
/// </item>
/// <item>
/// <term>SEC_E_INVALID_HANDLE</term>
/// <term>The SASL context handle specified by the ContextHandle parameter was not found in the SASL list.</term>
/// </item>
/// <item>
/// <term>SEC_E_UNSUPPORTED_FUNCTION</term>
/// <term>The option specified in the Option parameter is not valid.</term>
/// </item>
/// </list>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-saslsetcontextoption SECURITY_STATUS SEC_ENTRY
// SaslSetContextOption( PCtxtHandle ContextHandle, ULONG Option, PVOID Value, ULONG Size );
[DllImport(Lib.Secur32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("sspi.h", MSDNShortId = "3c3b1209-b0de-4100-8dfe-53ea314b790b")]
public static extern HRESULT SaslSetContextOption(in CtxtHandle ContextHandle, SASL_OPTION Option, in uint Value, uint Size = 4);
/// <summary>
/// Enables a transport application to set attributes of a security context for a security package. This function is supported only
/// by the Schannel security package.
/// </summary>
/// <param name="phContext">A handle to the security context to be set.</param>
/// <param name="ulAttribute">
/// <para>The attribute of the context to be set. This parameter can be one of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>SECPKG_ATTR_APP_DATA 94</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_SessionAppData structure. Sets application data for the session. This
/// attribute is supported only by the Schannel security package.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_EAP_PRF_INFO 101</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_EapPrfInfo structure. Sets the pseudo-random function (PRF) used by
/// the Extensible Authentication Protocol (EAP). This is the value that is returned by a call to the QueryContextAttributes
/// (Schannel) function when SECPKG_ATTR_EAP_KEY_BLOCK is passed as the value of the ulAttribute parameter. This attribute is
/// supported only by the Schannel security package.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_EARLY_START 105</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_EarlyStart structure. Sets the False Start feature. See the Building
/// a faster and more secure web blog post for information on this feature.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_DTLS_MTU 34</term>
/// <term>
/// Sets and retrieves the MTU (maximum transmission unit) value for use with DTLS. If DTLS is not enabled in a security context,
/// this attribute is not supported. Valid values are between 200 bytes and 64 kilobytes. The default DTLS MTU value in Schannel is
/// 1096 bytes.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_KEYING_MATERIAL_INFO 106</term>
/// <term>
/// The pBuffer parameter contains a pointer to a SecPkgContext_KeyingMaterialInfo structure. The keying material export feature
/// follows the RFC 5705 standard. This attribute is supported only by the Schannel security package in Windows 10 and Windows Server
/// 2016 or later versions.
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="pBuffer">
/// A pointer to a structure that contains values to set the attributes to. The type of structure pointed to depends on the value
/// specified in the ulAttribute parameter.
/// </param>
/// <param name="cbBuffer">The size, in bytes, of the pBuffer parameter.</param>
/// <returns>
/// <para>If the function succeeds, the function returns SEC_E_OK.</para>
/// <para>If the function fails, it returns a nonzero error code. The following error code is one of the possible error codes.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>SEC_E_UNSUPPORTED_FUNCTION</term>
/// <term>This value is returned by Schannel kernel mode to indicate that this function is not supported.</term>
/// </item>
/// </list>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-setcontextattributesa SECURITY_STATUS SEC_ENTRY
// SetContextAttributesA( PCtxtHandle phContext, unsigned long ulAttribute, void *pBuffer, unsigned long cbBuffer );
[DllImport(Lib.Secur32, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("sspi.h", MSDNShortId = "e3246c3e-3e8c-49fe-99d8-dfff1a10ab83")]
public static extern HRESULT SetContextAttributes(in CtxtHandle phContext, SECPKG_ATTR ulAttribute, IntPtr pBuffer, uint cbBuffer);
/// <summary>
/// Sets the attributes of a credential, such as the name associated with the credential. The information is valid for any security
/// context created with the specified credential.
/// </summary>
/// <param name="phCredential">A handle of the credentials to be set.</param>
/// <param name="ulAttribute">
/// <para>Specifies the attribute to set. This parameter can be any of the following attributes.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>SECPKG_CRED_ATTR_NAMES</term>
/// <term>
/// Sets the name of a credential in a pBuffer parameter of type SecPkgCredentials_Names. This attribute is not supported by Schannel
/// in WOW64 mode.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_CRED_ATTR_KDC_PROXY_SETTINGS</term>
/// <term>
/// Sets the Kerberos proxy setting in a pBuffer parameter of type SecPkgCredentials_KdcProxySettings. This attribute is only
/// supported by Kerberos.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_SUPPORTED_ALGS</term>
/// <term>
/// Sets the supported algorithms in a pBuffer parameter of type SecPkgCred_SupportedAlgs. All supported algorithms are included,
/// regardless of whether they are supported by the provided certificate or enabled on the local computer. This attribute is
/// supported only by Schannel.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_CIPHER_STRENGTHS</term>
/// <term>
/// Sets the cipher strengths in a pBuffer parameter of type SecPkgCred_CipherStrengths. This attribute is supported only by Schannel.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_ATTR_SUPPORTED_PROTOCOLS</term>
/// <term>
/// Sets the supported algorithms in a pBuffer parameter of type SecPkgCred_SupportedProtocols. All supported protocols are included,
/// regardless of whether they are supported by the provided certificate or enabled on the local computer. This attribute is
/// supported only by Schannel.
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="pBuffer">
/// A pointer to a buffer that contains the new attribute value. The type of structure returned depends on the value of ulAttribute.
/// </param>
/// <param name="cbBuffer">The size, in bytes, of the pBuffer buffer.</param>
/// <returns>
/// <para>If the function succeeds, the return value is SEC_E_OK.</para>
/// <para>If the function fails, the return value may be one of the following error codes.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>SEC_E_INVALID_HANDLE</term>
/// <term>The handle passed to the function is not valid.</term>
/// </item>
/// <item>
/// <term>SEC_E_UNSUPPORTED_FUNCTION</term>
/// <term>
/// The specified attribute is not supported by Schannel. This return value will only be returned when the Schannel SSP is being used.
/// </term>
/// </item>
/// <item>
/// <term>SEC_E_INSUFFICIENT_MEMORY</term>
/// <term>Not enough memory is available to complete the request.</term>
/// </item>
/// </list>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-setcredentialsattributesa SECURITY_STATUS SEC_ENTRY
// SetCredentialsAttributesA( PCredHandle phCredential, unsigned long ulAttribute, void *pBuffer, unsigned long cbBuffer );
[DllImport(Lib.Secur32, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("sspi.h", MSDNShortId = "419fb4f0-3dd1-4473-aeb2-8024355e0c1c")]
public static extern HRESULT SetCredentialsAttributes(in CredHandle phCredential, SECPKG_CRED_ATTR ulAttribute, IntPtr pBuffer, uint cbBuffer);
/// <summary>
/// <para>Compares the two specified credentials.</para>
/// </summary>
/// <param name="AuthIdentity1">
/// <para>A pointer to an opaque structure that specifies the first credential to compare.</para>
/// </param>
/// <param name="AuthIdentity2">
/// <para>A pointer to an opaque structure that specifies the second credential to compare.</para>
/// </param>
/// <param name="SameSuppliedUser">
/// <para>
/// <c>TRUE</c> if the user account specified by the AuthIdentity1 parameter is the same as the user account specified by the
/// AuthIdentity2 parameter; otherwise, <c>FALSE</c>.
/// </para>
/// </param>
/// <param name="SameSuppliedIdentity">
/// <para>
/// <c>TRUE</c> if the identity specified by the AuthIdentity1 parameter is the same as the identity specified by the AuthIdentity2
/// parameter; otherwise, <c>FALSE</c>.
/// </para>
/// </param>
/// <returns>
/// <para>If the function succeeds, it returns <c>SEC_E_OK</c>.</para>
/// <para>If the function fails, it returns a nonzero error code.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-sspicompareauthidentities SECURITY_STATUS SEC_ENTRY
// SspiCompareAuthIdentities( PSEC_WINNT_AUTH_IDENTITY_OPAQUE AuthIdentity1, PSEC_WINNT_AUTH_IDENTITY_OPAQUE AuthIdentity2, PBOOLEAN
// SameSuppliedUser, PBOOLEAN SameSuppliedIdentity );
[DllImport(Lib.Secur32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("sspi.h", MSDNShortId = "d2c4f363-3d86-48f0-bae1-4f9240d68bab")]
public static extern Win32Error SspiCompareAuthIdentities(PSEC_WINNT_AUTH_IDENTITY_OPAQUE AuthIdentity1, PSEC_WINNT_AUTH_IDENTITY_OPAQUE AuthIdentity2,
[MarshalAs(UnmanagedType.U1)] out bool SameSuppliedUser, [MarshalAs(UnmanagedType.U1)] out bool SameSuppliedIdentity);
/// <summary>
/// <para>Creates a copy of the specified opaque credential structure.</para>
/// </summary>
/// <param name="AuthData">
/// <para>The credential structure to be copied.</para>
/// </param>
/// <param name="AuthDataCopy">
/// <para>The structure that receives the copy of the structure specified by the AuthData parameter.</para>
/// </param>
/// <returns>
/// <para>If the function succeeds, it returns <c>SEC_E_OK</c>.</para>
/// <para>If the function fails, it returns a nonzero error code.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-sspicopyauthidentity SECURITY_STATUS SEC_ENTRY
// SspiCopyAuthIdentity( PSEC_WINNT_AUTH_IDENTITY_OPAQUE AuthData, PSEC_WINNT_AUTH_IDENTITY_OPAQUE *AuthDataCopy );
[DllImport(Lib.Secur32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("sspi.h", MSDNShortId = "e53807bf-b5a1-4479-a73b-dd85c5da173e")]
public static extern Win32Error SspiCopyAuthIdentity(PSEC_WINNT_AUTH_IDENTITY_OPAQUE AuthData, out SafePSEC_WINNT_AUTH_IDENTITY_OPAQUE AuthDataCopy);
/// <summary>
/// <para>Decrypts the specified encrypted credential.</para>
/// </summary>
/// <param name="EncryptedAuthData">
/// <para>
/// On input, a pointer to the encrypted credential structure to be decrypted. On output, a pointer to the decrypted credential structure.
/// </para>
/// </param>
/// <returns>
/// <para>If the function succeeds, it returns <c>SEC_E_OK</c>.</para>
/// <para>If the function fails, it returns a nonzero error code.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-sspidecryptauthidentity SECURITY_STATUS SEC_ENTRY
// SspiDecryptAuthIdentity( PSEC_WINNT_AUTH_IDENTITY_OPAQUE EncryptedAuthData );
[DllImport(Lib.Secur32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("sspi.h", MSDNShortId = "aef0206c-c376-4877-b1a6-5e86d2e35dea")]
public static extern Win32Error SspiDecryptAuthIdentity(PSEC_WINNT_AUTH_IDENTITY_OPAQUE EncryptedAuthData);
/// <summary>Decrypts a <c>SEC_WINNT_AUTH_IDENTITY_OPAQUE</c> structure.</summary>
/// <param name="Options">
/// <para>
/// Decryption options. This parameter should be the same value as the value passed to the SspiEncryptAuthIdentityEx function, which
/// can be one of the following values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>SEC_WINNT_AUTH_IDENTITY_ENCRYPT_SAME_LOGON</term>
/// <term>
/// The encrypted structure can only be decrypted by a security context in the same logon session. This option is used to protect an
/// identity buffer that is being sent over a local RPC.
/// </term>
/// </item>
/// <item>
/// <term>SEC_WINNT_AUTH_IDENTITY_ENCRYPT_SAME_PROCESS</term>
/// <term>
/// The encrypted structure can only be decrypted by the same process. Calling the function with this option is equivalent to calling
/// SspiEncryptAuthIdentity. This option is used to protect an identity buffer that is being persisted in a process's private memory
/// for an extended period.
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="EncryptedAuthData">This buffer is the output of the SspiEncryptAuthIdentityEx function.</param>
/// <returns>
/// <para>If the function succeeds, it returns SEC_E_OK.</para>
/// <para>If the function fails, it returns a nonzero error code.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-sspidecryptauthidentityex SECURITY_STATUS SEC_ENTRY
// SspiDecryptAuthIdentityEx( ULONG Options, PSEC_WINNT_AUTH_IDENTITY_OPAQUE EncryptedAuthData );
[DllImport(Lib.SspiCli, SetLastError = false, ExactSpelling = true)]
[PInvokeData("sspi.h", MSDNShortId = "86598BAA-0E87-46A9-AA1A-BF04BF0CDAFA")]
public static extern HRESULT SspiDecryptAuthIdentityEx(SEC_WINNT_AUTH_IDENTITY_ENCRYPT Options, PSEC_WINNT_AUTH_IDENTITY_OPAQUE EncryptedAuthData);
/// <summary>
/// <para>Encodes the specified authentication identity as three strings.</para>
/// </summary>
/// <param name="pAuthIdentity">
/// <para>The credential structure to be encoded.</para>
/// </param>
/// <param name="ppszUserName">
/// <para>The marshaled user name of the identity specified by the pAuthIdentity parameter.</para>
/// <para>When you have finished using this string, free it by calling the SspiFreeAuthIdentity function.</para>
/// </param>
/// <param name="ppszDomainName">
/// <para>The marshaled domain name of the identity specified by the pAuthIdentity parameter.</para>
/// <para>When you have finished using this string, free it by calling the SspiFreeAuthIdentity function.</para>
/// </param>
/// <param name="ppszPackedCredentialsString">
/// <para>An encoded string version of a SEC_WINNT_AUTH_IDENTITY_EX2 structure that specifies the users credentials.</para>
/// <para>When you have finished using this string, free it by calling the SspiFreeAuthIdentity function.</para>
/// </param>
/// <returns>
/// <para>If the function succeeds, it returns <c>SEC_E_OK</c>.</para>
/// <para>
/// If the function fails, it returns a nonzero error code. Possible values include, but are not limited to, those in the following table.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code/value</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>STATUS_INVALID_PARAMETER 0xC000000D</term>
/// <term>
/// The SEC_WINNT_AUTH_IDENTITY_FLAGS_PROCESS_ENCRYPTED flag is set in the identity structure specified by the pAuthIdentity parameter.
/// </term>
/// </item>
/// </list>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-sspiencodeauthidentityasstrings SECURITY_STATUS SEC_ENTRY
// SspiEncodeAuthIdentityAsStrings( PSEC_WINNT_AUTH_IDENTITY_OPAQUE pAuthIdentity, PCWSTR *ppszUserName, PCWSTR *ppszDomainName,
// PCWSTR *ppszPackedCredentialsString );
[DllImport(Lib.Secur32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("sspi.h", MSDNShortId = "0610a7b8-67e9-4c01-893f-da579eeea2f8")]
public static extern Win32Error SspiEncodeAuthIdentityAsStrings([In] PSEC_WINNT_AUTH_IDENTITY_OPAQUE pAuthIdentity,
[Out, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(SspiStringMarshaler))] out string ppszUserName,
[Out, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(SspiStringMarshaler))] out string ppszDomainName,
[Out, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(SspiStringMarshaler))] out string ppszPackedCredentialsString);
/// <summary>
/// <para>Encodes a set of three credential strings as an authentication identity structure.</para>
/// </summary>
/// <param name="pszUserName">
/// <para>The user name associated with the identity to encode.</para>
/// </param>
/// <param name="pszDomainName">
/// <para>The domain name associated with the identity to encode.</para>
/// </param>
/// <param name="pszPackedCredentialsString">
/// <para>An encoded string version of a SEC_WINNT_AUTH_IDENTITY_EX2 structure that specifies the user's credentials.</para>
/// </param>
/// <param name="ppAuthIdentity">
/// <para>A pointer to the encoded identity structure.</para>
/// <para>When you have finished using this structure, free it by calling the SspiFreeAuthIdentity function.</para>
/// </param>
/// <returns>
/// <para>If the function succeeds, it returns <c>SEC_E_OK</c>.</para>
/// <para>If the function fails, it returns a nonzero error code.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-sspiencodestringsasauthidentity SECURITY_STATUS SEC_ENTRY
// SspiEncodeStringsAsAuthIdentity( PCWSTR pszUserName, PCWSTR pszDomainName, PCWSTR pszPackedCredentialsString,
// PSEC_WINNT_AUTH_IDENTITY_OPAQUE *ppAuthIdentity );
[DllImport(Lib.Secur32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("sspi.h", MSDNShortId = "0aea2f00-fcf1-4c4e-a22f-a669dd4fb294")]
public static extern Win32Error SspiEncodeStringsAsAuthIdentity([MarshalAs(UnmanagedType.LPWStr)] string pszUserName, [MarshalAs(UnmanagedType.LPWStr)] string pszDomainName,
[MarshalAs(UnmanagedType.LPWStr)] string pszPackedCredentialsString, out SafePSEC_WINNT_AUTH_IDENTITY_OPAQUE ppAuthIdentity);
/// <summary>
/// <para>Encrypts the specified identity structure.</para>
/// </summary>
/// <param name="AuthData">
/// <para>On input, the identity structure to encrypt. On output, the encrypted identity structure.</para>
/// </param>
/// <returns>
/// <para>If the function succeeds, it returns <c>SEC_E_OK</c>.</para>
/// <para>If the function fails, it returns a nonzero error code.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-sspiencryptauthidentity SECURITY_STATUS SEC_ENTRY
// SspiEncryptAuthIdentity( PSEC_WINNT_AUTH_IDENTITY_OPAQUE AuthData );
[DllImport(Lib.Secur32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("sspi.h", MSDNShortId = "4460f7ec-35fd-4ad1-8c20-dda9f4d3477a")]
public static extern Win32Error SspiEncryptAuthIdentity(PSEC_WINNT_AUTH_IDENTITY_OPAQUE AuthData);
/// <summary>Encrypts a <c>SEC_WINNT_AUTH_IDENTITY_OPAQUE</c> structure.</summary>
/// <param name="Options">
/// <para>Encryption options. This can be one or more of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>SEC_WINNT_AUTH_IDENTITY_ENCRYPT_SAME_LOGON</term>
/// <term>
/// The encrypted structure can only be decrypted by a security context in the same logon session. This option is used to protect an
/// identity buffer that is being sent over a local RPC.
/// </term>
/// </item>
/// <item>
/// <term>SEC_WINNT_AUTH_IDENTITY_ENCRYPT_SAME_PROCESS</term>
/// <term>
/// The encrypted structure can only be decrypted by the same process. Calling the function with this option is equivalent to calling
/// SspiEncryptAuthIdentity. This option is used to protect an identity buffer that is being persisted in a process's private memory
/// for an extended period.
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="AuthData">
/// On input, a pointer to an identity buffer to encrypt. This buffer must be prepared for encryption prior to the call to this
/// function. This can be done by calling the function SspiEncryptAuthIdentity. On output, the encrypted identity buffer.
/// </param>
/// <returns>
/// <para>If the function succeeds, it returns SEC_E_OK.</para>
/// <para>If the function fails, it returns a nonzero error code.</para>
/// </returns>
/// <remarks>
/// To transfer credentials securely across processes, applications typically call this function with the
/// SEC_WINNT_AUTH_IDENTITY_ENCRYPT_SAME_LOGON option, followed by SspiMarshalAuthIdentity to obtain a marshaled authentication
/// buffer and its length. For example, Online Identity Credential Provider does this to return the authentication buffer from their
/// ICredentialProviderCredential::GetSerialization method.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-sspiencryptauthidentityex SECURITY_STATUS SEC_ENTRY
// SspiEncryptAuthIdentityEx( ULONG Options, PSEC_WINNT_AUTH_IDENTITY_OPAQUE AuthData );
[DllImport(Lib.SspiCli, SetLastError = false, ExactSpelling = true)]
[PInvokeData("sspi.h", MSDNShortId = "9290BEF8-24C9-47F0-B258-56ED7D67620B")]
public static extern HRESULT SspiEncryptAuthIdentityEx(SEC_WINNT_AUTH_IDENTITY_ENCRYPT Options, PSEC_WINNT_AUTH_IDENTITY_OPAQUE AuthData);
/// <summary>
/// <para>
/// Creates a new identity structure that is a copy of the specified identity structure modified to exclude the specified security
/// support provider (SSP).
/// </para>
/// </summary>
/// <param name="AuthIdentity">
/// <para>The identity structure to modify.</para>
/// </param>
/// <param name="pszPackageName">
/// <para>The SSP to exclude.</para>
/// </param>
/// <param name="ppNewAuthIdentity">
/// <para>The modified identity structure.</para>
/// </param>
/// <returns>
/// <para>If the function succeeds, it returns <c>SEC_E_OK</c>.</para>
/// <para>If the function fails, it returns a nonzero error code.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-sspiexcludepackage SECURITY_STATUS SEC_ENTRY SspiExcludePackage(
// PSEC_WINNT_AUTH_IDENTITY_OPAQUE AuthIdentity, PCWSTR pszPackageName, PSEC_WINNT_AUTH_IDENTITY_OPAQUE *ppNewAuthIdentity );
[DllImport(Lib.Secur32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("sspi.h", MSDNShortId = "2f85bb13-b72a-4c26-a328-9424a33a63b8")]
public static extern Win32Error SspiExcludePackage(PSEC_WINNT_AUTH_IDENTITY_OPAQUE AuthIdentity, [MarshalAs(UnmanagedType.LPWStr)] string pszPackageName, out SafePSEC_WINNT_AUTH_IDENTITY_OPAQUE ppNewAuthIdentity);
/// <summary>
/// <para>Frees the memory allocated for the specified identity structure.</para>
/// </summary>
/// <param name="AuthData">
/// <para>The identity structure to free.</para>
/// </param>
/// <returns>
/// <para>If the function succeeds, it returns <c>SEC_E_OK</c>.</para>
/// <para>If the function fails, it returns a nonzero error code.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-sspifreeauthidentity VOID SEC_ENTRY SspiFreeAuthIdentity(
// PSEC_WINNT_AUTH_IDENTITY_OPAQUE AuthData );
[DllImport(Lib.Secur32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("sspi.h", MSDNShortId = "6199f66e-7adb-4bb9-8e77-a735e31dd5f6")]
public static extern void SspiFreeAuthIdentity(IntPtr AuthData);
/// <summary>
/// <para>Gets the host name associated with the specified target.</para>
/// </summary>
/// <param name="pszTargetName">
/// <para>The target for which to get the host name.</para>
/// </param>
/// <param name="pszHostName">
/// <para>The name of the host associated with the target specified by the pszTargetName parameter.</para>
/// </param>
/// <returns>
/// <para>If the function succeeds, it returns <c>SEC_E_OK</c>.</para>
/// <para>If the function fails, it returns a nonzero error code.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-sspigettargethostname SECURITY_STATUS SEC_ENTRY
// SspiGetTargetHostName( PCWSTR pszTargetName, PWSTR *pszHostName );
[DllImport(Lib.Secur32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("sspi.h", MSDNShortId = "84570dfc-1890-4b82-b411-1f9eaa75537b")]
public static extern Win32Error SspiGetTargetHostName([MarshalAs(UnmanagedType.LPWStr)] string pszTargetName, [MarshalAs(UnmanagedType.LPWStr)] out string pszHostName);
/// <summary>
/// <para>Indicates whether the specified identity structure is encrypted.</para>
/// </summary>
/// <param name="EncryptedAuthData">
/// <para>The identity structure to test.</para>
/// </param>
/// <returns>
/// <para><c>TRUE</c> if the identity structure specified by the EncryptedAuthData parameter is encrypted; otherwise, <c>FALSE</c>.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-sspiisauthidentityencrypted BOOLEAN SEC_ENTRY
// SspiIsAuthIdentityEncrypted( PSEC_WINNT_AUTH_IDENTITY_OPAQUE EncryptedAuthData );
[DllImport(Lib.Secur32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("sspi.h", MSDNShortId = "b85095f5-0ca5-4d75-866d-9b756404c1d9")]
[return: MarshalAs(UnmanagedType.U1)]
public static extern bool SspiIsAuthIdentityEncrypted(PSEC_WINNT_AUTH_IDENTITY_OPAQUE EncryptedAuthData);
/// <summary>
/// <para>Frees the memory associated with the specified buffer.</para>
/// </summary>
/// <param name="DataBuffer">
/// <para>The buffer to free.</para>
/// </param>
/// <returns>
/// <para>This function does not return a value.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-sspilocalfree VOID SEC_ENTRY SspiLocalFree( PVOID DataBuffer );
[DllImport(Lib.Secur32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("sspi.h", MSDNShortId = "afb890a8-a2c3-4c35-ba76-758b047ababb")]
public static extern void SspiLocalFree(IntPtr DataBuffer);
/// <summary>
/// <para>Serializes the specified identity structure into a byte array.</para>
/// </summary>
/// <param name="AuthIdentity">
/// <para>The identity structure to serialize.</para>
/// </param>
/// <param name="AuthIdentityLength">
/// <para>The length, in bytes, of the AuthIdentityByteArray array.</para>
/// </param>
/// <param name="AuthIdentityByteArray">
/// <para>A pointer to an array of byte values that represents the identity specified by the AuthIdentity parameter.</para>
/// </param>
/// <returns>
/// <para>If the function succeeds, it returns <c>SEC_E_OK</c>.</para>
/// <para>If the function fails, it returns a nonzero error code.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-sspimarshalauthidentity SECURITY_STATUS SEC_ENTRY
// SspiMarshalAuthIdentity( PSEC_WINNT_AUTH_IDENTITY_OPAQUE AuthIdentity, unsigned long *AuthIdentityLength, char
// **AuthIdentityByteArray );
[DllImport(Lib.Secur32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("sspi.h", MSDNShortId = "e43135ad-7fcd-4da6-a4e4-c91c41eeb865")]
public static extern Win32Error SspiMarshalAuthIdentity(PSEC_WINNT_AUTH_IDENTITY_OPAQUE AuthIdentity, out uint AuthIdentityLength, out SafeSspiLocalMem AuthIdentityByteArray);
/// <summary>
/// <para>Generates a target name and credential type from the specified identity structure.</para>
/// <para>
/// The values that this function generates can be passed as the values of the TargetName and Type parameters in a call to the
/// CredRead function.
/// </para>
/// </summary>
/// <param name="AuthIdentity">
/// <para>The identity structure from which to generate the credentials to be passed to the CredRead function.</para>
/// </param>
/// <param name="pszTargetName">
/// <para>A target name that can be modified by this function depending on the value of the AuthIdentity parameter.</para>
/// </param>
/// <param name="pCredmanCredentialType">
/// <para>The credential type to pass to the CredRead function.</para>
/// </param>
/// <param name="ppszCredmanTargetName">
/// <para>The target name to pass to the CredRead function.</para>
/// </param>
/// <returns>
/// <para>If the function succeeds, it returns <c>SEC_E_OK</c>.</para>
/// <para>If the function fails, it returns a nonzero error code.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-sspiprepareforcredread SECURITY_STATUS SEC_ENTRY
// SspiPrepareForCredRead( PSEC_WINNT_AUTH_IDENTITY_OPAQUE AuthIdentity, PCWSTR pszTargetName, PULONG pCredmanCredentialType, PCWSTR
// *ppszCredmanTargetName );
[DllImport(Lib.Secur32, SetLastError = false, ExactSpelling = true, CharSet = CharSet.Unicode)]
[PInvokeData("sspi.h", MSDNShortId = "f473fd7a-5c0f-4a77-829b-28a82ad0d28d")]
public static extern Win32Error SspiPrepareForCredRead(PSEC_WINNT_AUTH_IDENTITY_OPAQUE AuthIdentity, string pszTargetName, out CRED_TYPE pCredmanCredentialType, out string ppszCredmanTargetName);
/// <summary>
/// <para>
/// Generates values from an identity structure that can be passed as the values of parameters in a call to the CredWrite function.
/// </para>
/// </summary>
/// <param name="AuthIdentity">
/// <para>The identity structure from which to generate the credentials to be passed to the CredWrite function.</para>
/// </param>
/// <param name="pszTargetName">
/// <para>A target name that can be modified by this function depending on the value of the AuthIdentity parameter.</para>
/// <para>Set the value of this parameter to <c>NULL</c> to use the user name as the target.</para>
/// </param>
/// <param name="pCredmanCredentialType">
/// <para>The credential type to pass to the CredWrite function.</para>
/// </param>
/// <param name="ppszCredmanTargetName">
/// <para>The target name to pass to the CredWrite function.</para>
/// </param>
/// <param name="ppszCredmanUserName">
/// <para>The user name to pass to the CredWrite function.</para>
/// </param>
/// <param name="ppCredentialBlob">
/// <para>The credential BLOB to send to the CredWrite function.</para>
/// </param>
/// <param name="pCredentialBlobSize">
/// <para>The size, in bytes, of the ppCredentialBlob buffer.</para>
/// </param>
/// <returns>
/// <para>If the function succeeds, it returns <c>SEC_E_OK</c>.</para>
/// <para>If the function fails, it returns a nonzero error code.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-sspiprepareforcredwrite SECURITY_STATUS SEC_ENTRY
// SspiPrepareForCredWrite( PSEC_WINNT_AUTH_IDENTITY_OPAQUE AuthIdentity, PCWSTR pszTargetName, PULONG pCredmanCredentialType, PCWSTR
// *ppszCredmanTargetName, PCWSTR *ppszCredmanUserName, PUCHAR *ppCredentialBlob, PULONG pCredentialBlobSize );
[DllImport(Lib.Secur32, SetLastError = false, ExactSpelling = true, CharSet = CharSet.Unicode)]
[PInvokeData("sspi.h", MSDNShortId = "4db92042-38f2-42c2-9c94-b24e0eaafdf9")]
public static extern Win32Error SspiPrepareForCredWrite(PSEC_WINNT_AUTH_IDENTITY_OPAQUE AuthIdentity, string pszTargetName, out CRED_TYPE pCredmanCredentialType, out string ppszCredmanTargetName, out string ppszCredmanUserName,
[Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 6)] out byte[] ppCredentialBlob, out uint pCredentialBlobSize);
/// <summary>
/// <para>Deserializes the specified array of byte values into an identity structure.</para>
/// </summary>
/// <param name="AuthIdentityLength">
/// <para>The size, in bytes, of the AuthIdentityByteArray array.</para>
/// </param>
/// <param name="AuthIdentityByteArray">
/// <para>The array of byte values to deserialize.</para>
/// </param>
/// <param name="ppAuthIdentity">
/// <para>The deserialized identity structure.</para>
/// </param>
/// <returns>
/// <para>If the function succeeds, it returns <c>SEC_E_OK</c>.</para>
/// <para>If the function fails, it returns a nonzero error code.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-sspiunmarshalauthidentity SECURITY_STATUS SEC_ENTRY
// SspiUnmarshalAuthIdentity( unsigned long AuthIdentityLength, char *AuthIdentityByteArray, PSEC_WINNT_AUTH_IDENTITY_OPAQUE
// *ppAuthIdentity );
[DllImport(Lib.Secur32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("sspi.h", MSDNShortId = "89798b37-808a-4174-8362-a2dc4ee1b460")]
public static extern Win32Error SspiUnmarshalAuthIdentity(uint AuthIdentityLength, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] byte[] AuthIdentityByteArray, out SafePSEC_WINNT_AUTH_IDENTITY_OPAQUE ppAuthIdentity);
/// <summary>
/// <para>Indicates whether the specified identity structure is valid.</para>
/// </summary>
/// <param name="AuthData">
/// <para>The identity structure to test.</para>
/// </param>
/// <returns>
/// <para>
/// If the function succeeds, it returns <c>SEC_E_OK</c>, which indicates that the identity structure specified by the AuthData
/// parameter is valid.
/// </para>
/// <para>
/// If the function fails, it returns a nonzero error code that indicates that the identity structure specified by the AuthData
/// parameter is not valid.
/// </para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-sspivalidateauthidentity SECURITY_STATUS SEC_ENTRY
// SspiValidateAuthIdentity( PSEC_WINNT_AUTH_IDENTITY_OPAQUE AuthData );
[DllImport(Lib.Secur32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("sspi.h", MSDNShortId = "82733abd-d984-4902-b6e4-c3809171ad51")]
public static extern Win32Error SspiValidateAuthIdentity(PSEC_WINNT_AUTH_IDENTITY_OPAQUE AuthData);
/// <summary>
/// <para>Fills the block of memory associated with the specified identity structure with zeros.</para>
/// </summary>
/// <param name="AuthData">
/// <para>The identity structure to fill with zeros.</para>
/// </param>
/// <returns>
/// <para>If the function succeeds, it returns <c>SEC_E_OK</c>.</para>
/// <para>If the function fails, it returns a nonzero error code.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-sspizeroauthidentity VOID SEC_ENTRY SspiZeroAuthIdentity(
// PSEC_WINNT_AUTH_IDENTITY_OPAQUE AuthData );
[DllImport(Lib.Secur32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("sspi.h", MSDNShortId = "50b1f24a-c802-4691-a450-316cb31bf44d")]
public static extern void SspiZeroAuthIdentity(PSEC_WINNT_AUTH_IDENTITY_OPAQUE AuthData);
/// <summary>
/// Verifies that a message signed by using the MakeSignature function was received in the correct sequence and has not been modified.
/// </summary>
/// <param name="phContext">A handle to the security context to use for the message.</param>
/// <param name="pMessage">
/// Pointer to a SecBufferDesc structure that references a set of SecBuffer structures that contain the message and signature to
/// verify. The signature is in a <c>SecBuffer</c> structure of type SECBUFFER_TOKEN.
/// </param>
/// <param name="MessageSeqNo">
/// Specifies the sequence number expected by the transport application, if any. If the transport application does not maintain
/// sequence numbers, this parameter is zero.
/// </param>
/// <param name="pfQOP">
/// <para>Pointer to a <c>ULONG</c> variable that receives package-specific flags that indicate the quality of protection.</para>
/// <para>Some security packages ignore this parameter.</para>
/// </param>
/// <returns>
/// <para>
/// If the function verifies that the message was received in the correct sequence and has not been modified, the return value is SEC_E_OK.
/// </para>
/// <para>
/// If the function determines that the message is not correct according to the information in the signature, the return value can be
/// one of the following error codes.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>SEC_E_OUT_OF_SEQUENCE</term>
/// <term>The message was not received in the correct sequence.</term>
/// </item>
/// <item>
/// <term>SEC_E_MESSAGE_ALTERED</term>
/// <term>The message has been altered.</term>
/// </item>
/// <item>
/// <term>SEC_E_INVALID_HANDLE</term>
/// <term>The context handle specified by phContext is not valid.</term>
/// </item>
/// <item>
/// <term>SEC_E_INVALID_TOKEN</term>
/// <term>pMessage did not contain a valid SECBUFFER_TOKEN buffer, or contained too few buffers.</term>
/// </item>
/// <item>
/// <term>SEC_E_QOP_NOT_SUPPORTED</term>
/// <term>The quality of protection negotiated between the client and server did not include integrity checking.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <c>Warning</c> The <c>VerifySignature</c> function will fail if the message was signed using the RsaSignPssSha512 algorithm on a
/// different version of Windows. For example, a message that was signed by calling the MakeSignature function on Windows 8 will
/// cause the <c>VerifySignature</c> function on Windows 8.1 to fail.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/nf-sspi-verifysignature KSECDDDECLSPEC SECURITY_STATUS SEC_ENTRY
// VerifySignature( PCtxtHandle phContext, PSecBufferDesc pMessage, unsigned long MessageSeqNo, unsigned long *pfQOP );
[DllImport(Lib.Secur32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("sspi.h", MSDNShortId = "bebeef92-1d6e-4879-846f-12d706db0653")]
public static extern HRESULT VerifySignature(in CtxtHandle phContext, in SecBufferDesc pMessage, uint MessageSeqNo, out SECQOP pfQOP);
/// <summary>Provides a handle to a auth identity.</summary>
[StructLayout(LayoutKind.Sequential)]
public struct PSEC_WINNT_AUTH_IDENTITY_OPAQUE : IHandle
{
private IntPtr handle;
/// <summary>Initializes a new instance of the <see cref="PSEC_WINNT_AUTH_IDENTITY_OPAQUE"/> struct.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
public PSEC_WINNT_AUTH_IDENTITY_OPAQUE(IntPtr preexistingHandle) => handle = preexistingHandle;
/// <summary>Returns an invalid handle by instantiating a <see cref="PSEC_WINNT_AUTH_IDENTITY_OPAQUE"/> object with <see cref="IntPtr.Zero"/>.</summary>
public static PSEC_WINNT_AUTH_IDENTITY_OPAQUE NULL => new PSEC_WINNT_AUTH_IDENTITY_OPAQUE(IntPtr.Zero);
/// <summary>Gets a value indicating whether this instance is a null handle.</summary>
public bool IsNull => handle == IntPtr.Zero;
/// <summary>Performs an explicit conversion from <see cref="PSEC_WINNT_AUTH_IDENTITY_OPAQUE"/> to <see cref="IntPtr"/>.</summary>
/// <param name="h">The handle.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator IntPtr(PSEC_WINNT_AUTH_IDENTITY_OPAQUE h) => h.handle;
/// <summary>Performs an implicit conversion from <see cref="IntPtr"/> to <see cref="PSEC_WINNT_AUTH_IDENTITY_OPAQUE"/>.</summary>
/// <param name="h">The pointer to a handle.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator PSEC_WINNT_AUTH_IDENTITY_OPAQUE(IntPtr h) => new PSEC_WINNT_AUTH_IDENTITY_OPAQUE(h);
/// <summary>Implements the operator !=.</summary>
/// <param name="h1">The first handle.</param>
/// <param name="h2">The second handle.</param>
/// <returns>The result of the operator.</returns>
public static bool operator !=(PSEC_WINNT_AUTH_IDENTITY_OPAQUE h1, PSEC_WINNT_AUTH_IDENTITY_OPAQUE h2) => !(h1 == h2);
/// <summary>Implements the operator ==.</summary>
/// <param name="h1">The first handle.</param>
/// <param name="h2">The second handle.</param>
/// <returns>The result of the operator.</returns>
public static bool operator ==(PSEC_WINNT_AUTH_IDENTITY_OPAQUE h1, PSEC_WINNT_AUTH_IDENTITY_OPAQUE h2) => h1.Equals(h2);
/// <inheritdoc/>
public override bool Equals(object obj) => obj is PSEC_WINNT_AUTH_IDENTITY_OPAQUE h ? handle == h.handle : false;
/// <inheritdoc/>
public override int GetHashCode() => handle.GetHashCode();
/// <inheritdoc/>
public IntPtr DangerousGetHandle() => handle;
}
/// <summary>Allows you to pass a particular user name and password to the run-time library for the purpose of authentication.</summary>
/// <remarks>
/// <para>When this structure is used with RPC, the structure must remain valid for the lifetime of the binding handle.</para>
/// <para>The strings may be ANSI or Unicode, depending on the value you assign to the <c>Flags</c> member.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/ns-sspi-_sec_winnt_auth_identity_a typedef struct
// _SEC_WINNT_AUTH_IDENTITY_A { unsigned char *User; unsigned long UserLength; unsigned char *Domain; unsigned long DomainLength;
// unsigned char *Password; unsigned long PasswordLength; unsigned long Flags; } SEC_WINNT_AUTH_IDENTITY_A, *PSEC_WINNT_AUTH_IDENTITY_A;
[PInvokeData("sspi.h", MSDNShortId = "a9c9471b-2134-4173-af86-18b277627d2a")]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct SEC_WINNT_AUTH_IDENTITY
{
/// <summary>A string that contains the user name.</summary>
[MarshalAs(UnmanagedType.LPTStr)]
public string User;
/// <summary>The length, in characters, of the user string, not including the terminating null character.</summary>
public int UserLength;
/// <summary>A string that contains the domain name or the workgroup name.</summary>
[MarshalAs(UnmanagedType.LPTStr)]
public string Domain;
/// <summary>The length, in characters, of the domain string, not including the terminating null character.</summary>
public int DomainLength;
/// <summary>
/// A string that contains the password of the user in the domain or workgroup. When you have finished using the password, remove
/// the sensitive information from memory by calling SecureZeroMemory. For more information about protecting the password, see
/// Handling Passwords.
/// </summary>
[MarshalAs(UnmanagedType.LPTStr)]
public string Password;
/// <summary>The length, in characters, of the password string, not including the terminating null character.</summary>
public int PasswordLength;
/// <summary>
/// <para>This member can be one of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>SEC_WINNT_AUTH_IDENTITY_ANSI</term>
/// <term>The strings in this structure are in ANSI format.</term>
/// </item>
/// <item>
/// <term>SEC_WINNT_AUTH_IDENTITY_UNICODE</term>
/// <term>The strings in this structure are in Unicode format.</term>
/// </item>
/// </list>
/// </summary>
public int Flags;
/// <summary>Initializes a new instance of the <see cref="SEC_WINNT_AUTH_IDENTITY"/> struct.</summary>
/// <param name="user">The user name.</param>
/// <param name="domain">The domain name or the workgroup name.</param>
/// <param name="password">The password of the user in the domain or workgroup.</param>
public SEC_WINNT_AUTH_IDENTITY(string user, string domain, string password)
{
User = user;
UserLength = user?.Length ?? 0;
Domain = domain;
DomainLength = domain?.Length ?? 0;
Password = password;
PasswordLength = password?.Length ?? 0;
Flags = StringHelper.GetCharSize();
}
}
/// <summary>
/// The <c>SEC_WINNT_AUTH_IDENTITY_EX</c> structure contains information about a user. Both an ANSI and Unicode form of this
/// structure are provided.
/// </summary>
/// <remarks>
/// Note that when this structure is used with RPC, the structure must remain valid for the lifetime of the binding handle.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/ns-sspi-_sec_winnt_auth_identity_exa typedef struct
// _SEC_WINNT_AUTH_IDENTITY_EXA { unsigned long Version; unsigned long Length; unsigned char *User; unsigned long UserLength;
// unsigned char *Domain; unsigned long DomainLength; unsigned char *Password; unsigned long PasswordLength; unsigned long Flags;
// unsigned char *PackageList; unsigned long PackageListLength; } SEC_WINNT_AUTH_IDENTITY_EXA, *PSEC_WINNT_AUTH_IDENTITY_EXA;
[PInvokeData("sspi.h", MSDNShortId = "6b95bce8-5613-4403-9bda-16262596bb1b")]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct SEC_WINNT_AUTH_IDENTITY_EX
{
/// <summary>An unsigned long that indicates the version number of the structure.</summary>
public uint Version;
/// <summary>An unsigned long that indicates the length, in bytes, of the structure.</summary>
public uint Length;
/// <summary>A Unicode or ANSI string that contains the name of the user account.</summary>
[MarshalAs(UnmanagedType.LPTStr)]
public string User;
/// <summary>The length, in characters, of the <c>User</c> string.</summary>
public uint UserLength;
/// <summary>A Unicode or ANSI string that contains the name of the domain for the user account.</summary>
[MarshalAs(UnmanagedType.LPTStr)]
public string Domain;
/// <summary>The length, in characters, of the <c>Domain</c> string.</summary>
public uint DomainLength;
/// <summary>
/// A Unicode or ANSI string that contains the user password in plaintext. When you have finished using the password, remove the
/// sensitive information from memory by calling the SecureZeroMemory function. For more information about protecting the
/// password, see Handling Passwords.
/// </summary>
[MarshalAs(UnmanagedType.LPTStr)]
public string Password;
/// <summary>The length, in characters, of the <c>Password</c> string.</summary>
public uint PasswordLength;
/// <summary>
/// <para>An unsigned long flag that indicates the type used by negotiable security packages.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>SEC_WINNT_AUTH_IDENTITY_MARSHALLED</term>
/// <term>All data is in one buffer.</term>
/// </item>
/// <item>
/// <term>SEC_WINNT_AUTH_IDENTITY_ONLY</term>
/// <term>
/// Used with the Kerberos security support provider (SSP). Credentials are for identity only. The Kerberos package is directed
/// to not include authorization data in the ticket.
/// </term>
/// </item>
/// <item>
/// <term>SEC_WINNT_AUTH_IDENTITY_ANSI</term>
/// <term>Credentials are in ANSI form.</term>
/// </item>
/// <item>
/// <term>SEC_WINNT_AUTH_IDENTITY_UNICODE</term>
/// <term>Credentials are in Unicode form.</term>
/// </item>
/// </list>
/// </summary>
public SEC_WINNT_AUTH_IDENTITY_FLAGS Flags;
/// <summary>
/// <para>
/// A Unicode or ANSI string that contains a comma-separated list of names of security packages that are available when using the
/// Microsoft Negotiate provider.
/// </para>
/// <para>Set this to "!ntlm" to specify that the NTLM package is not to be used.</para>
/// </summary>
[MarshalAs(UnmanagedType.LPTStr)]
public string PackageList;
/// <summary>The length, in characters, of the <c>PackageList</c> string.</summary>
public uint PackageListLength;
}
/// <summary>
/// Contains information about an authentication identity. The <c>SEC_WINNT_AUTH_IDENTITY_EX2</c> structure contains authentication
/// data that is provided to the AcquireCredentialsHandle function.
/// </summary>
/// <remarks>
/// <para>
/// This authentication identity buffer can be returned from several credential APIs, for example, the GetSerialization method and
/// the CredUIPromptForWindowsCredential and SspiPromptForCredentials functions.
/// </para>
/// <para>
/// The structure describes a header of the authentication identity buffer and the data is appended at the end of the structure.
/// Although the buffer size is specified by the <c>cbStructureLength</c> member, the actual buffer size can be larger or smaller
/// than <c>cbStructureLength</c>. Some functions, such as SspiValidateAuthIdentity, take a pointer, but not the buffer size, to the
/// identity structure as input. As a result, those functions can validate the internal buffer data but cannot verify the buffer
/// size. This can result in reading or writing data outside of the buffer range. To avoid buffer overruns when handling an untrusted
/// identity buffer, applications should call SspiUnmarshalAuthIdentity to obtain a pointer to an identity structure with a validated
/// size and then pass that pointer to the functions.
/// </para>
/// <para>
/// The <c>SEC_WINNT_AUTH_IDENTITY_EX2</c> structure can be returned by QueryContextAttributes(CredSSP) and consumed by
/// AcquireCredentialsHandle(CredSSP), LsaLogonUser, and other identity provider interfaces.
/// </para>
/// <para>
/// SEC_WINNT_AUTH_PACKED_CREDENTIALS can contain a password credential type, defined as SEC_WINNT_AUTH_DATA_TYPE_PASSWORD. This
/// credential type describes password credentials of a domain user as well as other online identities. Applications must define
/// _SEC_WINNT_AUTH_TYPES to compile code that references this credential type as well as other definitions of the
/// <c>SEC_WINNT_AUTH_PACKED_CREDENTIALS</c> structure.
/// </para>
/// <para>
/// Applications should not query or set the <c>Flags</c> member directly. Use the SspiIsAuthIdentityEncrypted,
/// SspiEncryptAuthIdentityEx, and SspiDecryptAuthIdentityEx functions to manage the encryption and decryption of the
/// <c>SEC_WINNT_AUTH_IDENTITY_EX2</c> structure.
/// </para>
/// <para>
/// Identity providers must explicitly check or set SEC_WINNT_AUTH_IDENTITY_FLAGS_ID_PROVIDER and the domain name fields to
/// differentiate their password credential from a domain password and another identity provider's password.
/// </para>
/// <para>
/// The CredPackAuthenticationBuffer function can be called with the CRED_PACK_ID_PROVIDER_CREDENTIALS option to create a
/// <c>SEC_WINNT_AUTH_IDENTITY_EX2</c> structure with the authentication data of SEC_WINNT_AUTH_DATA_TYPE_PASSWORD credential type, a
/// <c>Flags</c> member that contains the SEC_WINNT_AUTH_IDENTITY_FLAGS_ID_PROVIDER value, and a <c>DomainOffset</c> member set to
/// the provider name.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/ns-sspi-sec_winnt_auth_identity_ex2 typedef struct
// _SEC_WINNT_AUTH_IDENTITY_EX2 { unsigned long Version; unsigned short cbHeaderLength; unsigned long cbStructureLength; unsigned
// long UserOffset; unsigned short UserLength; unsigned long DomainOffset; unsigned short DomainLength; unsigned long
// PackedCredentialsOffset; unsigned short PackedCredentialsLength; unsigned long Flags; unsigned long PackageListOffset; unsigned
// short PackageListLength; } SEC_WINNT_AUTH_IDENTITY_EX2, *PSEC_WINNT_AUTH_IDENTITY_EX2;
[PInvokeData("sspi.h", MSDNShortId = "a6083d76-1774-428c-85ca-fea817827d6a")]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct SEC_WINNT_AUTH_IDENTITY_EX2
{
/// <summary>The version number of the structure. This must be <c>SEC_WINNT_AUTH_IDENTITY_VERSION_2</c>.</summary>
public uint Version;
/// <summary>The size, in bytes, of the structure header.</summary>
public ushort cbHeaderLength;
/// <summary>The size, in bytes, of the structure.</summary>
public uint cbStructureLength;
/// <summary>The offset from the beginning of the structure to the beginning of the user name string.</summary>
public uint UserOffset;
/// <summary>The size, in bytes, of the user name string.</summary>
public ushort UserLength;
/// <summary>
/// <para>The offset from the beginning of the structure to the beginning of the domain name string.</para>
/// <para>An identity credential should contain the identity provider name instead of the domain name.</para>
/// </summary>
public uint DomainOffset;
/// <summary>The size, in bytes, of the domain name string.</summary>
public ushort DomainLength;
/// <summary>
/// <para>The offset from the beginning of the structure to the beginning of the packed credentials.</para>
/// <para>
/// The packed credential is a SEC_WINNT_AUTH_PACKED_CREDENTIALS structure that contains a credential type that uniquely
/// specifies the credential type.
/// </para>
/// </summary>
public uint PackedCredentialsOffset;
/// <summary>The size, in bytes, of the packed credentials string.</summary>
public ushort PackedCredentialsLength;
/// <summary>
/// <para>An <c>unsigned long</c> flag that indicates the type used by negotiable security packages.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>SEC_WINNT_AUTH_IDENTITY_MARSHALLED 4 (0x4)</term>
/// <term>All data is in one buffer.</term>
/// </item>
/// <item>
/// <term>SEC_WINNT_AUTH_IDENTITY_ONLY 8 (0x8)</term>
/// <term>
/// Used with the Kerberos security support provider (SSP). Credentials are for identity only. The Kerberos package is directed
/// to not include authorization data in the ticket.
/// </term>
/// </item>
/// <item>
/// <term>SEC_WINNT_AUTH_IDENTITY_ANSI 1 (0x1)</term>
/// <term>Credentials are in ANSI form.</term>
/// </item>
/// <item>
/// <term>SEC_WINNT_AUTH_IDENTITY_UNICODE 2 (0x2)</term>
/// <term>Credentials are in Unicode form.</term>
/// </item>
/// <item>
/// <term>SEC_WINNT_AUTH_IDENTITY_FLAGS_ID_PROVIDER 524288 (0x80000)</term>
/// <term>
/// When the credential type is password, the presence of this flag specifies that the structure is an online ID credential. The
/// DomainOffset and DomainLength members correspond to the online ID provider name. Windows Server 2008 R2 and Windows 7: This
/// flag is not supported.
/// </term>
/// </item>
/// <item>
/// <term>SEC_WINNT_AUTH_IDENTITY_FLAGS_PROCESS_ENCRYPTED 16 (0x10)</term>
/// <term>
/// The structure is encrypted by the SspiEncryptAuthIdentity function or by the SspiEncryptAuthIdentityEx function with the
/// SEC_WINNT_AUTH_IDENTITY_ENCRYPT_SAME_PROCESS option. It can only be decrypted by the same process. Windows Server 2008 R2 and
/// Windows 7: This flag is not supported.
/// </term>
/// </item>
/// <item>
/// <term>SEC_WINNT_AUTH_IDENTITY_FLAGS_SYSTEM_PROTECTED 32 (0x20)</term>
/// <term>
/// The structure is encrypted by the SspiEncryptAuthIdentityEx function with the SEC_WINNT_AUTH_IDENTITY_ENCRYPT_SAME_LOGON
/// option under the SYSTEM security context. It can only be decrypted by a thread running as SYSTEM. Windows Server 2008 R2 and
/// Windows 7: This flag is not supported.
/// </term>
/// </item>
/// <item>
/// <term>SEC_WINNT_AUTH_IDENTITY_FLAGS_USER_PROTECTED 64 (0x40)</term>
/// <term>
/// The structure is encrypted by the SspiEncryptAuthIdentityEx function with the SEC_WINNT_AUTH_IDENTITY_ENCRYPT_SAME_LOGON
/// option under a non-SYSTEM security context. It can only be decrypted by a thread running in the same logon session in which
/// it was encrypted. Windows Server 2008 R2 and Windows 7: This flag is not supported.
/// </term>
/// </item>
/// <item>
/// <term>SEC_WINNT_AUTH_IDENTITY_FLAGS_RESERVED 65536 (0x10000)</term>
/// <term>
/// The authentication identity buffer is cbStructureLength + 8 padding bytes that are necessary for in-place encryption or
/// decryption of the identity.
/// </term>
/// </item>
/// </list>
/// </summary>
public SEC_WINNT_AUTH_IDENTITY_FLAGS Flags;
/// <summary>The offset from the beginning of the structure to the beginning of the list of supported packages.</summary>
public uint PackageListOffset;
/// <summary>The size, in bytes, of the supported package list.</summary>
public ushort PackageListLength;
}
/// <summary>The SecBuffer structure describes a buffer allocated by a transport application to pass to a security package.</summary>
[StructLayout(LayoutKind.Sequential)]
public struct SecBuffer
{
/// <summary>Specifies the size, in bytes, of the buffer pointed to by the pvBuffer member.</summary>
public int cbBuffer;
/// <summary>Bit flags that indicate the type of buffer. Must be one of the values of the SecBufferType enumeration.</summary>
public SecBufferType BufferType;
/// <summary>A pointer to a buffer.</summary>
public IntPtr pvBuffer;
/// <summary>Initializes a new instance of the <see cref="SecBuffer"/> struct.</summary>
/// <param name="type">The type of buffer.</param>
/// <param name="buffer">A pointer to an allocated buffer.</param>
/// <param name="bufferSize">Size of the allocated buffer.</param>
public SecBuffer(SecBufferType type, IntPtr buffer = default, int bufferSize = 0)
{
cbBuffer = bufferSize;
BufferType = type;
pvBuffer = buffer;
}
}
/// <summary>
/// The <c>SecBufferDesc</c> structure describes an array of SecBuffer structures to pass from a transport application to a security package.
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/ns-sspi-_secbufferdesc typedef struct _SecBufferDesc { unsigned long
// ulVersion; unsigned long cBuffers; PSecBuffer pBuffers; } SecBufferDesc, *PSecBufferDesc;
[PInvokeData("sspi.h", MSDNShortId = "fc6ef09c-3ba9-4bcb-a3c2-07422af8eaa9")]
[StructLayout(LayoutKind.Sequential)]
public struct SecBufferDesc
{
/// <summary>Current structure version.</summary>
public const uint SECBUFFER_VERSION = 0;
/// <summary>
/// <para>Specifies the version number of this structure. This member must be SECBUFFER_VERSION.</para>
/// </summary>
public uint ulVersion;
/// <summary>
/// <para>Indicates the number of SecBuffer structures in the <c>pBuffers</c> array.</para>
/// </summary>
public uint cBuffers;
/// <summary>
/// <para>Pointer to an array of SecBuffer structures.</para>
/// </summary>
public IntPtr pBuffers;
/// <summary>The default structure with the ulVersion field set correctly.</summary>
public static readonly SecBufferDesc Default = new SecBufferDesc { ulVersion = SECBUFFER_VERSION };
}
/// <summary>A security handle.</summary>
[PInvokeData("sspi.h")]
[StructLayout(LayoutKind.Sequential)]
public struct CredHandle : IEquatable<CredHandle>
{
/// <summary>Represents the invalid handle value.</summary>
public static readonly CredHandle Invalid = new CredHandle() { dwLower = UIntPtr.Zero, dwUpper = MaxValue };
/// <summary>Represents a NULL handle value.</summary>
public static readonly CredHandle Null = new CredHandle();
/// <summary>Lower value.</summary>
public UIntPtr dwLower;
/// <summary>Upper value.</summary>
public UIntPtr dwUpper;
private static readonly UIntPtr MaxValue = UIntPtr.Size == 4 ? new UIntPtr(uint.MaxValue) : new UIntPtr(ulong.MaxValue);
/// <summary>Gets a value indicating whether this instance is invalid.</summary>
/// <value><c>true</c> if this instance is invalid; otherwise, <c>false</c>.</value>
public bool IsInvalid => dwLower == MaxValue || dwUpper == MaxValue;
/// <summary>Gets a value indicating whether this instance is NULL.</summary>
/// <value><c>true</c> if this instance is NULL; otherwise, <c>false</c>.</value>
public bool IsNull => dwLower == UIntPtr.Zero && dwUpper == UIntPtr.Zero;
/// <summary>Implements the operator !=.</summary>
/// <param name="value1">The left value.</param>
/// <param name="value2">The right value.</param>
/// <returns>The result of the operator.</returns>
public static bool operator !=(CredHandle value1, CredHandle value2) => !value1.Equals(value2);
/// <summary>Implements the operator ==.</summary>
/// <param name="value1">The left value.</param>
/// <param name="value2">The right value.</param>
/// <returns>The result of the operator.</returns>
public static bool operator ==(CredHandle value1, CredHandle value2) => value1.Equals(value2);
/// <summary>Indicates whether the current object is equal to another object of the same type.</summary>
/// <param name="other">An object to compare with this object.</param>
/// <returns>true if the current object is equal to the <paramref name="other"/> parameter; otherwise, false.</returns>
public bool Equals(CredHandle other) => other.dwUpper == dwUpper && other.dwLower == dwLower;
/// <summary>Determines whether the specified <see cref="object"/>, is equal to this instance.</summary>
/// <param name="obj">The <see cref="object"/> to compare with this instance.</param>
/// <returns><c>true</c> if the specified <see cref="object"/> is equal to this instance; otherwise, <c>false</c>.</returns>
public override bool Equals(object obj) => obj is CredHandle h ? Equals(h) : base.Equals(obj);
/// <summary>Returns a hash code for this instance.</summary>
/// <returns>A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.</returns>
public override int GetHashCode() => base.GetHashCode();
/// <summary>Invalidates this instance.</summary>
public void Invalidate() { dwLower = UIntPtr.Zero; dwUpper = MaxValue; }
}
/// <summary>A security handle.</summary>
[PInvokeData("sspi.h")]
[StructLayout(LayoutKind.Sequential)]
public struct CtxtHandle : IEquatable<CtxtHandle>
{
/// <summary>Represents the invalid handle value.</summary>
public static readonly CtxtHandle Invalid = new CtxtHandle() { dwLower = UIntPtr.Zero, dwUpper = MaxValue };
/// <summary>Represents a NULL handle value.</summary>
public static readonly CtxtHandle Null = new CtxtHandle();
/// <summary>Lower value.</summary>`
public UIntPtr dwLower;
/// <summary>Upper value.</summary>
public UIntPtr dwUpper;
private static readonly UIntPtr MaxValue = UIntPtr.Size == 4 ? new UIntPtr(uint.MaxValue) : new UIntPtr(ulong.MaxValue);
/// <summary>Gets a value indicating whether this instance is invalid.</summary>
/// <value><c>true</c> if this instance is invalid; otherwise, <c>false</c>.</value>
public bool IsInvalid => dwLower == MaxValue || dwUpper == MaxValue;
/// <summary>Gets a value indicating whether this instance is NULL.</summary>
/// <value><c>true</c> if this instance is NULL; otherwise, <c>false</c>.</value>
public bool IsNull => dwLower == UIntPtr.Zero && dwUpper == UIntPtr.Zero;
/// <summary>Implements the operator !=.</summary>
/// <param name="value1">The left value.</param>
/// <param name="value2">The right value.</param>
/// <returns>The result of the operator.</returns>
public static bool operator !=(CtxtHandle value1, CtxtHandle value2) => !value1.Equals(value2);
/// <summary>Implements the operator ==.</summary>
/// <param name="value1">The left value.</param>
/// <param name="value2">The right value.</param>
/// <returns>The result of the operator.</returns>
public static bool operator ==(CtxtHandle value1, CtxtHandle value2) => value1.Equals(value2);
/// <summary>Indicates whether the current object is equal to another object of the same type.</summary>
/// <param name="other">An object to compare with this object.</param>
/// <returns>true if the current object is equal to the <paramref name="other"/> parameter; otherwise, false.</returns>
public bool Equals(CtxtHandle other) => other.dwUpper == dwUpper && other.dwLower == dwLower;
/// <summary>Determines whether the specified <see cref="object"/>, is equal to this instance.</summary>
/// <param name="obj">The <see cref="object"/> to compare with this instance.</param>
/// <returns><c>true</c> if the specified <see cref="object"/> is equal to this instance; otherwise, <c>false</c>.</returns>
public override bool Equals(object obj) => obj is CtxtHandle h ? Equals(h) : base.Equals(obj);
/// <summary>Returns a hash code for this instance.</summary>
/// <returns>A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.</returns>
public override int GetHashCode() => base.GetHashCode();
/// <summary>Invalidates this instance.</summary>
public void Invalidate() { dwLower = UIntPtr.Zero; dwUpper = MaxValue; }
}
/// <summary>
/// The <c>SecPkgContext_AccessToken</c> structure returns a handle to the access token for the current security context. The
/// returned handle can be used by the ImpersonateLoggedOnUser and GetTokenInformation functions. This structure is returned by the
/// QueryContextAttributes (General) function.
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/ns-sspi-_secpkgcontext_accesstoken typedef struct
// _SecPkgContext_AccessToken { void *AccessToken; } SecPkgContext_AccessToken, *PSecPkgContext_AccessToken;
[PInvokeData("sspi.h", MSDNShortId = "4dc11cbd-7f28-4cb9-aaea-6e5a89ac91f0")]
[StructLayout(LayoutKind.Sequential)]
public struct SecPkgContext_AccessToken
{
/// <summary>
/// <para>Pointer to a <c>void</c> that receives the handle to the access token that represents the authenticated user.</para>
/// <para>The returned handle is not duplicated, so the calling process must not call CloseHandle on the returned handle.</para>
/// <para>
/// If the security context is for a server or is incomplete, the returned handle may be <c>NULL</c>. Depending on the security
/// package, QueryContextAttributes (General) may return SEC_E_NO_IMPERSONATION for these cases.
/// </para>
/// </summary>
public IntPtr AccessToken;
}
/// <summary>
/// The <c>SecPkgContext_Authority</c> structure contains the name of the authenticating authority if one is available. It can be a
/// certification authority (CA) or the name of a server or domain that authenticated the connection. The QueryContextAttributes
/// (General) function uses this structure.
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/ns-sspi-_secpkgcontext_authoritya typedef struct
// _SecPkgContext_AuthorityA { SEC_CHAR *sAuthorityName; } SecPkgContext_AuthorityA, *PSecPkgContext_AuthorityA;
[PInvokeData("sspi.h", MSDNShortId = "619bf16b-c439-48e7-b013-3622e2f3bbc4")]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct SecPkgContext_Authority
{
/// <summary>Pointer to a null-terminated string containing the name of the authenticating authority, if available.</summary>
[MarshalAs(UnmanagedType.LPTStr)]
public string sAuthorityName;
}
/// <summary>Specifies a structure that contains channel binding information for a security context.</summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/ns-sspi-_secpkgcontext_bindings typedef struct _SecPkgContext_Bindings {
// unsigned long BindingsLength; SEC_CHANNEL_BINDINGS *Bindings; } SecPkgContext_Bindings, *PSecPkgContext_Bindings;
[PInvokeData("sspi.h", MSDNShortId = "6823cc31-acd3-4d67-92c6-65ff4d1c6aed")]
[StructLayout(LayoutKind.Sequential)]
public struct SecPkgContext_Bindings
{
/// <summary>The size, in bytes, of the structure specified by the <c>Bindings</c> member</summary>
public uint BindingsLength;
/// <summary>A pointer to a SEC_CHANNEL_BINDINGS structure that specifies channel binding information.</summary>
public IntPtr Bindings;
}
2018-09-30 17:37:25 -04:00
/// <summary>
/// The <c>SecPkgContext_ClientSpecifiedTarget</c> structure specifies the service principal name (SPN) of the initial target when
/// calling the QueryContextAttributes (Digest) function.
2018-09-30 17:37:25 -04:00
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/ns-sspi-_secpkgcontext_clientspecifiedtarget typedef struct
// _SecPkgContext_ClientSpecifiedTarget { SEC_WCHAR *sTargetName; } SecPkgContext_ClientSpecifiedTarget, *PSecPkgContext_ClientSpecifiedTarget;
[PInvokeData("sspi.h", MSDNShortId = "67536f69-a1fc-4f26-84dc-872635bafa3b")]
[StructLayout(LayoutKind.Sequential)]
public struct SecPkgContext_ClientSpecifiedTarget
{
/// <summary>The SPN of the initial target.</summary>
[MarshalAs(UnmanagedType.LPWStr)]
public string sTargetName;
}
/// <summary>Specifies the type of credentials used to create a client context.</summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/ns-sspi-_secpkgcontext_credinfo typedef struct _SecPkgContext_CredInfo {
// SECPKG_CRED_CLASS CredClass; unsigned long IsPromptingNeeded; } SecPkgContext_CredInfo, *PSecPkgContext_CredInfo;
[PInvokeData("sspi.h", MSDNShortId = "5c2c6d01-5de3-4dd1-9fa2-cce9eadd6902")]
[StructLayout(LayoutKind.Sequential)]
public struct SecPkgContext_CredInfo
{
/// <summary>A value of the SECPKG_CRED_CLASS enumeration that indicates the type of credentials.</summary>
public SECPKG_CRED_CLASS CredClass;
/// <summary>
/// A nonzero value indicates that the application must prompt the user for credentials. All other values indicate that the
/// application does not need to prompt the user.
/// </summary>
[MarshalAs(UnmanagedType.Bool)]
public bool IsPromptingNeeded;
}
2018-09-30 17:37:25 -04:00
/// <summary>
/// The <c>SecPkgContext_DceInfo</c> structure contains authorization data used by DCE services. The QueryContextAttributes (General)
/// function uses this structure.
2018-09-30 17:37:25 -04:00
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/ns-sspi-_secpkgcontext_dceinfo typedef struct _SecPkgContext_DceInfo {
// unsigned long AuthzSvc; void *pPac; } SecPkgContext_DceInfo, *PSecPkgContext_DceInfo;
[PInvokeData("sspi.h", MSDNShortId = "490688d0-efdd-4a40-88b9-eb53ff592d2a")]
[StructLayout(LayoutKind.Sequential)]
public struct SecPkgContext_DceInfo
{
/// <summary>Specifies the authorization service used. For DCE use only.</summary>
public uint AuthzSvc;
/// <summary>Pointer to package-specific authorization data.</summary>
public IntPtr pPac;
}
2018-09-30 17:37:25 -04:00
/// <summary>
/// The <c>SecPkgContext_Flags</c> structure contains information about the flags in the current security context. This structure is
/// returned by QueryContextAttributes (General).
2018-09-30 17:37:25 -04:00
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/ns-sspi-secpkgcontext_flags typedef struct _SecPkgContext_Flags {
// unsigned long Flags; } SecPkgContext_Flags, *PSecPkgContext_Flags;
[PInvokeData("sspi.h", MSDNShortId = "0be0e945-4048-4748-a9fd-15d08fb7ff3e")]
[StructLayout(LayoutKind.Sequential)]
public struct SecPkgContext_Flags
{
/// <summary>
/// Flag values for the current security context. These values correspond to the flags negotiated by the
/// InitializeSecurityContext (General) and AcceptSecurityContext (General) functions.
/// </summary>
public uint Flags;
}
/// <summary>
2018-09-30 17:37:25 -04:00
/// <para>
/// The <c>SecPkgContext_KeyInfo</c> structure contains information about the session keys used in a security context. The
/// QueryContextAttributes (General) function uses this structure.
2018-09-30 17:37:25 -04:00
/// </para>
/// <para>
/// Applications using the Schannel security support provider (SSP) should not use the <c>SecPkgContext_KeyInfo</c> structure.
/// Instead, use the SecPkgContext_ConnectionInfo structure.
2018-09-30 17:37:25 -04:00
/// </para>
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/ns-sspi-_secpkgcontext_keyinfoa typedef struct _SecPkgContext_KeyInfoA {
// SEC_CHAR *sSignatureAlgorithmName; SEC_CHAR *sEncryptAlgorithmName; unsigned long KeySize; unsigned long SignatureAlgorithm;
// unsigned long EncryptAlgorithm; } SecPkgContext_KeyInfoA, *PSecPkgContext_KeyInfoA;
[PInvokeData("sspi.h", MSDNShortId = "ec146329-6789-460c-ae62-629a1765a4c1")]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct SecPkgContext_KeyInfo
{
/// <summary>
/// Pointer to a null-terminated string that contains the name, if available, of the algorithm used for generating signatures,
/// for example "MD5" or "SHA-2".
/// </summary>
[MarshalAs(UnmanagedType.LPTStr)]
public string sSignatureAlgorithmName;
/// <summary>
/// Pointer to a null-terminated string that contains the name, if available, of the algorithm used for encrypting messages.
/// Reserved for future use.
/// </summary>
[MarshalAs(UnmanagedType.LPTStr)]
public string sEncryptAlgorithmName;
/// <summary>Specifies the effective key length, in bits, for the session key. This is typically 40, 56, or 128 bits.</summary>
public uint KeySize;
/// <summary>Specifies the algorithm identifier (ALG_ID) used for generating signatures, if available.</summary>
public ALG_ID SignatureAlgorithm;
/// <summary>Specifies the algorithm identifier (ALG_ID) used for encrypting messages. Reserved for future use.</summary>
public ALG_ID EncryptAlgorithm;
}
2018-09-30 17:37:25 -04:00
/// <summary>
/// Specifies whether the token from the most recent call to the InitializeSecurityContext function is the last token from the client.
2018-09-30 17:37:25 -04:00
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/ns-sspi-_secpkgcontext_lastclienttokenstatus typedef struct
// _SecPkgContext_LastClientTokenStatus { SECPKG_ATTR_LCT_STATUS LastClientTokenStatus; } SecPkgContext_LastClientTokenStatus, *PSecPkgContext_LastClientTokenStatus;
[PInvokeData("sspi.h", MSDNShortId = "ccb2bb4e-3c65-4305-95ad-b9111f3936b5")]
[StructLayout(LayoutKind.Sequential)]
public struct SecPkgContext_LastClientTokenStatus
{
/// <summary>
/// A value of the SECPKG_ATTR_LCT_STATUS enumeration that indicates the status of the token returned by the most recent call to InitializeSecurityContext.
/// </summary>
public SECPKG_ATTR_LCT_STATUS LastClientTokenStatus;
}
2018-09-30 17:37:25 -04:00
/// <summary>
/// The <c>SecPkgContext_Lifespan</c> structure indicates the life span of a security context. The QueryContextAttributes (General)
/// function uses this structure.
/// </summary>
/// <remarks>It is recommended that the security package always return these values in local time.</remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/ns-sspi-_secpkgcontext_lifespan typedef struct _SecPkgContext_Lifespan {
// TimeStamp tsStart; TimeStamp tsExpiry; } SecPkgContext_Lifespan, *PSecPkgContext_Lifespan;
[PInvokeData("sspi.h", MSDNShortId = "7ef45795-f6af-4dac-a498-c6f8c915a168")]
[StructLayout(LayoutKind.Sequential)]
public struct SecPkgContext_Lifespan
2018-09-30 17:37:25 -04:00
{
/// <summary>Time at which the context was established.</summary>
public TimeStamp tsStart;
2018-09-30 17:37:25 -04:00
/// <summary>Time at which the context will expire.</summary>
public TimeStamp tsExpiry;
}
2018-09-30 17:37:25 -04:00
/// <summary>
/// The <c>SecPkgContext_Names</c> structure indicates the name of the user associated with a security context. The
/// QueryContextAttributes (General) function uses this structure.
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/ns-sspi-_secpkgcontext_namesa typedef struct _SecPkgContext_NamesA {
// SEC_CHAR *sUserName; } SecPkgContext_NamesA, *PSecPkgContext_NamesA;
[PInvokeData("sspi.h", MSDNShortId = "9df0bf7c-ad5f-4cb8-8934-76062789735f")]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct SecPkgContext_Names
{
/// <summary>
/// Pointer to a null-terminated string containing the name of the user represented by the context. If the security package has
/// set the SECPKG_FLAG_ACCEPT_WIN32_NAME flag, this name can be used in other Windows calls.
/// </summary>
[MarshalAs(UnmanagedType.LPTStr)]
public string sUserName;
}
/// <summary>
/// The <c>SecPkgContext_NativeNames</c> structure returns the client and server principal names from the outbound ticket. This
/// structure is valid only for client outbound tickets. This structure is returned by QueryContextAttributes (General).
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/ns-sspi-_secpkgcontext_nativenamesa typedef struct
// _SecPkgContext_NativeNamesA { SEC_CHAR *sClientName; SEC_CHAR *sServerName; } SecPkgContext_NativeNamesA, *PSecPkgContext_NativeNamesA;
[PInvokeData("sspi.h", MSDNShortId = "f935093f-5661-4ced-94f1-c4b21c3b9f69")]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct SecPkgContext_NativeNames
{
/// <summary>
/// Pointer to a null-terminated string that represents the principal name for the client in the outbound ticket. This string
/// should never be <c>NULL</c> when querying a security context negotiated with Kerberos.
/// </summary>
[MarshalAs(UnmanagedType.LPTStr)]
public string sClientName;
/// <summary>
/// Pointer to a null-terminated string that represents the principal name for the server in the outbound ticket. This string
/// should never be <c>NULL</c> when querying a security context negotiated with Kerberos.
/// </summary>
[MarshalAs(UnmanagedType.LPTStr)]
public string sServerName;
}
/// <summary>Specifies the error status of the last attempt to create a client context.</summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/ns-sspi-_secpkgcontext_negostatus typedef struct
// _SecPkgContext_NegoStatus { unsigned long LastStatus; } SecPkgContext_NegoStatus, *PSecPkgContext_NegoStatus;
[PInvokeData("sspi.h", MSDNShortId = "09201338-4743-44a2-b84f-35b26116976d")]
[StructLayout(LayoutKind.Sequential)]
public struct SecPkgContext_NegoStatus
{
/// <summary>The error status of the last attempt to create a client context.</summary>
public uint LastStatus;
}
/// <summary>
/// The <c>SecPkgContext_NegotiationInfo</c> structure contains information on the security package that is being set up or has been
/// set up, and also gives the status on the negotiation to set up the security package.
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/ns-sspi-_secpkgcontext_negotiationinfoa typedef struct
// _SecPkgContext_NegotiationInfoA { PSecPkgInfoA PackageInfo; unsigned long NegotiationState; } SecPkgContext_NegotiationInfoA, *PSecPkgContext_NegotiationInfoA;
[PInvokeData("sspi.h", MSDNShortId = "3af724b8-fbe5-4a75-b128-9efe65381f2f")]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct SecPkgContext_NegotiationInfo
{
/// <summary>
/// Pointer to a SecPkgInfo structure that provides general information about the security package chosen in the negotiate
/// process, such as the name and capabilities of the package.
/// </summary>
public IntPtr PackageInfo;
/// <summary>
/// <para>
/// Indicator of the state of the negotiation for the security package identified in the <c>PackageInfo</c> member. This
/// attribute can be queried from the context handle before the setup is complete, such as when ISC returns SEC_I_CONTINUE_NEEDED.
/// </para>
/// <para>The following table shows values returned in this member.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>SECPKG_NEGOTIATION_COMPLETE</term>
/// <term>Negotiation has been completed.</term>
/// </item>
/// <item>
/// <term>SECPKG_NEGOTIATION_OPTIMISTIC</term>
/// <term>Negotiations not yet completed.</term>
/// </item>
/// <item>
/// <term>SECPKG_NEGOTIATION_IN_PROGRESS</term>
/// <term>Negotiations in progress.</term>
/// </item>
/// </list>
/// </summary>
public uint NegotiationState;
}
/// <summary>
/// The <c>SecPkgContext_PackageInfo</c> structure contains the name of a security support provider (SSP). This structure is returned
/// by the QueryContextAttributes (General) function. It would most often be used when the SSP in use was established using the
/// Negotiate security package.
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/ns-sspi-_secpkgcontext_packageinfoa typedef struct
// _SecPkgContext_PackageInfoA { PSecPkgInfoA PackageInfo; } SecPkgContext_PackageInfoA, *PSecPkgContext_PackageInfoA;
[PInvokeData("sspi.h", MSDNShortId = "94c21f22-d974-4ae5-beef-d4567e6ea7e1")]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct SecPkgContext_PackageInfo
{
/// <summary>Pointer to a SecPkgInfo structure containing the name of the SSP in use.</summary>
public IntPtr PackageInfo;
}
/// <summary>
/// The <c>SecPkgContext_PasswordExpiry</c> structure contains information about the expiration of a password or other credential
/// used for the security context. This structure is returned by QueryContextAttributes (General).
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/ns-sspi-secpkgcontext_passwordexpiry typedef struct
// _SecPkgContext_PasswordExpiry { TimeStamp tsPasswordExpires; } SecPkgContext_PasswordExpiry, *PSecPkgContext_PasswordExpiry;
[PInvokeData("sspi.h", MSDNShortId = "f45dde88-1520-4e65-8fae-8407dfaa0850")]
[StructLayout(LayoutKind.Sequential)]
public struct SecPkgContext_PasswordExpiry
{
/// <summary>
/// A TimeStamp variable that indicates when the credentials for the security context expire. For password-based packages, this
/// variable indicates when the password expires. For Kerberos, this variable indicates when the ticket expires.
/// </summary>
public TimeStamp tsPasswordExpires;
}
/// <summary>
/// <para>
/// [The <c>SecPkgContext_ProtoInfo</c> structure is available for use in the operating systems specified in the Requirements
/// section. It may be altered or unavailable in subsequent versions. Instead, use the SecPkgContext_ConnectionInfo structure.]
/// </para>
/// <para>The <c>SecPkgContext_ProtoInfo</c> structure holds information about the protocol in use.</para>
/// <para>This attribute is supported only by the Schannel security support provider (SSP).</para>
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/ns-sspi-secpkgcontext_protoinfoa typedef struct
// _SecPkgContext_ProtoInfoA { SEC_CHAR *sProtocolName; unsigned long majorVersion; unsigned long minorVersion; }
// SecPkgContext_ProtoInfoA, *PSecPkgContext_ProtoInfoA;
[PInvokeData("sspi.h", MSDNShortId = "c10eb1fc-b957-4853-86c1-070749488bb9")]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct SecPkgContext_ProtoInfo
{
/// <summary>Pointer to a string containing the name of the protocol.</summary>
[MarshalAs(UnmanagedType.LPTStr)]
public string sProtocolName;
/// <summary>Major version number.</summary>
public uint majorVersion;
/// <summary>Minor version number.</summary>
public uint minorVersion;
2018-09-30 17:37:25 -04:00
}
/// <summary>
/// The <c>SecPkgContext_SessionKey</c> structure contains information about the session key used for the security context. This
/// structure is returned by the QueryContextAttributes (General) function.
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/ns-sspi-_secpkgcontext_sessionkey typedef struct
// _SecPkgContext_SessionKey { unsigned long SessionKeyLength; unsigned char *SessionKey; } SecPkgContext_SessionKey, *PSecPkgContext_SessionKey;
[PInvokeData("sspi.h", MSDNShortId = "88cf437e-3be0-4f12-9058-ad078deed6a1")]
[StructLayout(LayoutKind.Sequential)]
public struct SecPkgContext_SessionKey
{
/// <summary>Size, in bytes, of the session key.</summary>
public uint SessionKeyLength;
/// <summary>The session key for the security context.</summary>
public IntPtr SessionKey;
}
/// <summary>
/// The <c>SecPkgContext_Sizes</c> structure indicates the sizes of important structures used in the message support functions. The
/// QueryContextAttributes (General) function uses this structure.
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/ns-sspi-_secpkgcontext_sizes typedef struct _SecPkgContext_Sizes {
// unsigned long cbMaxToken; unsigned long cbMaxSignature; unsigned long cbBlockSize; unsigned long cbSecurityTrailer; }
// SecPkgContext_Sizes, *PSecPkgContext_Sizes;
[PInvokeData("sspi.h", MSDNShortId = "46b6a155-8855-4aa0-a513-aa5b3760fcd4")]
[StructLayout(LayoutKind.Sequential)]
public struct SecPkgContext_Sizes
{
/// <summary>Specifies the maximum size of the security token used in the authentication exchanges.</summary>
public uint cbMaxToken;
/// <summary>
/// Specifies the maximum size of the signature created by the MakeSignature function. This member must be zero if integrity
/// services are not requested or available.
/// </summary>
public uint cbMaxSignature;
/// <summary>
/// Specifies the preferred integral size of the messages. For example, eight indicates that messages should be of size zero mod
/// eight for optimal performance. Messages other than this block size can be padded.
/// </summary>
public uint cbBlockSize;
/// <summary>
/// Size of the security trailer to be appended to messages. This member should be zero if the relevant services are not
/// requested or available.
/// </summary>
public uint cbSecurityTrailer;
}
/// <summary>
/// The <c>SecPkgContext_StreamSizes</c> structure indicates the sizes of the various parts of a stream for use with the message
/// support functions. The QueryContextAttributes (General) function uses this structure.
/// </summary>
/// <remarks>
/// Applications calling EncryptMessage (General) should check the values of the <c>cbHeader</c>, <c>cbTrailer</c>, and
/// <c>cbMaximumMessage</c> members to determine the size of the encrypted packet.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/ns-sspi-_secpkgcontext_streamsizes typedef struct
// _SecPkgContext_StreamSizes { unsigned long cbHeader; unsigned long cbTrailer; unsigned long cbMaximumMessage; unsigned long
// cBuffers; unsigned long cbBlockSize; } SecPkgContext_StreamSizes, *PSecPkgContext_StreamSizes;
[PInvokeData("sspi.h", MSDNShortId = "75e5fc96-56cc-4713-a34f-fca687798ad6")]
[StructLayout(LayoutKind.Sequential)]
public struct SecPkgContext_StreamSizes
{
/// <summary>Specifies the size, in bytes, of the header portion. If zero, no header is used.</summary>
public uint cbHeader;
/// <summary>Specifies the maximum size, in bytes, of the trailer portion. If zero, no trailer is used.</summary>
public uint cbTrailer;
/// <summary>Specifies the size, in bytes, of the largest message that can be encapsulated.</summary>
public uint cbMaximumMessage;
/// <summary>Specifies the number of buffers to pass.</summary>
public uint cBuffers;
/// <summary>
/// Specifies the preferred integral size of the messages. For example, eight indicates that messages should be of size zero mod
/// eight for optimal performance. Messages other than this block size can be padded.
/// </summary>
public uint cbBlockSize;
}
/// <summary>The <c>SecPkgContext_SubjectAttributes</c> structure returns the security attribute information.</summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/ns-sspi-_secpkgcontext_subjectattributes typedef struct
// _SecPkgContext_SubjectAttributes { void *AttributeInfo; } SecPkgContext_SubjectAttributes, *PSecPkgContext_SubjectAttributes;
[PInvokeData("sspi.h", MSDNShortId = "548E972F-EB94-4BBD-94F2-FA38184D179A")]
[StructLayout(LayoutKind.Sequential)]
public struct SecPkgContext_SubjectAttributes
{
/// <summary>
/// Pointer to a <c>void</c> that receives the attribute information stored in a AUTHZ_SECURITY_ATTRIBUTES_INFORMATION structure.
/// </summary>
public IntPtr AttributeInfo;
}
/// <summary>
/// The <c>SecPkgContext_TargetInformation</c> structure returns information about the credential used for the security context. This
/// structure is returned by the QueryContextAttributes (General) function.
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/ns-sspi-secpkgcontext_targetinformation typedef struct
// _SecPkgContext_TargetInformation { unsigned long MarshalledTargetInfoLength; unsigned char *MarshalledTargetInfo; }
// SecPkgContext_TargetInformation, *PSecPkgContext_TargetInformation;
[PInvokeData("sspi.h", MSDNShortId = "8a5a6bd6-8678-4544-a631-5ee4347bc685")]
[StructLayout(LayoutKind.Sequential)]
public struct SecPkgContext_TargetInformation
{
/// <summary>Size, in bytes, of <c>MarshalledTargetInfo</c>.</summary>
public uint MarshalledTargetInfoLength;
/// <summary>Array of bytes that represent the credential, if a credential is provided by a credential manager.</summary>
public IntPtr MarshalledTargetInfo;
}
/// <summary>Specifies the certificate credentials. The QueryCredentialsAttributes function uses this structure.</summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/ns-sspi-_secpkgcredentials_cert typedef struct _SecPkgCredentials_Cert {
// unsigned long EncodedCertSize; unsigned char *EncodedCert; } SecPkgCredentials_Cert, *PSecPkgCredentials_Cert;
[PInvokeData("sspi.h", MSDNShortId = "9EEE6E98-D45C-4929-9C9C-F344972D186F")]
[StructLayout(LayoutKind.Sequential)]
public struct SecPkgCredentials_Cert
{
/// <summary>Size of the encoded certificate.</summary>
public uint EncodedCertSize;
/// <summary>The encoded certificate.</summary>
public IntPtr EncodedCert;
}
/// <summary>Specifies the Kerberos proxy settings for the credentials.</summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/ns-sspi-_secpkgcredentials_kdcproxysettingsw typedef struct
// _SecPkgCredentials_KdcProxySettingsW { ULONG Version; ULONG Flags; USHORT ProxyServerOffset; USHORT ProxyServerLength; USHORT
// ClientTlsCredOffset; USHORT ClientTlsCredLength; } SecPkgCredentials_KdcProxySettingsW, *PSecPkgCredentials_KdcProxySettingsW;
[PInvokeData("sspi.h", MSDNShortId = "42BC75B8-6392-4FD4-95BC-266B3AFDDC62")]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct SecPkgCredentials_KdcProxySettingsW
{
/// <summary>Version for the Kerberos proxy settings where KDC_PROXY_SETTINGS_V1 is defined as 1.</summary>
public uint Version;
/// <summary>Flags for the Kerberos proxy settings.</summary>
public uint Flags;
/// <summary>The offset of the proxy server. This member is optional.</summary>
public ushort ProxyServerOffset;
/// <summary>Length of the proxy server.</summary>
public ushort ProxyServerLength;
/// <summary>The offset of the client credentials. This member is optional.</summary>
public ushort ClientTlsCredOffset;
/// <summary>Length of the client credentials.</summary>
public ushort ClientTlsCredLength;
}
/// <summary>
/// The <c>SecPkgCredentials_Names</c> structure holds the name of the user associated with a context. The QueryCredentialsAttributes
/// function uses this structure.
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/ns-sspi-_secpkgcredentials_namesa typedef struct
// _SecPkgCredentials_NamesA { SEC_CHAR *sUserName; } SecPkgCredentials_NamesA, *PSecPkgCredentials_NamesA;
[PInvokeData("sspi.h", MSDNShortId = "38123a10-72a4-46eb-974b-3c01142dfc74")]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct SecPkgCredentials_Names
{
/// <summary>
/// Pointer to a null-terminated string containing the name of the user represented by the credential. If the security package
/// sets the SECPKG_FLAG_ACCEPT_WIN32_NAME flag to indicate that it can process Windows names, this name can be used in other
/// Windows calls.
/// </summary>
[MarshalAs(UnmanagedType.LPTStr)]
public string sUserName;
}
/// <summary>
/// The <c>SecPkgCredentials_SSIProvider</c> structure holds the SSI provider information associated with a context. The
/// QueryCredentialsAttributes function uses this structure.
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/ns-sspi-secpkgcredentials_ssiprovidera typedef struct
// _SecPkgCredentials_SSIProviderA { SEC_CHAR *sProviderName; unsigned long ProviderInfoLength; char *ProviderInfo; }
// SecPkgCredentials_SSIProviderA, *PSecPkgCredentials_SSIProviderA;
[PInvokeData("sspi.h", MSDNShortId = "0C6D6217-3A97-40B5-A7FB-B9D49C5FBC7C")]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct SecPkgCredentials_SSIProvider
{
/// <summary>Pointer to a null-terminated string that contains the name of the provider represented by the credential.</summary>
[MarshalAs(UnmanagedType.LPTStr)]
public string sProviderName;
/// <summary>Length of the provider information.</summary>
public uint ProviderInfoLength;
/// <summary>The provider information.</summary>
public IntPtr ProviderInfo;
}
/// <summary>The <c>SecPkgInfo</c> structure provides general information about a security package, such as its name and capabilities.</summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/ns-sspi-_secpkginfoa typedef struct _SecPkgInfoA { unsigned long
// fCapabilities; unsigned short wVersion; unsigned short wRPCID; unsigned long cbMaxToken; SEC_CHAR *Name; SEC_CHAR *Comment; }
// SecPkgInfoA, *PSecPkgInfoA;
[PInvokeData("sspi.h", MSDNShortId = "d0bff3d8-63f1-4a4e-851f-177040af6bd2")]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct SecPkgInfo
{
/// <summary>
/// <para>
/// Set of bit flags that describes the capabilities of the security package. This member can be a combination of the following flags.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>SECPKG_FLAG_INTEGRITY 0x1</term>
/// <term>The security package supports the MakeSignature and VerifySignature functions.</term>
/// </item>
/// <item>
/// <term>SECPKG_FLAG_PRIVACY 0x2</term>
/// <term>The security package supports the EncryptMessage (General) and DecryptMessage (General) functions.</term>
/// </item>
/// <item>
/// <term>SECPKG_FLAG_TOKEN_ONLY 0x4</term>
/// <term>
/// The package is interested only in the security-token portion of messages, and will ignore any other buffers. This is a
/// performance-related issue.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_FLAG_DATAGRAM 0x8</term>
/// <term>Supports datagram-style authentication. For more information, see SSPI Context Semantics.</term>
/// </item>
/// <item>
/// <term>SECPKG_FLAG_CONNECTION 0x10</term>
/// <term>Supports connection-oriented style authentication. For more information, see SSPI Context Semantics.</term>
/// </item>
/// <item>
/// <term>SECPKG_FLAG_MULTI_REQUIRED 0x20</term>
/// <term>Multiple legs are required for authentication.</term>
/// </item>
/// <item>
/// <term>SECPKG_FLAG_CLIENT_ONLY 0x40</term>
/// <term>Server authentication support is not provided.</term>
/// </item>
/// <item>
/// <term>SECPKG_FLAG_EXTENDED_ERROR 0x80</term>
/// <term>Supports extended error handling. For more information, see Extended Error Information.</term>
/// </item>
/// <item>
/// <term>SECPKG_FLAG_IMPERSONATION 0x100</term>
/// <term>Supports Windows impersonation in server contexts.</term>
/// </item>
/// <item>
/// <term>SECPKG_FLAG_ACCEPT_WIN32_NAME 0x200</term>
/// <term>Understands Windows principal and target names.</term>
/// </item>
/// <item>
/// <term>SECPKG_FLAG_STREAM 0x400</term>
/// <term>Supports stream semantics. For more information, see SSPI Context Semantics.</term>
/// </item>
/// <item>
/// <term>SECPKG_FLAG_NEGOTIABLE 0X800</term>
/// <term>Can be used by the Microsoft Negotiate security package.</term>
/// </item>
/// <item>
/// <term>SECPKG_FLAG_GSS_COMPATIBLE 0x1000</term>
/// <term>Supports GSS compatibility.</term>
/// </item>
/// <item>
/// <term>SECPKG_FLAG_LOGON 0x2000</term>
/// <term>Supports LsaLogonUser.</term>
/// </item>
/// <item>
/// <term>SECPKG_FLAG_ASCII_BUFFERS 0x4000</term>
/// <term>Token buffers are in ASCII characters format.</term>
/// </item>
/// <item>
/// <term>SECPKG_FLAG_FRAGMENT 0x8000</term>
/// <term>
/// Supports separating large tokens into smaller buffers so that applications can make repeated calls to
/// InitializeSecurityContext (General) and AcceptSecurityContext (General) with the smaller buffers to complete authentication.
/// </term>
/// </item>
/// <item>
/// <term>SECPKG_FLAG_MUTUAL_AUTH 0x10000</term>
/// <term>Supports mutual authentication.</term>
/// </item>
/// <item>
/// <term>SECPKG_FLAG_DELEGATION 0x20000</term>
/// <term>Supports delegation.</term>
/// </item>
/// <item>
/// <term>SECPKG_FLAG_READONLY_WITH_CHECKSUM 0x40000</term>
/// <term>The security package supports using a checksum instead of in-place encryption when calling the EncryptMessage function.</term>
/// </item>
/// <item>
/// <term>SECPKG_FLAG_RESTRICTED_TOKENS 0x80000</term>
/// <term>Supports callers with restricted tokens.</term>
/// </item>
/// <item>
/// <term>SECPKG_FLAG_NEGO_EXTENDER 0x00100000</term>
/// <term>The security package extends the Microsoft Negotiate security package. There can be at most one package of this type.</term>
/// </item>
/// <item>
/// <term>SECPKG_FLAG_NEGOTIABLE2 0x00200000</term>
/// <term>This package is negotiated by the package of type SECPKG_FLAG_NEGO_EXTENDER.</term>
/// </item>
/// <item>
/// <term>SECPKG_FLAG_APPCONTAINER_PASSTHROUGH 0x00400000</term>
/// <term>This package receives all calls from app container apps.</term>
/// </item>
/// <item>
/// <term>SECPKG_FLAG_APPCONTAINER_CHECKS 0x00800000</term>
/// <term>This package receives calls from app container apps if one of the following checks succeeds.</term>
/// </item>
/// <item>
/// <term>SECPKG_CALLFLAGS_APPCONTAINER 0x00000001</term>
/// <term>The caller is an app container.</term>
/// </item>
/// <item>
/// <term>SECPKG_CALLFLAGS_AUTHCAPABLE 0x00000002</term>
/// <term>The caller can use default credentials.</term>
/// </item>
/// <item>
/// <term>SECPKG_CALLFLAGS_FORCE_SUPPLIED 0x00000004</term>
/// <term>The caller can only use supplied credentials.</term>
/// </item>
/// </list>
/// </summary>
public SECPKG_FLAG fCapabilities;
/// <summary>Specifies the version of the package protocol. Must be 1.</summary>
public ushort wVersion;
/// <summary>
/// Specifies a DCE RPC identifier, if appropriate. If the package does not implement one of the DCE registered security systems,
/// the reserved value SECPKG_ID_NONE is used.
/// </summary>
public ushort wRPCID;
/// <summary>Specifies the maximum size, in bytes, of the token.</summary>
public uint cbMaxToken;
/// <summary>Pointer to a null-terminated string that contains the name of the security package.</summary>
[MarshalAs(UnmanagedType.LPTStr)]
public string Name;
/// <summary>Pointer to a null-terminated string. This can be any additional string passed back by the package.</summary>
[MarshalAs(UnmanagedType.LPTStr)]
public string Comment;
}
/// <summary>Specifies information about a security package. This structure is used by the AddSecurityPackage function.</summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/ns-sspi-security_package_options typedef struct
// _SECURITY_PACKAGE_OPTIONS { unsigned long Size; unsigned long Type; unsigned long Flags; unsigned long SignatureSize; void
// *Signature; } SECURITY_PACKAGE_OPTIONS, *PSECURITY_PACKAGE_OPTIONS;
[PInvokeData("sspi.h", MSDNShortId = "2e9f65ec-72a5-4d6f-aa63-f83369f0dd07")]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct SECURITY_PACKAGE_OPTIONS
{
/// <summary>The size, in bytes, of this structure.</summary>
public uint Size;
/// <summary>
/// <para>The type of security package. This can be one of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>SECPKG_OPTIONS_TYPE_UNKNOWN 0</term>
/// <term>The package type is not known.</term>
/// </item>
/// <item>
/// <term>SECPKG_OPTIONS_TYPE_LSA 1</term>
/// <term>The security package is an LSA authentication package.</term>
/// </item>
/// <item>
/// <term>SECPKG_OPTIONS_TYPE_SSPI 2</term>
/// <term>The security package is a Security Support Provider Interface (SSPI) package.</term>
/// </item>
/// </list>
/// </summary>
public SECPKG_OPTIONS_TYPE Type;
/// <summary>This member is reserved. Do not use it.</summary>
public uint Flags;
/// <summary>The size, in bytes, of a digital signature for this security package.</summary>
public uint SignatureSize;
/// <summary>A digital signature for this security package.</summary>
public IntPtr Signature;
}
2018-09-30 17:37:25 -04:00
/// <summary>
/// The <c>SecurityFunctionTable</c> structure is a dispatch table that contains pointers to the functions defined in SSPI.
2018-09-30 17:37:25 -04:00
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/sspi/ns-sspi-_security_function_table_w typedef struct
// _SECURITY_FUNCTION_TABLE_W { unsigned long dwVersion; ENUMERATE_SECURITY_PACKAGES_FN_W EnumerateSecurityPackagesW;
// QUERY_CREDENTIALS_ATTRIBUTES_FN_W QueryCredentialsAttributesW; ACQUIRE_CREDENTIALS_HANDLE_FN_W AcquireCredentialsHandleW;
// FREE_CREDENTIALS_HANDLE_FN FreeCredentialsHandle; void *Reserved2; INITIALIZE_SECURITY_CONTEXT_FN_W InitializeSecurityContextW;
// ACCEPT_SECURITY_CONTEXT_FN AcceptSecurityContext; COMPLETE_AUTH_TOKEN_FN CompleteAuthToken; DELETE_SECURITY_CONTEXT_FN
// DeleteSecurityContext; APPLY_CONTROL_TOKEN_FN ApplyControlToken; QUERY_CONTEXT_ATTRIBUTES_FN_W QueryContextAttributesW;
// IMPERSONATE_SECURITY_CONTEXT_FN ImpersonateSecurityContext; REVERT_SECURITY_CONTEXT_FN RevertSecurityContext; MAKE_SIGNATURE_FN
// MakeSignature; VERIFY_SIGNATURE_FN VerifySignature; FREE_CONTEXT_BUFFER_FN FreeContextBuffer; QUERY_SECURITY_PACKAGE_INFO_FN_W
// QuerySecurityPackageInfoW; void *Reserved3; void *Reserved4; EXPORT_SECURITY_CONTEXT_FN ExportSecurityContext;
// IMPORT_SECURITY_CONTEXT_FN_W ImportSecurityContextW; ADD_CREDENTIALS_FN_W AddCredentialsW; void *Reserved8;
// QUERY_SECURITY_CONTEXT_TOKEN_FN QuerySecurityContextToken; ENCRYPT_MESSAGE_FN EncryptMessage; DECRYPT_MESSAGE_FN DecryptMessage;
// SET_CONTEXT_ATTRIBUTES_FN_W SetContextAttributesW; SET_CREDENTIALS_ATTRIBUTES_FN_W SetCredentialsAttributesW; CHANGE_PASSWORD_FN_W
// ChangeAccountPasswordW; void *Reserved9; QUERY_CONTEXT_ATTRIBUTES_EX_FN_W QueryContextAttributesExW;
// QUERY_CREDENTIALS_ATTRIBUTES_EX_FN_W QueryCredentialsAttributesExW; } SecurityFunctionTableW, *PSecurityFunctionTableW;
[PInvokeData("sspi.h", MSDNShortId = "6315e8d6-b40a-4dd6-b6a6-598a965f93dc")]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct SecurityFunctionTable
{
/// <summary>Version number of the table.</summary>
public uint dwVersion;
/// <summary>Pointer to the EnumerateSecurityPackages function.</summary>
public IntPtr EnumerateSecurityPackages;
/// <summary>Pointer to the QueryCredentialsAttributes function.</summary>
public IntPtr QueryCredentialsAttributes;
/// <summary>Pointer to the AcquireCredentialsHandle function.</summary>
public IntPtr AcquireCredentialsHandle;
/// <summary>Pointer to the FreeCredentialsHandle function.</summary>
public IntPtr FreeCredentialHandl;
/// <summary>Reserved for future use.</summary>
public IntPtr Reserved1;
/// <summary>Pointer to the InitializeSecurityContext (General) function.</summary>
public IntPtr InitializeSecurityContext;
/// <summary>Pointer to the AcceptSecurityContext (General) function.</summary>
public IntPtr AcceptSecurityContex;
/// <summary>Pointer to the CompleteAuthToken function.</summary>
public IntPtr CompleteAuthToke;
/// <summary>Pointer to the DeleteSecurityContext function.</summary>
public IntPtr DeleteSecurityContex;
/// <summary>Pointer to the ApplyControlToken function.</summary>
public IntPtr ApplyControlToke;
/// <summary>Pointer to the QueryContextAttributes (General) function.</summary>
public IntPtr QueryContextAttributes;
/// <summary>Pointer to the ImpersonateSecurityContext function.</summary>
public IntPtr ImpersonateSecurityContex;
/// <summary>Pointer to the RevertSecurityContext function.</summary>
public IntPtr RevertSecurityContex;
/// <summary>Pointer to the MakeSignature function.</summary>
public IntPtr MakeSignatur;
/// <summary>Pointer to the VerifySignature function.</summary>
public IntPtr VerifySignatur;
/// <summary>Pointer to the FreeContextBuffer function.</summary>
public IntPtr FreeContextBuffe;
/// <summary>Pointer to the QuerySecurityPackageInfo function.</summary>
public IntPtr QuerySecurityPackageInfo;
/// <summary>Reserved for future use.</summary>
public IntPtr Reserved2;
/// <summary>Reserved for future use.</summary>
public IntPtr Reserved3;
/// <summary>Pointer to the ExportSecurityContext function.</summary>
public IntPtr ExportSecurityContex;
/// <summary>Pointer to the ImportSecurityContext function.</summary>
public IntPtr ImportSecurityContext;
/// <summary>Pointer to the AddCredential function.</summary>
public IntPtr AddCredentials;
/// <summary>Reserved for future use.</summary>
public IntPtr Reserved4;
/// <summary>Pointer to the QuerySecurityContextToken function.</summary>
public IntPtr QuerySecurityContextToke;
/// <summary>Pointer to the EncryptMessage (General) function.</summary>
public IntPtr EncryptMessag;
/// <summary>Pointer to the DecryptMessage (General) function.</summary>
public IntPtr DecryptMessag;
/// <summary>Pointer to the SetContextAttributes function.</summary>
public IntPtr SetContextAttributes;
/// <summary>Pointer to the SetCredentialsAttributes function.</summary>
public IntPtr SetCredentialsAttributes;
/// <summary>Pointer to the ChangeAccountPassword function.</summary>
public IntPtr ChangeAccountPassword;
/// <summary>Pointer to the AddCredential function.</summary>
public IntPtr Reserved5;
/// <summary>Pointer to the QueryContextAttributesEx function.</summary>
public IntPtr QueryContextAttributesEx;
/// <summary>Pointer to the QueryCredentialsAttributesEx function.</summary>
public IntPtr QueryCredentialsAttributesEx;
}
/// <summary>Provides a <see cref="SafeHandle"/> for a context buffer that is disposed using <see cref="FreeContextBuffer"/>.</summary>
public class SafeContextBuffer : SafeHANDLE
{
/// <summary>Initializes a new instance of the <see cref="SafeContextBuffer"/> class and assigns an existing handle.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
/// <param name="ownsHandle">
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
/// </param>
public SafeContextBuffer(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
/// <summary>Initializes a new instance of the <see cref="SafeContextBuffer"/> class.</summary>
private SafeContextBuffer() : base() { }
/// <summary>
/// Extracts an array of structures of <typeparamref name="T"/> containing <paramref name="count"/> items. <note type="note">This
/// call can cause memory exceptions if the pointer does not have sufficient allocated memory to retrieve all the structures.</note>
/// </summary>
/// <typeparam name="T">The type of the structures to retrieve.</typeparam>
/// <param name="count">The number of structures to retrieve.</param>
/// <param name="prefixBytes">The number of bytes to skip before reading the structures.</param>
/// <returns>An array of structures of <typeparamref name="T"/>.</returns>
public T[] ToArray<T>(int count, int prefixBytes = 0)
{
if (IsInvalid) return null;
//if (Size < Marshal.SizeOf(typeof(T)) * count + prefixBytes)
// throw new InsufficientMemoryException("Requested array is larger than the memory allocated.");
if (!typeof(T).IsBlittable()) throw new ArgumentException(@"Structure layout is not sequential or explicit.");
return handle.ToArray<T>(count, prefixBytes);
}
/// <summary>
/// Marshals data from this block of memory to a newly allocated managed object of the type specified by a generic type parameter.
/// </summary>
/// <typeparam name="T">The type of the object to which the data is to be copied. This must be a structure.</typeparam>
/// <returns>A managed object that contains the data that this <see cref="SafeMemoryHandleExt{T}"/> holds.</returns>
public T ToStructure<T>()
{
if (IsInvalid) return default;
return handle.ToStructure<T>();
}
/// <inheritdoc/>
protected override bool InternalReleaseHandle() => FreeContextBuffer(handle).Succeeded;
}
/// <summary>Provides a safe version of <see cref="CredHandle"/> that is disposed using <see cref="FreeCredentialsHandle"/>.</summary>
[StructLayout(LayoutKind.Sequential)]
public sealed class SafeCredHandle : IDisposable
{
private CredHandle handle;
/// <summary>Initializes a new instance of the <see cref="SafeCredHandle"/> class and assigns an existing handle.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
public SafeCredHandle(CredHandle preexistingHandle) => handle = preexistingHandle;
/// <summary>Initializes a new instance of the <see cref="SafeCredHandle"/> class.</summary>
private SafeCredHandle() { }
/// <summary>Performs an implicit conversion from <see cref="SafeCredHandle"/> to <see cref="CredHandle"/>.</summary>
/// <param name="h">The safe handle instance.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator CredHandle(SafeCredHandle h) => h.handle;
/// <summary>Performs an implicit conversion from <see cref="SafeCredHandle"/> to <see cref="CredHandle"/>.</summary>
/// <param name="h">The safe handle.</param>
/// <returns>The result of the conversion.</returns>
public static unsafe implicit operator CredHandle* (SafeCredHandle h)
{
fixed (CredHandle* hp = &h.handle)
return hp;
}
/// <summary>Get a NULL reference to CredHandle.</summary>
public readonly static SafeCredHandle Null = new SafeCredHandle(CredHandle.Null);
/// <summary>
/// <para>
/// The <c>AcquireCredentialsHandle (CredSSP)</c> function acquires a handle to preexisting credentials of a security principal.
/// This handle is required by the InitializeSecurityContext (CredSSP) and AcceptSecurityContext (CredSSP) functions. These can
/// be either preexisting credentials, which are established through a system logon that is not described here, or the caller
/// can provide alternative credentials.
/// </para>
/// <note type="note">This is not a "log on to the network" and does not imply gathering of credentials.</note>
/// </summary>
/// <param name="pszPackage">
/// A string that specifies the name of the security package with which these credentials will be used. This is a security
/// package name returned in the <c>Name</c> member of a SecPkgInfo structure returned by the EnumerateSecurityPackages
/// function. After a context is established, QueryContextAttributes (CredSSP) can be called with ulAttribute set to
/// <c>SECPKG_ATTR_PACKAGE_INFO</c> to return information on the security package in use.
/// </param>
/// <param name="fCredentialUse">A flag that indicates how these credentials will be used.</param>
/// <returns>On success, this function returns a credential handle.</returns>
/// <remarks>
/// <para>
/// The <c>AcquireCredentialsHandle (CredSSP)</c> function returns a handle to the credentials of a principal, such as a user or
/// client, as used by a specific security package. The function can return the handle to either preexisting credentials or
/// newly created credentials and return it. This handle can be used in subsequent calls to the AcceptSecurityContext (CredSSP)
/// and InitializeSecurityContext (CredSSP) functions.
/// </para>
/// <para>
/// In general, <c>AcquireCredentialsHandle (CredSSP)</c> does not provide the credentials of other users logged on to the same
/// computer. However, a caller with SE_TCB_NAME privilege can obtain the credentials of an existing logon session by specifying
/// the logon identifier (LUID) of that session. Typically, this is used by kernel-mode modules that must act on behalf of a
/// logged-on user.
/// </para>
/// </remarks>
public static SafeCredHandle Acquire(string pszPackage, SECPKG_CRED fCredentialUse) => Acquire<int>(pszPackage, fCredentialUse, null, null, null, out _);
/// <summary>
/// <para>
/// The <c>AcquireCredentialsHandle (CredSSP)</c> function acquires a handle to preexisting credentials of a security principal. This
/// handle is required by the InitializeSecurityContext (CredSSP) and AcceptSecurityContext (CredSSP) functions. These can be either
/// preexisting credentials, which are established through a system logon that is not described here, or the caller can provide
/// alternative credentials.
/// </para>
/// <para>
/// <c>Note</c> This is not a "log on to the network" and does not imply gathering of credentials.</para>
/// </summary>
/// <typeparam name="TAuthData">The type of the authentication data structure.</typeparam>
/// <param name="pszPackage">A string that specifies the name of the security package with which these credentials will be used.
/// This is a security package name returned in the <c>Name</c> member of a SecPkgInfo structure returned by the
/// EnumerateSecurityPackages function. After a context is established, QueryContextAttributes (CredSSP) can be called with
/// ulAttribute set to <c>SECPKG_ATTR_PACKAGE_INFO</c> to return information on the security package in use.</param>
/// <param name="fCredentialUse">A flag that indicates how these credentials will be used.</param>
/// <param name="pAuthData">The optional authentication data structure.</param>
/// <returns>
/// On success, this function returns a credential handle.
/// </returns>
/// <remarks>
/// <para>
/// The <c>AcquireCredentialsHandle (CredSSP)</c> function returns a handle to the credentials of a principal, such as a user or
/// client, as used by a specific security package. The function can return the handle to either preexisting credentials or newly
/// created credentials and return it. This handle can be used in subsequent calls to the AcceptSecurityContext (CredSSP) and
/// InitializeSecurityContext (CredSSP) functions.
/// </para>
/// <para>
/// In general, <c>AcquireCredentialsHandle (CredSSP)</c> does not provide the credentials of other users logged on to the same
/// computer. However, a caller with SE_TCB_NAME privilege can obtain the credentials of an existing logon session by specifying the
/// logon identifier (LUID) of that session. Typically, this is used by kernel-mode modules that must act on behalf of a logged-on user.
/// </para>
/// </remarks>
public static SafeCredHandle Acquire<TAuthData>(string pszPackage, SECPKG_CRED fCredentialUse, TAuthData? pAuthData) where TAuthData : struct =>
Acquire(pszPackage, fCredentialUse, pAuthData, null, null, out _);
/// <summary>
/// <para>
/// The <c>AcquireCredentialsHandle (CredSSP)</c> function acquires a handle to preexisting credentials of a security principal. This
/// handle is required by the InitializeSecurityContext (CredSSP) and AcceptSecurityContext (CredSSP) functions. These can be either
/// preexisting credentials, which are established through a system logon that is not described here, or the caller can provide
/// alternative credentials.
/// </para>
/// <para>
/// <c>Note</c> This is not a "log on to the network" and does not imply gathering of credentials.</para>
/// </summary>
/// <typeparam name="TAuthData">The type of the authentication data.</typeparam>
/// <param name="pszPackage">A string that specifies the name of the security package with which these credentials will be used.
/// This is a security package name returned in the <c>Name</c> member of a SecPkgInfo structure returned by the
/// EnumerateSecurityPackages function. After a context is established, QueryContextAttributes (CredSSP) can be called with
/// ulAttribute set to <c>SECPKG_ATTR_PACKAGE_INFO</c> to return information on the security package in use.</param>
/// <param name="fCredentialUse">A flag that indicates how these credentials will be used.</param>
/// <param name="pAuthData">An optional structure that specifies authentication data. The structure allowed depends on the type of protocol.</param>
/// <param name="pszPrincipal"><para>An optional string that specifies the name of the principal whose credentials the handle will reference.</para>
/// <para>
/// <c>Note</c> If the process that requests the handle does not have access to the credentials, the function returns an error. A
/// null string indicates that the process requires a handle to the credentials of the user under whose security context it is executing.
/// </para></param>
/// <param name="pvLogonId">A locally unique identifier (LUID) that identifies the user. This parameter is provided for file-system processes
/// such as network redirectors. This parameter can be <c>NULL</c>.</param>
/// <param name="ptsExpiry">A TimeStamp structure that receives the time at which the returned credentials expire. The structure value received
/// depends on the security package, which must specify the value in local time.</param>
/// <returns>On success, this function returns a credential handle.</returns>
/// <remarks>
/// <para>
/// The <c>AcquireCredentialsHandle (CredSSP)</c> function returns a handle to the credentials of a principal, such as a user or
/// client, as used by a specific security package. The function can return the handle to either preexisting credentials or newly
/// created credentials and return it. This handle can be used in subsequent calls to the AcceptSecurityContext (CredSSP) and
/// InitializeSecurityContext (CredSSP) functions.
/// </para>
/// <para>
/// In general, <c>AcquireCredentialsHandle (CredSSP)</c> does not provide the credentials of other users logged on to the same
/// computer. However, a caller with SE_TCB_NAME privilege can obtain the credentials of an existing logon session by specifying the
/// logon identifier (LUID) of that session. Typically, this is used by kernel-mode modules that must act on behalf of a logged-on user.
/// </para>
/// </remarks>
public static SafeCredHandle Acquire<TAuthData>(string pszPackage, SECPKG_CRED fCredentialUse, TAuthData? pAuthData, string pszPrincipal,
LUID? pvLogonId, out TimeStamp ptsExpiry) where TAuthData : struct
{
using (var pinnedLuid = new PinnedObject(pvLogonId))
using (var pinnedAuthData = pAuthData.HasValue ? SafeHGlobalHandle.CreateFromStructure(pAuthData) : SafeHGlobalHandle.Null)
{
AcquireCredentialsHandle(pszPrincipal, pszPackage, fCredentialUse, pinnedLuid, (IntPtr)pinnedAuthData, IntPtr.Zero, IntPtr.Zero, out var hCred, out ptsExpiry).ThrowIfFailed();
return new SafeCredHandle(hCred);
}
}
/// <summary>
/// Get a dangerous reference to the underlying CredHandle. This value is mutable and may be invalid after this
/// <see cref="SafeCredHandle"/> instance is disposed.
/// </summary>
public CredHandle DangerousGetHandle() => handle;
void IDisposable.Dispose()
{
if (handle.IsInvalid || handle.IsNull) return;
FreeCredentialsHandle(ref handle);
handle = CredHandle.Null;
}
}
/// <summary>Provides a safe version of <see cref="CtxtHandle"/> that is disposed using <see cref="DeleteSecurityContext"/>.</summary>
[StructLayout(LayoutKind.Sequential)]
public sealed class SafeCtxtHandle : IDisposable
{
private CtxtHandle handle;
/// <summary>Initializes a new instance of the <see cref="SafeCtxtHandle"/> class.</summary>
public SafeCtxtHandle() => handle = CtxtHandle.Null;
/// <summary>Initializes a new instance of the <see cref="SafeCtxtHandle"/> class and assigns an existing handle.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
public SafeCtxtHandle(CtxtHandle preexistingHandle) => handle = preexistingHandle;
/// <summary>Performs an implicit conversion from <see cref="SafeCtxtHandle"/> to <see cref="CtxtHandle"/>.</summary>
/// <param name="h">The safe handle instance.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator CtxtHandle(SafeCtxtHandle h) => h.handle;
/// <summary>Performs an implicit conversion from <see cref="SafeCtxtHandle"/> to <see cref="CtxtHandle"/>.</summary>
/// <param name="h">The safe handle.</param>
/// <returns>The result of the conversion.</returns>
public static unsafe implicit operator CtxtHandle* (SafeCtxtHandle h)
{
if (h.handle.IsNull)
return null;
fixed (CtxtHandle* hp = &h.handle)
return hp;
}
/// <summary>Get a NULL reference to CredHandle.</summary>
public readonly static SafeCtxtHandle Null = new SafeCtxtHandle(CtxtHandle.Null);
/// <summary>
/// Get a dangerous reference to the underlying CtxtHandle. This value is mutable and may be invalid after this
/// <see cref="SafeCtxtHandle"/> instance is disposed.
/// </summary>
public CtxtHandle DangerousGetHandle() => handle;
void IDisposable.Dispose()
{
if (!handle.IsInvalid && !handle.IsNull) DeleteSecurityContext(handle);
}
internal void SetHandle(CtxtHandle h)
{
if (handle.IsNull) handle = h; else throw new InvalidOperationException();
}
}
/// <summary>Provides a <see cref="SafeHandle"/> for <see cref="PSEC_WINNT_AUTH_IDENTITY_OPAQUE"/> that is disposed using <see cref="SspiFreeAuthIdentity"/>.</summary>
public class SafePSEC_WINNT_AUTH_IDENTITY_OPAQUE : SafeHANDLE
2018-09-30 17:37:25 -04:00
{
/// <summary>
/// Represents a null instance.
/// </summary>
public static readonly SafePSEC_WINNT_AUTH_IDENTITY_OPAQUE Null = new SafePSEC_WINNT_AUTH_IDENTITY_OPAQUE();
2018-09-30 17:37:25 -04:00
/// <summary>
/// Initializes a new instance of the <see cref="SafePSEC_WINNT_AUTH_IDENTITY_OPAQUE"/> class and assigns an existing handle.
2018-09-30 17:37:25 -04:00
/// </summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
/// <param name="ownsHandle">
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
/// </param>
public SafePSEC_WINNT_AUTH_IDENTITY_OPAQUE(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
/// <summary>Initializes a new instance of the <see cref="SafePSEC_WINNT_AUTH_IDENTITY_OPAQUE"/> class.</summary>
private SafePSEC_WINNT_AUTH_IDENTITY_OPAQUE() : base() { }
/// <summary>Performs an implicit conversion from <see cref="SafePSEC_WINNT_AUTH_IDENTITY_OPAQUE"/> to <see cref="PSEC_WINNT_AUTH_IDENTITY_OPAQUE"/>.</summary>
/// <param name="h">The safe handle instance.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator PSEC_WINNT_AUTH_IDENTITY_OPAQUE(SafePSEC_WINNT_AUTH_IDENTITY_OPAQUE h) => h.handle;
2018-09-30 17:37:25 -04:00
/// <inheritdoc/>
protected override bool InternalReleaseHandle() { SspiZeroAuthIdentity(handle); SspiFreeAuthIdentity(handle); return true; }
2018-09-30 17:37:25 -04:00
}
/// <summary>
/// The <c>SafeSecBufferDesc</c> structure describes an array of SecBuffer structures to pass from a transport application to a
/// security package. It handles cleaning up allocated memory.
/// </summary>
/// <remarks>
/// This is a drop in replacement for anywhere a "SecBufferDesc*" or "ref SecBufferDesc" is required. This class will free all
/// allocated memory and will also free any memory created by Sspi methods that require a call to <see cref="FreeContextBuffer"/>.
/// <para>Sample code:</para><code>using (var edesc = new SafeSecBufferDesc())
/// {
/// edesc.Add(SecBufferType.SECBUFFER_TOKEN); // Add SecBuffer with type, but no values
/// edesc.Add(SecBufferType.SECBUFFER_EMPTY); // Add SecBuffer with empty type
/// edesc.Add(SecBufferType.SECBUFFER_DATA, msgStruct); // Add SecBuffer with type set and buffer filled with value of 'msgStruct'
/// edesc.Add(blockSize, SecBufferType.SECBUFFER_PADDING); // Add SecBuffer with type and allocated memory of size 'blockSize'
///
/// // Call method with ref
/// EncryptMessage(hCtx, 0, ref edesc.GetRef(), 0); // Use GetRef() method to get a reference to the internal SecBufferDesc structure
///
/// // Call method with *
/// unsafe
/// {
/// AcceptSecurityContext(hCred, hCtxt2, edesc, ...); // An implicit operator will cast to a SecBufferDesc*
/// }
/// }</code></remarks>
[PInvokeData("sspi.h", MSDNShortId = "fc6ef09c-3ba9-4bcb-a3c2-07422af8eaa9")]
public class SafeSecBufferDesc : SafeNativeArrayBase<SecBuffer, HGlobalMemoryMethods>
2018-09-30 17:37:25 -04:00
{
private static readonly uint HdrSize = (uint)Marshal.SizeOf(typeof(SecBufferDesc));
2018-09-30 17:37:25 -04:00
private readonly List<SafeAllocatedMemoryHandle> items = new List<SafeAllocatedMemoryHandle>();
private SecBufferDesc desc = SecBufferDesc.Default;
/// <summary>Initializes a new instance of the <see cref="SafeSecBufferDesc"/> class.</summary>
public SafeSecBufferDesc() : base(null, HdrSize) { }
/// <summary>Initializes a new instance of the <see cref="SafeSecBufferDesc"/> class.</summary>
public SafeSecBufferDesc(SecBufferType type) : base(new[] { new SecBuffer(type) }, HdrSize) { }
/// <summary>Performs an implicit conversion from <see cref="SafeSecBufferDesc"/> to <see cref="SecBufferDesc"/>.</summary>
/// <param name="sbd">The <see cref="SafeSecBufferDesc"/> instance.</param>
/// <returns>The result of the conversion.</returns>
public static unsafe implicit operator SecBufferDesc* (SafeSecBufferDesc sbd) => (SecBufferDesc*)sbd.handle;
/// <summary>Performs an implicit conversion from <see cref="SafeSecBufferDesc"/> to <see cref="SecBufferDesc"/>.</summary>
/// <param name="sbd">The <see cref="SafeSecBufferDesc"/> instance.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator SecBufferDesc? (SafeSecBufferDesc sbd) => (SecBufferDesc)sbd.handle.ToNullableStructure<SecBufferDesc>();
/// <summary>Adds the specified type with an empty value as a new SecBuffer item.</summary>
/// <param name="type">The type of the SecBuffer.</param>
public virtual void Add(SecBufferType type) => Add(new SecBuffer(type));
/// <summary>Adds the specified type and value as a new SecBuffer item.</summary>
/// <typeparam name="T">The type of the value to add</typeparam>
/// <param name="type">The type of the SecBuffer.</param>
/// <param name="value">The value to add.</param>
public virtual void Add<T>(SecBufferType type, T value = default) where T : struct
2018-09-30 17:37:25 -04:00
{
var mem = SafeHGlobalHandle.CreateFromStructure(value);
items.Add(mem);
Add(new SecBuffer(type, (IntPtr)mem, mem.Size));
2018-09-30 17:37:25 -04:00
}
/// <summary>Adds the specified type and value as a new SecBuffer item.</summary>
/// <typeparam name="T">The type of the element to add</typeparam>
/// <param name="type">The type of the SecBuffer.</param>
/// <param name="value">The list to add.</param>
public virtual void Add<T>(SecBufferType type, IEnumerable<T> value) where T : struct
2018-09-30 17:37:25 -04:00
{
var mem = SafeHGlobalHandle.CreateFromList(value);
items.Add(mem);
Add(new SecBuffer(type, (IntPtr)mem, mem.Size));
2018-09-30 17:37:25 -04:00
}
/// <summary>Adds the specified type and value as a new SecBuffer item.</summary>
/// <param name="type">The type of the SecBuffer.</param>
/// <param name="value">The list to add.</param>
public virtual void Add(SecBufferType type, string value)
{
var mem = new SafeHGlobalHandle(value);
items.Add(mem);
Add(new SecBuffer(type, (IntPtr)mem, mem.Size));
}
/// <summary>Adds the specified type with an allocated buffer of the specified size as a new SecBuffer item.</summary>
/// <param name="bufferSize">Size of the buffer.</param>
/// <param name="type">The type of the SecBuffer.</param>
public virtual void Add(int bufferSize, SecBufferType type)
{
var mem = new SafeHGlobalHandle(bufferSize);
items.Add(mem);
Add(new SecBuffer(type, (IntPtr)mem, mem.Size));
}
/// <summary>Performs an implicit conversion from <see cref="SafeSecBufferDesc"/> to <see cref="SecBufferDesc"/>.</summary>
/// <returns>A reference to a <see cref="SecBufferDesc"/> struct.</returns>
public ref SecBufferDesc GetRef() => ref desc;
/// <inheritdoc/>
protected override void OnCountChanged() => OnUpdateHeader();
2018-09-30 17:37:25 -04:00
/// <inheritdoc/>
protected override void OnUpdateHeader()
{
desc.cBuffers = (uint)Count;
desc.pBuffers = handle.Offset((int)HdrSize);
Marshal.StructureToPtr(desc, handle, false);
}
2018-09-30 17:37:25 -04:00
/// <inheritdoc/>
protected override bool ReleaseHandle()
{
var hash = new HashSet<IntPtr>(items.Select(i => i.DangerousGetHandle()));
foreach (var buf in this.Where(b => !hash.Contains(b.pvBuffer)))
FreeContextBuffer(buf.pvBuffer);
Clear();
foreach (var i in items)
i.Dispose();
items.Clear();
desc = SecBufferDesc.Default;
return base.ReleaseHandle();
}
2018-09-30 17:37:25 -04:00
}
/// <summary>Provides a <see cref="SafeHandle"/> for Sspi allocated memory that is disposed using <see cref="SspiLocalFree"/>.</summary>
public class SafeSspiLocalMem : SafeHANDLE
{
/// <summary>Initializes a new instance of the <see cref="SafeSspiLocalMem"/> class and assigns an existing handle.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
/// <param name="ownsHandle"><see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).</param>
public SafeSspiLocalMem(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
/// <summary>Initializes a new instance of the <see cref="SafeSspiLocalMem"/> class.</summary>
private SafeSspiLocalMem() : base() { }
/// <summary>Gets the bytes associated with this memory.</summary>
/// <param name="count">The count of bytes to get.</param>
/// <returns>A byte array.</returns>
public byte[] GetBytes(uint count) => handle.ToArray<byte>((int)count);
/// <inheritdoc/>
protected override bool InternalReleaseHandle() { SspiLocalFree(handle); return true; }
}
internal class SspiStringMarshaler : ICustomMarshaler
{
public static ICustomMarshaler GetInstance(string _) => new SspiStringMarshaler();
public void CleanUpManagedData(object ManagedObj)
{
}
public void CleanUpNativeData(IntPtr pNativeData)
{
if (pNativeData == IntPtr.Zero) return;
SspiFreeAuthIdentity(pNativeData);
}
public int GetNativeDataSize() => -1;
public IntPtr MarshalManagedToNative(object _) => IntPtr.Zero;
public object MarshalNativeToManaged(IntPtr pNativeData)
{
var ret = StringHelper.GetString(pNativeData, CharSet.Unicode);
System.Diagnostics.Debug.WriteLine($"SspiStringMarshaler: {ret ?? "null"}");
return ret.Clone();
}
}
2018-09-30 17:37:25 -04:00
}
}