Kids, I originally posted this message (below) to the Advanced .NET mailing list. However, I'd like to post it here also.
Cheers, John -- > -----Original Message----- > From: John Bristowe > Sent: Thursday, 25 April 2002 12:46 PM > To: '[EMAIL PROTECTED]' > Subject: Marshalling/Kerberos Issues > > > Kids, > > I'm having a tough time trying to collection information > about Kerberos tickets that exist for the current logon > session. (See attached code example - AccessTktCache.cs.) In > particular, I'm having trouble trying to figure out how to > marshal the following struct: > > public struct KERB_QUERY_TKT_CACHE_RESPONSE > { > public KERB_PROTOCOL_MESSAGE_TYPE MessageType; > public ulong CountOfTickets; > public KERB_TICKET_CACHE_INFO[] Tickets; > } > > The marshaller bombs each and every time, stating that the > Tickets array couldn't be marshalled as a struct. > > Any suggestions? (Yes, I realize that MC++ would be a much > easier route for me to do what I'm trying to do.) > > John // AccessTktCache.cs using System; using System.Runtime.InteropServices; namespace Kerberos { public struct LARGE_INTEGER { public uint LowPart; public int HighPart; public struct u { public uint LowPart; public int HighPart; } public long QuadPart; } public enum KERB_PROTOCOL_MESSAGE_TYPE { KerbDebugRequestMessage, KerbQueryTicketCacheMessage, KerbChangeMachinePasswordMessage, KerbVerifyPacMessage, KerbRetrieveTicketMessage, KerbUpdateAddressesMessage, KerbPurgeTicketCacheMessage, KerbChangePasswordMessage, KerbRetrieveEncodedTicketMessage, KerbDecryptDataMessage, KerbAddBindingCacheEntryMessage, KerbSetPasswordMessage, KerbSetPasswordExMessage, KerbVerifyCredentialsMessage, KerbQueryTicketCacheExMessage, KerbPurgeTicketCacheExMessage, } [StructLayout(LayoutKind.Sequential)] public struct LsaString { public ushort Length; public ushort MaximumLength; [MarshalAs(UnmanagedType.LPStr)] public string Buffer; } [StructLayout(LayoutKind.Sequential)] public struct LsaUString { public ushort Length; public ushort MaximumLength; [MarshalAs(UnmanagedType.LPWStr)] public string Buffer; } [StructLayout(LayoutKind.Sequential)] public struct LUID { public uint LowPart; public int HighPart; } [StructLayout(LayoutKind.Sequential)] public struct KERB_QUERY_TKT_CACHE_REQUEST { public KERB_PROTOCOL_MESSAGE_TYPE MessageType; public LUID LoginId; } [StructLayout(LayoutKind.Sequential)] public struct KERB_QUERY_TKT_CACHE_RESPONSE { public KERB_PROTOCOL_MESSAGE_TYPE MessageType; public uint CountOfTickets; public KERB_TICKET_CACHE_INFO[] Tickets; } [StructLayout(LayoutKind.Sequential)] public struct KERB_TICKET_CACHE_INFO { public LsaUString ServerName; public LsaUString RealmName; public LARGE_INTEGER StartTime; public LARGE_INTEGER EndTime; public LARGE_INTEGER RenewTime; public int EncryptionType; public uint TicketFlags; } public class AccessTktCacheExample { [DllImport("secur32.dll")] static extern void LsaConnectUntrusted(out IntPtr LsaHandle); [DllImport("secur32.dll")] static extern int LsaCallAuthenticationPackage( IntPtr LsaHandle, ulong AuthenticationPackage, ref KERB_QUERY_TKT_CACHE_REQUEST[] ProtocolSubmitBuffer, ref int SubmitBufferLength, ref KERB_QUERY_TKT_CACHE_RESPONSE[] ProtocolReturnBuffer, ref ulong ReturnBufferLength, ref int ProtocolStatus); [DllImport("secur32.dll")] static extern int LsaLookupAuthenticationPackage( IntPtr LsaHandle, ref LsaString PackageName, out ulong AuthenticationPackage); [DllImport("advapi32.dll")] static extern int LsaNtStatusToWinError(int status); static void Main() { AccessTktCache(); } static unsafe void AccessTktCache() { IntPtr lsaHandle; // connect to the LSA outside the TCB LsaConnectUntrusted(out lsaHandle); string kerberos = "Kerberos"; LsaString lsaString = new LsaString(); lsaString.Length = Convert.ToUInt16(kerberos.Length); lsaString.MaximumLength = Convert.ToUInt16(kerberos.Length); lsaString.Buffer = kerberos; ulong authenticationPackage = 0; // lookup the index for the Kerberos authentication package int ntStatus = LsaLookupAuthenticationPackage(lsaHandle, ref lsaString, out authenticationPackage); if (ntStatus == 0) { KERB_QUERY_TKT_CACHE_REQUEST[] protocolSubmitBuffer = new KERB_QUERY_TKT_CACHE_REQUEST[1]; protocolSubmitBuffer[0].MessageType = KERB_PROTOCOL_MESSAGE_TYPE.KerbQueryTicketCacheMessage; int submitBufferLength = sizeof(KERB_QUERY_TKT_CACHE_REQUEST); KERB_QUERY_TKT_CACHE_RESPONSE[] protocolReturnBuffer = null; ulong returnBufferLength = 0; int protocolStatus = 0; // send the request to Kerberos and get a response ntStatus = LsaCallAuthenticationPackage(lsaHandle, authenticationPackage, ref protocolSubmitBuffer, ref submitBufferLength, ref protocolReturnBuffer, ref returnBufferLength, ref protocolStatus); if (ntStatus != 0) { int winError = LsaNtStatusToWinError(ntStatus); Console.WriteLine("WinError: " + winError); } } else { int winError = LsaNtStatusToWinError(ntStatus); Console.WriteLine("WinError: " + winError); } Console.ReadLine(); } } } You can read messages from the DOTNET archive, unsubscribe from DOTNET, or subscribe to other DevelopMentor lists at http://discuss.develop.com.