diff --git a/PInvoke/Security/AdvApi32/WinNT.cs b/PInvoke/Security/AdvApi32/WinNT.cs index 82fcaa0f..e94fa558 100644 --- a/PInvoke/Security/AdvApi32/WinNT.cs +++ b/PInvoke/Security/AdvApi32/WinNT.cs @@ -14,6 +14,9 @@ namespace Vanara.PInvoke { public const uint SECURITY_DESCRIPTOR_REVISION = 1; public const uint SECURITY_DESCRIPTOR_REVISION1 = 1; + public const int SID_MAX_SUB_AUTHORITIES = 15; + public const int SID_RECOMMENDED_SUB_AUTHORITIES = 1; // Will change to around 6 + public const uint SID_REVISION = 1; // Current revision level /// Indicates whether the ObjectTypeName and InheritedObjectTypeName members contain strings. [PInvokeData("winnt.h")] diff --git a/PInvoke/Security/Secur32/NTSecApi.cs b/PInvoke/Security/Secur32/NTSecApi.cs index 60c6b830..6af6f1ce 100644 --- a/PInvoke/Security/Secur32/NTSecApi.cs +++ b/PInvoke/Security/Secur32/NTSecApi.cs @@ -1,5 +1,8 @@ using System; +using System.Collections.Generic; using System.Runtime.InteropServices; +using Vanara.Extensions; +using Vanara.InteropServices; using static Vanara.PInvoke.AdvApi32; using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME; @@ -8,6 +11,10 @@ namespace Vanara.PInvoke /// Functions, enumerations and structures found in Secur32.dll. public static partial class Secur32 { + /// Microsoft CredSSP Security Provider. + [PInvokeData("credssp.h")] + public const string CREDSSP_NAME = "CREDSSP"; + /// The Kerberos authentication package name. [PInvokeData("Ntsecapi.h")] public const string MICROSOFT_KERBEROS_NAME = "Kerberos"; @@ -24,22 +31,17 @@ namespace Vanara.PInvoke [PInvokeData("Security.h")] public const string NTLMSP_NAME = "NTLM"; - /// Digest Authentication for Windows. - [PInvokeData("wdigest.h")] - public const string WDIGEST_SP_NAME = "WDigest"; - - /// Microsoft CredSSP Security Provider. - [PInvokeData("credssp.h")] - public const string CREDSSP_NAME = "CREDSSP"; + /// TS Service Security Package + [PInvokeData("Ntsecapi.h")] + public const string PKU2U_PACKAGE_NAME = "pku2u"; /// TS Service Security Package [PInvokeData("credssp.h")] public const string TS_SSP_NAME = "TSSSP"; - /// TS Service Security Package - [PInvokeData("Ntsecapi.h")] - public const string PKU2U_PACKAGE_NAME = "pku2u"; - + /// Digest Authentication for Windows. + [PInvokeData("wdigest.h")] + public const string WDIGEST_SP_NAME = "WDigest"; /// Kerberos encryption types. [PInvokeData("Ntsecapi.h", MSDNShortId = "3b088c94-810b-44c7-887a-58e8dbd13603")] public enum KERB_ETYPE @@ -85,6 +87,40 @@ namespace Vanara.PInvoke KERB_ETYPE_RC4_HMAC_NT_EXP = 24 } + /// The KERB_LOGON_SUBMIT_TYPE enumeration identifies the type of logon being requested. + // https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/ne-ntsecapi-kerb_logon_submit_type + // typedef enum _KERB_LOGON_SUBMIT_TYPE { KerbInteractiveLogon, KerbSmartCardLogon, KerbWorkstationUnlockLogon, KerbSmartCardUnlockLogon, KerbProxyLogon, KerbTicketLogon, KerbTicketUnlockLogon, KerbS4ULogon, KerbCertificateLogon, KerbCertificateS4ULogon, KerbCertificateUnlockLogon, KerbNoElevationLogon, KerbLuidLogon } KERB_LOGON_SUBMIT_TYPE, *PKERB_LOGON_SUBMIT_TYPE; + [PInvokeData("ntsecapi.h", MSDNShortId = "500bee53-638b-4782-b42d-1df158396fb6")] + public enum KERB_LOGON_SUBMIT_TYPE + { + /// Perform an interactive logon. + KerbInteractiveLogon = 2, + /// Logon using a smart card. + KerbSmartCardLogon = 6, + /// Unlock a workstation. + KerbWorkstationUnlockLogon, + /// Unlock a workstation using a smart card. + KerbSmartCardUnlockLogon, + /// Logon using a proxy server. + KerbProxyLogon, + /// Logon using a valid Kerberos ticket as a credential. + KerbTicketLogon, + /// Unlock a workstation by using a Kerberos ticket. + KerbTicketUnlockLogon, + /// Perform a service for user logon. + KerbS4ULogon, + /// Logon interactively using a certificate stored on a smart card. + KerbCertificateLogon, + /// Perform a service for user logon using a certificate stored on a smart card. + KerbCertificateS4ULogon, + /// Unlock a workstation using a certificate stored on a smart card. + KerbCertificateUnlockLogon, + /// + KerbNoElevationLogon = 83, + /// + KerbLuidLogon, + } + /// /// /// The KERB_PROTOCOL_MESSAGE_TYPE enumeration lists the types of messages that can be sent to the Kerberos authentication @@ -242,38 +278,77 @@ namespace Vanara.PInvoke KerbQueryS4U2ProxyCacheMessage, } - /// The KERB_LOGON_SUBMIT_TYPE enumeration identifies the type of logon being requested. - // https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/ne-ntsecapi-kerb_logon_submit_type - // typedef enum _KERB_LOGON_SUBMIT_TYPE { KerbInteractiveLogon, KerbSmartCardLogon, KerbWorkstationUnlockLogon, KerbSmartCardUnlockLogon, KerbProxyLogon, KerbTicketLogon, KerbTicketUnlockLogon, KerbS4ULogon, KerbCertificateLogon, KerbCertificateS4ULogon, KerbCertificateUnlockLogon, KerbNoElevationLogon, KerbLuidLogon } KERB_LOGON_SUBMIT_TYPE, *PKERB_LOGON_SUBMIT_TYPE; - [PInvokeData("ntsecapi.h", MSDNShortId = "500bee53-638b-4782-b42d-1df158396fb6")] - public enum KERB_LOGON_SUBMIT_TYPE + /// Ticket flags, as defined in Internet RFC 4120. This parameter can be one or more of the following values. + [PInvokeData("ntsecapi.h", MSDNShortId = "742e2795-ec74-4856-a680-7a1c233a2934")] + [Flags] + public enum KERB_TICKET_FLAGS : uint { - /// Perform an interactive logon. - KerbInteractiveLogon = 2, - /// Logon using a smart card. - KerbSmartCardLogon = 6, - /// Unlock a workstation. - KerbWorkstationUnlockLogon, - /// Unlock a workstation using a smart card. - KerbSmartCardUnlockLogon, - /// Logon using a proxy server. - KerbProxyLogon, - /// Logon using a valid Kerberos ticket as a credential. - KerbTicketLogon, - /// Unlock a workstation by using a Kerberos ticket. - KerbTicketUnlockLogon, - /// Perform a service for user logon. - KerbS4ULogon, - /// Logon interactively using a certificate stored on a smart card. - KerbCertificateLogon, - /// Perform a service for user logon using a certificate stored on a smart card. - KerbCertificateS4ULogon, - /// Unlock a workstation using a certificate stored on a smart card. - KerbCertificateUnlockLogon, - /// - KerbNoElevationLogon = 83, - /// - KerbLuidLogon, + /// + /// The ticket-granting server can issue a new ticket-granting ticket with a different network address, based on the presented ticket. + /// + KERB_TICKET_FLAGS_forwardable = 0x40000000, + + /// + /// The ticket has either been forwarded or was issued based on authentication that involved a forwarded ticket-granting ticket. + /// + KERB_TICKET_FLAGS_forwarded = 0x20000000, + + /// + /// The protocol employed for initial authentication required the use of hardware expected to be possessed solely by the named + /// client. The hardware authentication method is selected by the KDC, and the strength of the method is not indicated. + /// + KERB_TICKET_FLAGS_hw_authent = 0x00100000, + + /// + /// The ticket was issued by using the Authentication Service protocol instead of being based on a ticket-granting ticket. + /// + KERB_TICKET_FLAGS_initial = 0x00400000, + + /// The ticket is not valid. + KERB_TICKET_FLAGS_invalid = 0x01000000, + + /// + /// Indicates to the ticket-granting server that a postdated ticket can be issued based on this ticket-granting ticket. + /// + KERB_TICKET_FLAGS_may_postdate = 0x04000000, + + /// + /// The target of the ticket is trusted by the directory service for delegation. Thus, the clients may delegate their + /// credentials to the server, which lets the server act as the client when talking to other services. + /// + KERB_TICKET_FLAGS_ok_as_delegate = 0x00040000, + + /// + /// The ticket has been postdated. The end service can check the ticket's authtime member to determine when the original + /// authentication occurred. + /// + KERB_TICKET_FLAGS_postdated = 0x02000000, + + /// + /// During initial authentication, the client was authenticated by the KDC before a ticket was issued. The strength of the + /// preauthentication method is not indicated but is acceptable to the KDC. + /// + KERB_TICKET_FLAGS_pre_authent = 0x00200000, + + /// + /// Indicates to the ticket-granting server that only nonticket-granting tickets can be issued with different network addresses. + /// + KERB_TICKET_FLAGS_proxiable = 0x10000000, + + /// The ticket is a proxy. + KERB_TICKET_FLAGS_proxy = 0x08000000, + + /// + /// The ticket is renewable. If this flag is set, the time limit for renewing the ticket is set in the RenewTime member of a + /// KERB_TICKET_CACHE_INFO structure. A renewable ticket can be used to obtain a replacement ticket that expires at a later date. + /// + KERB_TICKET_FLAGS_renewable = 0x00800000, + + /// Reserved for future use. Do not set this flag. + KERB_TICKET_FLAGS_reserved = 0x80000000, + + /// Reserved. + KERB_TICKET_FLAGS_reserved1 = 0x00000001, } [PInvokeData("ntsecapi.h", MSDNShortId = "8ed37546-6443-4010-a078-4359dd1c2861")] @@ -1646,8 +1721,16 @@ namespace Vanara.PInvoke [FieldOffset(8)] public IntPtr Names; - // /// public override string ToString() => NameCount == 0 ? "" : string.Join("; ", - // Array.ConvertAll(Names.ToArray(NameCount), s => s.ToString())); + /// Extracts the names from . + /// A sequence of names. + public IEnumerable GetNames() + { + if (NameCount == 0) + yield break; + using var pin = new PinnedObject(this); + foreach (var us in ((IntPtr)pin).ToIEnum(NameCount, 8)) + yield return us.ToString(); + } } /// @@ -1785,7 +1868,7 @@ namespace Vanara.PInvoke /// /// /// - public uint TicketFlags; + public KERB_TICKET_FLAGS TicketFlags; /// Reserved for future use. Set this member to zero. public uint Flags; @@ -1849,6 +1932,105 @@ namespace Vanara.PInvoke public LSA_UNICODE_STRING Password; } + /// + /// The KERB_PURGE_TKT_CACHE_REQUEST structure contains information used to delete entries from the ticket cache. + /// It is used by LsaCallAuthenticationPackage. + /// + /// + /// + /// If both ServerName and RealmName are of zero length, LsaCallAuthenticationPackage will delete all tickets for the + /// logon session identified by LogonId. Otherwise, LsaCallAuthenticationPackage will search the cache tickets for + /// ServerName@ RealmName, and will delete all such tickets. + /// + /// + /// LsaCallAuthenticationPackage does not return this buffer. It returns STATUS_SUCCESS if one or more tickets are deleted. If no + /// tickets are found, the function returns SEC_E_NO_CREDENTIALS. + /// + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/ns-ntsecapi-kerb_purge_tkt_cache_request typedef struct + // _KERB_PURGE_TKT_CACHE_REQUEST { KERB_PROTOCOL_MESSAGE_TYPE MessageType; LUID LogonId; UNICODE_STRING ServerName; UNICODE_STRING + // RealmName; } KERB_PURGE_TKT_CACHE_REQUEST, *PKERB_PURGE_TKT_CACHE_REQUEST; + [PInvokeData("ntsecapi.h", MSDNShortId = "4e5e944a-8163-42de-b534-3b0478d9f334")] + [StructLayout(LayoutKind.Sequential)] + public struct KERB_PURGE_TKT_CACHE_REQUEST + { + /// KERB_PROTOCOL_MESSAGE_TYPE value identifying the type of request being made. This member must be set to KerbPurgeTicketCacheMessage. + public KERB_PROTOCOL_MESSAGE_TYPE MessageType; + + /// + /// LUID structure containing the logon session identifier. This can be zero for the current user's logon session. If not zero, + /// the caller must have the SeTcbPrivilege privilege set. If this fails, the Kerberos authentication package sets the + /// ProtocolStatus parameter of LsaCallAuthenticationPackage to STATUS_ACCESS_DENIED. + /// + public LUID LogonId; + + /// UNICODE_STRING containing the name of the service whose tickets should be deleted from the cache. + public LSA_UNICODE_STRING ServerName; + + /// UNICODE_STRING containing the name of the realm whose tickets should be deleted from the cache. + public LSA_UNICODE_STRING RealmName; + } + + /// + /// The KERB_QUERY_TKT_CACHE_REQUEST structure contains information used to query the ticket cache. + /// It is used by LsaCallAuthenticationPackage. + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/ns-ntsecapi-kerb_query_tkt_cache_request typedef struct + // _KERB_QUERY_TKT_CACHE_REQUEST { KERB_PROTOCOL_MESSAGE_TYPE MessageType; LUID LogonId; } KERB_QUERY_TKT_CACHE_REQUEST, *PKERB_QUERY_TKT_CACHE_REQUEST; + [PInvokeData("ntsecapi.h", MSDNShortId = "3c8e63b3-9ac4-4228-87e1-6802c3d12d6c")] + [StructLayout(LayoutKind.Sequential)] + public struct KERB_QUERY_TKT_CACHE_REQUEST + { + /// + /// + /// KERB_PROTOCOL_MESSAGE_TYPE value identifying the type of request being made. This member must be set to + /// KerbQueryTicketCacheMessage or KerbRetrieveTicketMessage. + /// + /// + /// If this member is set to KerbQueryTicketCacheMessage, the request is for information about all of the cached tickets + /// for the specified user logon session. If it is set to KerbRetrieveTicketMessage, the request is for the ticket + /// granting ticket from the ticket cache of the specified user logon session. + /// + /// + public KERB_PROTOCOL_MESSAGE_TYPE MessageType; + + /// + /// LUID structure containing the logon session identifier. This can be zero for the current user's logon session. If not zero, + /// the caller must have the SeTcbPrivilege privilege set. If this fails, the Kerberos authentication package sets the + /// ProtocolStatus parameter of LsaCallAuthenticationPackage to STATUS_ACCESS_DENIED. + /// + public LUID LogonId; + } + + /// + /// The KERB_QUERY_TKT_CACHE_RESPONSE structure contains the results of querying the ticket cache. + /// It is used by LsaCallAuthenticationPackage. + /// + /// + /// This buffer is allocated by the Kerberos authentication package and should be deleted by the application that called + /// LsaCallAuthenticationPackage, using LsaFreeReturnBuffer. + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/ns-ntsecapi-kerb_query_tkt_cache_response typedef struct + // _KERB_QUERY_TKT_CACHE_RESPONSE { KERB_PROTOCOL_MESSAGE_TYPE MessageType; ULONG CountOfTickets; KERB_TICKET_CACHE_INFO + // Tickets[ANYSIZE_ARRAY]; } KERB_QUERY_TKT_CACHE_RESPONSE, *PKERB_QUERY_TKT_CACHE_RESPONSE; + [PInvokeData("ntsecapi.h", MSDNShortId = "2101c1de-f304-4d44-899f-f9f03cd50934")] + [StructLayout(LayoutKind.Sequential)] + [VanaraMarshaler(typeof(SafeAnysizeStructMarshaler), nameof(CountOfTickets))] + public struct KERB_QUERY_TKT_CACHE_RESPONSE + { + /// KERB_PROTOCOL_MESSAGE_TYPE value identifying the type of request being made. This member must be set to KerbQueryTicketCacheMessage. + public KERB_PROTOCOL_MESSAGE_TYPE MessageType; + + /// + /// Number of tickets in Tickets array. This can be zero if no tickets are available for the specified logon session. + /// + public uint CountOfTickets; + + /// Array of length CountOfTickets of KERB_TICKET_CACHE_INFO structures. + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] + public KERB_TICKET_CACHE_INFO[] Tickets; + } + /// /// The KERB_RETRIEVE_TKT_REQUEST structure contains information used to retrieve a ticket. /// @@ -2011,6 +2193,139 @@ namespace Vanara.PInvoke public KERB_EXTERNAL_TICKET Ticket; } + /// + /// + /// The KERB_TICKET_CACHE_INFO structure contains information about a cached Kerberos ticket. The Kerberos ticket is defined + /// in Internet RFC 4120. For more information, see http://www.ietf.org. + /// + /// + /// It can be used both for retrieving tickets and querying the ticket cache. The KERB_QUERY_TKT_CACHE_RESPONSE structure uses this structure. + /// + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/ns-ntsecapi-kerb_ticket_cache_info typedef struct + // _KERB_TICKET_CACHE_INFO { UNICODE_STRING ServerName; UNICODE_STRING RealmName; LARGE_INTEGER StartTime; LARGE_INTEGER EndTime; + // LARGE_INTEGER RenewTime; LONG EncryptionType; ULONG TicketFlags; } KERB_TICKET_CACHE_INFO, *PKERB_TICKET_CACHE_INFO; + [PInvokeData("ntsecapi.h", MSDNShortId = "e9ac70f0-65dc-4c5a-b41f-7c4659680333")] + [StructLayout(LayoutKind.Sequential)] + public struct KERB_TICKET_CACHE_INFO + { + /// + /// A UNICODE_STRING that contains the name of the server the ticket applies to. This name is combined with the RealmName + /// value to create the full name ServerName@ RealmName. + /// + public LSA_UNICODE_STRING ServerName; + + /// A UNICODE_STRING that contains the name of the realm the ticket applies to. + public LSA_UNICODE_STRING RealmName; + + /// + /// A FILETIME structure that contains the time at which the ticket becomes valid. If the starttime member of the ticket + /// is not set, this value defaults to the time when the ticket was initially authenticated, authtime. The + /// starttime member of a ticket is optional. + /// + public FILETIME StartTime; + + /// A FILETIME structure that contains the time when the ticket expires. + public FILETIME EndTime; + + /// + /// If KERB_TICKET_FLAGS_renewable is set in TicketFlags, this member is a FILETIME structure that contains the time + /// beyond which the ticket cannot be renewed. + /// + public FILETIME RenewTime; + + /// The type of encryption used in the ticket. + public KERB_ETYPE EncryptionType; + + /// + /// The ticket flags, as defined in Internet RFC 4120. These flags can be one or more of the following values. + /// + /// + /// Value + /// Meaning + /// + /// + /// KERB_TICKET_FLAGS_forwardable 0x40000000 + /// + /// The ticket-granting server can issue a new ticket-granting ticket with a different network address based on the presented ticket. + /// + /// + /// + /// KERB_TICKET_FLAGS_forwarded 0x20000000 + /// + /// The ticket has either been forwarded or was issued based on authentication that involved a forwarded ticket-granting ticket. + /// + /// + /// + /// KERB_TICKET_FLAGS_hw_authent 0x00100000 + /// + /// The protocol employed for initial authentication required the use of hardware expected to be possessed solely by the named + /// client. The hardware authentication method is selected by the KDC and the strength of the method is not indicated. + /// + /// + /// + /// KERB_TICKET_FLAGS_initial 0x00400000 + /// The ticket was issued by using the Authentication Service protocol instead of being based on a ticket-granting ticket. + /// + /// + /// KERB_TICKET_FLAGS_invalid 0x01000000 + /// The ticket is not valid. + /// + /// + /// KERB_TICKET_FLAGS_may_postdate 0x04000000 + /// Indicates to the ticket-granting server that a postdated ticket can be issued based on this ticket-granting ticket. + /// + /// + /// KERB_TICKET_FLAGS_ok_as_delegate 0x00040000 + /// + /// The target of the ticket is trusted by the directory service for delegation. Thus, clients may delegate their credentials to + /// the server, which lets the server act as the client when talking to other services. + /// + /// + /// + /// KERB_TICKET_FLAGS_postdated 0x02000000 + /// + /// The ticket has been postdated. The end-service can check the ticket's authtime member to see when the original + /// authentication occurred. + /// + /// + /// + /// KERB_TICKET_FLAGS_pre_authent 0x00200000 + /// + /// During initial authentication, the client was authenticated by the Key Distribution Center (KDC) before a ticket was issued. + /// The strength of the preauthentication method is not indicated, but is acceptable to the KDC. + /// + /// + /// + /// KERB_TICKET_FLAGS_proxiable 0x10000000 + /// + /// Indicates to the ticket-granting server that only nonticket-granting tickets can be issued based on this ticket but with a + /// different network addresses. + /// + /// + /// + /// KERB_TICKET_FLAGS_proxy 0x08000000 + /// The ticket is a proxy. + /// + /// + /// KERB_TICKET_FLAGS_renewable 0x00800000 + /// + /// The ticket is renewable. If this flag is set, the time limit for renewing the ticket is set in RenewTime. A renewable ticket + /// can be used to obtain a replacement ticket that expires at a later date. + /// + /// + /// + /// KERB_TICKET_FLAGS_reserved 0x80000000 + /// Reserved for future use. Do not set this flag. + /// + /// + /// KERB_TICKET_FLAGS_reserved1 0x00000001 + /// Reserved. + /// + /// + /// + public KERB_TICKET_FLAGS TicketFlags; + } /// The LSA_LAST_INTER_LOGON_INFO structure contains information about a logon session. // https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/ns-ntsecapi-_lsa_last_inter_logon_info typedef struct // _LSA_LAST_INTER_LOGON_INFO { LARGE_INTEGER LastSuccessfulLogon; LARGE_INTEGER LastFailedLogon; ULONG