Figure 3 Connecting to the Kerberos Provider


/////////////////////////////////////////////////
// excerpt from ntsecapi.h (link to secur32.lib)
NTSTATUS
NTAPI
LsaConnectUntrusted (OUT PHANDLE LsaHandle);

NTSTATUS
NTAPI
LsaLookupAuthenticationPackage (
    IN HANDLE LsaHandle,
    IN PLSA_STRING PackageName,
    OUT PULONG AuthenticationPackage
    );

/////////////////////////////////////////////////
// excerpt from TktView application
void _initString(LSA_STRING& s, char* psz) {
  if (psz) {
    USHORT cch = lstrlenA(psz);
    s.Length = cch;
    s.MaximumLength = cch + 1;
    s.Buffer = psz;
  }
  else {
    s.Length = s.MaximumLength = 0;
    s.Buffer = 0;
  }
}

bool TktViewMainWnd::_connectToLSA() {
  // make a connection to the LSA from outside the TCB
  NTSTATUS s = LsaConnectUntrusted(&m_hLSA);
  if (s) {
    _lsaErrMsg(L"LsaConnectUntrusted", s);
    return false;
  }

  // look up the index for the Kerb authn package
  LSA_STRING sKerb;
  _initString(sKerb, MICROSOFT_KERBEROS_NAME_A);
  s = LsaLookupAuthenticationPackage(m_hLSA, &sKerb, &m_nKerbIndex);
  if (s) {
    _lsaErrMsg(L"LsaLookupAuthenticationPackage", s);
    return false;
  }
  return true;
}
Figure 4 Enumerating Tickets

/////////////////////////////////////////////////
// excerpt from ntsecapi.h (link to secur32.lib)
NTSTATUS
NTAPI
LsaCallAuthenticationPackage (
    IN HANDLE LsaHandle,
    IN ULONG AuthenticationPackage,
    IN PVOID ProtocolSubmitBuffer,
    IN ULONG SubmitBufferLength,
    OUT PVOID *ProtocolReturnBuffer,
    OUT PULONG ReturnBufferLength,
    OUT PNTSTATUS ProtocolStatus
    );

typedef enum _KERB_PROTOCOL_MESSAGE_TYPE {
    KerbDebugRequestMessage = 0,
    KerbQueryTicketCacheMessage,
    KerbChangeMachinePasswordMessage,
    KerbVerifyPacMessage,
    KerbRetrieveTicketMessage,
    KerbUpdateAddressesMessage,
    KerbPurgeTicketCacheMessage,
    KerbChangePasswordMessage,
    KerbRetrieveEncodedTicketMessage,
    KerbDecryptDataMessage,
    KerbAddBindingCacheEntryMessage,
    KerbSetPasswordMessage
} KERB_PROTOCOL_MESSAGE_TYPE;

typedef struct _KERB_QUERY_TKT_CACHE_REQUEST {
    KERB_PROTOCOL_MESSAGE_TYPE MessageType;
    LUID LogonId;
} KERB_QUERY_TKT_CACHE_REQUEST;

/////////////////////////////////////////////////
// excerpt from TktView application
void TktViewMainWnd::_readTktCache() {

  // clean up any existing cached information
  if (m_pTktCache) {
    LsaFreeReturnBuffer(m_pTktCache);
    m_pTktCache = 0;
  }

  // form the request (note that most of the structure is initialized by
  // the compiler to NULLs)
  KERB_QUERY_TKT_CACHE_REQUEST req = {
    KerbQueryTicketCacheMessage
  };

  // send the request to Kerb and get a response
  void* pRep;
  DWORD cbRep;
  NTSTATUS pkgStatus;
  NTSTATUS s = LsaCallAuthenticationPackage(
      m_hLSA, m_nKerbIndex,
      &req, sizeof req,
      &pRep, &cbRep, &pkgStatus);
  if (s) {
    _lsaErrMsg(L"LsaCallAuthenticationPackage", s);
    return;
  }
  if (pkgStatus) {
    _lsaErrMsg(L"KerbQueryTicketCacheMessage",
               pkgStatus);
    return;
  }

  // we now have a collection of information about
  // all tickets in the current logon session
  m_pTktCache = (KERB_QUERY_TKT_CACHE_RESPONSE*)pRep;
}
Figure 5 Purging the Cache

/////////////////////////////////////////////////
// excerpt from ntsecapi.h (link to secur32.lib)
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;

/////////////////////////////////////////////////
// excerpt from TktView application
void TktViewMainWnd::_purgeTicketCache(int id) {

  // the purge request is pretty simple if you
  // don't bother filtering it; I've not yet
  // gotten the filter to work (see the full
  // source code for TktView to see how I'm
  // applying the filter)
  KERB_PURGE_TKT_CACHE_REQUEST req = {
    KerbPurgeTicketCacheMessage
  };

  // note that in this case there is no response
  // other than the status returned from Kerb
  NTSTATUS pkgStatus;
  NTSTATUS s = LsaCallAuthenticationPackage(
      m_hLSA, m_nKerbIndex,
      &req, sizeof req,
      0, 0, &pkgStatus);
  if (s) {
    _lsaErrMsg(L"LsaCallAuthenticationPackage", s);
    return;
  }
  if (pkgStatus) {
    _lsaErrMsg(L"KerbPurgeTicketCacheMessage", pkgStatus);
    return;
  }
}