Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2101 lines
50 KiB

/*--
Copyright (c) 1998 Microsoft Corporation
Module Name:
kerbtray.c
Abstract:
Displays a dialog with list of Kerberos tickets for the current user.
Author:
14-Dec-1998 (jbrezak)
Environment:
User mode only.
Requires ANSI C extensions: slash-slash comments, long external names.
Revision History:
12-Apr-2002 JBrezak Cleanup prefast issues and security review.
--*/
#define UNICODE
#define _UNICODE
#define STRICT
#include <windows.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <shellapi.h>
#include <shlwapi.h>
#include <commctrl.h>
#include <commdlg.h>
#include <time.h>
#include <assert.h>
#include <string.h>
#include <malloc.h>
#define SECURITY_WIN32
#include <security.h>
#include <ntsecapi.h>
#ifndef NO_CRYPTDLL
#include "cryptdll.h"
#endif
#include "kerbtray.h"
#define SEC_SUCCESS(Status) ((Status) >= 0)
#define TSIZE(b) (sizeof(b)/sizeof(TCHAR))
#define IDI_FIRST_CLOCK IDI_0_MIN
#define IDI_LAST_CLOCK IDI_TICKET
#define MAX_ICONS (IDI_LAST_CLOCK - IDI_FIRST_CLOCK + 1)
#define KWIN_UPDATE_PERIOD 60000 // Every 60 seconds update the screen
#define PPAGE_NAMES 0
#define PPAGE_TIMES 1
#define PPAGE_FLAGS 2
#define PPAGE_ETYPES 3
#define C_PAGES 4
#define CX_ICON 20
#define CY_ICON 20
#define TPS (10*1000*1000)
typedef struct
{
HWND hwndTab;
HWND hwndDisplay;
RECT rcDisplay;
DLGTEMPLATE *apRes[C_PAGES];
PKERB_QUERY_TKT_CACHE_RESPONSE Tickets;
} DLGTABHDR;
OSVERSIONINFO osvers;
HWND hWnd, hDlgTickets;
HINSTANCE hInstance;
HANDLE hModule;
#define SHORTSTRING 40
#define LONGSTRING 256
TCHAR progname[SHORTSTRING];
ULONG PackageId;
HANDLE LogonHandle = NULL;
HWND hWndUsers;
HIMAGELIST himl;
HTREEITEM tgt = NULL;
static HICON kwin_icons[MAX_ICONS]; // Icons depicting time
static INT domain_icon;
static LPCTSTR dt_output_dhms = TEXT("%d %s %02d:%02d:%02d");
static LPCTSTR dt_day_plural = TEXT("days");
static LPCTSTR dt_day_singular = TEXT("day");
static LPCTSTR dt_output_donly = TEXT("%d %s");
static LPCTSTR dt_output_hms = TEXT("%d:%02d:%02d");
static LPCTSTR ftime_default_fmt = TEXT("%02d/%02d/%02d %02d:%02d");
#define WM_NOTIFY_ICON (WM_APP+100)
#ifndef NO_CRYPTDLL
typedef NTSTATUS (NTAPI *CDLOCATECSYSTEM)(ULONG dwEtype, PCRYPTO_SYSTEM * ppcsSystem);
CDLOCATECSYSTEM pCDLocateCSystem;
#endif
LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK AboutProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK TicketsProc(HWND, UINT, WPARAM, LPARAM);
void About(void);
void Tickets(void);
void PurgeCache(void);
void PropsheetDisplay(HWND hDlg);
void SelectTicket(HWND hDlg);
void FillinTicket(HWND hDlg);
LPTSTR etype_string(int enctype);
LPTSTR GetStringRes(int);
#ifdef DEBUG
#define DPRINTF(s) dprintf s
int debug = 1;
void dprintf(LPCTSTR fmt, ...)
{
TCHAR szTemp[512];
va_list ap;
if (!debug)
return;
va_start (ap, fmt);
#ifdef UNICODE
_vsnwprintf(szTemp, TSIZE(szTemp), fmt, ap);
#else
_vsnprintf(szTemp, TSIZE(szTemp), fmt, ap);
#endif
szTemp[TSIZE(szTemp)-1] = 0;
OutputDebugString(szTemp);
va_end (ap);
}
#else
#define DPRINTF(s)
#endif
void
ShowMessage(int level, LPCTSTR msg)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
if (level)
MessageBeep(level);
MessageBox(NULL, msg, progname,
level | MB_OK | MB_TASKMODAL | MB_SETFOREGROUND);
}
void
Error(LPCTSTR fmt, ...)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
TCHAR szTemp[512];
va_list ap;
va_start (ap, fmt);
#ifdef UNICODE
_vsnwprintf(szTemp, TSIZE(szTemp), fmt, ap);
#else
_vsnprintf(szTemp, TSIZE(szTemp), fmt, ap);
#endif
szTemp[TSIZE(szTemp)-1] = 0;
OutputDebugString(szTemp);
ShowMessage(MB_ICONINFORMATION, szTemp);
va_end (ap);
}
void
ErrorExit(LPCTSTR lpszMessage)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
MessageBox(hWnd, lpszMessage, TEXT("Error"), MB_OK);
ExitProcess(0);
}
int
GetIconIndex(long dt)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
int ixicon;
dt = dt / 60; // convert to minutes
if (dt <= 0)
ixicon = IDI_EXPIRED - IDI_FIRST_CLOCK;
else if (dt > 60)
ixicon = IDI_TICKET - IDI_FIRST_CLOCK;
else
ixicon = (int)(dt / 5);
return ixicon;
}
void
SetTray(
HWND hwnd,
HICON hIcon,
LPCTSTR tip
)
/*++
Routine Description:
Activate or update the tray icon
Arguments:
Return Value:
--*/
{
static tray_inited = 0;
NOTIFYICONDATA tnd;
tnd.cbSize = sizeof(NOTIFYICONDATA);
tnd.hWnd = hwnd;
tnd.uID = IDI_KDC;
tnd.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP;
tnd.uCallbackMessage = WM_NOTIFY_ICON;
tnd.hIcon = hIcon;
StrNCpy(tnd.szTip, tip, TSIZE(tnd.szTip));
Shell_NotifyIcon((tray_inited)?NIM_MODIFY:NIM_ADD, &tnd);
if (tray_inited == 0)
tray_inited++;
DestroyIcon(tnd.hIcon);
}
void
DeleteTray(HWND hwnd)
/*++
Routine Description:
Remove the tray icon
Arguments:
Return Value:
--*/
{
NOTIFYICONDATA tnd;
tnd.cbSize = sizeof(NOTIFYICONDATA);
tnd.hWnd = hwnd;
tnd.uID = IDI_KDC;
tnd.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP;
tnd.uCallbackMessage = WM_NOTIFY_ICON;
tnd.hIcon = NULL;
tnd.szTip[0] = '\0';
Shell_NotifyIcon(NIM_DELETE, &tnd);
}
BOOL
UpdateTray(HWND hwnd)
/*++
Routine Description:
Update the tray icon based on the time to live of the TGT
Arguments:
Return Value:
--*/
{
HICON hicon;
TCHAR buf[SHORTSTRING];
BOOL expired = FALSE;
NTSTATUS Status, SubStatus;
KERB_QUERY_TKT_CACHE_REQUEST CacheRequest;
PKERB_RETRIEVE_TKT_RESPONSE TicketEntry = NULL;
PKERB_EXTERNAL_TICKET Ticket;
ULONG ResponseSize;
FILETIME CurrentFileTime;
LARGE_INTEGER Quad;
long dt = 0L;
int days, hours, minutes, seconds;
DWORD tt;
TCHAR buf2[SHORTSTRING];
StrNCpy(buf, progname, TSIZE(buf));
//
// Get the TGT from the ticket cache
//
CacheRequest.MessageType = KerbRetrieveTicketMessage;
CacheRequest.LogonId.LowPart = 0;
CacheRequest.LogonId.HighPart = 0;
Status = LsaCallAuthenticationPackage(LogonHandle,
PackageId,
&CacheRequest,
sizeof(CacheRequest),
(PVOID *) &TicketEntry,
&ResponseSize,
&SubStatus);
//
// If no TGT, display the correct icon
//
if (!SEC_SUCCESS(Status) || !SEC_SUCCESS(SubStatus)) {
hicon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_KDC));
StrCatBuff(buf, GetStringRes(IDS_NO_CREDS), TSIZE(buf));
}
else {
//
// Select the correct icon based on the time left of the TGT
//
Ticket = &(TicketEntry->Ticket);
GetSystemTimeAsFileTime(&CurrentFileTime);
Quad.LowPart = CurrentFileTime.dwLowDateTime;
Quad.HighPart = CurrentFileTime.dwHighDateTime;
dt = (long)((Ticket->EndTime.QuadPart - Quad.QuadPart) / TPS);
LsaFreeReturnBuffer(TicketEntry);
hicon = kwin_icons[GetIconIndex(dt)];
StrCatBuff(buf, TEXT(" - "), TSIZE(buf));
if (dt <= 0) {
StrCatBuff(buf, GetStringRes(IDS_EXPIRED), TSIZE(buf));
expired = TRUE;
}
else {
days = (int) (dt / (24*3600l));
tt = dt % (24*3600l);
hours = (int) (tt / 3600);
tt %= 3600;
minutes = (int) (tt / 60);
seconds = (int) (tt % 60);
if (days) {
if (hours || minutes || seconds) {
_snwprintf(buf2, TSIZE(buf2), dt_output_dhms, days,
(days > 1) ? dt_day_plural : dt_day_singular,
hours, minutes, seconds);
}
else {
_snwprintf(buf2, TSIZE(buf2), dt_output_donly, days,
(days > 1) ? dt_day_plural : dt_day_singular);
}
}
else {
_snwprintf(buf2, TSIZE(buf2), dt_output_hms,
hours, minutes, seconds);
}
_snwprintf(buf, TSIZE(buf), TEXT("%s %s"), progname, buf2);
}
}
SetTray(hwnd, hicon, buf);
return(expired);
}
BOOL
InitializeApp(
HANDLE hInstance,
int nCmdShow
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
LSA_STRING Name;
NTSTATUS Status;
WNDCLASSEX wc;
HWND hwnd;
int i;
//
// Check for an existing instance
//
hwnd = FindWindow(TEXT("MainWindowClass"), TEXT("KerbTray"));
if (hwnd) {
//
// Popup the tickets dialog, if one found
// Run only one instance of kerbtray
//
SendMessage(hwnd, WM_NOTIFY_ICON, 0, WM_LBUTTONDBLCLK);
ExitProcess(0);
}
hModule = GetModuleHandle(NULL);
InitCommonControls();
LoadString(hInstance, IDS_KRB5_NAME, progname, TSIZE(progname));
//
// Setup connection for LSA to Kerberos package
//
Status = LsaConnectUntrusted(&LogonHandle);
if (!SEC_SUCCESS(Status)) {
Error(TEXT("Failed to register as a logon process: 0x%x"), Status);
return FALSE;
}
Name.Buffer = MICROSOFT_KERBEROS_NAME_A;
Name.Length = (USHORT) strlen(Name.Buffer);
Name.MaximumLength = Name.Length + 1;
Status = LsaLookupAuthenticationPackage(
LogonHandle,
&Name,
&PackageId
);
if (!SEC_SUCCESS(Status)){
printf("Failed to lookup package %Z: 0x%x\n",&Name, Status);
return FALSE;
}
//
// Create the image list.
//
if ((himl = ImageList_Create(CX_ICON, CY_ICON, ILC_COLOR, MAX_ICONS, 0)) == NULL)
return FALSE;
ImageList_SetBkColor(himl, CLR_NONE);
for (i = IDI_FIRST_CLOCK; i <= IDI_LAST_CLOCK; i++) {
#ifndef COLOR_ICONS
kwin_icons[i - IDI_FIRST_CLOCK] = LoadIcon(hInstance,
MAKEINTRESOURCE(i));
#else
kwin_icons[i - IDI_FIRST_CLOCK] = LoadImage(hInstance,
MAKEINTRESOURCE(i),
IMAGE_ICON, 0, 0,
LR_DEFAULTCOLOR|LR_DEFAULTSIZE|LR_LOADTRANSPARENT|LR_LOADMAP3DCOLORS);
#endif
(void) ImageList_AddIcon(himl, kwin_icons[i - IDI_FIRST_CLOCK]);
}
#ifndef COLOR_ICONS
domain_icon = ImageList_AddIcon(himl,
LoadIcon(hInstance, MAKEINTRESOURCE(IDI_DOMAIN)));
#else
domain_icon = ImageList_AddIcon(himl,
LoadImage(hInstance, MAKEINTRESOURCE(IDI_DOMAIN),
IMAGE_ICON, 0, 0,
LR_DEFAULTCOLOR|LR_DEFAULTSIZE|LR_LOADTRANSPARENT|LR_LOADMAP3DCOLORS));
#endif
//
// Register a window class for the main window.
//
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW|CS_VREDRAW;
wc.lpfnWndProc = MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hModule, MAKEINTRESOURCE(IDI_EXPIRED));
wc.hIconSm = LoadIcon(hModule, MAKEINTRESOURCE(IDI_EXPIRED));
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = 0;
wc.lpszClassName = TEXT("MainWindowClass");
if (!RegisterClassEx(&wc)) {
Error(TEXT("RegisterClassEx failed"));
return FALSE;
}
//
// Create the main window
//
hWnd = CreateWindowEx(WS_EX_APPWINDOW,
TEXT("MainWindowClass"),
TEXT("KerbTray"),
WS_OVERLAPPEDWINDOW,
0, 0,
5, 5,
NULL,
NULL,
hModule,
NULL);
if (hWnd == NULL) {
Error(TEXT("CreateWindowEx failed"));
return FALSE;
}
ShowWindow(hWnd, SW_HIDE);
return TRUE;
}
int WINAPI
WinMain(
HINSTANCE hInst,
HINSTANCE hPrevInst,
LPSTR lpszCmdLn,
int nShowCmd
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
MSG msg;
HANDLE hAccelTable, hCryptDll;
hInstance = hInst;
hModule = GetModuleHandle(NULL);
osvers.dwOSVersionInfoSize = sizeof(osvers);
GetVersionEx(&osvers);
#ifndef NO_CRYPTDLL
hCryptDll = LoadLibrary(TEXT("CRYPTDLL.DLL"));
if (!hCryptDll)
ErrorExit(TEXT("Unable to load cryptdll.dll"));
pCDLocateCSystem = (CDLOCATECSYSTEM) GetProcAddress(hCryptDll, "CDLocateCSystem");
if (!pCDLocateCSystem)
ErrorExit(TEXT("Unable to link cryptdll.dll::CDLocateCSystem"));
#endif
if (! InitializeApp(hInst, nShowCmd))
ErrorExit(TEXT("InitializeApp failure"));
hAccelTable = LoadAccelerators(hInst, TEXT("KerbTray"));
while (GetMessage(&msg, NULL, 0, 0)) {
if (!IsDialogMessage(hDlgTickets, &msg)) {
if (!TranslateAccelerator (msg.hwnd, hAccelTable, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
return 1;
UNREFERENCED_PARAMETER(hPrevInst);
UNREFERENCED_PARAMETER(lpszCmdLn);
}
LRESULT CALLBACK
MainWndProc(HWND hwnd, UINT uiMessage, WPARAM wParam, LPARAM lParam)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
POINT pos;
static HMENU hPopupMenu;
switch (uiMessage) {
//
// Someone clicked the icon
//
case WM_NOTIFY_ICON:
switch (lParam) {
case WM_LBUTTONDBLCLK:
Tickets();
return 0L;
case WM_RBUTTONDOWN:
if (hPopupMenu) {
if (GetCursorPos(&pos)) {
if (TrackPopupMenu(hPopupMenu,
TPM_RIGHTALIGN|TPM_LEFTBUTTON,
pos.x, pos.y,
0, hwnd, NULL) == 0)
Error(TEXT("TrackPopupMenuFailed: 0x%x"),
GetLastError());
}
}
return 0L;
}
break;
//
// Create a client windows
//
case WM_CREATE:
hPopupMenu = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_MENU));
if (!hPopupMenu)
Error(TEXT("LoadMenu failed %d"), GetLastError());
hPopupMenu = GetSubMenu(hPopupMenu, 0);
if (!hPopupMenu)
Error(TEXT("LoadMenu failed %d"), GetLastError());
(void) UpdateTray(hwnd);
//
// Start timer for watching the TGT
//
if (!SetTimer(hwnd, 1, KWIN_UPDATE_PERIOD, NULL)) {
ErrorExit(TEXT("SetTimer failed"));
}
return 0L;
//
// Update the tray icon
//
case WM_TIMER:
(void) UpdateTray(hwnd);
return(0L);
case WM_ENDSESSION:
return(0L);
//
// Close the main window. First set fKillAll to TRUE to
// terminate all threads. Then wait for the threads to exit
// before passing a close message to a default handler. If you
// don't wait for threads to terminate, process terminates
// with no chance for thread cleanup.
//
case WM_CLOSE:
exit:;
{
DeleteTray(hWnd);
KillTimer(hWnd, 1);
PostQuitMessage(0);
return 0L;
}
//
// Terminate the process
//
case WM_DESTROY:
PostQuitMessage(0);
return 0L;
//
// Handle the menu commands
//
case WM_COMMAND:
switch (LOWORD(wParam)) {
case ID_ABOUT:
About();
return 0L;
case ID_TICKETS:
Tickets();
return 0L;
case ID_PURGE:
PurgeCache();
return 0L;
case ID_EXIT:
goto exit;
}
}
return DefWindowProc(hwnd, uiMessage, wParam, lParam);
}
LPTSTR
GetStringRes(int id)
/*++
Routine Description:
Load a string from the resources
Arguments:
Return Value:
--*/
{
static TCHAR buffer[MAX_PATH];
buffer[0] = 0;
LoadString(GetModuleHandle (NULL), id, buffer, MAX_PATH);
return buffer;
}
LRESULT CALLBACK
AboutProc(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
static HFONT hfontDlg; // Font for dialog text
DWORD dwVerInfoSize; // Size of version information block
LPTSTR lpVersion; // String pointer to 'version' text
DWORD dwVerHnd = 0; // An 'ignored' parameter, always '0'
UINT uVersionLen;
DWORD wRootLen;
BOOL bRetCode;
int i;
TCHAR szFullPath[LONGSTRING];
TCHAR szResult[LONGSTRING];
TCHAR szGetName[LONGSTRING];
TCHAR szVersion[SHORTSTRING];
DWORD dwResult;
int resmap[6] = {
IDC_COMPANY,
IDC_FILEDESC,
IDC_PRODVER,
IDC_COPYRIGHT,
IDC_OSVERSION,
};
LPSTR lpstrVffInfo;
HANDLE hMem;
switch (message) {
case WM_INITDIALOG:
ShowWindow(hDlg, SW_HIDE);
hfontDlg = CreateFont(14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
VARIABLE_PITCH | FF_SWISS, TEXT(""));
GetModuleFileName(hInstance, szFullPath, TSIZE(szFullPath));
szFullPath[TSIZE(szFullPath) - 1] = 0;
//
// Now lets dive in and pull out the version information:
//
dwVerInfoSize = GetFileVersionInfoSize(szFullPath, &dwVerHnd);
if (dwVerInfoSize) {
hMem = GlobalAlloc(GMEM_MOVEABLE, dwVerInfoSize);
if (!hMem) {
ErrorExit(TEXT("Unable to allocate memory"));
}
lpstrVffInfo = GlobalLock(hMem);
if (!lpstrVffInfo) {
ErrorExit(TEXT("Unable to lock memory"));
}
GetFileVersionInfo(szFullPath, dwVerHnd, dwVerInfoSize, lpstrVffInfo);
//
// The below 'hex' value looks a little confusing, but
// essentially what it is, is the hexidecimal representation
// of a couple different values that represent the language
// and character set that we are wanting string values for.
// 040904E4 is a very common one, because it means:
// US English, Windows MultiLingual characterset
// Or to pull it all apart:
// 04------ = SUBLANG_ENGLISH_USA
// --09---- = LANG_ENGLISH
// ----04E4 = 1252 = Codepage for Windows:Multilingual
//
StrNCpy(szGetName, GetStringRes(IDS_VER_INFO_LANG), TSIZE(szGetName));
wRootLen = lstrlen(szGetName); // Save this position
//
// Set the title of the dialog
//
StrCatBuff(szGetName, TEXT("ProductName"), TSIZE(szGetName));
bRetCode = VerQueryValue((LPVOID)lpstrVffInfo,
(LPTSTR)szGetName,
(LPVOID)&lpVersion,
(UINT *)&uVersionLen);
StrNCpy(szResult, TEXT("About "), TSIZE(szResult));
StrCatBuff(szResult, lpVersion, TSIZE(szResult));
SetWindowText(hDlg, szResult);
//
// Walk through the dialog items that we want to replace
//
for (i = 0; i < 6; i++) {
GetDlgItemText(hDlg, resmap[i], szResult, TSIZE(szResult));
szGetName[wRootLen] = TEXT('\0');
StrCatBuff(szGetName, szResult, TSIZE(szGetName));
uVersionLen = 0;
lpVersion = NULL;
bRetCode = VerQueryValue((LPVOID)lpstrVffInfo,
(LPTSTR)szGetName,
(LPVOID)&lpVersion,
(UINT *)&uVersionLen);
if ( bRetCode && uVersionLen && lpVersion) {
// Replace dialog item text with version info
StrNCpy(szResult, lpVersion, TSIZE(szResult));
SetDlgItemText(hDlg, resmap[i], szResult);
} else {
dwResult = GetLastError();
_snwprintf(szResult, TSIZE(szResult),
TEXT("Error %lu"), dwResult);
SetDlgItemText (hDlg, resmap[i], szResult);
}
SendMessage(GetDlgItem(hDlg, resmap[i]), WM_SETFONT,
(WPARAM)hfontDlg,
TRUE);
}
GlobalUnlock(hMem);
GlobalFree(hMem);
}
else {
// No version information available
}
SendMessage(GetDlgItem (hDlg, IDC_LABEL), WM_SETFONT,
(WPARAM)hfontDlg,(LPARAM)TRUE);
_snwprintf(szVersion, TSIZE(szVersion),
TEXT("Microsoft Windows %u.%u (Build: %u)"),
osvers.dwMajorVersion,
osvers.dwMinorVersion,
osvers.dwBuildNumber);
szVersion[SHORTSTRING - 1] = 0;
SetWindowText(GetDlgItem(hDlg, IDC_OSVERSION), szVersion);
ShowWindow(hDlg, SW_SHOW);
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
case IDCANCEL:
EndDialog(hDlg, 0);
break;
}
}
return FALSE;
}
void
About(void)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
DialogBox(hInstance, MAKEINTRESOURCE(IDD_ABOUT), hWnd, AboutProc);
}
#define CheckDlgButtonFlag(b, f) \
CheckDlgButton(hDlg, b, (flags & f)?BST_CHECKED:BST_UNCHECKED)
VOID
ShowFlags(HWND hDlg, ULONG flags)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
CheckDlgButtonFlag(IDC_FORWARDABLE, KERB_TICKET_FLAGS_forwardable);
CheckDlgButtonFlag(IDC_FORWARDED, KERB_TICKET_FLAGS_forwarded);
CheckDlgButtonFlag(IDC_PROXIABLE, KERB_TICKET_FLAGS_proxiable);
CheckDlgButtonFlag(IDC_PROXY, KERB_TICKET_FLAGS_proxy);
CheckDlgButtonFlag(IDC_MAY_POSTDATE, KERB_TICKET_FLAGS_may_postdate);
CheckDlgButtonFlag(IDC_POSTDATED, KERB_TICKET_FLAGS_postdated);
CheckDlgButtonFlag(IDC_INVALID, KERB_TICKET_FLAGS_invalid);
CheckDlgButtonFlag(IDC_RENEWABLE, KERB_TICKET_FLAGS_renewable);
CheckDlgButtonFlag(IDC_INITIAL, KERB_TICKET_FLAGS_initial);
CheckDlgButtonFlag(IDC_HWAUTH, KERB_TICKET_FLAGS_hw_authent);
CheckDlgButtonFlag(IDC_PREAUTH, KERB_TICKET_FLAGS_pre_authent);
CheckDlgButtonFlag(IDC_OK_AS_DELEGATE, KERB_TICKET_FLAGS_ok_as_delegate);
}
LPTSTR
ETypeString(
int enctype
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
#ifndef NO_CRYPTDLL
static PCRYPTO_SYSTEM pcsSystem;
static TCHAR buf[12] = {0};
if (pCDLocateCSystem(enctype, &pcsSystem) == S_OK)
return pcsSystem->Name;
else {
_snwprintf(buf, TSIZE(buf), TEXT("etype %d"), enctype);
buf[11] = 0;
return buf;
}
#else
static TCHAR buf[12];
switch (enctype) {
case KERB_ETYPE_NULL:
return TEXT("NULL");
break;
case KERB_ETYPE_DES_CBC_CRC:
return TEXT("Kerberos DES-CBC-CRC");
break;
case KERB_ETYPE_DES_CBC_MD5:
return TEXT("Kerberos DES-CBC-MD5");
break;
case KERB_ETYPE_RC4_MD4:
return TEXT("RSADSI RC4-MD4");
break;
case KERB_ETYPE_RC4_PLAIN2:
return TEXT("RSADSI RC4-PLAIN");
break;
case KERB_ETYPE_RC4_LM:
return TEXT("RSADSI RC4-LM");
break;
case KERB_ETYPE_DES_PLAIN:
return TEXT("Kerberos DES-Plain");
break;
#ifdef KERB_ETYPE_RC4_HMAC
case KERB_ETYPE_RC4_HMAC:
return TEXT("RSADSI RC4-HMAC");
break;
#endif
case KERB_ETYPE_RC4_PLAIN:
return TEXT("RSADSI RC4");
break;
#ifdef KERB_ETYPE_RC4_HMAC_EXP
case KERB_ETYPE_RC4_HMAC_EXP:
return TEXT("RSADSI RC4-HMAC(Export)");
break;
#endif
case KERB_ETYPE_RC4_PLAIN_EXP:
return TEXT("RSADSI RC4(Export)");
break;
case KERB_ETYPE_DES_CBC_MD5_EXP:
return TEXT("Kerberos DES-CBC-MD5-EXP(Export)");
break;
case KERB_ETYPE_DES_PLAIN_EXP:
return TEXT("Kerberos DES-Plain(Export)");
break;
default:
_snwprintf(buf, TSIZE(buf), TEXT("etype %d"), enctype);
buf[11] = 0;
return buf;
break;
}
#endif
}
LPTSTR
TimeString(TimeStamp ConvertTime)
/*++
Routine Description:
Convert a TimeStamp into something readable
Arguments:
Return Value:
--*/
{
SYSTEMTIME SystemTime;
FILETIME LocalFileTime;
static TCHAR buf[LONGSTRING];
if (ConvertTime.HighPart == 0x7FFFFFFF &&
ConvertTime.LowPart == 0xFFFFFFFF) {
return(GetStringRes(IDS_INFINITE));
}
if (FileTimeToLocalFileTime(
(PFILETIME) &ConvertTime,
&LocalFileTime) &&
FileTimeToSystemTime(
&LocalFileTime,
&SystemTime)) {
_snwprintf(buf, TSIZE(buf), ftime_default_fmt,
SystemTime.wMonth,
SystemTime.wDay,
SystemTime.wYear,
SystemTime.wHour,
SystemTime.wMinute);
buf[TSIZE(buf)-1] = 0;
}
else
return(GetStringRes(IDS_INVALID));
return(buf);
}
DLGTEMPLATE * WINAPI
DoLockDlgRes(LPCTSTR lpszResName)
/*++
Routine Description:
loads and locks a dialog template resource
Arguments:
lpszResName - name of the resource
Return Value:
Returns the address of the locked resource.
--*/
{
HRSRC hrsrc;
HGLOBAL hglb;
DLGTEMPLATE *pDlg;
hrsrc = FindResource(NULL, lpszResName, RT_DIALOG);
if (!hrsrc) {
Error(TEXT("Unable to locate resource '%s'"), lpszResName);
ExitProcess(0);
}
hglb = LoadResource(hInstance, hrsrc);
if (!hglb) {
Error(TEXT("Unable to load resource '%s'"), lpszResName);
ExitProcess(0);
}
pDlg = (DLGTEMPLATE *)LockResource(hglb);
if (!pDlg) {
Error(TEXT("Unable to lock resource '%s'"), lpszResName);
ExitProcess(0);
}
return pDlg;
}
void
PurgeCache(void)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
KERB_PURGE_TKT_CACHE_REQUEST CacheRequest;
PVOID Response;
ULONG ResponseSize;
NTSTATUS Status, SubStatus;
memset(&CacheRequest, 0, sizeof(CacheRequest));
//
// Purge all tickets in the cache
//
CacheRequest.MessageType = KerbPurgeTicketCacheMessage;
Status = LsaCallAuthenticationPackage(LogonHandle,
PackageId,
&CacheRequest,
sizeof(CacheRequest),
&Response,
&ResponseSize,
&SubStatus);
if (SEC_SUCCESS(Status) && SEC_SUCCESS(SubStatus)) {
ShowMessage(MB_ICONINFORMATION, GetStringRes(IDS_PURGED));
}
else {
Error(TEXT("Failed to purge ticket cache - 0x%x"), Status);
}
if (Response != NULL) {
LsaFreeReturnBuffer(Response);
}
}
HTREEITEM
AddOneItem(
HTREEITEM hParent,
LPTSTR szText,
HTREEITEM hInsAfter,
int iImage,
HWND hwndTree,
LPARAM lParam
)
/*++
Routine Description:
Add the item to the specified TreeView
Arguments:
Return Value:
--*/
{
HTREEITEM hItem;
TV_ITEM tvI;
TV_INSERTSTRUCT tvIns;
tvI.mask = TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_PARAM;
tvI.pszText = szText;
tvI.cchTextMax = lstrlen(szText);
tvI.lParam = lParam;
tvI.iImage = iImage;
tvI.iSelectedImage = iImage;
tvIns.item = tvI;
tvIns.hInsertAfter = hInsAfter;
tvIns.hParent = hParent;
hItem = TreeView_InsertItem(hwndTree, &tvIns);
return(hItem);
}
HTREEITEM
FindDomainByName(LPTSTR name)
/*++
Routine Description:
Find the tree for the specified Domain
Arguments:
Return Value:
--*/
{
HTREEITEM dom = NULL;
TVITEM item;
TCHAR buf[LONGSTRING];
dom = TreeView_GetRoot(hWndUsers);
if (!dom)
return NULL;
do {
item.mask = TVIF_TEXT;
item.pszText = buf;
item.cchTextMax = sizeof(buf);
item.hItem = dom;
if (TreeView_GetItem(hWndUsers, &item)) {
if (wcscmp(name, buf) == 0) {
return dom;
}
}
} while (dom = TreeView_GetNextSibling(hWndUsers, dom));
return NULL;
}
HTREEITEM
AddDomain(
LPTSTR name
)
/*++
Routine Description:
Add the named Domain to the tree
Arguments:
Return Value:
--*/
{
HTREEITEM hItem;
if (!(hItem = FindDomainByName(name))) {
hItem = AddOneItem(NULL, _wcsdup(name), TVI_ROOT,
domain_icon, hWndUsers, 0);
}
return(hItem);
}
HTREEITEM
FindTicketByName(HTREEITEM lip, LPTSTR name)
/*++
Routine Description:
Find a ticket by name in the tree
Arguments:
Return Value:
--*/
{
HTREEITEM tick = NULL;
TVITEM item;
TCHAR buf[LONGSTRING];
tick = TreeView_GetChild(hWndUsers, lip);
if (!tick)
return NULL;
do {
item.mask = TVIF_TEXT;
item.pszText = buf;
item.cchTextMax = sizeof(buf);
item.hItem = tick;
if (TreeView_GetItem(hWndUsers, &item)) {
if (wcscmp(name, buf) == 0) {
return tick;
}
}
} while (tick = TreeView_GetNextSibling(hWndUsers, tick));
return NULL;
}
HTREEITEM
AddTicket(
HTREEITEM dom,
LPTSTR name,
int idx,
LPARAM lParam
)
/*++
Routine Description:
Add a ticket to the domain branch.
Arguments:
Return Value:
--*/
{
HTREEITEM hItem;
hItem = AddOneItem(dom, name, TVI_SORT, idx, hWndUsers, lParam);
TreeView_Expand(hWndUsers, dom, TVE_EXPAND);
return(hItem);
}
void
ShowTicket(
HWND hDlg,
PKERB_TICKET_CACHE_INFO tix,
int i,
BOOL ShowExpiredTickets
)
/*++
Routine Description:
Updates a Ticket for display
Arguments:
Return Value:
--*/
{
TCHAR sname[LONGSTRING];
HTREEITEM dom, tick;
FILETIME CurrentFileTime;
LARGE_INTEGER Quad;
long dt = 0L;
memset(sname, 0, sizeof(sname));
//
// Calculate ticket lifetime
//
GetSystemTimeAsFileTime(&CurrentFileTime);
Quad.LowPart = CurrentFileTime.dwLowDateTime;
Quad.HighPart = CurrentFileTime.dwHighDateTime;
dt = (long)((tix->EndTime.QuadPart - Quad.QuadPart) / TPS);
//
// Only display valid tickets
//
if (dt > 0 || ShowExpiredTickets)
{
//
// Add realm to tree control
//
swprintf(sname, TEXT("%wZ"), &tix->RealmName);
dom = AddDomain(sname);
//
// Add ticket under realm
//
swprintf(sname, TEXT("%wZ"), &tix->ServerName);
tick = AddTicket(dom, sname, GetIconIndex(dt), (LPARAM)tix);
//
// Look for initial TGT
//
if (tix->TicketFlags & KERB_TICKET_FLAGS_initial)
tgt = tick;
}
}
void
DisplayCreds(
HWND hDlg
)
/*++
Routine Description:
Get the list of tickets to display
Arguments:
Return Value:
--*/
{
KERB_QUERY_TKT_CACHE_REQUEST CacheRequest;
PKERB_RETRIEVE_TKT_RESPONSE TicketEntry = NULL;
PKERB_EXTERNAL_TICKET Ticket;
NTSTATUS Status, SubStatus;
ULONG ResponseSize;
DWORD i;
DLGTABHDR *pHdr;
TCITEM tie;
DWORD dwDlgBase = GetDialogBaseUnits();
int cxMargin = LOWORD(dwDlgBase) / 4;
int cyMargin = HIWORD(dwDlgBase) / 8;
RECT rcTab;
static TCHAR princ[LONGSTRING];
pHdr = (DLGTABHDR *) LocalAlloc(LPTR|LMEM_ZEROINIT, sizeof(DLGTABHDR));
if (!pHdr)
ErrorExit(TEXT("Unable to allocate memory"));
//
// Save a pointer to the DLGHDR structure.
//
SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG_PTR)pHdr);
pHdr->hwndTab = GetDlgItem(hDlg, IDC_TAB_ATTRIBUTES);
hWndUsers = GetDlgItem(hDlg, IDC_TICKETS);
//
// Associate the image list with the tree view control.
//
//TreeView_SetImageList(hWndUsers, himl, TVSIL_NORMAL);
//
// Add a tab for each of the three child dialog boxes.
//
tie.mask = TCIF_TEXT | TCIF_IMAGE;
tie.iImage = -1;
tie.pszText = GetStringRes(IDS_LNAMES);
TabCtrl_InsertItem(pHdr->hwndTab, PPAGE_NAMES, &tie);
tie.pszText = GetStringRes(IDS_LTIMES);
TabCtrl_InsertItem(pHdr->hwndTab, PPAGE_TIMES, &tie);
tie.pszText = GetStringRes(IDS_LFLAGS);
TabCtrl_InsertItem(pHdr->hwndTab, PPAGE_FLAGS, &tie);
tie.pszText = GetStringRes(IDS_LENCTYPE);
TabCtrl_InsertItem(pHdr->hwndTab, PPAGE_ETYPES, &tie);
//
// Lock the resources for the three child dialog boxes.
//
pHdr->apRes[PPAGE_NAMES] = DoLockDlgRes(MAKEINTRESOURCE(IDD_PROP_NAMES));
pHdr->apRes[PPAGE_TIMES] = DoLockDlgRes(MAKEINTRESOURCE(IDD_PROP_TIMES));
pHdr->apRes[PPAGE_FLAGS] = DoLockDlgRes(MAKEINTRESOURCE(IDD_PROP_TKT_FLAGS));
pHdr->apRes[PPAGE_ETYPES] = DoLockDlgRes(MAKEINTRESOURCE(IDD_PROP_ENCTYPES));
//
// Determine the bounding rectangle for all child dialog boxes.
//
SetRectEmpty(&rcTab);
for (i = 0; i < C_PAGES; i++) {
if (pHdr->apRes[i]->cx > rcTab.right)
rcTab.right = pHdr->apRes[i]->cx;
if (pHdr->apRes[i]->cy > rcTab.bottom)
rcTab.bottom = pHdr->apRes[i]->cy;
}
rcTab.right = rcTab.right * LOWORD(dwDlgBase) / 4;
rcTab.bottom = rcTab.bottom * HIWORD(dwDlgBase) / 8;
//
// Calculate how large to make the tab control, so
// the display area can accommodate all the child dialog boxes.
//
TabCtrl_AdjustRect(pHdr->hwndTab, TRUE, &rcTab);
OffsetRect(&rcTab, cxMargin - rcTab.left,
cyMargin - rcTab.top);
//
// Calculate the display rectangle.
//
CopyRect(&pHdr->rcDisplay, &rcTab);
TabCtrl_AdjustRect(pHdr->hwndTab, FALSE, &pHdr->rcDisplay);
//
// Get the User's TGT for the client name
//
CacheRequest.MessageType = KerbRetrieveTicketMessage;
CacheRequest.LogonId.LowPart = 0;
CacheRequest.LogonId.HighPart = 0;
Status = LsaCallAuthenticationPackage(LogonHandle,
PackageId,
&CacheRequest,
sizeof(CacheRequest),
(PVOID *) &TicketEntry,
&ResponseSize,
&SubStatus);
if (SEC_SUCCESS(Status) && SEC_SUCCESS(SubStatus)) {
//
// Got the cname/crealm format it and display
//
Ticket = &(TicketEntry->Ticket);
memset(princ, 0, sizeof(princ));
swprintf(princ, TEXT("%wZ@%wZ"),
&Ticket->ClientName->Names[0],
&Ticket->DomainName);
SetDlgItemText(hDlg, IDC_PRINC_LABEL, princ);
}
else {
//
// No TGT, clear out the client name
//
SetDlgItemText(hDlg, IDC_PRINC_LABEL,
GetStringRes(IDS_NO_NET_CREDS));
SetDlgItemText(hDlg, IDC_PRINC_START,
TEXT(""));
if (TicketEntry)
LsaFreeReturnBuffer(TicketEntry);
return;
}
//
// Done with the TGT
//
if (TicketEntry) {
LsaFreeReturnBuffer(TicketEntry);
TicketEntry = NULL;
}
//
// Get the list of cached tickets
//
CacheRequest.MessageType = KerbQueryTicketCacheMessage;
CacheRequest.LogonId.LowPart = 0;
CacheRequest.LogonId.HighPart = 0;
Status = LsaCallAuthenticationPackage(LogonHandle,
PackageId,
&CacheRequest,
sizeof(CacheRequest),
(PVOID *) &pHdr->Tickets,
&ResponseSize,
&SubStatus);
if (SEC_SUCCESS(Status) && SEC_SUCCESS(SubStatus)) {
for (i = 0; i < pHdr->Tickets->CountOfTickets; i++) {
ShowTicket(hDlg, &pHdr->Tickets->Tickets[i], i, FALSE);
}
}
//
// Position the selection on the initial TGT
//
if (tgt)
TreeView_SelectItem(hWndUsers, tgt);
PropsheetDisplay(hDlg);
SelectTicket(hDlg);
}
LRESULT CALLBACK
PropSheetProc(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
DLGTABHDR *pHdr;
HWND hwndParent = GetParent(hDlg);
hwndParent = GetParent(hwndParent);
pHdr = (DLGTABHDR *) GetWindowLongPtr(hwndParent, GWLP_USERDATA);
switch (message) {
case WM_INITDIALOG:
SetWindowPos(hDlg, HWND_TOP,
pHdr->rcDisplay.left, pHdr->rcDisplay.top,
0, 0, SWP_NOSIZE);
return TRUE;
}
return FALSE;
}
void
PropsheetDisplay(HWND hDlg)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
DLGTABHDR *pHdr = (DLGTABHDR *) GetWindowLongPtr(hDlg, GWLP_USERDATA);
int iSel = TabCtrl_GetCurSel(pHdr->hwndTab);
//
// Destroy the current child dialog box, if any.
//
if (pHdr->hwndDisplay != NULL)
DestroyWindow(pHdr->hwndDisplay);
//
// Create the new child dialog box.
//
pHdr->hwndDisplay = CreateDialogIndirect(hInstance, pHdr->apRes[iSel],
pHdr->hwndTab, PropSheetProc);
}
INT
UnparseExternalName(
PKERB_EXTERNAL_NAME iName,
PUNICODE_STRING *np
)
/*++
Routine Description:
Format the name list into a "/" seperated name for display.
Arguments:
Return Value:
--*/
{
int len, cnt;
PUNICODE_STRING name;
for (len = 0, cnt = 0; cnt < iName->NameCount; cnt++) {
len += iName->Names[cnt].Length;
if ((cnt + 1) < iName->NameCount)
len += 2;
}
name = malloc(sizeof(UNICODE_STRING));
if (!name)
return -1;
name->Buffer = malloc(len + 2);
if (!name->Buffer) {
free(name);
return -1;
}
name->Length = 0;
name->MaximumLength = len+2;
memset(name->Buffer, 0, len + 2);
for (cnt = 0; cnt < iName->NameCount; cnt++) {
wcsncat(name->Buffer, iName->Names[cnt].Buffer, iName->Names[cnt].Length/2);
name->Length += iName->Names[cnt].Length;
if ((cnt + 1) < iName->NameCount) {
wcsncat(name->Buffer, L"/", 1);
name->Length += 2;
}
}
*np = name;
return 0;
}
VOID
FreeUnicodeString(
PUNICODE_STRING ustr
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
if (ustr) {
free(ustr->Buffer);
free(ustr);
}
}
void
SelectTicket(HWND hDlg)
/*++
Routine Description:
Respond to the user clicking on a ticket in the tree
Arguments:
Return Value:
--*/
{
DLGTABHDR *pHdr = (DLGTABHDR *) GetWindowLongPtr(hDlg, GWLP_USERDATA);
int iSel = TabCtrl_GetCurSel(pHdr->hwndTab);
HTREEITEM hItem = TreeView_GetSelection(hWndUsers);
TVITEM item;
TCHAR sname[LONGSTRING];
PKERB_TICKET_CACHE_INFO tix;
FILETIME CurrentFileTime;
LARGE_INTEGER Quad;
long dt = 0L;
//
// No selection
//
if (!hItem)
return;
item.hItem = hItem;
item.mask = TVIF_PARAM;
item.lParam = 0;
TreeView_GetItem(hWndUsers, &item);
//
// No info on the leaf
//
if (!item.lParam) {
SetDlgItemText(hDlg, IDC_SERVICE_PRINC_LABEL,
GetStringRes(IDS_DOMAIN));
SetDlgItemText(hDlg, IDC_SERVICE_PRINC, TEXT(""));
FillinTicket(hDlg);
return;
}
SetDlgItemText(hDlg, IDC_SERVICE_PRINC_LABEL,
GetStringRes(IDS_SERVICE_PRINCIPAL));
tix = (PKERB_TICKET_CACHE_INFO)item.lParam;
//
// Calculate lifetime
//
GetSystemTimeAsFileTime(&CurrentFileTime);
Quad.LowPart = CurrentFileTime.dwLowDateTime;
Quad.HighPart = CurrentFileTime.dwHighDateTime;
dt = (long)((tix->EndTime.QuadPart - Quad.QuadPart) / TPS);
if (dt > 0) {
swprintf(sname, TEXT("%wZ@%wZ"),
&tix->ServerName,
&tix->RealmName);
SetDlgItemText(hDlg, IDC_SERVICE_PRINC, sname);
}
else {
SetDlgItemText(hDlg, IDC_SERVICE_PRINC_LABEL,
GetStringRes(IDS_EXPIRED));
SetDlgItemText(hDlg, IDC_SERVICE_PRINC,
TEXT(""));
}
FillinTicket(hDlg);
}
void
FillinTicket(HWND hDlg)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
PKERB_TICKET_CACHE_INFO tix;
DLGTABHDR *pHdr = (DLGTABHDR *) GetWindowLongPtr(hDlg, GWLP_USERDATA);
int iSel = TabCtrl_GetCurSel(pHdr->hwndTab);
HTREEITEM hItem = TreeView_GetSelection(hWndUsers);
TVITEM item;
PKERB_RETRIEVE_TKT_REQUEST TicketRequest;
ULONG ResponseSize;
NTSTATUS Status, SubStatus;
PKERB_EXTERNAL_TICKET ticket;
int sz;
TCHAR sname[LONGSTRING];
PUNICODE_STRING svc;
if (!hItem)
return;
item.hItem = hItem;
item.mask = TVIF_PARAM;
item.lParam = 0;
TreeView_GetItem(hWndUsers, &item);
switch(iSel) {
case PPAGE_NAMES:
SetDlgItemText(pHdr->hwndDisplay, IDC_SERVICENAME,
TEXT(""));
SetDlgItemText(pHdr->hwndDisplay, IDC_TARGETNAME,
TEXT(""));
#if 0
SetDlgItemText(pHdr->hwndDisplay, IDC_CLIENTNAME,
TEXT(""));
#endif
break;
case PPAGE_TIMES:
SetDlgItemText(pHdr->hwndDisplay, IDC_STARTTIME,
TEXT(""));
SetDlgItemText(pHdr->hwndDisplay, IDC_ENDTIME,
TEXT(""));
SetDlgItemText(pHdr->hwndDisplay, IDC_RENEW_UNTIL,
TEXT(""));
break;
case PPAGE_ETYPES:
SetDlgItemText(pHdr->hwndDisplay, IDC_TKT_ENCTYPE,
TEXT(""));
SetDlgItemText(pHdr->hwndDisplay, IDC_KEY_ENCTYPE,
TEXT(""));
break;
case PPAGE_FLAGS:
ShowFlags(pHdr->hwndDisplay, 0);
break;
}
if (!item.lParam) {
return;
}
//
// Retrieve full ticket for properties
//
tix = (PKERB_TICKET_CACHE_INFO)item.lParam;
swprintf(sname, TEXT("%wZ@%wZ"),
&tix->ServerName,
&tix->RealmName);
sz = sizeof(WCHAR)*(wcslen(sname) + 1);
TicketRequest = LocalAlloc(LMEM_ZEROINIT,
sizeof(KERB_RETRIEVE_TKT_REQUEST) + sz);
if (!TicketRequest)
ErrorExit(TEXT("Unable to allocate memory"));
TicketRequest->MessageType = KerbRetrieveEncodedTicketMessage;
TicketRequest->LogonId.LowPart = 0;
TicketRequest->LogonId.HighPart = 0;
TicketRequest->TargetName.Length = wcslen(sname) * sizeof(WCHAR);
TicketRequest->TargetName.MaximumLength =
TicketRequest->TargetName.Length + sizeof(WCHAR);
TicketRequest->TargetName.Buffer = (LPWSTR) (TicketRequest + 1);
wcsncpy(TicketRequest->TargetName.Buffer, sname, wcslen(sname));
TicketRequest->CacheOptions = KERB_RETRIEVE_TICKET_USE_CACHE_ONLY;
TicketRequest->EncryptionType = 0L;
TicketRequest->TicketFlags = 0L;
Status = LsaCallAuthenticationPackage(LogonHandle,
PackageId,
TicketRequest,
(sizeof(KERB_RETRIEVE_TKT_REQUEST) + sz),
(PVOID *)&ticket,
&ResponseSize,
&SubStatus);
//
// Don't need the request buffer anymore
//
LocalFree(TicketRequest);
if (SEC_SUCCESS(Status) && SEC_SUCCESS(SubStatus)) {
switch(iSel) {
case PPAGE_NAMES:
//
// Get the service name for the ticket
//
if (ticket->ServiceName && ticket->DomainName.Length &&
!UnparseExternalName(ticket->ServiceName, &svc)) {
swprintf(sname, TEXT("%wZ@%wZ"),
svc,
&ticket->DomainName);
SetDlgItemText(pHdr->hwndDisplay, IDC_SERVICENAME,
sname);
FreeUnicodeString(svc);
}
#if 0
//
// Get the client name from the buffer
//
// Bug - client name is wrong from the kerberos ssp. Use
// the TGT client name.
//
if (ticket->ClientName && ticket->DomainName.Length &&
!UnparseExternalName(ticket->ClientName, &svc)) {
swprintf(sname, TEXT("%wZ@%wZ"),
svc,
&ticket->DomainName);
SetDlgItemText(pHdr->hwndDisplay, IDC_CLIENTNAME,
sname);
FreeUnicodeString(svc);
}
#endif
//
// Get the requested target name for the ticket
//
if (ticket->TargetName && ticket->TargetDomainName.Length &&
!UnparseExternalName(ticket->TargetName, &svc)) {
swprintf(sname, TEXT("%wZ@%wZ"),
svc,
&ticket->TargetDomainName);
SetDlgItemText(pHdr->hwndDisplay, IDC_TARGETNAME,
sname);
FreeUnicodeString(svc);
}
break;
case PPAGE_TIMES:
//
// Display the ticket times
//
SetDlgItemText(pHdr->hwndDisplay, IDC_STARTTIME,
TimeString(tix->StartTime));
SetDlgItemText(pHdr->hwndDisplay, IDC_ENDTIME,
TimeString(tix->EndTime));
if (tix->TicketFlags & KERB_TICKET_FLAGS_renewable) {
SetDlgItemText(pHdr->hwndDisplay, IDC_RENEW_UNTIL,
TimeString(tix->RenewTime));
ShowWindow(GetDlgItem(pHdr->hwndDisplay, IDC_RENEW_UNTIL),
SW_SHOW);
}
else {
ShowWindow(GetDlgItem(pHdr->hwndDisplay, IDC_RENEW_UNTIL),
SW_HIDE);
}
break;
case PPAGE_ETYPES:
//
// Display ticket and session key enctype
//
SetDlgItemText(pHdr->hwndDisplay, IDC_TKT_ENCTYPE,
ETypeString(tix->EncryptionType));
SetDlgItemText(pHdr->hwndDisplay, IDC_KEY_ENCTYPE,
ETypeString(ticket->SessionKey.KeyType));
break;
case PPAGE_FLAGS:
//
// Display the ticket flags
//
ShowFlags(pHdr->hwndDisplay, tix->TicketFlags);
break;
}
LsaFreeReturnBuffer(ticket);
}
}
LRESULT CALLBACK
TicketsProc(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
LPNMHDR nm;
DLGTABHDR *pHdr;
switch (message) {
case WM_INITDIALOG:
DisplayCreds(hDlg);
ShowWindow(hDlg, SW_SHOW);
return TRUE;
case WM_NOTIFY: {
nm = (LPNMHDR)lParam;
switch (nm->code) {
case TCN_SELCHANGING:
return FALSE;
case TCN_SELCHANGE:
PropsheetDisplay(hDlg);
FillinTicket(hDlg);
return TRUE;
case TVN_SELCHANGED:
SelectTicket(hDlg);
break;
}
}
break;
case WM_SYSCOMMAND:
switch (wParam) {
case SC_CLOSE:
goto close_tix;
}
break;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDC_CLOSE:
close_tix:
pHdr = (DLGTABHDR *) GetWindowLongPtr(hDlg, GWLP_USERDATA);
if (pHdr->hwndDisplay != NULL)
DestroyWindow(pHdr->hwndDisplay);
DestroyWindow(hDlgTickets);
LsaFreeReturnBuffer(pHdr->Tickets);
LocalFree(pHdr);
hDlgTickets = NULL;
break;
}
break;
}
return FALSE;
}
void
Tickets(void)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
if (!hDlgTickets)
hDlgTickets = CreateDialog(hInstance,
MAKEINTRESOURCE(IDD_TICKETS),
hWnd,
TicketsProc);
else {
ShowWindow(hDlgTickets, SW_SHOW);
SetForegroundWindow(hDlgTickets);
}
}