summaryrefslogtreecommitdiffstats
path: root/src/windows/leash/Leash.cpp
diff options
context:
space:
mode:
authorSam Hartman <hartmans@mit.edu>2011-09-28 21:02:14 +0000
committerSam Hartman <hartmans@mit.edu>2011-09-28 21:02:14 +0000
commitcaef99b21536d9e8c2f9c637fcf020b4e082db5d (patch)
treeb360ec8449876ea170691685cde758d9849fc8ef /src/windows/leash/Leash.cpp
parent8481c14298a1886f63bec0d7cdfd800a86b4c127 (diff)
downloadkrb5-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.cpp1618
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