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.