diff options
author | Sam Hartman <hartmans@mit.edu> | 2011-09-28 21:02:14 +0000 |
---|---|---|
committer | Sam Hartman <hartmans@mit.edu> | 2011-09-28 21:02:14 +0000 |
commit | caef99b21536d9e8c2f9c637fcf020b4e082db5d (patch) | |
tree | b360ec8449876ea170691685cde758d9849fc8ef /src/windows/leash/Leash.cpp | |
parent | 8481c14298a1886f63bec0d7cdfd800a86b4c127 (diff) | |
download | krb5-caef99b21536d9e8c2f9c637fcf020b4e082db5d.tar.gz krb5-caef99b21536d9e8c2f9c637fcf020b4e082db5d.tar.xz krb5-caef99b21536d9e8c2f9c637fcf020b4e082db5d.zip |
Initial import of KFW 3.2.2 Leash32 code
Signed-off-by: Alexey Melnikov <aamelnikov@gmail.com>
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@25278 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/windows/leash/Leash.cpp')
-rw-r--r-- | src/windows/leash/Leash.cpp | 1618 |
1 files changed, 1618 insertions, 0 deletions
diff --git a/src/windows/leash/Leash.cpp b/src/windows/leash/Leash.cpp new file mode 100644 index 0000000000..eb2c11026c --- /dev/null +++ b/src/windows/leash/Leash.cpp @@ -0,0 +1,1618 @@ +//************************************************************************** +// File: Leash.cpp +// By: Arthur David Leather +// Created: 12/02/98 +// Copyright: 1998 Massachusetts Institute of Technology - All rights +// reserved. +// +// Description: CPP file for Leash.h. Contains variables and functions +// for Leash +// +// History: +// +// MM/DD/YY Inits Description of Change +// 12/02/98 ADL Original +//************************************************************************** + +#include "stdafx.h" +#include "Leash.h" + +#include "MainFrm.h" +#include "LeashDoc.h" +#include "LeashView.h" +#include "LeashAboutBox.h" + +#include "reminder.h" +#include "mitwhich.h" +#include <leasherr.h> +#include "lglobals.h" +#include <krb5.h> +#include <com_err.h> + +#include <wshelper.h> + +#ifndef NO_AFS +#include "afscompat.h" +#endif + +#include <errno.h> + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +extern "C" int VScheckVersion(HWND hWnd, HANDLE hThisInstance); + +TicketInfoWrapper ticketinfo; +#ifndef KRB5_TC_NOTICKET /* test for krb5 1.4 and thread safety */ +HANDLE m_tgsReqMutex = 0; +#endif + +HWND CLeashApp::m_hProgram = 0; +HINSTANCE CLeashApp::m_hLeashDLL = 0; +HINSTANCE CLeashApp::m_hKrb4DLL = 0; +HINSTANCE CLeashApp::m_hKrb5DLL = 0; +HINSTANCE CLeashApp::m_hKrb5ProfileDLL= 0; +HINSTANCE CLeashApp::m_hAfsDLL = 0; +HINSTANCE CLeashApp::m_hPsapi = 0; +HINSTANCE CLeashApp::m_hToolHelp32 = 0; +krb5_context CLeashApp::m_krbv5_context = 0; +profile_t CLeashApp::m_krbv5_profile = 0; +HINSTANCE CLeashApp::m_hKrbLSA = 0; + +///////////////////////////////////////////////////////////////////////////// +// CLeashApp + + +BEGIN_MESSAGE_MAP(CLeashApp, CWinApp) + //{{AFX_MSG_MAP(CLeashApp) + //}}AFX_MSG_MAP + // Standard file based document commands + ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) + ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CLeashApp construction +CLeashApp::CLeashApp() +{ + m_krbv5_context = NULL; + m_krbv5_profile = NULL; + // TODO: add construction code here, + // Place all significant initialization in InitInstance + + // Memory may not be initialized to zeros (in debug) + memset(&ticketinfo, 0, sizeof(ticketinfo)); + + ticketinfo.lockObj = CreateMutex(NULL, FALSE, NULL); +#ifndef KRB5_TC_NOTICKET + m_tgsReqMutex = CreateMutex(NULL, FALSE, NULL); +#endif + +#ifdef USE_HTMLHELP +#if _MSC_VER >= 1300 + EnableHtmlHelp(); +#endif +#endif +} + +CLeashApp::~CLeashApp() +{ + if ( m_krbv5_context ) { + pkrb5_free_context(m_krbv5_context); + m_krbv5_context = NULL; + } + + if ( m_krbv5_profile ) { + pprofile_release(m_krbv5_profile); + m_krbv5_profile = NULL; + } + +#ifdef COMMENT + /* Do not free the locking objects. Doing so causes an invalid handle access */ + CloseHandle(ticketinfo.lockObj); +#ifndef KRB5_TC_NOTICKET + CloseHandle(m_tgsReqMutex); +#endif +#endif + AfxFreeLibrary(m_hLeashDLL); + AfxFreeLibrary(m_hKrb4DLL); + AfxFreeLibrary(m_hKrb5DLL); + AfxFreeLibrary(m_hKrb5ProfileDLL); + AfxFreeLibrary(m_hAfsDLL); + AfxFreeLibrary(m_hPsapi); + AfxFreeLibrary(m_hToolHelp32); + AfxFreeLibrary(m_hKrbLSA); +} + +///////////////////////////////////////////////////////////////////////////// +// The one and only CLeashApp object + +CLeashApp theApp; + +///////////////////////////////////////////////////////////////////////////// +// CLeashApp initialization + +void CLeashApp::ParseParam (LPCTSTR lpszParam,BOOL bFlag,BOOL bLast) +{ + //CCommandLineInfo::ParseParam(lpszParam, bFlag, bLast) ; +} + +extern "C" { + LRESULT WINAPI LeashWindowProc( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) + { + switch ( Msg ) { + case WM_SYSCOMMAND: + if (SC_CLOSE == (wParam & 0xfff0)) { + wParam = (wParam & ~0xfff0) | SC_MINIMIZE; + } + break; + } + return ::DefWindowProc(hWnd, Msg, wParam, lParam); + } +} + +BOOL CLeashApp::InitInstance() +{ + // NOTE: Not used at this time + /// Set LEASH_DLL to the path where the Leash.exe is + char modulePath[MAX_PATH]; + DWORD result = GetModuleFileName(AfxGetInstanceHandle(), modulePath, MAX_PATH); + ASSERT(result); + + char* pPath = modulePath + strlen(modulePath) - 1; + while (*pPath != '\\') + { + *pPath = 0; + pPath--; + } + strcat(modulePath, LEASH_HELP_FILE); + m_helpFile = modulePath; + + ///strcat(dllFile, LEASH_DLL); + ///m_leashDLL = dllFile; + + BOOL autoInit = FALSE; + HWND hMsg = GetForegroundWindow(); + if (!InitDLLs()) + return FALSE; //exit program, can't load LEASHDLL + + // Check for args (switches) + LPCTSTR exeFile = __targv[0]; + LPCTSTR optionParam = __targv[1]; + + if (optionParam) + { + if (*optionParam == '-' || *optionParam == '/') + { + if (0 == stricmp(optionParam+1, "kinit") || + 0 == stricmp(optionParam+1, "i")) + { + LSH_DLGINFO_EX ldi; + char username[64]=""; + char realm[192]=""; + int i=0, j=0; + TicketList* ticketList = NULL; + if (WaitForSingleObject( ticketinfo.lockObj, INFINITE ) != WAIT_OBJECT_0) + throw("Unable to lock ticketinfo"); + + pLeashKRB5GetTickets(&ticketinfo.Krb5, &ticketList, + &CLeashApp::m_krbv5_context); + pLeashFreeTicketList(&ticketList); + pLeashKRB4GetTickets(&ticketinfo.Krb4, &ticketList); + pLeashFreeTicketList(&ticketList); + + if ( ticketinfo.Krb5.btickets && ticketinfo.Krb5.principal[0] ) { + for (; ticketinfo.Krb5.principal[i] && ticketinfo.Krb5.principal[i] != '@'; i++) + { + username[i] = ticketinfo.Krb5.principal[i]; + } + username[i] = '\0'; + if (ticketinfo.Krb5.principal[i]) { + for (i++ ; ticketinfo.Krb5.principal[i] ; i++, j++) + { + realm[j] = ticketinfo.Krb5.principal[i]; + } + } + realm[j] = '\0'; + } else if ( ticketinfo.Krb4.btickets && ticketinfo.Krb4.principal[0] ) { + for (; ticketinfo.Krb4.principal[i] && ticketinfo.Krb4.principal[i] != '@'; i++) + { + username[i] = ticketinfo.Krb4.principal[i]; + } + username[i] = '\0'; + if (ticketinfo.Krb4.principal[i]) { + for (i++ ; ticketinfo.Krb4.principal[i] ; i++, j++) + { + realm[j] = ticketinfo.Krb4.principal[i]; + } + } + realm[j] = '\0'; + } + ReleaseMutex(ticketinfo.lockObj); + + ldi.size = sizeof(ldi); + ldi.dlgtype = DLGTYPE_PASSWD; + ldi.title = "Initialize Ticket"; + ldi.username = username; + ldi.realm = realm; + ldi.dlgtype = DLGTYPE_PASSWD; + ldi.use_defaults = 1; + + if (!pLeash_kinit_dlg_ex(hMsg, &ldi)) + { + MessageBox(hMsg, "There was an error getting tickets!", + "Error", MB_OK); + return FALSE; + } + return TRUE; + } + else if (0 == stricmp(optionParam+1, "ms2mit") || + 0 == stricmp(optionParam+1, "import") || + 0 == stricmp(optionParam+1, "m")) + { + if (!pLeash_importable()) { + MessageBox(hMsg, + "The Microsoft Logon Session does not support importing Ticket Getting Tickets!", + "Error", MB_OK); + return FALSE; + } + + if (!pLeash_import()) + { + MessageBox(hMsg, + "There was an error importing tickets from the Microsoft Logon Session!", + "Error", MB_OK); + return FALSE; + } + return TRUE; + } + else if (0 == stricmp(optionParam+1, "destroy") || + 0 == stricmp(optionParam+1, "d")) + { + if (pLeash_kdestroy()) + { + MessageBox(hMsg, + "There was an error destroying tickets!", + "Error", MB_OK); + return FALSE; + } + return TRUE; + } + else if (0 == stricmp(optionParam+1, "renew") || + 0 == stricmp(optionParam+1, "r")) + { + if (!pLeash_renew()) + { + MessageBox(hMsg, + "There was an error renewing tickets!", + "Error", MB_OK); + return FALSE; + } + return TRUE; + } + else if (0 == stricmp(optionParam+1, "autoinit") || + 0 == stricmp(optionParam+1, "a")) + { + autoInit = TRUE; + } + else + { + MessageBox(hMsg, + "'-kinit' or '-i' to perform ticket initialization (and exit)\n" + "'-renew' or '-r' to perform ticket renewal (and exit)\n" + "'-destroy' or '-d' to perform ticket destruction (and exit)\n" + "'-autoinit' or '-a' to perform automatic ticket initialization\n" + "'-ms2mit' or '-import' or '-m' to perform ticket importation (and exit)", + "Leash Error", MB_OK); + return FALSE; + } + } + else + { + MessageBox(hMsg, + "'-kinit' or '-i' to perform ticket initialization (and exit)\n" + "'-renew' or '-r' to perform ticket renewal (and exit)\n" + "'-destroy' or '-d' to perform ticket destruction (and exit)\n" + "'-autoinit' or '-a' to perform automatic ticket initialization\n" + "'-ms2mit' or '-import' or '-m' to perform ticket importation (and exit)", + "Leash Error", MB_OK); + return FALSE; + } + } + + // Insure only one instance of Leash + if (!FirstInstance()) + return FALSE; + + //register our unique wnd class name to find it later + WNDCLASS wndcls; + memset(&wndcls, 0, sizeof(WNDCLASS)); + wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW; + wndcls.lpfnWndProc = ::LeashWindowProc; + wndcls.hInstance = AfxGetInstanceHandle(); + wndcls.hIcon = LoadIcon(IDR_MAINFRAME); + wndcls.hCursor = LoadCursor(IDC_ARROW); + wndcls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wndcls.lpszMenuName = NULL; + //now the wnd class name to find it + wndcls.lpszClassName = _T("LEASH.0WNDCLASS"); + + //register the new class + if(!AfxRegisterClass(&wndcls)) + { + TRACE("Class registration failed\n"); + return FALSE; + } + + AfxEnableControlContainer(); + + // Standard initialization + // If you are not using these features and wish to reduce the size + // of your final executable, you should remove from the following + // the specific initialization routines you do not need. + +#if _MSC_VER < 1300 +#ifdef _AFXDLL + Enable3dControls(); // Call this when using MFC in a shared DLL +#else + Enable3dControlsStatic(); // Call this when linking to MFC statically +#endif +#endif + + // Registry key under which our settings are stored. + if (m_pszAppName) + free((void*)m_pszAppName); + m_pszAppName = _tcsdup("Leash32"); + SetRegistryKey(_T("MIT")); + + LoadStdProfileSettings(); // Load standard INI file options (including MRU) + + // Register the application's document templates. Document templates + // serve as the connection between documents, frame windows and views. + + CSingleDocTemplate* pDocTemplate; + pDocTemplate = new CSingleDocTemplate( + IDR_MAINFRAME, + RUNTIME_CLASS(LeashDoc), + RUNTIME_CLASS(CMainFrame), // main SDI frame window + RUNTIME_CLASS(CLeashView)); + AddDocTemplate(pDocTemplate); + + // Parse command line for standard shell commands, DDE, file open + CCommandLineInfo cmdInfo; + ParseCommandLine(cmdInfo); + + // Dispatch commands specified on the command line + if (!ProcessShellCommand(cmdInfo)) + return FALSE; + + // Check to see if there are any tickets in the cache + // If not and the Windows Logon Session is Kerberos authenticated attempt an import + { + TicketList* ticketList = NULL; + if (WaitForSingleObject( ticketinfo.lockObj, INFINITE ) != WAIT_OBJECT_0) + throw("Unable to lock ticketinfo"); + pLeashKRB5GetTickets(&ticketinfo.Krb5, &ticketList, &CLeashApp::m_krbv5_context); + pLeashFreeTicketList(&ticketList); + pLeashKRB4GetTickets(&ticketinfo.Krb4, &ticketList); + pLeashFreeTicketList(&ticketList); + BOOL b_autoinit = !ticketinfo.Krb4.btickets && !ticketinfo.Krb5.btickets; + ReleaseMutex(ticketinfo.lockObj); + + DWORD dwMsLsaImport = pLeash_get_default_mslsa_import(); + + if ( b_autoinit && dwMsLsaImport && pLeash_importable() ) { + // We have the option of importing tickets from the MSLSA + // but should we? Do the tickets in the MSLSA cache belong + // to the default realm used by Leash? If so, import. + int import = 0; + + if ( dwMsLsaImport == 1 ) { /* always import */ + import = 1; + } else if ( dwMsLsaImport == 2 ) { /* import when realms match */ + krb5_error_code code; + krb5_ccache mslsa_ccache=0; + krb5_principal princ = 0; + char ms_realm[128] = "", *def_realm = 0, *r; + int i; + + if (code = pkrb5_cc_resolve(CLeashApp::m_krbv5_context, "MSLSA:", &mslsa_ccache)) + goto cleanup; + + if (code = pkrb5_cc_get_principal(CLeashApp::m_krbv5_context, mslsa_ccache, &princ)) + goto cleanup; + + for ( r=ms_realm, i=0; i<krb5_princ_realm(CLeashApp::m_krb5v5_context, princ)->length; r++, i++ ) { + *r = krb5_princ_realm(CLeashApp::m_krb5v5_context, princ)->data[i]; + } + *r = '\0'; + + if (code = pkrb5_get_default_realm(CLeashApp::m_krbv5_context, &def_realm)) + goto cleanup; + + import = !strcmp(def_realm, ms_realm); + + cleanup: + if (def_realm) + pkrb5_free_default_realm(CLeashApp::m_krbv5_context, def_realm); + + if (princ) + pkrb5_free_principal(CLeashApp::m_krbv5_context, princ); + + if (mslsa_ccache) + pkrb5_cc_close(CLeashApp::m_krbv5_context, mslsa_ccache); + } + + if (import && pLeash_import()) { + CLeashView::m_importedTickets = 1; + ::PostMessage(m_pMainWnd->m_hWnd, WM_COMMAND, ID_UPDATE_DISPLAY, 0); + b_autoinit = FALSE; + } + } + + if (autoInit) { + if ( b_autoinit ) + AfxBeginThread(InitWorker, m_pMainWnd->m_hWnd); + + IpAddrChangeMonitorInit(m_pMainWnd->m_hWnd); + } + } + + VScheckVersion(m_pMainWnd->m_hWnd, AfxGetInstanceHandle()); + + // The one and only window has been initialized, so show and update it. + m_pMainWnd->SetWindowText("Leash"); + m_pMainWnd->UpdateWindow(); + m_pMainWnd->ShowWindow(SW_SHOW); + m_pMainWnd->SetForegroundWindow(); + + ValidateConfigFiles(); + + return TRUE; +} + + +///////////////////////////////////////////////////////////////////////////// +// CLeashApp commands + +// leash functions +DECL_FUNC_PTR(not_an_API_LeashKRB4GetTickets); +DECL_FUNC_PTR(not_an_API_LeashKRB5GetTickets); +DECL_FUNC_PTR(not_an_API_LeashAFSGetToken); +DECL_FUNC_PTR(not_an_API_LeashFreeTicketList); +DECL_FUNC_PTR(not_an_API_LeashGetTimeServerName); +DECL_FUNC_PTR(Leash_kdestroy); +DECL_FUNC_PTR(Leash_changepwd_dlg); +DECL_FUNC_PTR(Leash_changepwd_dlg_ex); +DECL_FUNC_PTR(Leash_kinit_dlg); +DECL_FUNC_PTR(Leash_kinit_dlg_ex); +DECL_FUNC_PTR(Leash_timesync); +DECL_FUNC_PTR(Leash_get_default_lifetime); +DECL_FUNC_PTR(Leash_set_default_lifetime); +DECL_FUNC_PTR(Leash_get_default_forwardable); +DECL_FUNC_PTR(Leash_set_default_forwardable); +DECL_FUNC_PTR(Leash_get_default_renew_till); +DECL_FUNC_PTR(Leash_set_default_renew_till); +DECL_FUNC_PTR(Leash_get_default_noaddresses); +DECL_FUNC_PTR(Leash_set_default_noaddresses); +DECL_FUNC_PTR(Leash_get_default_proxiable); +DECL_FUNC_PTR(Leash_set_default_proxiable); +DECL_FUNC_PTR(Leash_get_default_publicip); +DECL_FUNC_PTR(Leash_set_default_publicip); +DECL_FUNC_PTR(Leash_get_default_use_krb4); +DECL_FUNC_PTR(Leash_set_default_use_krb4); +DECL_FUNC_PTR(Leash_get_default_life_min); +DECL_FUNC_PTR(Leash_set_default_life_min); +DECL_FUNC_PTR(Leash_get_default_life_max); +DECL_FUNC_PTR(Leash_set_default_life_max); +DECL_FUNC_PTR(Leash_get_default_renew_min); +DECL_FUNC_PTR(Leash_set_default_renew_min); +DECL_FUNC_PTR(Leash_get_default_renew_max); +DECL_FUNC_PTR(Leash_set_default_renew_max); +DECL_FUNC_PTR(Leash_get_default_renewable); +DECL_FUNC_PTR(Leash_set_default_renewable); +DECL_FUNC_PTR(Leash_get_lock_file_locations); +DECL_FUNC_PTR(Leash_set_lock_file_locations); +DECL_FUNC_PTR(Leash_get_default_uppercaserealm); +DECL_FUNC_PTR(Leash_set_default_uppercaserealm); +DECL_FUNC_PTR(Leash_get_default_mslsa_import); +DECL_FUNC_PTR(Leash_set_default_mslsa_import); +DECL_FUNC_PTR(Leash_get_default_preserve_kinit_settings); +DECL_FUNC_PTR(Leash_set_default_preserve_kinit_settings); +DECL_FUNC_PTR(Leash_import); +DECL_FUNC_PTR(Leash_importable); +DECL_FUNC_PTR(Leash_renew); +DECL_FUNC_PTR(Leash_reset_defaults); + +FUNC_INFO leash_fi[] = { + MAKE_FUNC_INFO(not_an_API_LeashKRB4GetTickets), + MAKE_FUNC_INFO(not_an_API_LeashKRB5GetTickets), + MAKE_FUNC_INFO(not_an_API_LeashAFSGetToken), + MAKE_FUNC_INFO(not_an_API_LeashFreeTicketList), + MAKE_FUNC_INFO(not_an_API_LeashGetTimeServerName), + MAKE_FUNC_INFO(Leash_kdestroy), + MAKE_FUNC_INFO(Leash_changepwd_dlg), + MAKE_FUNC_INFO(Leash_changepwd_dlg_ex), + MAKE_FUNC_INFO(Leash_kinit_dlg), + MAKE_FUNC_INFO(Leash_kinit_dlg_ex), + MAKE_FUNC_INFO(Leash_timesync), + MAKE_FUNC_INFO(Leash_get_default_lifetime), + MAKE_FUNC_INFO(Leash_set_default_lifetime), + MAKE_FUNC_INFO(Leash_get_default_renew_till), + MAKE_FUNC_INFO(Leash_set_default_renew_till), + MAKE_FUNC_INFO(Leash_get_default_forwardable), + MAKE_FUNC_INFO(Leash_set_default_forwardable), + MAKE_FUNC_INFO(Leash_get_default_noaddresses), + MAKE_FUNC_INFO(Leash_set_default_noaddresses), + MAKE_FUNC_INFO(Leash_get_default_proxiable), + MAKE_FUNC_INFO(Leash_set_default_proxiable), + MAKE_FUNC_INFO(Leash_get_default_publicip), + MAKE_FUNC_INFO(Leash_set_default_publicip), + MAKE_FUNC_INFO(Leash_get_default_use_krb4), + MAKE_FUNC_INFO(Leash_set_default_use_krb4), + MAKE_FUNC_INFO(Leash_get_default_life_min), + MAKE_FUNC_INFO(Leash_set_default_life_min), + MAKE_FUNC_INFO(Leash_get_default_life_max), + MAKE_FUNC_INFO(Leash_set_default_life_max), + MAKE_FUNC_INFO(Leash_get_default_renew_min), + MAKE_FUNC_INFO(Leash_set_default_renew_min), + MAKE_FUNC_INFO(Leash_get_default_renew_max), + MAKE_FUNC_INFO(Leash_set_default_renew_max), + MAKE_FUNC_INFO(Leash_get_default_renewable), + MAKE_FUNC_INFO(Leash_set_default_renewable), + MAKE_FUNC_INFO(Leash_get_lock_file_locations), + MAKE_FUNC_INFO(Leash_set_lock_file_locations), + MAKE_FUNC_INFO(Leash_get_default_uppercaserealm), + MAKE_FUNC_INFO(Leash_set_default_uppercaserealm), + MAKE_FUNC_INFO(Leash_get_default_mslsa_import), + MAKE_FUNC_INFO(Leash_set_default_mslsa_import), + MAKE_FUNC_INFO(Leash_get_default_preserve_kinit_settings), + MAKE_FUNC_INFO(Leash_set_default_preserve_kinit_settings), + MAKE_FUNC_INFO(Leash_import), + MAKE_FUNC_INFO(Leash_importable), + MAKE_FUNC_INFO(Leash_renew), + MAKE_FUNC_INFO(Leash_reset_defaults), + END_FUNC_INFO +}; + +// krb4 functions +DECL_FUNC_PTR(set_krb_debug); +DECL_FUNC_PTR(set_krb_ap_req_debug); +DECL_FUNC_PTR(krb_get_krbconf2); +DECL_FUNC_PTR(krb_get_krbrealm2); +DECL_FUNC_PTR(tkt_string); +DECL_FUNC_PTR(krb_set_tkt_string); +DECL_FUNC_PTR(krb_realmofhost); +DECL_FUNC_PTR(krb_get_lrealm); +DECL_FUNC_PTR(krb_get_krbhst); +DECL_FUNC_PTR(tf_init); +DECL_FUNC_PTR(tf_close); +DECL_FUNC_PTR(krb_get_tf_realm); + +FUNC_INFO krb4_fi[] = { + MAKE_FUNC_INFO(set_krb_debug), + MAKE_FUNC_INFO(set_krb_ap_req_debug), + MAKE_FUNC_INFO(krb_get_krbconf2), + MAKE_FUNC_INFO(krb_get_krbrealm2), + MAKE_FUNC_INFO(tkt_string), + MAKE_FUNC_INFO(krb_set_tkt_string), + MAKE_FUNC_INFO(krb_realmofhost), + MAKE_FUNC_INFO(krb_get_lrealm), + MAKE_FUNC_INFO(krb_get_krbhst), + MAKE_FUNC_INFO(tf_init), + MAKE_FUNC_INFO(tf_close), + MAKE_FUNC_INFO(krb_get_tf_realm), + END_FUNC_INFO +}; + + +// psapi functions +DECL_FUNC_PTR(GetModuleFileNameExA); +DECL_FUNC_PTR(EnumProcessModules); + +FUNC_INFO psapi_fi[] = { + MAKE_FUNC_INFO(GetModuleFileNameExA), + MAKE_FUNC_INFO(EnumProcessModules), + END_FUNC_INFO +}; + +// toolhelp functions +DECL_FUNC_PTR(CreateToolhelp32Snapshot); +DECL_FUNC_PTR(Module32First); +DECL_FUNC_PTR(Module32Next); + +FUNC_INFO toolhelp_fi[] = { + MAKE_FUNC_INFO(CreateToolhelp32Snapshot), + MAKE_FUNC_INFO(Module32First), + MAKE_FUNC_INFO(Module32Next), + END_FUNC_INFO +}; + +// krb5 functions +DECL_FUNC_PTR(krb5_cc_default_name); +DECL_FUNC_PTR(krb5_cc_set_default_name); +DECL_FUNC_PTR(krb5_get_default_config_files); +DECL_FUNC_PTR(krb5_free_config_files); +DECL_FUNC_PTR(krb5_free_context); +DECL_FUNC_PTR(krb5_get_default_realm); +DECL_FUNC_PTR(krb5_free_default_realm); +DECL_FUNC_PTR(krb5_init_context); +DECL_FUNC_PTR(krb5_cc_default); +DECL_FUNC_PTR(krb5_parse_name); +DECL_FUNC_PTR(krb5_free_principal); +DECL_FUNC_PTR(krb5_cc_close); +DECL_FUNC_PTR(krb5_cc_get_principal); +DECL_FUNC_PTR(krb5_build_principal); +DECL_FUNC_PTR(krb5_c_random_make_octets); +DECL_FUNC_PTR(krb5_get_init_creds_password); +DECL_FUNC_PTR(krb5_free_cred_contents); +DECL_FUNC_PTR(krb5_cc_resolve); +DECL_FUNC_PTR(krb5_unparse_name); +DECL_FUNC_PTR(krb5_free_unparsed_name); + +FUNC_INFO krb5_fi[] = { + MAKE_FUNC_INFO(krb5_cc_default_name), + MAKE_FUNC_INFO(krb5_cc_set_default_name), + MAKE_FUNC_INFO(krb5_get_default_config_files), + MAKE_FUNC_INFO(krb5_free_config_files), + MAKE_FUNC_INFO(krb5_free_context), + MAKE_FUNC_INFO(krb5_get_default_realm), + MAKE_FUNC_INFO(krb5_free_default_realm), + MAKE_FUNC_INFO(krb5_init_context), + MAKE_FUNC_INFO(krb5_cc_default), + MAKE_FUNC_INFO(krb5_parse_name), + MAKE_FUNC_INFO(krb5_free_principal), + MAKE_FUNC_INFO(krb5_cc_close), + MAKE_FUNC_INFO(krb5_cc_get_principal), + MAKE_FUNC_INFO(krb5_build_principal), + MAKE_FUNC_INFO(krb5_c_random_make_octets), + MAKE_FUNC_INFO(krb5_get_init_creds_password), + MAKE_FUNC_INFO(krb5_free_cred_contents), + MAKE_FUNC_INFO(krb5_cc_resolve), + MAKE_FUNC_INFO(krb5_unparse_name), + MAKE_FUNC_INFO(krb5_free_unparsed_name), + END_FUNC_INFO +}; + +// profile functions +DECL_FUNC_PTR(profile_release); +DECL_FUNC_PTR(profile_init); +DECL_FUNC_PTR(profile_flush); +DECL_FUNC_PTR(profile_rename_section); +DECL_FUNC_PTR(profile_update_relation); +DECL_FUNC_PTR(profile_clear_relation); +DECL_FUNC_PTR(profile_add_relation); +DECL_FUNC_PTR(profile_get_relation_names); +DECL_FUNC_PTR(profile_get_subsection_names); +DECL_FUNC_PTR(profile_get_values); +DECL_FUNC_PTR(profile_free_list); +DECL_FUNC_PTR(profile_abandon); +DECL_FUNC_PTR(profile_get_string); +DECL_FUNC_PTR(profile_release_string); + +FUNC_INFO profile_fi[] = { + MAKE_FUNC_INFO(profile_release), + MAKE_FUNC_INFO(profile_init), + MAKE_FUNC_INFO(profile_flush), + MAKE_FUNC_INFO(profile_rename_section), + MAKE_FUNC_INFO(profile_update_relation), + MAKE_FUNC_INFO(profile_clear_relation), + MAKE_FUNC_INFO(profile_add_relation), + MAKE_FUNC_INFO(profile_get_relation_names), + MAKE_FUNC_INFO(profile_get_subsection_names), + MAKE_FUNC_INFO(profile_get_values), + MAKE_FUNC_INFO(profile_free_list), + MAKE_FUNC_INFO(profile_abandon), + MAKE_FUNC_INFO(profile_get_string), + MAKE_FUNC_INFO(profile_release_string), + END_FUNC_INFO +}; + +// Tries to load the .DLL files. If it works, we get some functions from them +// and return a TRUE. If it doesn't work, we return a FALSE. +BOOL CLeashApp::InitDLLs() +{ + m_hLeashDLL = AfxLoadLibrary(LEASHDLL); + m_hKrb4DLL = AfxLoadLibrary(KERB4DLL); + m_hKrb5DLL = AfxLoadLibrary(KERB5DLL); + m_hKrb5ProfileDLL = AfxLoadLibrary(KERB5_PPROFILE_DLL); + +#ifndef NO_AFS + afscompat_init(); + m_hAfsDLL = AfxLoadLibrary(AFSAuthentDLL()); +#endif + +#define PSAPIDLL "psapi.dll" +#define TOOLHELPDLL "kernel32.dll" + + m_hPsapi = AfxLoadLibrary(PSAPIDLL); + m_hToolHelp32 = AfxLoadLibrary(TOOLHELPDLL); + + HWND hwnd = GetForegroundWindow(); + if (!m_hLeashDLL) + { + // We couldn't load the m_hLeashDLL. + m_msgError = "Couldn't load the Leash DLL or one of its dependents."; + MessageBox(hwnd, m_msgError, "Error", MB_OK); + return FALSE; + } + + if (!LoadFuncs(LEASHDLL, leash_fi, 0, 0, 1, 0, 0)) + { + MessageBox(hwnd, + "Functions within the Leash DLL didn't load properly!", + "Error", MB_OK); + return FALSE; + } + + if (m_hKrb4DLL) + { + if (!LoadFuncs(KERB4DLL, krb4_fi, 0, 0, 1, 0, 0)) + { + MessageBox(hwnd, + "Unexpected error while loading " KERB4DLL ".\n" + "Kerberos 4 functionality will be disabled.\n", + "Error", MB_OK); + } + } + + if (m_hKrb5DLL) + { + if (!LoadFuncs(KERB5DLL, krb5_fi, 0, 0, 1, 0, 0)) + { + MessageBox(hwnd, + "Unexpected error while loading " KERB5DLL ".\n" + "Kerberos 5 functionality will be disabled.\n", + "Error", MB_OK); + AfxFreeLibrary(m_hKrb5DLL); + m_hKrb5DLL = 0; + } + else if (!m_hKrb5ProfileDLL || + !LoadFuncs(KERB5_PPROFILE_DLL, profile_fi, 0, 0, 1, 0, 0)) + { + MessageBox(hwnd, + "Unexpected error while loading "KERB5_PPROFILE_DLL".\n" + "Kerberos 5 functionality will be disabled.\n", + "Error", MB_OK); + AfxFreeLibrary(m_hKrb5ProfileDLL); + m_hKrb5ProfileDLL = 0; + // Use m_hKrb5DLL to undo LoadLibrary in loadfuncs... + UnloadFuncs(krb5_fi, m_hKrb5DLL); + AfxFreeLibrary(m_hKrb5DLL); + m_hKrb5DLL = 0; + } + + } + + OSVERSIONINFO osvi; + memset(&osvi, 0, sizeof(OSVERSIONINFO)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&osvi); + + // XXX: We should really use feature testing, first + // checking for CreateToolhelp32Snapshot. If that's + // not around, we try the psapi stuff. + // + // Only load LSA functions if on NT/2000/XP + if(osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) + { + // Windows 9x + AfxFreeLibrary(m_hPsapi); + m_hPsapi = NULL; + if (!m_hToolHelp32 || + !LoadFuncs(TOOLHELPDLL, toolhelp_fi, 0, 0, 1, 0, 0)) + { + MessageBox(hwnd, "Could not load " TOOLHELPDLL "!", "Error", + MB_OK); + return FALSE; + } + } + else if(osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) + { + // Windows NT + AfxFreeLibrary(m_hToolHelp32); + m_hToolHelp32 = NULL; + if (!m_hPsapi || + !LoadFuncs(PSAPIDLL, psapi_fi, 0, 0, 1, 0, 0)) + { + MessageBox(hwnd, "Could not load " PSAPIDLL "!", "Error", MB_OK); + return FALSE; + } + + m_hKrbLSA = AfxLoadLibrary(SECUR32DLL); + } + else + { + MessageBox(hwnd, + "Unrecognized Operating System!", + "Error", MB_OK); + return FALSE; + } + + return TRUE; +} + + +BOOL CLeashApp::FirstInstance() +{ + CWnd* pWndprev; + CWnd* pWndchild; + + //find if it exists + pWndprev = CWnd::FindWindow(_T("LEASH.0WNDCLASS"), NULL); + if (pWndprev) + { + //if it has popups + pWndchild = pWndprev->GetLastActivePopup(); + //if iconic restore + if (pWndprev->IsIconic()) + pWndprev->ShowWindow(SW_RESTORE); + + //bring the wnd to foreground + pWndchild->SetForegroundWindow(); + + return FALSE; + } + //we could not find prev instance + else + return TRUE; +} + +void +CLeashApp::ValidateConfigFiles() +{ + CStdioFile krbCon; + char confname[257]; + char realm[256]=""; + + CWinApp * pApp = AfxGetApp(); + if (pApp) + if (!pApp->GetProfileInt("Settings", "CreateMissingConfig", FALSE_FLAG)) + return; + + if ( m_hKrb5DLL ) { + int krb_con_open = 0; + + // Create the empty KRB5.INI file + if (!GetProfileFile(confname,sizeof(confname))) { + const char *filenames[2]; + filenames[0] = confname; + filenames[1] = NULL; + long retval = pprofile_init(filenames, &m_krbv5_profile); + if (!retval) + return; + else if (retval == ENOENT) { + FILE * f = fopen(confname,"w"); + if (f != NULL) { + fclose(f); + retval = pprofile_init(filenames, &m_krbv5_profile); + } + } + + + if ( !GetKrb4ConFile(confname,sizeof(confname)) ) { + if (!krbCon.Open(confname, CFile::modeNoTruncate | CFile::modeRead)) + { + if (krbCon.Open(confname, CFile::modeCreate | CFile::modeWrite)) + { + krb_con_open = 1; + } + } + } + + const char* lookupKdc[] = {"libdefaults", "dns_lookup_kdc", NULL}; + const char* lookupRealm[] = {"libdefaults", "dns_lookup_realm", NULL}; + const char* defRealm[] = {"libdefaults", "default_realm", NULL}; + const char* noAddresses[] = {"libdefaults", "noaddresses", NULL}; + + // activate DNS KDC Lookups + const char** names = lookupKdc; + retval = pprofile_add_relation(m_krbv5_profile, + names, + "true"); + + // activate No Addresses + names = noAddresses; + retval = pprofile_add_relation(m_krbv5_profile, + names, + "true"); + + // Get Windows 2000/XP/2003 Kerberos config + if ( m_hKrbLSA && m_hKrb5DLL ) + { + char domain[256]=""; + HKEY hk=0; + DWORD dwType, dwSize, dwIndex; + + if ( !RegOpenKeyEx(HKEY_CURRENT_USER, + "Volatile Environment", 0, + KEY_READ, &hk) ) + { + dwSize = sizeof(domain); + RegQueryValueEx(hk, "USERDNSDOMAIN", 0, 0, (LPBYTE)domain, &dwSize); + RegCloseKey(hk); + } + else if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE, + "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", + 0, KEY_READ, &hk)) + { + + dwSize = sizeof(domain); + RegQueryValueEx( hk, "DefaultDomainName", + NULL, &dwType, (unsigned char *)&domain, &dwSize); + RegCloseKey(hk); + } + + char realmkey[256]="SYSTEM\\CurrentControlSet\\Control\\Lsa\\Kerberos\\Domains\\"; + int keylen = strlen(realmkey)-1; + + if ( domain[0] ) { + strncpy(realm,domain,256); + realm[255] = '\0'; + if ( krb_con_open ) { + krbCon.WriteString(realm); + krbCon.WriteString("\n"); + } + strncat(realmkey,domain,256-strlen(realmkey)); + realmkey[255] = '\0'; + } + + if ( domain[0] && + !RegOpenKeyEx(HKEY_LOCAL_MACHINE, + realmkey, + 0, + KEY_READ, + &hk) + ) + { + RegCloseKey(hk); + + realmkey[keylen] = '\0'; + RegOpenKeyEx(HKEY_LOCAL_MACHINE, + realmkey, + 0, + KEY_READ|KEY_ENUMERATE_SUB_KEYS, + &hk); + + dwIndex = 0; + unsigned char subkey[256]; + FILETIME ft; + dwSize = 256; + while ( ERROR_SUCCESS == RegEnumKeyEx(hk,dwIndex++, + (char *)subkey, + &dwSize, + 0, + 0, + 0, + &ft) ) + { + HKEY hksub; + + if ( !RegOpenKeyEx(hk, + (char *)subkey, + 0, + KEY_READ, + &hksub) ) + { + unsigned char * lpszValue = NULL, *p; + dwSize = 0; + dwType = 0; + RegQueryValueEx( hksub, "KdcNames", + NULL, &dwType, lpszValue, &dwSize); + if ( dwSize > 0 ) { + lpszValue = (unsigned char *)malloc(dwSize+1); + dwSize += 1; + RegQueryValueEx( hksub, "KdcNames", + NULL, &dwType, lpszValue, &dwSize); + + p = lpszValue; + while ( *p ) { + const char* realmKdc[] = {"realms", (const char *)subkey, "kdc", NULL}; + names = realmKdc; + retval = pprofile_add_relation(m_krbv5_profile, + names, + (const char *)p); + + if ( krb_con_open ) { + krbCon.WriteString((const char *)subkey); + krbCon.WriteString("\t"); + krbCon.WriteString((const char *)p); + krbCon.WriteString("\n"); + } + + p += strlen((char*)p) + 1; + } + free(lpszValue); + } + RegCloseKey(hksub); + } + } + RegCloseKey(hk); + } + } else { + // activate DNS Realm Lookups (temporarily) + names = lookupRealm; + retval = pprofile_add_relation(m_krbv5_profile, + names, + "true"); + } + + // Save to Kerberos Five config. file "Krb5.ini" + retval = pprofile_flush(m_krbv5_profile); + + + // Use DNS to retrieve the realm (if possible) + if (!realm[0]) { + krb5_context ctx = 0; + krb5_principal me = 0; + krb5_error_code code = 0; + + code = pkrb5_init_context(&ctx); + if (code) goto no_k5_realm; + + code = pkrb5_parse_name(ctx, "foo", &me); + if (code) goto no_k5_realm; + + if ( krb5_princ_realm(ctx,me)->length < sizeof(realm) - 1) { + memcpy(realm, krb5_princ_realm(ctx,me)->data, + krb5_princ_realm(ctx,me)->length); + realm[krb5_princ_realm(ctx,me)->length] = '\0'; + } + + if ( krb_con_open ) { + krbCon.WriteString(realm); + krbCon.WriteString("\n"); + } + + no_k5_realm: + if ( me ) + pkrb5_free_principal(ctx,me); + if ( ctx ) + pkrb5_free_context(ctx); + } + + // disable DNS Realm Lookups + retval = pprofile_update_relation(m_krbv5_profile, + names, + "true", "false"); + + // save the default realm if it was discovered + if ( realm[0] ) { + names = defRealm; + retval = pprofile_add_relation(m_krbv5_profile, + names, + realm); + + // It would be nice to be able to generate a list of KDCs + // but to do so based upon the contents of DNS would be + // wrong for several reasons: + // . it would make static the values inserted into DNS SRV + // records + // . DNS cannot necessarily be trusted + } + + // Save to Kerberos Five config. file "Krb5.ini" + retval = pprofile_flush(m_krbv5_profile); + + pprofile_release(m_krbv5_profile); + m_krbv5_profile = NULL; + + // Close KRB.CON file + if ( krb_con_open ) { + krbCon.WriteString(".KERBEROS.OPTION. dns\n"); + krbCon.Close(); + } + + // Create the empty KRBREALM.CON file + if ( !GetKrb4RealmFile(confname,sizeof(confname)) ) { + if (!krbCon.Open(confname, CFile::modeNoTruncate | CFile::modeRead)) + { + if (krbCon.Open(confname, CFile::modeCreate | CFile::modeWrite)) + { + krbCon.Close(); + } + } else + krbCon.Close(); + } + + } + } else if ( m_hKrb4DLL ) { + if ( !realm[0] ) { + /* Open ticket file */ + char * file = ptkt_string(); + int k_errno; + + if (file != NULL && file[0]) { + if ((k_errno = ptf_init(file, R_TKT_FIL)) == KSUCCESS) { + /* Close ticket file */ + (void) ptf_close(); + + k_errno = pkrb_get_tf_realm(file, realm); + } + if (k_errno != KSUCCESS) { + k_errno = pkrb_get_lrealm(realm, 1); + } + } + } + + if ( !GetKrb4ConFile(confname,sizeof(confname)) ) { + if (!krbCon.Open(confname, CFile::modeNoTruncate | CFile::modeRead)) + { + if (krbCon.Open(confname, CFile::modeCreate | CFile::modeWrite)) + { + if ( realm[0] ) + krbCon.WriteString(realm); + krbCon.WriteString("\n.KERBEROS.OPTION. dns\n"); + krbCon.Close(); + } + } else + krbCon.Close(); + } + + if ( !GetKrb4RealmFile(confname,sizeof(confname)) ) { + if (!krbCon.Open(confname, CFile::modeNoTruncate | CFile::modeRead)) + { + if (krbCon.Open(confname, CFile::modeCreate | CFile::modeWrite)) + { + krbCon.Close(); + } + } else + krbCon.Close(); + } + } +} + +BOOL +CLeashApp::GetKrb4ConFile( + LPSTR confname, + UINT szConfname + ) +{ + if (m_hKrb5DLL && !m_hKrb4DLL) + { // hold krb.con where krb5.ini is located + CHAR krbConFile[MAX_PATH]=""; + //strcpy(krbConFile, CLeashApp::m_krbv5_profile->first_file->filename); + if (GetProfileFile(krbConFile, sizeof(krbConFile))) + { + GetWindowsDirectory(krbConFile,sizeof(krbConFile)); + krbConFile[MAX_PATH-1] = '\0'; + strncat(krbConFile,"\\KRB5.INI",sizeof(krbConFile)-strlen(krbConFile)-1); + krbConFile[MAX_PATH-1] = '\0'; + } + + LPSTR pFind = strrchr(krbConFile, '\\'); + if (pFind) + { + *pFind = 0; + strncat(krbConFile, "\\",MAX_PATH-1); + krbConFile[MAX_PATH-1] = '\0'; + strncat(krbConFile, KRB_FILE,MAX_PATH-1); + krbConFile[MAX_PATH-1] = '\0'; + } + else + ASSERT(0); + + strncpy(confname, krbConFile, szConfname); + confname[szConfname-1] = '\0'; + } + else if (m_hKrb4DLL) + { + unsigned int size = szConfname; + memset(confname, '\0', szConfname); + if (!pkrb_get_krbconf2(confname, &size)) + { // Error has happened + GetWindowsDirectory(confname,szConfname); + confname[szConfname-1] = '\0'; + strncat(confname, "\\",szConfname); + confname[szConfname-1] = '\0'; + strncat(confname,KRB_FILE,szConfname); + confname[szConfname-1] = '\0'; + } + } + return FALSE; +} + +BOOL +CLeashApp::GetKrb4RealmFile( + LPSTR confname, + UINT szConfname + ) +{ + if (m_hKrb5DLL && !m_hKrb4DLL) + { // hold krb.con where krb5.ini is located + CHAR krbRealmConFile[MAX_PATH]; + //strcpy(krbRealmConFile, CLeashApp::m_krbv5_profile->first_file->filename); + if (GetProfileFile(krbRealmConFile, sizeof(krbRealmConFile))) + { + GetWindowsDirectory(krbRealmConFile,sizeof(krbRealmConFile)); + krbRealmConFile[MAX_PATH-1] = '\0'; + strncat(krbRealmConFile,"\\KRB5.INI",sizeof(krbRealmConFile)-strlen(krbRealmConFile)); + krbRealmConFile[MAX_PATH-1] = '\0'; + } + + LPSTR pFind = strrchr(krbRealmConFile, '\\'); + if (pFind) + { + *pFind = 0; + strncat(krbRealmConFile, "\\",MAX_PATH-1-strlen(krbRealmConFile)); + krbRealmConFile[MAX_PATH-1] = '\0'; + strncat(krbRealmConFile, KRBREALM_FILE,MAX_PATH-1-strlen(krbRealmConFile)); + krbRealmConFile[MAX_PATH-1] = '\0'; + } + else + ASSERT(0); + + strncpy(confname, krbRealmConFile, szConfname); + confname[szConfname-1] = '\0'; + } + else if (m_hKrb4DLL) + { + unsigned int size = szConfname; + memset(confname, '\0', szConfname); + if (!pkrb_get_krbrealm2(confname, &size)) + { + GetWindowsDirectory(confname,szConfname); + confname[szConfname-1] = '\0'; + strncat(confname, "\\",szConfname-strlen(confname)); + confname[szConfname-1] = '\0'; + strncat(confname,KRBREALM_FILE,szConfname-strlen(confname)); + confname[szConfname-1] = '\0'; + return TRUE; + } + } + return FALSE; +} + +BOOL +CLeashApp::GetProfileFile( + LPSTR confname, + UINT szConfname + ) +{ + char **configFile = NULL; + if (!m_hKrb5DLL) + return NULL; + + if (pkrb5_get_default_config_files(&configFile)) + { + GetWindowsDirectory(confname,szConfname); + confname[szConfname-1] = '\0'; + strncat(confname,"\\KRB5.INI",szConfname-strlen(confname)); + confname[szConfname-1] = '\0'; + return FALSE; + } + + *confname = 0; + + if (configFile) + { + strncpy(confname, *configFile, szConfname); + confname[szConfname-1] = '\0'; + pkrb5_free_config_files(configFile); + } + + if (!*confname) + { + GetWindowsDirectory(confname,szConfname); + confname[szConfname-1] = '\0'; + strncat(confname,"\\KRB5.INI",szConfname-strlen(confname)); + confname[szConfname-1] = '\0'; + } + + return FALSE; +} + +#define PROBE_USERNAME "KERBEROS-KDC-PROBE" +#define PROBE_PASSWORD_LEN 16 + +BOOL +CLeashApp::ProbeKDC(void) +{ + krb5_context ctx=0; + krb5_ccache cc=0; + krb5_principal principal = 0; + krb5_principal probeprinc = 0; + krb5_creds creds; + krb5_error_code code; + krb5_data pwdata; + char password[PROBE_PASSWORD_LEN+1]; + long success = FALSE; + + if (!pkrb5_init_context) + return success; + + memset(&creds, 0, sizeof(creds)); + + code = pkrb5_init_context(&ctx); + if (code) + goto cleanup; + + code = pkrb5_cc_default(ctx, &cc); + if (code) + goto cleanup; + + code = pkrb5_cc_get_principal(ctx, cc, &principal); + if ( code ) + code = pkrb5_parse_name(ctx, "foo", &principal); + if ( code ) + goto cleanup; + + code = pkrb5_build_principal( ctx, &probeprinc, + krb5_princ_realm(ctx,principal)->length, + krb5_princ_realm(ctx,principal)->data, + PROBE_USERNAME, NULL, NULL); + if ( code ) + goto cleanup; + + pwdata.data = password; + pwdata.length = PROBE_PASSWORD_LEN; + code = pkrb5_c_random_make_octets(ctx, &pwdata); + if (code) { + int i; + for ( i=0 ; i<PROBE_PASSWORD_LEN ; i ) + password[i] = 'x'; + } + password[PROBE_PASSWORD_LEN] = '\0'; + + code = pkrb5_get_init_creds_password(ctx, + &creds, + probeprinc, + password, // password + NULL, // prompter + 0, // prompter data + 0, // start time + 0, // service name + 0 // no options + ); + + switch ( code ) { + case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN: + case KRB5KDC_ERR_CLIENT_REVOKED: + case KRB5KDC_ERR_CLIENT_NOTYET: + case KRB5KDC_ERR_PREAUTH_FAILED: + case KRB5KDC_ERR_PREAUTH_REQUIRED: + case KRB5KDC_ERR_PADATA_TYPE_NOSUPP: + success = TRUE; + break; + } + cleanup: + if (creds.client == probeprinc) + creds.client = 0; + pkrb5_free_cred_contents(ctx, &creds); + if (principal) + pkrb5_free_principal(ctx,principal); + if (probeprinc) + pkrb5_free_principal(ctx,probeprinc); + if (cc) + pkrb5_cc_close(ctx,cc); + if (ctx) + pkrb5_free_context(ctx); + return success; +} + +VOID +CLeashApp::ObtainTicketsViaUserIfNeeded(HWND hWnd) +{ + TicketList* ticketList = NULL; + if (WaitForSingleObject( ticketinfo.lockObj, INFINITE ) != WAIT_OBJECT_0) + throw("Unable to lock ticketinfo"); + pLeashKRB5GetTickets(&ticketinfo.Krb5, &ticketList, &CLeashApp::m_krbv5_context); + pLeashFreeTicketList(&ticketList); + pLeashKRB4GetTickets(&ticketinfo.Krb4, &ticketList); + pLeashFreeTicketList(&ticketList); + + if ( !ticketinfo.Krb4.btickets && !ticketinfo.Krb5.btickets ) { + ReleaseMutex(ticketinfo.lockObj); +#ifndef KRB5_TC_NOTICKET + if (WaitForSingleObject( m_tgsReqMutex, INFINITE ) != WAIT_OBJECT_0) + throw("Unable to lock TGS mutex"); +#endif + if ( pLeash_importable() ) { + if (pLeash_import()) + CLeashView::m_importedTickets = 1; +#ifndef KRB5_TC_NOTICKET + ReleaseMutex(m_tgsReqMutex); +#endif + } + else if ( ProbeKDC() ) { +#ifndef KRB5_TC_NOTICKET + ReleaseMutex(m_tgsReqMutex); +#endif + LSH_DLGINFO_EX ldi; + ldi.size = sizeof(ldi); + ldi.dlgtype = DLGTYPE_PASSWD; + ldi.title = "Initialize Ticket"; + ldi.username = NULL; + ldi.realm = NULL; + ldi.dlgtype = DLGTYPE_PASSWD; + ldi.use_defaults = 1; + + pLeash_kinit_dlg_ex(hWnd, &ldi); + } +#ifndef KRB5_TC_NOTICKET + else { + ReleaseMutex(m_tgsReqMutex); + } +#endif + } else if ( ticketinfo.Krb5.btickets ) { + ReleaseMutex(ticketinfo.lockObj); +#ifndef KRB5_TC_NOTICKET + if (WaitForSingleObject( m_tgsReqMutex, INFINITE ) != WAIT_OBJECT_0) + throw("Unable to TGS mutex"); +#endif + if ( CLeashView::m_importedTickets && pLeash_importable() ) { + if (pLeash_import()) + CLeashView::m_importedTickets = 1; +#ifndef KRB5_TC_NOTICKET + ReleaseMutex(m_tgsReqMutex); +#endif + } + else if ( ProbeKDC() && !pLeash_renew() ) { +#ifndef KRB5_TC_NOTICKET + ReleaseMutex(m_tgsReqMutex); +#endif + LSH_DLGINFO_EX ldi; + ldi.size = sizeof(ldi); + ldi.dlgtype = DLGTYPE_PASSWD; + ldi.title = "Initialize Ticket"; + ldi.username = NULL; + ldi.realm = NULL; + ldi.dlgtype = DLGTYPE_PASSWD; + ldi.use_defaults = 1; + + pLeash_kinit_dlg_ex(hWnd, &ldi); + } +#ifndef KRB5_TC_NOTICKET + else { + ReleaseMutex(m_tgsReqMutex); + } +#endif + } else if ( ticketinfo.Krb4.btickets ) { + ReleaseMutex(ticketinfo.lockObj); +#ifndef KRB5_TC_NOTICKET + if (WaitForSingleObject( m_tgsReqMutex, INFINITE ) != WAIT_OBJECT_0) + throw("Unable to lock TGS mutex"); +#endif + if ( ProbeKDC() ) { +#ifndef KRB5_TC_NOTICKET + ReleaseMutex(m_tgsReqMutex); +#endif + LSH_DLGINFO_EX ldi; + ldi.size = sizeof(ldi); + ldi.dlgtype = DLGTYPE_PASSWD; + ldi.title = "Initialize Ticket"; + ldi.username = NULL; + ldi.realm = NULL; + ldi.dlgtype = DLGTYPE_PASSWD; + ldi.use_defaults = 1; + + pLeash_kinit_dlg_ex(hWnd, &ldi); + } +#ifndef KRB5_TC_NOTICKET + else { + ReleaseMutex(m_tgsReqMutex); + } +#endif + } else { + ReleaseMutex(ticketinfo.lockObj); + // Do nothing ... + } + return; +} + +// IP Change Monitoring Functions +#include <Iphlpapi.h> + + +DWORD +CLeashApp::GetNumOfIpAddrs(void) +{ + PMIB_IPADDRTABLE pIpAddrTable = 0; + ULONG dwSize; + DWORD code; + DWORD index; + DWORD validAddrs = 0; + + dwSize = 0; + code = GetIpAddrTable(NULL, &dwSize, 0); + if (code == ERROR_INSUFFICIENT_BUFFER) { + pIpAddrTable = (PMIB_IPADDRTABLE) malloc(dwSize); + code = GetIpAddrTable(pIpAddrTable, &dwSize, 0); + if ( code == NO_ERROR ) { + for ( index=0; index < pIpAddrTable->dwNumEntries; index++ ) { + if (pIpAddrTable->table[index].dwAddr != 0) + validAddrs++; + } + } + free(pIpAddrTable); + } + return validAddrs; +} + +UINT +CLeashApp::IpAddrChangeMonitor(void * hWnd) +{ + DWORD Result; + DWORD prevNumOfAddrs = GetNumOfIpAddrs(); + DWORD NumOfAddrs; + + if ( !hWnd ) + return 0; + + while ( TRUE ) { + Result = NotifyAddrChange(NULL,NULL); + if ( Result != NO_ERROR ) { + // We do not have permission to open the device + return 0; + } + + NumOfAddrs = GetNumOfIpAddrs(); + if ( NumOfAddrs != prevNumOfAddrs ) { + // wait for the network state to stablize + Sleep(2000); + // this call should probably be mutex protected + ObtainTicketsViaUserIfNeeded((HWND)hWnd); + } + prevNumOfAddrs = NumOfAddrs; + } + + return 0; +} + + +DWORD +CLeashApp::IpAddrChangeMonitorInit(HWND hWnd) +{ + AfxBeginThread(IpAddrChangeMonitor, hWnd); + return 0; +} + +UINT +CLeashApp::InitWorker(void * hWnd) +{ +#ifndef KRB5_TC_NOTICKET + if (WaitForSingleObject( m_tgsReqMutex, INFINITE ) != WAIT_OBJECT_0) + throw("Unable to lock tgsReq"); +#endif + if ( ProbeKDC() ) { + LSH_DLGINFO_EX ldi; + ldi.size = sizeof(ldi); + ldi.dlgtype = DLGTYPE_PASSWD; + ldi.title = "Initialize Ticket"; + ldi.username = NULL; + ldi.realm = NULL; + ldi.use_defaults = 1; + +#ifndef KRB5_TC_NOTICKET + ReleaseMutex(m_tgsReqMutex); +#endif + pLeash_kinit_dlg_ex((HWND)hWnd, &ldi); + ::SendMessage((HWND)hWnd, WM_COMMAND, ID_UPDATE_DISPLAY, 0); + } +#ifndef KRB5_TC_NOTICKET + else + ReleaseMutex(m_tgsReqMutex); +#endif + return 0; +} + +#ifdef USE_HTMLHELP +#if _MSC_VER < 1300 +void +CLeashApp::WinHelp(DWORD dwData, UINT nCmd) +{ + switch (nCmd) + { + case HELP_CONTEXT: + ::HtmlHelp(GetDesktopWindow(), m_helpFile, HH_HELP_CONTEXT, dwData ); + break; + case HELP_FINDER: + ::HtmlHelp(GetDesktopWindow(), m_helpFile, HH_DISPLAY_TOPIC, 0); + break; + } +} +#endif +#endif |