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.

Reply via email to