Path: blob/main/crypto/krb5/src/windows/leash/Leash.cpp
34907 views
//**************************************************************************1// File: Leash.cpp2// By: Arthur David Leather3// Created: 12/02/984// Copyright: 1998 Massachusetts Institute of Technology - All rights5// reserved.6//7// Description: CPP file for Leash.h. Contains variables and functions8// for Leash9//10// History:11//12// MM/DD/YY Inits Description of Change13// 12/02/98 ADL Original14//**************************************************************************1516#include "stdafx.h"17#include "Leash.h"1819#include "MainFrm.h"20#include "LeashDoc.h"21#include "LeashView.h"22#include "LeashAboutBox.h"2324#include "reminder.h"25#include <leasherr.h>26#include "lglobals.h"27#include <krb5.h>28#include <com_err.h>2930#include <errno.h>3132#include <afxwin.h>3334#ifdef _DEBUG35#define new DEBUG_NEW36#undef THIS_FILE37static char THIS_FILE[] = __FILE__;38#endif3940TicketInfoWrapper ticketinfo;4142HWND CLeashApp::m_hProgram = 0;43HINSTANCE CLeashApp::m_hLeashDLL = 0;44HINSTANCE CLeashApp::m_hComErr = 0;45HINSTANCE CLeashApp::m_hKrb5DLL = 0;46HINSTANCE CLeashApp::m_hKrb5ProfileDLL= 0;47HINSTANCE CLeashApp::m_hPsapi = 0;48HINSTANCE CLeashApp::m_hToolHelp32 = 0;49krb5_context CLeashApp::m_krbv5_context = 0;50profile_t CLeashApp::m_krbv5_profile = 0;51HINSTANCE CLeashApp::m_hKrbLSA = 0;52int CLeashApp::m_useRibbon = TRUE;53BOOL CLeashApp::m_bUpdateDisplay = FALSE;5455/////////////////////////////////////////////////////////////////////////////56// CLeashApp575859BEGIN_MESSAGE_MAP(CLeashApp, CWinApp)60//{{AFX_MSG_MAP(CLeashApp)61//}}AFX_MSG_MAP62// Standard file based document commands63ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)64ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)65END_MESSAGE_MAP()6667/////////////////////////////////////////////////////////////////////////////68// CLeashApp construction69CLeashApp::CLeashApp()70{71m_krbv5_context = NULL;72m_krbv5_profile = NULL;73// TODO: add construction code here,74// Place all significant initialization in InitInstance7576// Memory may not be initialized to zeros (in debug)77memset(&ticketinfo, 0, sizeof(ticketinfo));7879ticketinfo.lockObj = CreateMutex(NULL, FALSE, NULL);8081#ifdef USE_HTMLHELP82#if _MSC_VER >= 130083EnableHtmlHelp();84#endif85#endif86}8788CLeashApp::~CLeashApp()89{90if ( m_krbv5_context ) {91pkrb5_free_context(m_krbv5_context);92m_krbv5_context = NULL;93}9495if ( m_krbv5_profile ) {96pprofile_release(m_krbv5_profile);97m_krbv5_profile = NULL;98}99100#ifdef COMMENT101/* Do not free the locking objects. Doing so causes an invalid handle access */102CloseHandle(ticketinfo.lockObj);103#endif104AfxFreeLibrary(m_hLeashDLL);105AfxFreeLibrary(m_hKrb5DLL);106AfxFreeLibrary(m_hKrb5ProfileDLL);107AfxFreeLibrary(m_hPsapi);108AfxFreeLibrary(m_hToolHelp32);109AfxFreeLibrary(m_hKrbLSA);110#ifdef DEBUG111_CrtDumpMemoryLeaks();112#endif113}114115/////////////////////////////////////////////////////////////////////////////116// The one and only CLeashApp object117118CLeashApp theApp;119120/////////////////////////////////////////////////////////////////////////////121// CLeashApp initialization122123void CLeashApp::ParseParam (LPCTSTR lpszParam,BOOL bFlag,BOOL bLast)124{125//CCommandLineInfo::ParseParam(lpszParam, bFlag, bLast) ;126}127128extern "C" {129LRESULT WINAPI LeashWindowProc( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)130{131switch ( Msg ) {132case WM_SYSCOMMAND:133if (SC_CLOSE == (wParam & 0xfff0)) {134wParam = (wParam & ~0xfff0) | SC_MINIMIZE;135}136break;137}138return ::DefWindowProc(hWnd, Msg, wParam, lParam);139}140}141142BOOL CLeashApp::InitInstance()143{144#ifdef DEBUG145_CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );146_CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT );147_CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );148_CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT );149150int tmp = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG);151_CrtSetDbgFlag( tmp | _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);152#endif153AfxOleInit();154// NOTE: Not used at this time155/// Set LEASH_DLL to the path where the Leash.exe is156char modulePath[MAX_PATH];157krb5_error_code code;158DWORD result = GetModuleFileName(AfxGetInstanceHandle(), modulePath, MAX_PATH);159ASSERT(result);160161char* pPath = modulePath + strlen(modulePath) - 1;162while (*pPath != '\\')163{164*pPath = 0;165pPath--;166}167strcat(modulePath, LEASH_HELP_FILE);168m_helpFile = modulePath;169170///strcat(dllFile, LEASH_DLL);171///m_leashDLL = dllFile;172173BOOL autoInit = FALSE;174HWND hMsg = GetForegroundWindow();175if (!InitDLLs())176return FALSE; //exit program, can't load LEASHDLL177code = pkrb5_init_context(&m_krbv5_context);178if (code) {179// @TODO: report error180return FALSE;181}182183// Check for args (switches)184LPCTSTR exeFile = __targv[0];185for (int argi = 1; argi < __argc; argi++) {186LPCTSTR optionParam = __targv[argi];187188if (!optionParam)189continue;190191if (*optionParam == '-' || *optionParam == '/')192{193if (0 == stricmp(optionParam+1, "kinit") ||1940 == stricmp(optionParam+1, "i"))195{196LSH_DLGINFO_EX ldi;197char username[64]="";198char realm[192]="";199int i=0, j=0;200if (WaitForSingleObject( ticketinfo.lockObj, INFINITE ) != WAIT_OBJECT_0)201throw("Unable to lock ticketinfo");202203LeashKRB5ListDefaultTickets(&ticketinfo.Krb5);204205if ( ticketinfo.Krb5.btickets && ticketinfo.Krb5.principal ) {206for (; ticketinfo.Krb5.principal[i] && ticketinfo.Krb5.principal[i] != '@'; i++)207{208username[i] = ticketinfo.Krb5.principal[i];209}210username[i] = '\0';211if (ticketinfo.Krb5.principal[i]) {212for (i++ ; ticketinfo.Krb5.principal[i] ; i++, j++)213{214realm[j] = ticketinfo.Krb5.principal[i];215}216}217realm[j] = '\0';218}219220LeashKRB5FreeTicketInfo(&ticketinfo.Krb5);221222ReleaseMutex(ticketinfo.lockObj);223224ldi.size = LSH_DLGINFO_EX_V1_SZ;225ldi.dlgtype = DLGTYPE_PASSWD;226ldi.title = "MIT Kerberos: Get Ticket";227ldi.username = username;228ldi.realm = realm;229ldi.dlgtype = DLGTYPE_PASSWD;230ldi.use_defaults = 1;231232if (!pLeash_kinit_dlg_ex(hMsg, &ldi))233{234MessageBox(hMsg, "There was an error getting tickets!",235"Error", MB_OK);236return FALSE;237}238return TRUE;239}240else if (0 == stricmp(optionParam+1, "destroy") ||2410 == stricmp(optionParam+1, "d"))242{243if (pLeash_kdestroy())244{245MessageBox(hMsg,246"There was an error destroying tickets!",247"Error", MB_OK);248return FALSE;249}250return TRUE;251}252else if (0 == stricmp(optionParam+1, "renew") ||2530 == stricmp(optionParam+1, "r"))254{255if (!pLeash_renew())256{257MessageBox(hMsg,258"There was an error renewing tickets!",259"Error", MB_OK);260return FALSE;261}262return TRUE;263}264else if (0 == stricmp(optionParam+1, "autoinit") ||2650 == stricmp(optionParam+1, "a"))266{267autoInit = TRUE;268}269else if (0 == stricmp(optionParam+1, "console") ||2700 == stricmp(optionParam+1, "c"))271{272FILE *dummy;273AllocConsole();274freopen_s(&dummy, "CONOUT$", "w", stderr);275freopen_s(&dummy, "CONOUT$", "w", stdout);276}277else if (0 == stricmp(optionParam+1, "noribbon"))278{279m_useRibbon = FALSE;280}281else282{283MessageBox(hMsg,284"'-kinit' or '-i' to perform ticket initialization (and exit)\n"285"'-renew' or '-r' to perform ticket renewal (and exit)\n"286"'-destroy' or '-d' to perform ticket destruction (and exit)\n"287"'-autoinit' or '-a' to perform automatic ticket initialization\n"288"'-console' or '-c' to attach a console for debugging\n",289"MIT Kerberos Error", MB_OK);290return FALSE;291}292}293else294{295MessageBox(hMsg,296"'-kinit' or '-i' to perform ticket initialization (and exit)\n"297"'-renew' or '-r' to perform ticket renewal (and exit)\n"298"'-destroy' or '-d' to perform ticket destruction (and exit)\n"299"'-autoinit' or '-a' to perform automatic ticket initialization\n",300"MIT Kerberos Error", MB_OK);301return FALSE;302}303}304305// Insure only one instance of Leash306if (!FirstInstance())307return FALSE;308309if (!CWinAppEx::InitInstance())310return FALSE;311312//register our unique wnd class name to find it later313WNDCLASS wndcls;314memset(&wndcls, 0, sizeof(WNDCLASS));315wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;316wndcls.lpfnWndProc = ::LeashWindowProc;317wndcls.hInstance = AfxGetInstanceHandle();318wndcls.hIcon = LoadIcon(IDR_MAINFRAME);319wndcls.hCursor = LoadCursor(IDC_ARROW);320wndcls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);321wndcls.lpszMenuName = NULL;322//now the wnd class name to find it323wndcls.lpszClassName = _T("LEASH.0WNDCLASS");324325//register the new class326if(!AfxRegisterClass(&wndcls))327{328TRACE("Class registration failed\n");329return FALSE;330}331332AfxEnableControlContainer();333334// Standard initialization335// If you are not using these features and wish to reduce the size336// of your final executable, you should remove from the following337// the specific initialization routines you do not need.338339#if _MSC_VER < 1300340#ifdef _AFXDLL341Enable3dControls(); // Call this when using MFC in a shared DLL342#else343Enable3dControlsStatic(); // Call this when linking to MFC statically344#endif345#endif346347// Registry key under which our settings are stored.348if (m_pszAppName)349free((void*)m_pszAppName);350m_pszAppName = _tcsdup("MIT Kerberos");351SetRegistryKey(_T("MIT"));352353LoadStdProfileSettings(); // Load standard INI file options (including MRU)354355// Register the application's document templates. Document templates356// serve as the connection between documents, frame windows and views.357358CSingleDocTemplate* pDocTemplate;359pDocTemplate = new CSingleDocTemplate(360IDR_MAINFRAME,361RUNTIME_CLASS(LeashDoc),362RUNTIME_CLASS(CMainFrame), // main SDI frame window363RUNTIME_CLASS(CLeashView));364AddDocTemplate(pDocTemplate);365366// Parse command line for standard shell commands, DDE, file open367CCommandLineInfo cmdInfo;368ParseCommandLine(cmdInfo);369370// Dispatch commands specified on the command line371if (!ProcessShellCommand(cmdInfo))372return FALSE;373374// Check to see if there are any tickets in the cache. If not and375// autoinitialization is enabled, display the initial tickets dialog.376{377if (WaitForSingleObject( ticketinfo.lockObj, INFINITE ) != WAIT_OBJECT_0)378throw("Unable to lock ticketinfo");379LeashKRB5ListDefaultTickets(&ticketinfo.Krb5);380BOOL b_autoinit = !ticketinfo.Krb5.btickets;381LeashKRB5FreeTicketInfo(&ticketinfo.Krb5);382ReleaseMutex(ticketinfo.lockObj);383384if (autoInit) {385if ( b_autoinit )386AfxBeginThread(InitWorker, m_pMainWnd->m_hWnd);387388IpAddrChangeMonitorInit(m_pMainWnd->m_hWnd);389}390}391392// The one and only window has been initialized, so show and update it.393m_pMainWnd->SetWindowText("MIT Kerberos");394m_pMainWnd->UpdateWindow();395m_pMainWnd->ShowWindow(SW_SHOW);396m_pMainWnd->SetForegroundWindow();397398ValidateConfigFiles();399400return TRUE;401}402403404/////////////////////////////////////////////////////////////////////////////405// CLeashApp commands406407// leash functions408DECL_FUNC_PTR(Leash_kdestroy);409DECL_FUNC_PTR(Leash_changepwd_dlg);410DECL_FUNC_PTR(Leash_changepwd_dlg_ex);411DECL_FUNC_PTR(Leash_kinit_dlg);412DECL_FUNC_PTR(Leash_kinit_dlg_ex);413DECL_FUNC_PTR(Leash_timesync);414DECL_FUNC_PTR(Leash_get_default_uppercaserealm);415DECL_FUNC_PTR(Leash_set_default_uppercaserealm);416DECL_FUNC_PTR(Leash_renew);417418FUNC_INFO leash_fi[] = {419MAKE_FUNC_INFO(Leash_kdestroy),420MAKE_FUNC_INFO(Leash_changepwd_dlg),421MAKE_FUNC_INFO(Leash_changepwd_dlg_ex),422MAKE_FUNC_INFO(Leash_kinit_dlg),423MAKE_FUNC_INFO(Leash_kinit_dlg_ex),424MAKE_FUNC_INFO(Leash_timesync),425MAKE_FUNC_INFO(Leash_get_default_uppercaserealm),426MAKE_FUNC_INFO(Leash_set_default_uppercaserealm),427MAKE_FUNC_INFO(Leash_renew),428END_FUNC_INFO429};430431// com_err functions432DECL_FUNC_PTR(error_message);433FUNC_INFO ce_fi[] = {434MAKE_FUNC_INFO(error_message),435END_FUNC_INFO436};437438// psapi functions439DECL_FUNC_PTR(GetModuleFileNameExA);440DECL_FUNC_PTR(EnumProcessModules);441442FUNC_INFO psapi_fi[] = {443MAKE_FUNC_INFO(GetModuleFileNameExA),444MAKE_FUNC_INFO(EnumProcessModules),445END_FUNC_INFO446};447448// toolhelp functions449DECL_FUNC_PTR(CreateToolhelp32Snapshot);450DECL_FUNC_PTR(Module32First);451DECL_FUNC_PTR(Module32Next);452453FUNC_INFO toolhelp_fi[] = {454MAKE_FUNC_INFO(CreateToolhelp32Snapshot),455MAKE_FUNC_INFO(Module32First),456MAKE_FUNC_INFO(Module32Next),457END_FUNC_INFO458};459460// krb5 functions461DECL_FUNC_PTR(krb5_cc_default_name);462DECL_FUNC_PTR(krb5_cc_set_default_name);463DECL_FUNC_PTR(krb5_get_default_config_files);464DECL_FUNC_PTR(krb5_free_config_files);465DECL_FUNC_PTR(krb5_free_context);466DECL_FUNC_PTR(krb5_get_default_realm);467DECL_FUNC_PTR(krb5_free_default_realm);468DECL_FUNC_PTR(krb5_init_context);469DECL_FUNC_PTR(krb5_cc_default);470DECL_FUNC_PTR(krb5_parse_name);471DECL_FUNC_PTR(krb5_free_principal);472DECL_FUNC_PTR(krb5_cc_close);473DECL_FUNC_PTR(krb5_cc_get_principal);474DECL_FUNC_PTR(krb5_build_principal);475DECL_FUNC_PTR(krb5_c_random_make_octets);476DECL_FUNC_PTR(krb5_get_init_creds_password);477DECL_FUNC_PTR(krb5_free_cred_contents);478DECL_FUNC_PTR(krb5_cc_resolve);479DECL_FUNC_PTR(krb5_unparse_name);480DECL_FUNC_PTR(krb5_free_unparsed_name);481DECL_FUNC_PTR(krb5_cc_destroy);482DECL_FUNC_PTR(krb5_cccol_cursor_new);483DECL_FUNC_PTR(krb5_cccol_cursor_free);484DECL_FUNC_PTR(krb5_cccol_cursor_next);485DECL_FUNC_PTR(krb5_cc_start_seq_get);486DECL_FUNC_PTR(krb5_cc_next_cred);487DECL_FUNC_PTR(krb5_cc_end_seq_get);488DECL_FUNC_PTR(krb5_cc_get_name);489DECL_FUNC_PTR(krb5_cc_set_flags);490DECL_FUNC_PTR(krb5_is_config_principal);491DECL_FUNC_PTR(krb5_free_ticket);492DECL_FUNC_PTR(krb5_decode_ticket);493DECL_FUNC_PTR(krb5_cc_switch);494DECL_FUNC_PTR(krb5_build_principal_ext);495DECL_FUNC_PTR(krb5_get_renewed_creds);496DECL_FUNC_PTR(krb5_cc_initialize);497DECL_FUNC_PTR(krb5_cc_store_cred);498DECL_FUNC_PTR(krb5_cc_get_full_name);499DECL_FUNC_PTR(krb5_free_string);500DECL_FUNC_PTR(krb5_enctype_to_name);501DECL_FUNC_PTR(krb5_cc_get_type);502DECL_FUNC_PTR(krb5int_cc_user_set_default_name);503504FUNC_INFO krb5_fi[] = {505MAKE_FUNC_INFO(krb5_cc_default_name),506MAKE_FUNC_INFO(krb5_cc_set_default_name),507MAKE_FUNC_INFO(krb5_get_default_config_files),508MAKE_FUNC_INFO(krb5_free_config_files),509MAKE_FUNC_INFO(krb5_free_context),510MAKE_FUNC_INFO(krb5_get_default_realm),511MAKE_FUNC_INFO(krb5_free_default_realm),512MAKE_FUNC_INFO(krb5_init_context),513MAKE_FUNC_INFO(krb5_cc_default),514MAKE_FUNC_INFO(krb5_parse_name),515MAKE_FUNC_INFO(krb5_free_principal),516MAKE_FUNC_INFO(krb5_cc_close),517MAKE_FUNC_INFO(krb5_cc_get_principal),518MAKE_FUNC_INFO(krb5_build_principal),519MAKE_FUNC_INFO(krb5_c_random_make_octets),520MAKE_FUNC_INFO(krb5_get_init_creds_password),521MAKE_FUNC_INFO(krb5_free_cred_contents),522MAKE_FUNC_INFO(krb5_cc_resolve),523MAKE_FUNC_INFO(krb5_unparse_name),524MAKE_FUNC_INFO(krb5_free_unparsed_name),525MAKE_FUNC_INFO(krb5_cc_destroy),526MAKE_FUNC_INFO(krb5_cccol_cursor_new),527MAKE_FUNC_INFO(krb5_cccol_cursor_next),528MAKE_FUNC_INFO(krb5_cccol_cursor_free),529MAKE_FUNC_INFO(krb5_cc_start_seq_get),530MAKE_FUNC_INFO(krb5_cc_next_cred),531MAKE_FUNC_INFO(krb5_cc_end_seq_get),532MAKE_FUNC_INFO(krb5_cc_get_name),533MAKE_FUNC_INFO(krb5_cc_set_flags),534MAKE_FUNC_INFO(krb5_is_config_principal),535MAKE_FUNC_INFO(krb5_free_ticket),536MAKE_FUNC_INFO(krb5_decode_ticket),537MAKE_FUNC_INFO(krb5_cc_switch),538MAKE_FUNC_INFO(krb5_build_principal_ext),539MAKE_FUNC_INFO(krb5_get_renewed_creds),540MAKE_FUNC_INFO(krb5_cc_initialize),541MAKE_FUNC_INFO(krb5_cc_store_cred),542MAKE_FUNC_INFO(krb5_cc_get_full_name),543MAKE_FUNC_INFO(krb5_free_string),544MAKE_FUNC_INFO(krb5_enctype_to_name),545MAKE_FUNC_INFO(krb5_cc_get_type),546MAKE_FUNC_INFO(krb5int_cc_user_set_default_name),547END_FUNC_INFO548};549550// profile functions551DECL_FUNC_PTR(profile_release);552DECL_FUNC_PTR(profile_init);553DECL_FUNC_PTR(profile_flush);554DECL_FUNC_PTR(profile_rename_section);555DECL_FUNC_PTR(profile_update_relation);556DECL_FUNC_PTR(profile_clear_relation);557DECL_FUNC_PTR(profile_add_relation);558DECL_FUNC_PTR(profile_get_relation_names);559DECL_FUNC_PTR(profile_get_subsection_names);560DECL_FUNC_PTR(profile_get_values);561DECL_FUNC_PTR(profile_free_list);562DECL_FUNC_PTR(profile_abandon);563DECL_FUNC_PTR(profile_get_string);564DECL_FUNC_PTR(profile_release_string);565566FUNC_INFO profile_fi[] = {567MAKE_FUNC_INFO(profile_release),568MAKE_FUNC_INFO(profile_init),569MAKE_FUNC_INFO(profile_flush),570MAKE_FUNC_INFO(profile_rename_section),571MAKE_FUNC_INFO(profile_update_relation),572MAKE_FUNC_INFO(profile_clear_relation),573MAKE_FUNC_INFO(profile_add_relation),574MAKE_FUNC_INFO(profile_get_relation_names),575MAKE_FUNC_INFO(profile_get_subsection_names),576MAKE_FUNC_INFO(profile_get_values),577MAKE_FUNC_INFO(profile_free_list),578MAKE_FUNC_INFO(profile_abandon),579MAKE_FUNC_INFO(profile_get_string),580MAKE_FUNC_INFO(profile_release_string),581END_FUNC_INFO582};583584// Tries to load the .DLL files. If it works, we get some functions from them585// and return a TRUE. If it doesn't work, we return a FALSE.586BOOL CLeashApp::InitDLLs()587{588m_hLeashDLL = AfxLoadLibrary(LEASHDLL);589m_hKrb5DLL = AfxLoadLibrary(KERB5DLL);590m_hKrb5ProfileDLL = AfxLoadLibrary(KERB5_PPROFILE_DLL);591m_hComErr = AfxLoadLibrary(COMERR_DLL);592593#define PSAPIDLL "psapi.dll"594#define TOOLHELPDLL "kernel32.dll"595596m_hPsapi = AfxLoadLibrary(PSAPIDLL);597m_hToolHelp32 = AfxLoadLibrary(TOOLHELPDLL);598599HWND hwnd = GetForegroundWindow();600if (!m_hLeashDLL)601{602// We couldn't load the m_hLeashDLL.603m_msgError = "Couldn't load the Leash DLL or one of its dependents.";604MessageBox(hwnd, m_msgError, "Error", MB_OK);605return FALSE;606}607608if (!LoadFuncs(LEASHDLL, leash_fi, 0, 0, 1, 0, 0))609{610MessageBox(hwnd,611"Functions within the Leash DLL didn't load properly!",612"Error", MB_OK);613return FALSE;614}615616if (!LoadFuncs(COMERR_DLL, ce_fi, &m_hComErr, 0, 0, 1, 0)) {617MessageBox(hwnd,618"Functions within " COMERR_DLL "didn't load properly!",619"Error", MB_OK);620return FALSE;621}622623if (m_hKrb5DLL)624{625if (!LoadFuncs(KERB5DLL, krb5_fi, 0, 0, 1, 0, 0))626{627MessageBox(hwnd,628"Unexpected error while loading " KERB5DLL ".\n"629"Kerberos 5 functionality will be disabled.\n",630"Error", MB_OK);631AfxFreeLibrary(m_hKrb5DLL);632m_hKrb5DLL = 0;633}634else if (!m_hKrb5ProfileDLL ||635!LoadFuncs(KERB5_PPROFILE_DLL, profile_fi, 0, 0, 1, 0, 0))636{637MessageBox(hwnd,638"Unexpected error while loading " KERB5_PPROFILE_DLL "."639"\nKerberos 5 functionality will be disabled.\n",640"Error", MB_OK);641AfxFreeLibrary(m_hKrb5ProfileDLL);642m_hKrb5ProfileDLL = 0;643// Use m_hKrb5DLL to undo LoadLibrary in loadfuncs...644UnloadFuncs(krb5_fi, m_hKrb5DLL);645AfxFreeLibrary(m_hKrb5DLL);646m_hKrb5DLL = 0;647}648649}650651OSVERSIONINFO osvi;652memset(&osvi, 0, sizeof(OSVERSIONINFO));653osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);654GetVersionEx(&osvi);655656// XXX: We should really use feature testing, first657// checking for CreateToolhelp32Snapshot. If that's658// not around, we try the psapi stuff.659//660// Only load LSA functions if on NT/2000/XP661if(osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)662{663// Windows 9x664AfxFreeLibrary(m_hPsapi);665m_hPsapi = NULL;666if (!m_hToolHelp32 ||667!LoadFuncs(TOOLHELPDLL, toolhelp_fi, 0, 0, 1, 0, 0))668{669MessageBox(hwnd, "Could not load " TOOLHELPDLL "!", "Error",670MB_OK);671return FALSE;672}673}674else if(osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)675{676// Windows NT677AfxFreeLibrary(m_hToolHelp32);678m_hToolHelp32 = NULL;679if (!m_hPsapi ||680!LoadFuncs(PSAPIDLL, psapi_fi, 0, 0, 1, 0, 0))681{682MessageBox(hwnd, "Could not load " PSAPIDLL "!", "Error", MB_OK);683return FALSE;684}685686m_hKrbLSA = AfxLoadLibrary(SECUR32DLL);687}688else689{690MessageBox(hwnd,691"Unrecognized Operating System!",692"Error", MB_OK);693return FALSE;694}695696return TRUE;697}698699700BOOL CLeashApp::FirstInstance()701{702CWnd* pWndprev;703CWnd* pWndchild;704705//find if it exists706pWndprev = CWnd::FindWindow(_T("LEASH.0WNDCLASS"), NULL);707if (pWndprev)708{709//if it has popups710pWndchild = pWndprev->GetLastActivePopup();711//if iconic restore712if (pWndprev->IsIconic())713pWndprev->ShowWindow(SW_RESTORE);714715//bring the wnd to foreground716pWndchild->SetForegroundWindow();717718return FALSE;719}720//we could not find prev instance721else722return TRUE;723}724725void726CLeashApp::ValidateConfigFiles()727{728char confname[257];729char realm[256]="";730731CWinApp * pApp = AfxGetApp();732if (pApp)733if (!pApp->GetProfileInt("Settings", "CreateMissingConfig", FALSE_FLAG))734return;735736if ( m_hKrb5DLL ) {737// Create the empty KRB5.INI file738if (!GetProfileFile(confname,sizeof(confname))) {739const char *filenames[2];740filenames[0] = confname;741filenames[1] = NULL;742long retval = pprofile_init(filenames, &m_krbv5_profile);743if (!retval)744return;745else if (retval == ENOENT) {746FILE * f = fopen(confname,"w");747if (f != NULL) {748fclose(f);749retval = pprofile_init(filenames, &m_krbv5_profile);750}751}752753754const char* lookupKdc[] = {"libdefaults", "dns_lookup_kdc", NULL};755const char* lookupRealm[] = {"libdefaults", "dns_lookup_realm", NULL};756const char* defRealm[] = {"libdefaults", "default_realm", NULL};757const char* noAddresses[] = {"libdefaults", "noaddresses", NULL};758759// activate DNS KDC Lookups760const char** names = lookupKdc;761retval = pprofile_add_relation(m_krbv5_profile,762names,763"true");764765// activate No Addresses766names = noAddresses;767retval = pprofile_add_relation(m_krbv5_profile,768names,769"true");770771// Get Windows 2000/XP/2003 Kerberos config772if ( m_hKrbLSA && m_hKrb5DLL )773{774char domain[256]="";775HKEY hk=0;776DWORD dwType, dwSize, dwIndex;777778if ( !RegOpenKeyEx(HKEY_CURRENT_USER,779"Volatile Environment", 0,780KEY_READ, &hk) )781{782dwSize = sizeof(domain);783RegQueryValueEx(hk, "USERDNSDOMAIN", 0, 0, (LPBYTE)domain, &dwSize);784RegCloseKey(hk);785}786else if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE,787"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon",7880, KEY_READ, &hk))789{790791dwSize = sizeof(domain);792RegQueryValueEx( hk, "DefaultDomainName",793NULL, &dwType, (unsigned char *)&domain, &dwSize);794RegCloseKey(hk);795}796797char realmkey[256]="SYSTEM\\CurrentControlSet\\Control\\Lsa\\Kerberos\\Domains\\";798size_t keylen = strlen(realmkey)-1;799800if ( domain[0] ) {801strncpy(realm,domain,256);802realm[255] = '\0';803strncat(realmkey,domain,256-strlen(realmkey));804realmkey[255] = '\0';805}806807if ( domain[0] &&808!RegOpenKeyEx(HKEY_LOCAL_MACHINE,809realmkey,8100,811KEY_READ,812&hk)813)814{815RegCloseKey(hk);816817realmkey[keylen] = '\0';818RegOpenKeyEx(HKEY_LOCAL_MACHINE,819realmkey,8200,821KEY_READ|KEY_ENUMERATE_SUB_KEYS,822&hk);823824dwIndex = 0;825unsigned char subkey[256];826FILETIME ft;827dwSize = 256;828while ( ERROR_SUCCESS == RegEnumKeyEx(hk,dwIndex++,829(char *)subkey,830&dwSize,8310,8320,8330,834&ft) )835{836HKEY hksub;837838if ( !RegOpenKeyEx(hk,839(char *)subkey,8400,841KEY_READ,842&hksub) )843{844unsigned char * lpszValue = NULL, *p;845dwSize = 0;846dwType = 0;847RegQueryValueEx( hksub, "KdcNames",848NULL, &dwType, lpszValue, &dwSize);849if ( dwSize > 0 ) {850lpszValue = (unsigned char *)malloc(dwSize+1);851dwSize += 1;852RegQueryValueEx( hksub, "KdcNames",853NULL, &dwType, lpszValue, &dwSize);854855p = lpszValue;856while ( *p ) {857const char* realmKdc[] = {"realms", (const char *)subkey, "kdc", NULL};858names = realmKdc;859retval = pprofile_add_relation(m_krbv5_profile,860names,861(const char *)p);862863p += strlen((char*)p) + 1;864}865free(lpszValue);866}867RegCloseKey(hksub);868}869}870RegCloseKey(hk);871}872} else {873// activate DNS Realm Lookups (temporarily)874names = lookupRealm;875retval = pprofile_add_relation(m_krbv5_profile,876names,877"true");878}879880// Save to Kerberos Five config. file "Krb5.ini"881retval = pprofile_flush(m_krbv5_profile);882883884// Use DNS to retrieve the realm (if possible)885if (!realm[0]) {886krb5_context ctx = 0;887krb5_principal me = 0;888krb5_error_code code = 0;889890code = pkrb5_init_context(&ctx);891if (code) goto no_k5_realm;892893code = pkrb5_parse_name(ctx, "foo", &me);894if (code) goto no_k5_realm;895896if ( krb5_princ_realm(ctx,me)->length < sizeof(realm) - 1) {897memcpy(realm, krb5_princ_realm(ctx,me)->data,898krb5_princ_realm(ctx,me)->length);899realm[krb5_princ_realm(ctx,me)->length] = '\0';900}901902no_k5_realm:903if ( me )904pkrb5_free_principal(ctx,me);905if ( ctx )906pkrb5_free_context(ctx);907}908909// disable DNS Realm Lookups910retval = pprofile_update_relation(m_krbv5_profile,911names,912"true", "false");913914// save the default realm if it was discovered915if ( realm[0] ) {916names = defRealm;917retval = pprofile_add_relation(m_krbv5_profile,918names,919realm);920921// It would be nice to be able to generate a list of KDCs922// but to do so based upon the contents of DNS would be923// wrong for several reasons:924// . it would make static the values inserted into DNS SRV925// records926// . DNS cannot necessarily be trusted927}928929// Save to Kerberos Five config. file "Krb5.ini"930retval = pprofile_flush(m_krbv5_profile);931932pprofile_release(m_krbv5_profile);933m_krbv5_profile = NULL;934935}936}937}938939BOOL940CLeashApp::GetProfileFile(941LPSTR confname,942UINT szConfname943)944{945char **configFile = NULL;946if (!m_hKrb5DLL)947return NULL;948949if (pkrb5_get_default_config_files(&configFile))950{951GetWindowsDirectory(confname,szConfname);952confname[szConfname-1] = '\0';953strncat(confname,"\\KRB5.INI",szConfname-strlen(confname));954confname[szConfname-1] = '\0';955return FALSE;956}957958*confname = 0;959960if (configFile)961{962strncpy(confname, *configFile, szConfname);963confname[szConfname-1] = '\0';964pkrb5_free_config_files(configFile);965}966967if (!*confname)968{969GetWindowsDirectory(confname,szConfname);970confname[szConfname-1] = '\0';971strncat(confname,"\\KRB5.INI",szConfname-strlen(confname));972confname[szConfname-1] = '\0';973}974975return FALSE;976}977978#define PROBE_USERNAME "KERBEROS-KDC-PROBE"979#define PROBE_PASSWORD_LEN 16980981BOOL982CLeashApp::ProbeKDC(void)983{984krb5_context ctx=0;985krb5_ccache cc=0;986krb5_principal principal = 0;987krb5_principal probeprinc = 0;988krb5_creds creds;989krb5_error_code code;990krb5_data pwdata;991char password[PROBE_PASSWORD_LEN+1];992long success = FALSE;993994if (!pkrb5_init_context)995return success;996997memset(&creds, 0, sizeof(creds));998999code = pkrb5_init_context(&ctx);1000if (code)1001goto cleanup;10021003code = pkrb5_cc_default(ctx, &cc);1004if (code)1005goto cleanup;10061007code = pkrb5_cc_get_principal(ctx, cc, &principal);1008if ( code )1009code = pkrb5_parse_name(ctx, "foo", &principal);1010if ( code )1011goto cleanup;10121013code = pkrb5_build_principal( ctx, &probeprinc,1014krb5_princ_realm(ctx,principal)->length,1015krb5_princ_realm(ctx,principal)->data,1016PROBE_USERNAME, NULL, NULL);1017if ( code )1018goto cleanup;10191020pwdata.data = password;1021pwdata.length = PROBE_PASSWORD_LEN;1022code = pkrb5_c_random_make_octets(ctx, &pwdata);1023if (code) {1024int i;1025for ( i=0 ; i<PROBE_PASSWORD_LEN ; i )1026password[i] = 'x';1027}1028password[PROBE_PASSWORD_LEN] = '\0';10291030code = pkrb5_get_init_creds_password(ctx,1031&creds,1032probeprinc,1033password, // password1034NULL, // prompter10350, // prompter data10360, // start time10370, // service name10380 // no options1039);10401041switch ( code ) {1042case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:1043case KRB5KDC_ERR_CLIENT_REVOKED:1044case KRB5KDC_ERR_CLIENT_NOTYET:1045case KRB5KDC_ERR_PREAUTH_FAILED:1046case KRB5KDC_ERR_PREAUTH_REQUIRED:1047case KRB5KDC_ERR_PADATA_TYPE_NOSUPP:1048success = TRUE;1049break;1050}1051cleanup:1052if (creds.client == probeprinc)1053creds.client = 0;1054pkrb5_free_cred_contents(ctx, &creds);1055if (principal)1056pkrb5_free_principal(ctx,principal);1057if (probeprinc)1058pkrb5_free_principal(ctx,probeprinc);1059if (cc)1060pkrb5_cc_close(ctx,cc);1061if (ctx)1062pkrb5_free_context(ctx);1063return success;1064}10651066VOID1067CLeashApp::ObtainTicketsViaUserIfNeeded(HWND hWnd)1068{1069if (WaitForSingleObject( ticketinfo.lockObj, INFINITE ) != WAIT_OBJECT_0)1070throw("Unable to lock ticketinfo");1071LeashKRB5ListDefaultTickets(&ticketinfo.Krb5);1072int btickets = ticketinfo.Krb5.btickets;1073LeashKRB5FreeTicketInfo(&ticketinfo.Krb5);1074ReleaseMutex(ticketinfo.lockObj);10751076if (ProbeKDC() && (!btickets || !pLeash_renew())) {1077LSH_DLGINFO_EX ldi;1078ldi.size = LSH_DLGINFO_EX_V1_SZ;1079ldi.dlgtype = DLGTYPE_PASSWD;1080ldi.title = "MIT Kerberos: Get Ticket";1081ldi.username = NULL;1082ldi.realm = NULL;1083ldi.dlgtype = DLGTYPE_PASSWD;1084ldi.use_defaults = 1;10851086pLeash_kinit_dlg_ex(hWnd, &ldi);1087}1088return;1089}10901091// IP Change Monitoring Functions1092#include <Iphlpapi.h>109310941095DWORD1096CLeashApp::GetNumOfIpAddrs(void)1097{1098PMIB_IPADDRTABLE pIpAddrTable = 0;1099ULONG dwSize;1100DWORD code;1101DWORD index;1102DWORD validAddrs = 0;11031104dwSize = 0;1105code = GetIpAddrTable(NULL, &dwSize, 0);1106if (code == ERROR_INSUFFICIENT_BUFFER) {1107pIpAddrTable = (PMIB_IPADDRTABLE) malloc(dwSize);1108code = GetIpAddrTable(pIpAddrTable, &dwSize, 0);1109if ( code == NO_ERROR ) {1110for ( index=0; index < pIpAddrTable->dwNumEntries; index++ ) {1111if (pIpAddrTable->table[index].dwAddr != 0)1112validAddrs++;1113}1114}1115free(pIpAddrTable);1116}1117return validAddrs;1118}11191120UINT1121CLeashApp::IpAddrChangeMonitor(void * hWnd)1122{1123DWORD Result;1124DWORD prevNumOfAddrs = GetNumOfIpAddrs();1125DWORD NumOfAddrs;11261127if ( !hWnd )1128return 0;11291130while ( TRUE ) {1131Result = NotifyAddrChange(NULL,NULL);1132if ( Result != NO_ERROR ) {1133// We do not have permission to open the device1134return 0;1135}11361137NumOfAddrs = GetNumOfIpAddrs();1138if ( NumOfAddrs != prevNumOfAddrs ) {1139// wait for the network state to stabilize1140Sleep(2000);1141// this call should probably be mutex protected1142ObtainTicketsViaUserIfNeeded((HWND)hWnd);1143}1144prevNumOfAddrs = NumOfAddrs;1145}11461147return 0;1148}114911501151DWORD1152CLeashApp::IpAddrChangeMonitorInit(HWND hWnd)1153{1154AfxBeginThread(IpAddrChangeMonitor, hWnd);1155return 0;1156}11571158UINT1159CLeashApp::InitWorker(void * hWnd)1160{1161if ( ProbeKDC() ) {1162LSH_DLGINFO_EX ldi;1163ldi.size = LSH_DLGINFO_EX_V1_SZ;1164ldi.dlgtype = DLGTYPE_PASSWD;1165ldi.title = "Initialize Ticket";1166ldi.username = NULL;1167ldi.realm = NULL;1168ldi.use_defaults = 1;11691170pLeash_kinit_dlg_ex((HWND)hWnd, &ldi);1171::SendMessage((HWND)hWnd, WM_COMMAND, ID_UPDATE_DISPLAY, 0);1172}1173return 0;1174}11751176#ifdef USE_HTMLHELP1177#if _MSC_VER < 13001178void1179CLeashApp::WinHelp(DWORD dwData, UINT nCmd)1180{1181switch (nCmd)1182{1183case HELP_CONTEXT:1184::HtmlHelp(GetDesktopWindow(), m_helpFile, HH_HELP_CONTEXT, dwData );1185break;1186case HELP_FINDER:1187::HtmlHelp(GetDesktopWindow(), m_helpFile, HH_DISPLAY_TOPIC, 0);1188break;1189}1190}1191#endif1192#endif119311941195BOOL CLeashApp::OnIdle(LONG lCount)1196{1197// TODO: Add your specialized code here and/or call the base class1198BOOL retval = CWinAppEx::OnIdle(lCount);1199if ((lCount == 0) && m_bUpdateDisplay) {1200m_bUpdateDisplay = FALSE;1201m_pMainWnd->SendMessage(WM_COMMAND, ID_UPDATE_DISPLAY, 0);1202}1203return retval;1204}120512061207